Skip to content

Commit 2c82079

Browse files
authored
[clang][bytecode] Fix Pointer::toAPValue() for multidimensional arrays (#114400)
When we see an array root, that pointer might yet again be an array element, so check for that.
1 parent 1e072ae commit 2c82079

File tree

3 files changed

+45
-9
lines changed

3 files changed

+45
-9
lines changed

clang/lib/AST/ByteCode/Descriptor.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,16 @@ QualType Descriptor::getElemQualType() const {
411411
QualType T = getType();
412412
if (T->isPointerOrReferenceType())
413413
return T->getPointeeType();
414-
if (const auto *AT = T->getAsArrayTypeUnsafe())
414+
if (const auto *AT = T->getAsArrayTypeUnsafe()) {
415+
// For primitive arrays, we don't save a QualType at all,
416+
// just a PrimType. Try to figure out the QualType here.
417+
if (isPrimitiveArray()) {
418+
while (T->isArrayType())
419+
T = T->getAsArrayTypeUnsafe()->getElementType();
420+
return T;
421+
}
415422
return AT->getElementType();
423+
}
416424
if (const auto *CT = T->getAs<ComplexType>())
417425
return CT->getElementType();
418426
if (const auto *CT = T->getAs<VectorType>())

clang/lib/AST/ByteCode/Pointer.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,15 +200,26 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
200200
// Build the path into the object.
201201
Pointer Ptr = *this;
202202
while (Ptr.isField() || Ptr.isArrayElement()) {
203+
203204
if (Ptr.isArrayRoot()) {
204-
Path.push_back(APValue::LValuePathEntry(
205-
{Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
205+
// An array root may still be an array element itself.
206+
if (Ptr.isArrayElement()) {
207+
Ptr = Ptr.expand();
208+
unsigned Index = Ptr.getIndex();
209+
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
210+
QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
211+
Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));
212+
Ptr = Ptr.getArray();
213+
} else {
214+
Path.push_back(APValue::LValuePathEntry(
215+
{Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
206216

207-
if (const auto *FD =
208-
dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
209-
Offset += getFieldOffset(FD);
217+
if (const auto *FD =
218+
dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
219+
Offset += getFieldOffset(FD);
210220

211-
Ptr = Ptr.getBase();
221+
Ptr = Ptr.getBase();
222+
}
212223
} else if (Ptr.isArrayElement()) {
213224
Ptr = Ptr.expand();
214225
unsigned Index;
@@ -219,7 +230,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
219230

220231
QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
221232
Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));
222-
223233
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
224234
Ptr = Ptr.getArray();
225235
} else {

clang/unittests/AST/ByteCode/toAPValue.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ TEST(ToAPValue, Pointers) {
2222
"constexpr S d = {{{true, false}, {false, true}, {false, false}}};\n"
2323
"constexpr const bool *b = &d.a[1].z;\n"
2424
"const void *p = (void*)12;\n"
25-
"const void *nullp = (void*)0;\n";
25+
"const void *nullp = (void*)0;\n"
26+
"extern int earr[5][5];\n"
27+
"constexpr const int *arrp = &earr[2][4];\n";
2628

2729
auto AST = tooling::buildASTFromCodeWithArgs(
2830
Code, {"-fexperimental-new-constant-interpreter"});
@@ -87,6 +89,22 @@ TEST(ToAPValue, Pointers) {
8789
ASSERT_TRUE(Success);
8890
ASSERT_EQ(I, 0);
8991
}
92+
93+
// A multidimensional array.
94+
{
95+
const ValueDecl *D = getDecl("arrp");
96+
ASSERT_NE(D, nullptr);
97+
const Pointer &GP = getGlobalPtr("arrp").deref<Pointer>();
98+
APValue A = GP.toAPValue(ASTCtx);
99+
ASSERT_TRUE(A.isLValue());
100+
ASSERT_TRUE(A.hasLValuePath());
101+
ASSERT_EQ(A.getLValuePath().size(), 2u);
102+
ASSERT_EQ(A.getLValuePath()[0].getAsArrayIndex(), 2u);
103+
ASSERT_EQ(A.getLValuePath()[1].getAsArrayIndex(), 4u);
104+
ASSERT_EQ(A.getLValueOffset().getQuantity(), 56u);
105+
ASSERT_TRUE(
106+
GP.atIndex(0).getFieldDesc()->getElemQualType()->isIntegerType());
107+
}
90108
}
91109

92110
TEST(ToAPValue, FunctionPointers) {

0 commit comments

Comments
 (0)