Skip to content

Commit 7fa354a

Browse files
committed
[clang][bytecode] Fix initialing array struct fields from an APValue
We need to recurse once more here and move the array case into the bigger if chain.
1 parent eef5ea0 commit 7fa354a

File tree

3 files changed

+59
-32
lines changed

3 files changed

+59
-32
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3650,7 +3650,7 @@ bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
36503650

36513651
assert(V.isStruct());
36523652
assert(V.getStructNumBases() == 0);
3653-
if (!this->visitAPValueInitializer(V, E))
3653+
if (!this->visitAPValueInitializer(V, E, E->getType()))
36543654
return false;
36553655

36563656
return this->emitFinishInit(E);
@@ -4637,48 +4637,27 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
46374637

46384638
template <class Emitter>
46394639
bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
4640-
const Expr *E) {
4641-
4640+
const Expr *E, QualType T) {
46424641
if (Val.isStruct()) {
4643-
const Record *R = this->getRecord(E->getType());
4642+
const Record *R = this->getRecord(T);
46444643
assert(R);
46454644
for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) {
46464645
const APValue &F = Val.getStructField(I);
46474646
const Record::Field *RF = R->getField(I);
4647+
QualType FieldType = RF->Decl->getType();
46484648

4649-
if (F.isInt() || F.isFloat() || F.isLValue() || F.isMemberPointer()) {
4650-
PrimType T = classifyPrim(RF->Decl->getType());
4651-
if (!this->visitAPValue(F, T, E))
4652-
return false;
4653-
if (!this->emitInitField(T, RF->Offset, E))
4654-
return false;
4655-
} else if (F.isArray()) {
4656-
assert(RF->Desc->isPrimitiveArray());
4657-
const auto *ArrType = RF->Decl->getType()->getAsArrayTypeUnsafe();
4658-
PrimType ElemT = classifyPrim(ArrType->getElementType());
4659-
assert(ArrType);
4660-
4661-
if (!this->emitGetPtrField(RF->Offset, E))
4649+
if (std::optional<PrimType> PT = classify(FieldType)) {
4650+
if (!this->visitAPValue(F, *PT, E))
46624651
return false;
4663-
4664-
for (unsigned A = 0, AN = F.getArraySize(); A != AN; ++A) {
4665-
if (!this->visitAPValue(F.getArrayInitializedElt(A), ElemT, E))
4666-
return false;
4667-
if (!this->emitInitElem(ElemT, A, E))
4668-
return false;
4669-
}
4670-
4671-
if (!this->emitPopPtr(E))
4652+
if (!this->emitInitField(*PT, RF->Offset, E))
46724653
return false;
4673-
} else if (F.isStruct() || F.isUnion()) {
4654+
} else {
46744655
if (!this->emitGetPtrField(RF->Offset, E))
46754656
return false;
4676-
if (!this->visitAPValueInitializer(F, E))
4657+
if (!this->visitAPValueInitializer(F, E, FieldType))
46774658
return false;
46784659
if (!this->emitPopPtr(E))
46794660
return false;
4680-
} else {
4681-
assert(false && "I don't think this should be possible");
46824661
}
46834662
}
46844663
return true;
@@ -4692,6 +4671,28 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
46924671
if (!this->visitAPValue(F, T, E))
46934672
return false;
46944673
return this->emitInitField(T, RF->Offset, E);
4674+
} else if (Val.isArray()) {
4675+
const auto *ArrType = T->getAsArrayTypeUnsafe();
4676+
QualType ElemType = ArrType->getElementType();
4677+
for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {
4678+
const APValue &Elem = Val.getArrayInitializedElt(A);
4679+
if (std::optional<PrimType> ElemT = classify(ElemType)) {
4680+
if (!this->visitAPValue(Elem, *ElemT, E))
4681+
return false;
4682+
if (!this->emitInitElem(*ElemT, A, E))
4683+
return false;
4684+
} else {
4685+
if (!this->emitConstUint32(A, E))
4686+
return false;
4687+
if (!this->emitArrayElemPtrUint32(E))
4688+
return false;
4689+
if (!this->visitAPValueInitializer(Elem, E, ElemType))
4690+
return false;
4691+
if (!this->emitPopPtr(E))
4692+
return false;
4693+
}
4694+
}
4695+
return true;
46954696
}
46964697
// TODO: Other types.
46974698

@@ -6374,7 +6375,8 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
63746375
return false;
63756376
return this->emitInitGlobal(*T, *Index, E);
63766377
}
6377-
return this->visitAPValueInitializer(TPOD->getValue(), E);
6378+
return this->visitAPValueInitializer(TPOD->getValue(), E,
6379+
TPOD->getType());
63786380
}
63796381
return false;
63806382
}

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
290290
VarCreationState visitDecl(const VarDecl *VD);
291291
/// Visit an APValue.
292292
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
293-
bool visitAPValueInitializer(const APValue &Val, const Expr *E);
293+
bool visitAPValueInitializer(const APValue &Val, const Expr *E, QualType T);
294294
/// Visit the given decl as if we have a reference to it.
295295
bool visitDeclRef(const ValueDecl *D, const Expr *E);
296296

clang/test/AST/ByteCode/cxx20.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,3 +964,28 @@ namespace PseudoDtor {
964964
static_assert(f3() == 0);
965965
#endif
966966
}
967+
968+
namespace NastyChar {
969+
struct nasty_char {
970+
template <typename T> friend auto operator<=>(T, T) = delete;
971+
template <typename T> friend void operator+(T &&) = delete;
972+
template <typename T> friend void operator-(T &&) = delete;
973+
template <typename T> friend void operator&(T &&) = delete;
974+
975+
char c;
976+
};
977+
978+
979+
template <unsigned N> struct ToNastyChar {
980+
constexpr ToNastyChar(const char (&r)[N]) {
981+
for (unsigned I = 0; I != N; ++I)
982+
text[I] = nasty_char{r[I]};
983+
}
984+
nasty_char text[N];
985+
};
986+
987+
template <unsigned N> ToNastyChar(const char (&)[N]) -> ToNastyChar<N>;
988+
989+
template <ToNastyChar t> constexpr auto to_nasty_char() { return t; }
990+
constexpr auto result = to_nasty_char<"12345">();
991+
}

0 commit comments

Comments
 (0)