[clang] f926e19 - Reapply "[clang][Interp] Fix init chain in local initializers"

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 5 03:16:33 PDT 2024


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, "");
+}


        


More information about the cfe-commits mailing list