-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[clang][bytecode] Explicit composite array descriptor types #129376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesWhen 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. 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:
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);
+ }
+ }
+}
|
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.
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/42/builds/3497 Here is the relevant piece of the build log for the reference |
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 descriptor types though and not just composite array, but I'm leaving that to a later patch.