From 846b3c4ffb1b45d637cf8a651fb866d25dfef955 Mon Sep 17 00:00:00 2001 From: Vince Bridgers Date: Tue, 29 Jul 2025 22:24:58 +0200 Subject: [PATCH] [analyzer] Fix getElementRegion to retain address space information This change modifies getElementRegion to retain address space information when removing all QualType qualifiers. Always removing address space qualifiers can expose cases where QualTypes for different pointer types may be different depending on how the QualTypes are obtained. clang: clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp:785: void assertEqualBitWidths(clang::ento::ProgramStateRef, clang::ento::Loc, clang::ento::Loc): Assertion `RhsBitwidth == LhsBitwidth && "RhsLoc and LhsLoc bitwidth must be same!"' failed. #0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (clang-21) ... #7 (anonymous namespace)::SimpleSValBuilder::evalBinOpLL(llvm::IntrusiveRefCntPtr, clang::BinaryOperatorKind, clang::ento::Loc, clang::ento::Loc, clang::QualType) SimpleSValBuilder.cpp:0:0 #8 clang::ento::SValBuilder::evalBinOp(llvm::IntrusiveRefCntPtr, clang::BinaryOperatorKind, clang::ento::SVal, clang::ento::SVal, clang::QualType) (clang-21) #9 clang::ento::ExprEngine::VisitBinaryOperator(clang::BinaryOperator const*, clang::ento::ExplodedNode*, clang::ento::ExplodedNodeSet&) (clang-21) --- clang/include/clang/AST/Type.h | 10 ++++++++++ clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 2 +- .../test/Analysis/element-region-addr-space.c | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 clang/test/Analysis/element-region-addr-space.c diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 98810fbea726e..a56fbbe1fac56 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1188,6 +1188,7 @@ class QualType { void removeLocalConst(); void removeLocalVolatile(); void removeLocalRestrict(); + QualType removeNonAddressSpaceQualifiers(); void removeLocalFastQualifiers() { Value.setInt(0); } void removeLocalFastQualifiers(unsigned Mask) { @@ -8274,6 +8275,15 @@ inline void QualType::removeLocalVolatile() { removeLocalFastQualifiers(Qualifiers::Volatile); } +inline QualType QualType::removeNonAddressSpaceQualifiers() { + if (getQualifiers().hasTargetSpecificAddressSpace()) { + removeLocalFastQualifiers(); + } else { + return getCanonicalType().getUnqualifiedType(); + } + return *this; +} + /// Check if this type has any address space qualifier. inline bool QualType::hasAddressSpace() const { return getQualifiers().hasAddressSpace(); diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 3e68373028b10..895f2ab43dc35 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -1217,7 +1217,7 @@ const ElementRegion * MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, const SubRegion *superRegion, const ASTContext &Ctx) { - QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType(); + QualType T = elementType.removeNonAddressSpaceQualifiers(); llvm::FoldingSetNodeID ID; ElementRegion::ProfileRegion(ID, T, Idx, superRegion); diff --git a/clang/test/Analysis/element-region-addr-space.c b/clang/test/Analysis/element-region-addr-space.c new file mode 100644 index 0000000000000..f8a1185fd1ecf --- /dev/null +++ b/clang/test/Analysis/element-region-addr-space.c @@ -0,0 +1,18 @@ +// RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown \ +// RUN: -analyzer-checker=core,unix.Malloc,debug.ExprInspection -verify \ +// RUN: -Wno-incompatible-pointer-types -Wno-unused-comparison %s + +// expected-no-diagnostics +// +// By default, pointers are 64-bits. +#define ADDRESS_SPACE_32BITS __attribute__((address_space(3))) +ADDRESS_SPACE_32BITS void *b(); +ADDRESS_SPACE_32BITS int *c(); +typedef struct { + ADDRESS_SPACE_32BITS int *e; +} f; +void g() { + ADDRESS_SPACE_32BITS void *h = b(); + ADDRESS_SPACE_32BITS f *j = c(); + j->e == h; +}