https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/131983
We need to recurse once more here and move the array case into the bigger if chain. >From 7fa354a81378172ce3cd5488b457f129da883698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Wed, 19 Mar 2025 08:54:58 +0100 Subject: [PATCH] [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. --- clang/lib/AST/ByteCode/Compiler.cpp | 64 +++++++++++++++-------------- clang/lib/AST/ByteCode/Compiler.h | 2 +- clang/test/AST/ByteCode/cxx20.cpp | 25 +++++++++++ 3 files changed, 59 insertions(+), 32 deletions(-) diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 3524ab5f86de8..6c846c01fc848 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -3650,7 +3650,7 @@ bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { assert(V.isStruct()); assert(V.getStructNumBases() == 0); - if (!this->visitAPValueInitializer(V, E)) + if (!this->visitAPValueInitializer(V, E, E->getType())) return false; return this->emitFinishInit(E); @@ -4637,48 +4637,27 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType, template <class Emitter> bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val, - const Expr *E) { - + const Expr *E, QualType T) { if (Val.isStruct()) { - const Record *R = this->getRecord(E->getType()); + const Record *R = this->getRecord(T); assert(R); for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) { const APValue &F = Val.getStructField(I); const Record::Field *RF = R->getField(I); + QualType FieldType = RF->Decl->getType(); - if (F.isInt() || F.isFloat() || F.isLValue() || F.isMemberPointer()) { - PrimType T = classifyPrim(RF->Decl->getType()); - if (!this->visitAPValue(F, T, E)) - return false; - if (!this->emitInitField(T, RF->Offset, E)) - return false; - } else if (F.isArray()) { - assert(RF->Desc->isPrimitiveArray()); - const auto *ArrType = RF->Decl->getType()->getAsArrayTypeUnsafe(); - PrimType ElemT = classifyPrim(ArrType->getElementType()); - assert(ArrType); - - if (!this->emitGetPtrField(RF->Offset, E)) + if (std::optional<PrimType> PT = classify(FieldType)) { + if (!this->visitAPValue(F, *PT, E)) return false; - - for (unsigned A = 0, AN = F.getArraySize(); A != AN; ++A) { - if (!this->visitAPValue(F.getArrayInitializedElt(A), ElemT, E)) - return false; - if (!this->emitInitElem(ElemT, A, E)) - return false; - } - - if (!this->emitPopPtr(E)) + if (!this->emitInitField(*PT, RF->Offset, E)) return false; - } else if (F.isStruct() || F.isUnion()) { + } else { if (!this->emitGetPtrField(RF->Offset, E)) return false; - if (!this->visitAPValueInitializer(F, E)) + if (!this->visitAPValueInitializer(F, E, FieldType)) return false; if (!this->emitPopPtr(E)) return false; - } else { - assert(false && "I don't think this should be possible"); } } return true; @@ -4692,6 +4671,28 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val, if (!this->visitAPValue(F, T, E)) return false; return this->emitInitField(T, RF->Offset, E); + } else if (Val.isArray()) { + const auto *ArrType = T->getAsArrayTypeUnsafe(); + QualType ElemType = ArrType->getElementType(); + for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) { + const APValue &Elem = Val.getArrayInitializedElt(A); + if (std::optional<PrimType> ElemT = classify(ElemType)) { + if (!this->visitAPValue(Elem, *ElemT, E)) + return false; + if (!this->emitInitElem(*ElemT, A, E)) + return false; + } else { + if (!this->emitConstUint32(A, E)) + return false; + if (!this->emitArrayElemPtrUint32(E)) + return false; + if (!this->visitAPValueInitializer(Elem, E, ElemType)) + return false; + if (!this->emitPopPtr(E)) + return false; + } + } + return true; } // TODO: Other types. @@ -6374,7 +6375,8 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) { return false; return this->emitInitGlobal(*T, *Index, E); } - return this->visitAPValueInitializer(TPOD->getValue(), E); + return this->visitAPValueInitializer(TPOD->getValue(), E, + TPOD->getType()); } return false; } diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 902da8ffdd330..256e917728886 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -290,7 +290,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>, VarCreationState visitDecl(const VarDecl *VD); /// Visit an APValue. bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E); - bool visitAPValueInitializer(const APValue &Val, const Expr *E); + bool visitAPValueInitializer(const APValue &Val, const Expr *E, QualType T); /// Visit the given decl as if we have a reference to it. bool visitDeclRef(const ValueDecl *D, const Expr *E); diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp index 06501de64916a..42e6ae33e92e4 100644 --- a/clang/test/AST/ByteCode/cxx20.cpp +++ b/clang/test/AST/ByteCode/cxx20.cpp @@ -964,3 +964,28 @@ namespace PseudoDtor { static_assert(f3() == 0); #endif } + +namespace NastyChar { + struct nasty_char { + template <typename T> friend auto operator<=>(T, T) = delete; + template <typename T> friend void operator+(T &&) = delete; + template <typename T> friend void operator-(T &&) = delete; + template <typename T> friend void operator&(T &&) = delete; + + char c; + }; + + + template <unsigned N> struct ToNastyChar { + constexpr ToNastyChar(const char (&r)[N]) { + for (unsigned I = 0; I != N; ++I) + text[I] = nasty_char{r[I]}; + } + nasty_char text[N]; + }; + + template <unsigned N> ToNastyChar(const char (&)[N]) -> ToNastyChar<N>; + + template <ToNastyChar t> constexpr auto to_nasty_char() { return t; } + constexpr auto result = to_nasty_char<"12345">(); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits