[clang] 72fb188 - [clang][Interp] Handle Pointer::toAPValue() for expr bases (#101937)

via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 5 02:11:00 PDT 2024


Author: Timm Baeder
Date: 2024-08-05T11:10:56+02:00
New Revision: 72fb1889424fc371ef7d630009e4e579d18b9247

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

LOG: [clang][Interp] Handle Pointer::toAPValue() for expr bases (#101937)

No reason to return early for them anymore.

Added: 
    

Modified: 
    clang/lib/AST/Interp/Pointer.cpp
    clang/test/AST/Interp/codegen.cpp
    clang/test/AST/Interp/new-delete.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index f86be1214826d..2b1f8b460510c 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -16,6 +16,7 @@
 #include "MemberPointer.h"
 #include "PrimType.h"
 #include "Record.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/RecordLayout.h"
 
 using namespace clang;
@@ -155,12 +156,32 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
   APValue::LValueBase Base;
   if (const auto *VD = Desc->asValueDecl())
     Base = VD;
-  else if (const auto *E = Desc->asExpr())
-    Base = E;
-  else
+  else if (const auto *E = Desc->asExpr()) {
+    // Create a DynamicAlloc base of the right type.
+    if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
+      QualType AllocatedType;
+      if (NewExpr->isArray()) {
+        assert(Desc->isArray());
+        APInt ArraySize(64, static_cast<uint64_t>(Desc->getNumElems()),
+                        /*IsSigned=*/false);
+        AllocatedType =
+            ASTCtx.getConstantArrayType(NewExpr->getAllocatedType(), ArraySize,
+                                        nullptr, ArraySizeModifier::Normal, 0);
+      } else {
+        AllocatedType = NewExpr->getAllocatedType();
+      }
+      // FIXME: Suboptimal counting of dynamic allocations. Move this to Context
+      // or InterpState?
+      static int ReportedDynamicAllocs = 0;
+      DynamicAllocLValue DA(ReportedDynamicAllocs++);
+      Base = APValue::LValueBase::getDynamicAlloc(DA, AllocatedType);
+    } else {
+      Base = E;
+    }
+  } else
     llvm_unreachable("Invalid allocation type");
 
-  if (isUnknownSizeArray() || Desc->asExpr())
+  if (isUnknownSizeArray())
     return APValue(Base, CharUnits::Zero(), Path,
                    /*IsOnePastEnd=*/isOnePastEnd(), /*IsNullPtr=*/false);
 

diff  --git a/clang/test/AST/Interp/codegen.cpp b/clang/test/AST/Interp/codegen.cpp
index f1f0a33673a5b..42d98a079e120 100644
--- a/clang/test/AST/Interp/codegen.cpp
+++ b/clang/test/AST/Interp/codegen.cpp
@@ -32,6 +32,16 @@ namespace BaseClassOffsets {
   B* b = &c;
 }
 
+namespace ExprBase {
+  struct A { int n; };
+  struct B { int n; };
+  struct C : A, B {};
+
+  extern const int &&t = ((B&&)C{}).n;
+  // CHECK: @_ZGRN8ExprBase1tE_ = internal global {{.*}} zeroinitializer,
+  // CHECK: @_ZN8ExprBase1tE = constant ptr {{.*}} @_ZGRN8ExprBase1tE_, {{.*}} 8
+}
+
 namespace reinterpretcast {
   const unsigned int n = 1234;
   extern const int &s = reinterpret_cast<const int&>(n);

diff  --git a/clang/test/AST/Interp/new-delete.cpp b/clang/test/AST/Interp/new-delete.cpp
index ddf91005c61d9..325ce27c6d51d 100644
--- a/clang/test/AST/Interp/new-delete.cpp
+++ b/clang/test/AST/Interp/new-delete.cpp
@@ -358,7 +358,7 @@ namespace delete_random_things {
                                              // both-note {{delete of pointer to subobject }}
   static_assert((delete (new int + 1), true)); // both-error {{}} \
                                                // ref-note {{delete of pointer '&{*new int#0} + 1' that does not point to complete object}} \
-                                               // expected-note {{delete of pointer '&new int + 1' that does not point to complete object}}
+                                               // expected-note {{delete of pointer '&{*new int#1} + 1' that does not point to complete object}}
   static_assert((delete[] (new int[3] + 1), true)); // both-error {{}} \
                                                     // both-note {{delete of pointer to subobject}}
   static_assert((delete &(int&)(int&&)0, true)); // both-error {{}} \


        


More information about the cfe-commits mailing list