Author: Timm Baeder Date: 2025-10-23T15:22:17+02:00 New Revision: ece83ed7dfe6ef65ac100efcc61f50a2a337436a
URL: https://github.com/llvm/llvm-project/commit/ece83ed7dfe6ef65ac100efcc61f50a2a337436a DIFF: https://github.com/llvm/llvm-project/commit/ece83ed7dfe6ef65ac100efcc61f50a2a337436a.diff LOG: [clang][bytecode] Fix instance pointer in IndirectFieldDecl inits (#164751) Points to the first chain link in this case. Added: Modified: clang/lib/AST/ByteCode/Compiler.cpp clang/test/AST/ByteCode/records.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index b484ca8ce038a..836d22f6e5389 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -5384,55 +5384,57 @@ bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) { // instance pointer of the current function frame, but e.g. to the declaration // currently being initialized. Here we emit the necessary instruction(s) for // this scenario. - if (!InitStackActive) + if (!InitStackActive || InitStack.empty()) return this->emitThis(E); - if (!InitStack.empty()) { - // If our init stack is, for example: - // 0 Stack: 3 (decl) - // 1 Stack: 6 (init list) - // 2 Stack: 1 (field) - // 3 Stack: 6 (init list) - // 4 Stack: 1 (field) - // - // We want to find the LAST element in it that's an init list, - // which is marked with the K_InitList marker. The index right - // before that points to an init list. We need to find the - // elements before the K_InitList element that point to a base - // (e.g. a decl or This), optionally followed by field, elem, etc. - // In the example above, we want to emit elements [0..2]. - unsigned StartIndex = 0; - unsigned EndIndex = 0; - // Find the init list. - for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) { - if (InitStack[StartIndex].Kind == InitLink::K_InitList || - InitStack[StartIndex].Kind == InitLink::K_This) { - EndIndex = StartIndex; - --StartIndex; - break; - } + // If our init stack is, for example: + // 0 Stack: 3 (decl) + // 1 Stack: 6 (init list) + // 2 Stack: 1 (field) + // 3 Stack: 6 (init list) + // 4 Stack: 1 (field) + // + // We want to find the LAST element in it that's an init list, + // which is marked with the K_InitList marker. The index right + // before that points to an init list. We need to find the + // elements before the K_InitList element that point to a base + // (e.g. a decl or This), optionally followed by field, elem, etc. + // In the example above, we want to emit elements [0..2]. + unsigned StartIndex = 0; + unsigned EndIndex = 0; + // Find the init list. + for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) { + if (InitStack[StartIndex].Kind == InitLink::K_InitList || + InitStack[StartIndex].Kind == InitLink::K_This) { + EndIndex = StartIndex; + --StartIndex; + break; } + } - // Walk backwards to find the base. - for (; StartIndex > 0; --StartIndex) { - if (InitStack[StartIndex].Kind == InitLink::K_InitList) - continue; + // Walk backwards to find the base. + for (; StartIndex > 0; --StartIndex) { + if (InitStack[StartIndex].Kind == InitLink::K_InitList) + continue; - if (InitStack[StartIndex].Kind != InitLink::K_Field && - InitStack[StartIndex].Kind != InitLink::K_Elem) - break; - } + if (InitStack[StartIndex].Kind != InitLink::K_Field && + InitStack[StartIndex].Kind != InitLink::K_Elem) + break; + } - // Emit the instructions. - for (unsigned I = StartIndex; I != EndIndex; ++I) { - if (InitStack[I].Kind == InitLink::K_InitList) - continue; - if (!InitStack[I].template emit<Emitter>(this, E)) - return false; - } - return true; + if (StartIndex == 0 && EndIndex == 0) + EndIndex = InitStack.size() - 1; + + assert(StartIndex < EndIndex); + + // Emit the instructions. + for (unsigned I = StartIndex; I != (EndIndex + 1); ++I) { + if (InitStack[I].Kind == InitLink::K_InitList) + continue; + if (!InitStack[I].template emit<Emitter>(this, E)) + return false; } - return this->emitThis(E); + return true; } template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) { @@ -6294,6 +6296,10 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) { } assert(NestedField); + unsigned FirstLinkOffset = + R->getField(cast<FieldDecl>(IFD->chain()[0]))->Offset; + InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(InitExpr)); + InitLinkScope<Emitter> ILS(this, InitLink::Field(FirstLinkOffset)); if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr, IsUnion)) return false; diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp index 5040b54de3229..00218ba02bb31 100644 --- a/clang/test/AST/ByteCode/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -1162,6 +1162,19 @@ namespace IndirectFieldInit { static_assert(s2.x == 1 && s2.y == 2 && s2.a == 3 && s2.b == 4); #endif + + + struct B { + struct { + union { + int x = 3; + }; + int y = this->x; + }; + + constexpr B() {} + }; + static_assert(B().y == 3, ""); } namespace InheritedConstructor { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
