Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions clang/lib/AST/ByteCode/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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()))
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/AST/ByteCode/Descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/AST/ByteCode/DynamicAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
66 changes: 66 additions & 0 deletions clang/unittests/AST/ByteCode/toAPValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,69 @@ TEST(ToAPValue, MemberPointers) {
ASSERT_EQ(A.getKind(), APValue::MemberPointer);
}
}

/// Compare outputs between the two interpreters.
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 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);
}
}
}