[clang] [analyzer] Fix getElementRegion to retain address space information (PR #151249)

via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 29 15:59:51 PDT 2025


https://github.com/vabridgers created https://github.com/llvm/llvm-project/pull/151249

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 <addr> llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (clang-21)
 ...
 #7 <addr> (anonymous namespace)::SimpleSValBuilder::evalBinOpLL(llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>,
  clang::BinaryOperatorKind, clang::ento::Loc, clang::ento::Loc, clang::QualType) SimpleSValBuilder.cpp:0:0
 #8 <addr> clang::ento::SValBuilder::evalBinOp(llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>,
  clang::BinaryOperatorKind, clang::ento::SVal, clang::ento::SVal, clang::QualType) (clang-21)
 #9 <addr> clang::ento::ExprEngine::VisitBinaryOperator(clang::BinaryOperator const*, clang::ento::ExplodedNode*,
  clang::ento::ExplodedNodeSet&) (clang-21)

>From 846b3c4ffb1b45d637cf8a651fb866d25dfef955 Mon Sep 17 00:00:00 2001
From: Vince Bridgers <vince.a.bridgers at ericsson.com>
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 <addr> llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (clang-21)
 ...
 #7 <addr> (anonymous namespace)::SimpleSValBuilder::evalBinOpLL(llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>,
  clang::BinaryOperatorKind, clang::ento::Loc, clang::ento::Loc, clang::QualType) SimpleSValBuilder.cpp:0:0
 #8 <addr> clang::ento::SValBuilder::evalBinOp(llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>,
  clang::BinaryOperatorKind, clang::ento::SVal, clang::ento::SVal, clang::QualType) (clang-21)
 #9 <addr> 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;
+}



More information about the cfe-commits mailing list