Author: Timm Bäder Date: 2024-07-05T12:16:18+02:00 New Revision: f926e19aa9c0bdca3f05322e1b62562a9a3a05e2
URL: https://github.com/llvm/llvm-project/commit/f926e19aa9c0bdca3f05322e1b62562a9a3a05e2 DIFF: https://github.com/llvm/llvm-project/commit/f926e19aa9c0bdca3f05322e1b62562a9a3a05e2.diff LOG: Reapply "[clang][Interp] Fix init chain in local initializers" This reverts commit 2dda8a2650927e4b0fbb459507684455e196d9a9. Added: Modified: clang/lib/AST/Interp/Compiler.cpp clang/lib/AST/Interp/Compiler.h clang/lib/AST/Interp/EvalEmitter.cpp clang/lib/AST/Interp/Pointer.h clang/test/AST/Interp/records.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp index 2fd20d8022126..2ada68f6bc756 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/Interp/Compiler.cpp @@ -85,8 +85,12 @@ bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const { case K_Field: // We're assuming there's a base pointer on the stack already. return Ctx->emitGetPtrFieldPop(Offset, E); + case K_Temp: + return Ctx->emitGetPtrLocal(Offset, E); case K_Decl: return Ctx->visitDeclRef(D, E); + default: + llvm_unreachable("Unhandled InitLink kind"); } return true; } @@ -1330,6 +1334,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, auto initCompositeField = [=](const Record::Field *FieldToInit, const Expr *Init) -> bool { + InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset)); // Non-primitive case. Get a pointer to the field-to-initialize // on the stack and recurse into visitInitializer(). if (!this->emitGetPtrField(FieldToInit->Offset, Init)) @@ -2271,6 +2276,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr( const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments(); if (std::optional<unsigned> LocalIndex = allocateLocal(Inner, E->getExtendingDecl())) { + InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex)); if (!this->emitGetPtrLocal(*LocalIndex, E)) return false; return this->visitInitializer(SubExpr); @@ -2449,6 +2455,7 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) { // Trivial copy/move constructor. Avoid copy. if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() && + Ctor->isTrivial() && E->getArg(0)->isTemporaryObject(Ctx.getASTContext(), T->getAsCXXRecordDecl())) return this->visitInitializer(E->getArg(0)); @@ -3583,6 +3590,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve return !Init || (checkDecl() && initGlobal(*GlobalIndex)); } else { VariableScope<Emitter> LocalScope(this, VD); + InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD)); if (VarT) { unsigned Offset = this->allocateLocalPrimitive( @@ -3917,7 +3925,8 @@ bool Compiler<Emitter>::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) { SourceLocScope<Emitter> SLS(this, E); bool Old = InitStackActive; - InitStackActive = !isa<FunctionDecl>(E->getUsedContext()); + InitStackActive = + !(E->getUsedContext()->getDeclKind() == Decl::CXXConstructor); bool Result = this->delegate(E->getExpr()); InitStackActive = Old; return Result; @@ -3979,8 +3988,14 @@ bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) { // currently being initialized. Here we emit the necessary instruction(s) for // this scenario. if (InitStackActive && !InitStack.empty()) { - for (const InitLink &IL : InitStack) { - if (!IL.emit<Emitter>(this, E)) + unsigned StartIndex = 0; + for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) { + if (InitStack[StartIndex].Kind != InitLink::K_Field) + break; + } + + for (unsigned I = StartIndex, N = InitStack.size(); I != N; ++I) { + if (!InitStack[I].emit<Emitter>(this, E)) return false; } return true; diff --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h index d28526c76fe13..1405abfc1a1e2 100644 --- a/clang/lib/AST/Interp/Compiler.h +++ b/clang/lib/AST/Interp/Compiler.h @@ -47,7 +47,8 @@ struct InitLink { enum { K_This = 0, K_Field = 1, - K_Decl = 2, + K_Temp = 2, + K_Decl = 3, }; static InitLink This() { return InitLink{K_This}; } @@ -56,6 +57,11 @@ struct InitLink { IL.Offset = Offset; return IL; } + static InitLink Temp(unsigned Offset) { + InitLink IL{K_Temp}; + IL.Offset = Offset; + return IL; + } static InitLink Decl(const ValueDecl *D) { InitLink IL{K_Decl}; IL.D = D; @@ -66,7 +72,6 @@ struct InitLink { template <class Emitter> bool emit(Compiler<Emitter> *Ctx, const Expr *E) const; -private: uint32_t Kind; union { unsigned Offset; diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp index 5d20a0b8182a9..acd1f2c673ce0 100644 --- a/clang/lib/AST/Interp/EvalEmitter.cpp +++ b/clang/lib/AST/Interp/EvalEmitter.cpp @@ -57,6 +57,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, bool CheckFullyInitialized) { this->CheckFullyInitialized = CheckFullyInitialized; S.EvaluatingDecl = VD; + EvalResult.setSource(VD); if (const Expr *Init = VD->getAnyInitializer()) { QualType T = VD->getType(); diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index fdd921050fd80..7785da1d68f63 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -638,6 +638,7 @@ class Pointer { /// Returns the embedded descriptor preceding a field. InlineDescriptor *getInlineDesc() const { assert(asBlockPointer().Base != sizeof(GlobalInlineDescriptor)); + assert(asBlockPointer().Base <= asBlockPointer().Pointee->getSize()); return getDescriptor(asBlockPointer().Base); } diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 9f341f5bc6d1d..1554e54275598 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1482,3 +1482,15 @@ namespace FloatAPValue { ClassTemplateArgRefTemplate<ClassTemplateArgObj.Arg> ClassTemplateArgRefObj; } #endif + +namespace LocalWithThisPtrInit { + struct S { + int i; + int *p = &i; + }; + constexpr int foo() { + S s{2}; + return *s.p; + } + static_assert(foo() == 2, ""); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits