[clang] b4fc141 - [clang][Interp] Fix ArrayInitLoop common expr life time

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 24 03:20:57 PDT 2023


Author: Timm Bäder
Date: 2023-10-24T12:20:02+02:00
New Revision: b4fc1418d9765bfb605387efc70ecf233d27b383

URL: https://github.com/llvm/llvm-project/commit/b4fc1418d9765bfb605387efc70ecf233d27b383
DIFF: https://github.com/llvm/llvm-project/commit/b4fc1418d9765bfb605387efc70ecf233d27b383.diff

LOG: [clang][Interp] Fix ArrayInitLoop common expr life time

The local variable needs to survive for all the interations of the
ArrayInitLoopExpr. So, visit it explicitly before we iterate.

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/test/AST/Interp/cxx20.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index eb96f021258b114..1b33c69b93aa4b9 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -820,14 +820,24 @@ bool ByteCodeExprGen<Emitter>::VisitArrayInitLoopExpr(
   //   Investigate compiling this to a loop.
 
   const Expr *SubExpr = E->getSubExpr();
+  const Expr *CommonExpr = E->getCommonExpr();
   size_t Size = E->getArraySize().getZExtValue();
   std::optional<PrimType> ElemT = classify(SubExpr->getType());
 
+  // If the common expression is an opaque expression, we visit it
+  // here once so we have its value cached.
+  // FIXME: This might be necessary (or useful) for all expressions.
+  if (isa<OpaqueValueExpr>(CommonExpr)) {
+    if (!this->discard(CommonExpr))
+      return false;
+  }
+
   // So, every iteration, we execute an assignment here
   // where the LHS is on the stack (the target array)
   // and the RHS is our SubExpr.
   for (size_t I = 0; I != Size; ++I) {
     ArrayIndexScope<Emitter> IndexScope(this, I);
+    BlockScope<Emitter> BS(this);
 
     if (ElemT) {
       if (!this->visit(SubExpr))
@@ -856,7 +866,7 @@ bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
 
   PrimType SubExprT = classify(E->getSourceExpr()).value_or(PT_Ptr);
   if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end())
-    return this->emitGetLocal(SubExprT, It->getSecond(), E);
+    return this->emitGetLocal(SubExprT, It->second, E);
 
   if (!this->visit(E->getSourceExpr()))
     return false;
@@ -873,8 +883,10 @@ bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
 
   // Here the local variable is created but the value is removed from the stack,
   // so we put it back, because the caller might need it.
-  if (!this->emitGetLocal(SubExprT, *LocalIndex, E))
-    return false;
+  if (!DiscardResult) {
+    if (!this->emitGetLocal(SubExprT, *LocalIndex, E))
+      return false;
+  }
 
   // FIXME: Ideally the cached value should be cleaned up later.
   OpaqueExprs.insert({E, *LocalIndex});

diff  --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp
index 553bc6eb4d5244f..f0bb4e9e0d0711b 100644
--- a/clang/test/AST/Interp/cxx20.cpp
+++ b/clang/test/AST/Interp/cxx20.cpp
@@ -701,13 +701,12 @@ namespace ThreeWayCmp {
   static_assert(pa2 <=> pa1 == 1, "");
 }
 
-// FIXME: Interp should also be able to evaluate this snippet properly.
 namespace ConstexprArrayInitLoopExprDestructors
 {
   struct Highlander {
       int *p = 0;
       constexpr Highlander() {}
-      constexpr void set(int *p) { this->p = p; ++*p; if (*p != 1) throw "there can be only one"; } // expected-note {{not valid in a constant expression}}
+      constexpr void set(int *p) { this->p = p; ++*p; if (*p != 1) throw "there can be only one"; }
       constexpr ~Highlander() { --*p; }
   };
 
@@ -715,23 +714,18 @@ namespace ConstexprArrayInitLoopExprDestructors
       int *p;
       constexpr X(int *p) : p(p) {}
       constexpr X(const X &x, Highlander &&h = Highlander()) : p(x.p) {
-          h.set(p); // expected-note {{in call to '&Highlander()->set(&n)'}}
+          h.set(p);
       }
   };
 
   constexpr int f() {
       int n = 0;
       X x[3] = {&n, &n, &n};
-      auto [a, b, c] = x; // expected-note {{in call to 'X(x[0], Highlander())'}}
+      auto [a, b, c] = x;
       return n;
   }
 
-  static_assert(f() == 0); // expected-error {{not an integral constant expression}} \
-                           // expected-note {{in call to 'f()'}}
-
-  int main() {
-      return f();
-  }
+  static_assert(f() == 0);
 }
 
 namespace NonPrimitiveOpaqueValue


        


More information about the cfe-commits mailing list