[clang] [clang][bytecode] Fix Pointer::toAPValue() for multidimensional arrays (PR #114400)

via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 31 06:03:00 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

When we see an array root, that pointer might yet again be an array element, so check for that.

---
Full diff: https://github.com/llvm/llvm-project/pull/114400.diff


3 Files Affected:

- (modified) clang/lib/AST/ByteCode/Descriptor.cpp (+9-1) 
- (modified) clang/lib/AST/ByteCode/Pointer.cpp (+17-7) 
- (modified) clang/unittests/AST/ByteCode/toAPValue.cpp (+19-1) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp
index 5a8a2b64d5582d..39a54e4902cd2a 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -411,8 +411,16 @@ QualType Descriptor::getElemQualType() const {
   QualType T = getType();
   if (T->isPointerOrReferenceType())
     return T->getPointeeType();
-  if (const auto *AT = T->getAsArrayTypeUnsafe())
+  if (const auto *AT = T->getAsArrayTypeUnsafe()) {
+    // For primitive arrays, we don't save a QualType at all,
+    // just a PrimType. Try to figure out the QualType here.
+    if (isPrimitiveArray()) {
+      while (T->isArrayType())
+        T = T->getAsArrayTypeUnsafe()->getElementType();
+      return T;
+    }
     return AT->getElementType();
+  }
   if (const auto *CT = T->getAs<ComplexType>())
     return CT->getElementType();
   if (const auto *CT = T->getAs<VectorType>())
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index c9de039c195d94..54484853fcdaea 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -200,15 +200,26 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
   // Build the path into the object.
   Pointer Ptr = *this;
   while (Ptr.isField() || Ptr.isArrayElement()) {
+
     if (Ptr.isArrayRoot()) {
-      Path.push_back(APValue::LValuePathEntry(
-          {Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
+      // An array root may still be an array element itself.
+      if (Ptr.isArrayElement()) {
+        Ptr = Ptr.expand();
+        unsigned Index = Ptr.getIndex();
+        Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
+        QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
+        Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));
+        Ptr = Ptr.getArray();
+      } else {
+        Path.push_back(APValue::LValuePathEntry(
+            {Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
 
-      if (const auto *FD =
-              dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
-        Offset += getFieldOffset(FD);
+        if (const auto *FD =
+                dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
+          Offset += getFieldOffset(FD);
 
-      Ptr = Ptr.getBase();
+        Ptr = Ptr.getBase();
+      }
     } else if (Ptr.isArrayElement()) {
       Ptr = Ptr.expand();
       unsigned Index;
@@ -219,7 +230,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
 
       QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
       Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));
-
       Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
       Ptr = Ptr.getArray();
     } else {
diff --git a/clang/unittests/AST/ByteCode/toAPValue.cpp b/clang/unittests/AST/ByteCode/toAPValue.cpp
index 3f141878fb9594..cd62338ee23c14 100644
--- a/clang/unittests/AST/ByteCode/toAPValue.cpp
+++ b/clang/unittests/AST/ByteCode/toAPValue.cpp
@@ -22,7 +22,9 @@ TEST(ToAPValue, Pointers) {
       "constexpr S d = {{{true, false}, {false, true}, {false, false}}};\n"
       "constexpr const bool *b = &d.a[1].z;\n"
       "const void *p = (void*)12;\n"
-      "const void *nullp = (void*)0;\n";
+      "const void *nullp = (void*)0;\n"
+      "extern int earr[5][5];\n"
+      "constexpr const int *arrp = &earr[2][4];\n";
 
   auto AST = tooling::buildASTFromCodeWithArgs(
       Code, {"-fexperimental-new-constant-interpreter"});
@@ -87,6 +89,22 @@ TEST(ToAPValue, Pointers) {
     ASSERT_TRUE(Success);
     ASSERT_EQ(I, 0);
   }
+
+  // A multidimensional array.
+  {
+    const ValueDecl *D = getDecl("arrp");
+    ASSERT_NE(D, nullptr);
+    const Pointer &GP = getGlobalPtr("arrp").deref<Pointer>();
+    APValue A = GP.toAPValue(ASTCtx);
+    ASSERT_TRUE(A.isLValue());
+    ASSERT_TRUE(A.hasLValuePath());
+    ASSERT_EQ(A.getLValuePath().size(), 2u);
+    ASSERT_EQ(A.getLValuePath()[0].getAsArrayIndex(), 2u);
+    ASSERT_EQ(A.getLValuePath()[1].getAsArrayIndex(), 4u);
+    ASSERT_EQ(A.getLValueOffset().getQuantity(), 56u);
+    ASSERT_TRUE(
+        GP.atIndex(0).getFieldDesc()->getElemQualType()->isIntegerType());
+  }
 }
 
 TEST(ToAPValue, FunctionPointers) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/114400


More information about the cfe-commits mailing list