llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

When creating descriptor for array element types, we only save the original 
source, e.g. int[2][2][2]. So later calls to getType() of the element 
descriptors will also return int[2][2][2], instead of e.g. int[2][2] for the 
second dimension.
Fix this by explicitly tracking the array types.
The last attached test case used to have an lvalue offset of 32 instead of 24.

We should do this for more desriptor types though and not just composite array, 
but I'm leaving that to a later patch.

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


5 Files Affected:

- (modified) clang/lib/AST/ByteCode/Descriptor.cpp (+6-2) 
- (modified) clang/lib/AST/ByteCode/Descriptor.h (+4-2) 
- (modified) clang/lib/AST/ByteCode/DynamicAllocator.cpp (+3-1) 
- (modified) clang/lib/AST/ByteCode/Program.cpp (+1-1) 
- (modified) clang/unittests/AST/ByteCode/toAPValue.cpp (+67) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp 
b/clang/lib/AST/ByteCode/Descriptor.cpp
index 6017f6dd61cb3..bcd9f6f3d078a 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -367,10 +367,12 @@ Descriptor::Descriptor(const DeclTy &D, PrimType Type, 
MetadataSize MD,
 }
 
 /// Arrays of composite elements.
-Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize 
MD,
+Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy,
+                       const Descriptor *Elem, MetadataSize MD,
                        unsigned NumElems, bool IsConst, bool IsTemporary,
                        bool IsMutable)
-    : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
+    : Source(D), SourceType(SourceTy),
+      ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
       Size(ElemSize * NumElems), MDSize(MD.value_or(0)),
       AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize),
       ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable),
@@ -410,6 +412,8 @@ Descriptor::Descriptor(const DeclTy &D)
 }
 
 QualType Descriptor::getType() const {
+  if (SourceType)
+    return QualType(SourceType, 0);
   if (const auto *D = asValueDecl())
     return D->getType();
   if (const auto *T = dyn_cast_if_present<TypeDecl>(asDecl()))
diff --git a/clang/lib/AST/ByteCode/Descriptor.h 
b/clang/lib/AST/ByteCode/Descriptor.h
index 01fa4b198de67..b2e9f1b6bded4 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -124,6 +124,7 @@ struct Descriptor final {
 private:
   /// Original declaration, used to emit the error message.
   const DeclTy Source;
+  const Type *SourceType = nullptr;
   /// Size of an element, in host bytes.
   const unsigned ElemSize;
   /// Size of the storage, in host bytes.
@@ -186,8 +187,9 @@ struct Descriptor final {
              bool IsTemporary, UnknownSize);
 
   /// Allocates a descriptor for an array of composites.
-  Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD,
-             unsigned NumElems, bool IsConst, bool IsTemporary, bool 
IsMutable);
+  Descriptor(const DeclTy &D, const Type *SourceTy, const Descriptor *Elem,
+             MetadataSize MD, unsigned NumElems, bool IsConst, bool 
IsTemporary,
+             bool IsMutable);
 
   /// Allocates a descriptor for an array of composites of unknown size.
   Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD,
diff --git a/clang/lib/AST/ByteCode/DynamicAllocator.cpp 
b/clang/lib/AST/ByteCode/DynamicAllocator.cpp
index 3ef8c2e1f3e7c..728bd75d7d141 100644
--- a/clang/lib/AST/ByteCode/DynamicAllocator.cpp
+++ b/clang/lib/AST/ByteCode/DynamicAllocator.cpp
@@ -57,8 +57,10 @@ Block *DynamicAllocator::allocate(const Descriptor 
*ElementDesc,
   assert(ElementDesc->getMetadataSize() == 0);
   // Create a new descriptor for an array of the specified size and
   // element type.
+  // FIXME: Pass proper element type.
   const Descriptor *D = allocateDescriptor(
-      ElementDesc->asExpr(), ElementDesc, Descriptor::InlineDescMD, 
NumElements,
+      ElementDesc->asExpr(), nullptr, ElementDesc, Descriptor::InlineDescMD,
+      NumElements,
       /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false);
   return allocate(D, EvalID, AllocForm);
 }
diff --git a/clang/lib/AST/ByteCode/Program.cpp 
b/clang/lib/AST/ByteCode/Program.cpp
index 0754e259b7cb3..cc2cfc9b03b41 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -419,7 +419,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, 
const Type *Ty,
         unsigned ElemSize = ElemDesc->getAllocSize() + 
sizeof(InlineDescriptor);
         if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems)
           return {};
-        return allocateDescriptor(D, ElemDesc, MDSize, NumElems, IsConst,
+        return allocateDescriptor(D, Ty, ElemDesc, MDSize, NumElems, IsConst,
                                   IsTemporary, IsMutable);
       }
     }
diff --git a/clang/unittests/AST/ByteCode/toAPValue.cpp 
b/clang/unittests/AST/ByteCode/toAPValue.cpp
index cd62338ee23c1..c7df97c81b16f 100644
--- a/clang/unittests/AST/ByteCode/toAPValue.cpp
+++ b/clang/unittests/AST/ByteCode/toAPValue.cpp
@@ -254,3 +254,70 @@ TEST(ToAPValue, MemberPointers) {
     ASSERT_EQ(A.getKind(), APValue::MemberPointer);
   }
 }
+
+/// Test the various toAPValue implementations.
+TEST(ToAPValue, Comparison) {
+  constexpr char Code[] =
+      "constexpr int GI = 12;\n"
+      "constexpr const int *PI = &GI;\n"
+      "struct S{int a; };\n"
+      "constexpr S GS[] = {{}, {}};\n"
+      "constexpr const S* OS = GS + 1;\n"
+      "constexpr S DS = *OS;\n"
+      "constexpr int IA[2][2][2] = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};\n"
+      "constexpr const int *PIA = IA[1][1];\n";
+
+  for (const char *Arg : {"", "-fexperimental-new-constant-interpreter"}) {
+    auto AST = tooling::buildASTFromCodeWithArgs(Code, {Arg});
+
+    // auto &ASTCtx = AST->getASTContext();
+    auto getDecl = [&](const char *Name) -> const VarDecl * {
+      auto Nodes =
+          match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
+      assert(Nodes.size() == 1);
+      const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
+      assert(D);
+      return cast<VarDecl>(D);
+    };
+
+    {
+      const VarDecl *GIDecl = getDecl("GI");
+      const APValue *V = GIDecl->evaluateValue();
+      ASSERT_TRUE(V->isInt());
+    }
+
+    {
+      const VarDecl *GIDecl = getDecl("GI");
+      const VarDecl *PIDecl = getDecl("PI");
+      const APValue *V = PIDecl->evaluateValue();
+      ASSERT_TRUE(V->isLValue());
+      ASSERT_TRUE(V->hasLValuePath());
+      ASSERT_EQ(V->getLValueBase().get<const ValueDecl *>(), GIDecl);
+      ASSERT_EQ(V->getLValuePath().size(), 0u);
+    }
+
+    {
+      const APValue *V = getDecl("OS")->evaluateValue();
+      ASSERT_TRUE(V->isLValue());
+      ASSERT_EQ(V->getLValueOffset().getQuantity(), (unsigned)sizeof(int));
+      ASSERT_TRUE(V->hasLValuePath());
+      ASSERT_EQ(V->getLValuePath().size(), 1u);
+      ASSERT_EQ(V->getLValuePath()[0].getAsArrayIndex(), 1u);
+    }
+
+    {
+      const APValue *V = getDecl("DS")->evaluateValue();
+      ASSERT_TRUE(V->isStruct());
+    }
+    {
+      const APValue *V = getDecl("PIA")->evaluateValue();
+      ASSERT_TRUE(V->isLValue());
+      ASSERT_TRUE(V->hasLValuePath());
+      ASSERT_EQ(V->getLValuePath().size(), 3u);
+      ASSERT_EQ(V->getLValuePath()[0].getAsArrayIndex(), 1u);
+      ASSERT_EQ(V->getLValuePath()[1].getAsArrayIndex(), 1u);
+      ASSERT_EQ(V->getLValuePath()[2].getAsArrayIndex(), 0u);
+      ASSERT_EQ(V->getLValueOffset().getQuantity(), (unsigned)sizeof(int) * 6);
+    }
+  }
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/129376
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to