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()); + } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits