Skip to content

Commit 46d8bb0

Browse files
committed
[clang][Interp] Fix initializing zero-size arrays
1 parent 5693678 commit 46d8bb0

File tree

3 files changed

+28
-3
lines changed

3 files changed

+28
-3
lines changed

clang/lib/AST/Interp/Pointer.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,12 +556,16 @@ class Pointer {
556556
if (!asBlockPointer().Pointee)
557557
return false;
558558

559-
return isElementPastEnd() || getSize() == getOffset();
559+
return isElementPastEnd() ||
560+
(getSize() == getOffset() && !isZeroSizeArray());
560561
}
561562

562563
/// Checks if the pointer is an out-of-bounds element pointer.
563564
bool isElementPastEnd() const { return Offset == PastEndMark; }
564565

566+
/// Checks if the pointer is pointing to a zero-size array.
567+
bool isZeroSizeArray() const { return getFieldDesc()->isZeroSizeArray(); }
568+
565569
/// Dereferences the pointer, if it's live.
566570
template <typename T> T &deref() const {
567571
assert(isLive() && "Invalid pointer");

clang/test/AST/Interp/arrays.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ static_assert(foo[2][2] == nullptr, "");
2626
static_assert(foo[2][3] == &m, "");
2727
static_assert(foo[2][4] == nullptr, "");
2828

29+
constexpr int ZeroSizeArray[] = {};
2930

3031
constexpr int SomeInt[] = {1};
3132
constexpr int getSomeInt() { return *SomeInt; }

clang/unittests/AST/Interp/Descriptor.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ TEST(Descriptor, Primitives) {
2222
" char s[4];\n"
2323
" A a[3];\n"
2424
" short l[3][3];\n"
25+
" int EmptyA[0];\n"
2526
"};\n"
2627
"constexpr S d = {0.0, \"foo\", {{true, false}, {false, true}, {false, false}},\n"
27-
" {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}};\n";
28+
" {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, {}};\n";
2829

2930
auto AST = tooling::buildASTFromCodeWithArgs(
3031
Code, {"-fexperimental-new-constant-interpreter"});
@@ -64,7 +65,7 @@ TEST(Descriptor, Primitives) {
6465
// Test the Record for the struct S.
6566
const Record *SRecord = GlobalDesc->ElemRecord;
6667
ASSERT_TRUE(SRecord);
67-
ASSERT_TRUE(SRecord->getNumFields() == 4);
68+
ASSERT_TRUE(SRecord->getNumFields() == 5);
6869
ASSERT_TRUE(SRecord->getNumBases() == 0);
6970
ASSERT_FALSE(SRecord->getDestructor());
7071

@@ -113,6 +114,16 @@ TEST(Descriptor, Primitives) {
113114
ASSERT_TRUE(F4->Desc->getElemSize() > 0);
114115
ASSERT_TRUE(F4->Desc->ElemDesc->isPrimitiveArray());
115116

117+
// Fifth field. Zero-size array.
118+
const Record::Field *F5 = SRecord->getField(4u);
119+
ASSERT_TRUE(F5);
120+
ASSERT_FALSE(F5->isBitField());
121+
ASSERT_TRUE(F5->Desc->isArray());
122+
ASSERT_FALSE(F5->Desc->isCompositeArray());
123+
ASSERT_TRUE(F5->Desc->isPrimitiveArray());
124+
ASSERT_FALSE(F5->Desc->isPrimitive());
125+
ASSERT_EQ(F5->Desc->getNumElems(), 0u);
126+
116127
// Check pointer stuff.
117128
// Global variables have an inline descriptor.
118129
ASSERT_TRUE(GlobalPtr.isRoot());
@@ -382,4 +393,13 @@ TEST(Descriptor, Primitives) {
382393
ASSERT_EQ(PE3.getArray(), NE3);
383394
ASSERT_EQ(PE3.getIndex(), 2u);
384395
}
396+
397+
// Zero-size array.
398+
{
399+
const Pointer &PF5 = GlobalPtr.atField(F5->Offset);
400+
401+
ASSERT_TRUE(PF5.isZeroSizeArray());
402+
ASSERT_FALSE(PF5.isOnePastEnd());
403+
ASSERT_FALSE(PF5.isElementPastEnd());
404+
}
385405
}

0 commit comments

Comments
 (0)