[clang] 46d8bb0 - [clang][Interp] Fix initializing zero-size arrays
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Tue May 21 04:46:50 PDT 2024
Author: Timm Bäder
Date: 2024-05-21T13:46:36+02:00
New Revision: 46d8bb08cfd3798977b4e22881514dc9d77425c2
URL: https://github.com/llvm/llvm-project/commit/46d8bb08cfd3798977b4e22881514dc9d77425c2
DIFF: https://github.com/llvm/llvm-project/commit/46d8bb08cfd3798977b4e22881514dc9d77425c2.diff
LOG: [clang][Interp] Fix initializing zero-size arrays
Added:
Modified:
clang/lib/AST/Interp/Pointer.h
clang/test/AST/Interp/arrays.cpp
clang/unittests/AST/Interp/Descriptor.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 9900f37e60d4e..3ade5756e580e 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -556,12 +556,16 @@ class Pointer {
if (!asBlockPointer().Pointee)
return false;
- return isElementPastEnd() || getSize() == getOffset();
+ return isElementPastEnd() ||
+ (getSize() == getOffset() && !isZeroSizeArray());
}
/// Checks if the pointer is an out-of-bounds element pointer.
bool isElementPastEnd() const { return Offset == PastEndMark; }
+ /// Checks if the pointer is pointing to a zero-size array.
+ bool isZeroSizeArray() const { return getFieldDesc()->isZeroSizeArray(); }
+
/// Dereferences the pointer, if it's live.
template <typename T> T &deref() const {
assert(isLive() && "Invalid pointer");
diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp
index 71b6dabf39e45..e936ec6dc894b 100644
--- a/clang/test/AST/Interp/arrays.cpp
+++ b/clang/test/AST/Interp/arrays.cpp
@@ -26,6 +26,7 @@ static_assert(foo[2][2] == nullptr, "");
static_assert(foo[2][3] == &m, "");
static_assert(foo[2][4] == nullptr, "");
+constexpr int ZeroSizeArray[] = {};
constexpr int SomeInt[] = {1};
constexpr int getSomeInt() { return *SomeInt; }
diff --git a/clang/unittests/AST/Interp/Descriptor.cpp b/clang/unittests/AST/Interp/Descriptor.cpp
index 053d579ea3919..3157b4d401f98 100644
--- a/clang/unittests/AST/Interp/Descriptor.cpp
+++ b/clang/unittests/AST/Interp/Descriptor.cpp
@@ -22,9 +22,10 @@ TEST(Descriptor, Primitives) {
" char s[4];\n"
" A a[3];\n"
" short l[3][3];\n"
+ " int EmptyA[0];\n"
"};\n"
"constexpr S d = {0.0, \"foo\", {{true, false}, {false, true}, {false, false}},\n"
- " {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}};\n";
+ " {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, {}};\n";
auto AST = tooling::buildASTFromCodeWithArgs(
Code, {"-fexperimental-new-constant-interpreter"});
@@ -64,7 +65,7 @@ TEST(Descriptor, Primitives) {
// Test the Record for the struct S.
const Record *SRecord = GlobalDesc->ElemRecord;
ASSERT_TRUE(SRecord);
- ASSERT_TRUE(SRecord->getNumFields() == 4);
+ ASSERT_TRUE(SRecord->getNumFields() == 5);
ASSERT_TRUE(SRecord->getNumBases() == 0);
ASSERT_FALSE(SRecord->getDestructor());
@@ -113,6 +114,16 @@ TEST(Descriptor, Primitives) {
ASSERT_TRUE(F4->Desc->getElemSize() > 0);
ASSERT_TRUE(F4->Desc->ElemDesc->isPrimitiveArray());
+ // Fifth field. Zero-size array.
+ const Record::Field *F5 = SRecord->getField(4u);
+ ASSERT_TRUE(F5);
+ ASSERT_FALSE(F5->isBitField());
+ ASSERT_TRUE(F5->Desc->isArray());
+ ASSERT_FALSE(F5->Desc->isCompositeArray());
+ ASSERT_TRUE(F5->Desc->isPrimitiveArray());
+ ASSERT_FALSE(F5->Desc->isPrimitive());
+ ASSERT_EQ(F5->Desc->getNumElems(), 0u);
+
// Check pointer stuff.
// Global variables have an inline descriptor.
ASSERT_TRUE(GlobalPtr.isRoot());
@@ -382,4 +393,13 @@ TEST(Descriptor, Primitives) {
ASSERT_EQ(PE3.getArray(), NE3);
ASSERT_EQ(PE3.getIndex(), 2u);
}
+
+ // Zero-size array.
+ {
+ const Pointer &PF5 = GlobalPtr.atField(F5->Offset);
+
+ ASSERT_TRUE(PF5.isZeroSizeArray());
+ ASSERT_FALSE(PF5.isOnePastEnd());
+ ASSERT_FALSE(PF5.isElementPastEnd());
+ }
}
More information about the cfe-commits
mailing list