Author: Timm Baeder Date: 2024-10-31T15:15:59+01:00 New Revision: 2c82079924f1e43b211a6f233ea04ea911a7b581
URL: https://github.com/llvm/llvm-project/commit/2c82079924f1e43b211a6f233ea04ea911a7b581 DIFF: https://github.com/llvm/llvm-project/commit/2c82079924f1e43b211a6f233ea04ea911a7b581.diff LOG: [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. Added: Modified: clang/lib/AST/ByteCode/Descriptor.cpp clang/lib/AST/ByteCode/Pointer.cpp clang/unittests/AST/ByteCode/toAPValue.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp index 5a8a2b64d5582d..39a54e4902cd2a 100644 --- a/clang/lib/AST/ByteCode/Descriptor.cpp +++ b/clang/lib/AST/ByteCode/Descriptor.cpp @@ -411,8 +411,16 @@ QualType Descriptor::getElemQualType() const { QualType T = getType(); if (T->isPointerOrReferenceType()) return T->getPointeeType(); - if (const auto *AT = T->getAsArrayTypeUnsafe()) + if (const auto *AT = T->getAsArrayTypeUnsafe()) { + // For primitive arrays, we don't save a QualType at all, + // just a PrimType. Try to figure out the QualType here. + if (isPrimitiveArray()) { + while (T->isArrayType()) + T = T->getAsArrayTypeUnsafe()->getElementType(); + return T; + } return AT->getElementType(); + } if (const auto *CT = T->getAs<ComplexType>()) return CT->getElementType(); if (const auto *CT = T->getAs<VectorType>()) diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index c9de039c195d94..54484853fcdaea 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -200,15 +200,26 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { // Build the path into the object. Pointer Ptr = *this; while (Ptr.isField() || Ptr.isArrayElement()) { + if (Ptr.isArrayRoot()) { - Path.push_back(APValue::LValuePathEntry( - {Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false})); + // An array root may still be an array element itself. + if (Ptr.isArrayElement()) { + Ptr = Ptr.expand(); + unsigned Index = Ptr.getIndex(); + Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index)); + QualType ElemType = Ptr.getFieldDesc()->getElemQualType(); + Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType)); + Ptr = Ptr.getArray(); + } else { + Path.push_back(APValue::LValuePathEntry( + {Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false})); - if (const auto *FD = - dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl())) - Offset += getFieldOffset(FD); + if (const auto *FD = + dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl())) + Offset += getFieldOffset(FD); - Ptr = Ptr.getBase(); + Ptr = Ptr.getBase(); + } } else if (Ptr.isArrayElement()) { Ptr = Ptr.expand(); unsigned Index; @@ -219,7 +230,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { QualType ElemType = Ptr.getFieldDesc()->getElemQualType(); Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType)); - Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index)); Ptr = Ptr.getArray(); } else { diff --git a/clang/unittests/AST/ByteCode/toAPValue.cpp b/clang/unittests/AST/ByteCode/toAPValue.cpp index 3f141878fb9594..cd62338ee23c14 100644 --- a/clang/unittests/AST/ByteCode/toAPValue.cpp +++ b/clang/unittests/AST/ByteCode/toAPValue.cpp @@ -22,7 +22,9 @@ TEST(ToAPValue, Pointers) { "constexpr S d = {{{true, false}, {false, true}, {false, false}}};\n" "constexpr const bool *b = &d.a[1].z;\n" "const void *p = (void*)12;\n" - "const void *nullp = (void*)0;\n"; + "const void *nullp = (void*)0;\n" + "extern int earr[5][5];\n" + "constexpr const int *arrp = &earr[2][4];\n"; auto AST = tooling::buildASTFromCodeWithArgs( Code, {"-fexperimental-new-constant-interpreter"}); @@ -87,6 +89,22 @@ TEST(ToAPValue, Pointers) { ASSERT_TRUE(Success); ASSERT_EQ(I, 0); } + + // A multidimensional array. + { + const ValueDecl *D = getDecl("arrp"); + ASSERT_NE(D, nullptr); + const Pointer &GP = getGlobalPtr("arrp").deref<Pointer>(); + APValue A = GP.toAPValue(ASTCtx); + ASSERT_TRUE(A.isLValue()); + ASSERT_TRUE(A.hasLValuePath()); + ASSERT_EQ(A.getLValuePath().size(), 2u); + ASSERT_EQ(A.getLValuePath()[0].getAsArrayIndex(), 2u); + ASSERT_EQ(A.getLValuePath()[1].getAsArrayIndex(), 4u); + ASSERT_EQ(A.getLValueOffset().getQuantity(), 56u); + ASSERT_TRUE( + GP.atIndex(0).getFieldDesc()->getElemQualType()->isIntegerType()); + } } TEST(ToAPValue, FunctionPointers) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits