[clang] [analyzer] Retain address space information in getElementRegion (PR #151370)

DonĂ¡t Nagy via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 31 06:42:36 PDT 2025


https://github.com/NagyDonat updated https://github.com/llvm/llvm-project/pull/151370

>From 690e311be23ef506c1316d076991d3b557718474 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Wed, 30 Jul 2025 19:40:10 +0200
Subject: [PATCH 1/2] [analyzer] Retain address space information in
 getElementRegion

The factory method `MemRegionManager::getElementRegion()` is the main
way of constructing `ElementRegion` objects, which are widespread in the
analysis and may represent array elements (as lvalues), pointer
arithmetics and type conversions.

This factory method used to strip all qualifiers from the type
associated with the element (after canonicalizing it), but the address
space qualifier can affect the size of a pointer type, so stripping it
caused an assertion failure (in `evalBinOpLL`):

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.

Co-authored-by: Vince Bridgers <vince.a.bridgers at ericsson.com>
---
 clang/lib/StaticAnalyzer/Core/MemRegion.cpp        | 10 ++++++++++
 clang/test/Analysis/element-region-address-space.c | 11 +++++++++++
 2 files changed, 21 insertions(+)
 create mode 100644 clang/test/Analysis/element-region-address-space.c

diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 3e68373028b10..0058a0ddfb0df 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -1219,6 +1219,16 @@ MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
                                    const ASTContext &Ctx) {
   QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
 
+  // The address space must be preserved because some target-specific address
+  // spaces influence the size of the pointer value which is represented by the
+  // element region.
+  LangAS AS = elementType.getAddressSpace();
+  if (AS != LangAS::Default) {
+    Qualifiers Quals;
+    Quals.setAddressSpace(AS);
+    T = Ctx.getQualifiedType(T, Quals);
+  }
+
   llvm::FoldingSetNodeID ID;
   ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
 
diff --git a/clang/test/Analysis/element-region-address-space.c b/clang/test/Analysis/element-region-address-space.c
new file mode 100644
index 0000000000000..fddc1bb840231
--- /dev/null
+++ b/clang/test/Analysis/element-region-address-space.c
@@ -0,0 +1,11 @@
+// RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown \
+// RUN: -analyzer-checker=core,unix.Malloc -verify %s
+
+// expected-no-diagnostics
+//
+// By default, pointers are 64-bits.
+#define ADDRESS_SPACE_32BITS __attribute__((address_space(3)))
+
+int test(ADDRESS_SPACE_32BITS int *p, ADDRESS_SPACE_32BITS void *q) {
+  return p == q;
+}

>From 2ceb18bd912cd7b27e5134f3c2a31d8f0a2b6a7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Thu, 31 Jul 2025 15:42:28 +0200
Subject: [PATCH 2/2] Apply suggestions from code review

Co-authored-by: Balazs Benics <benicsbalazs at gmail.com>
---
 clang/lib/StaticAnalyzer/Core/MemRegion.cpp        | 3 +--
 clang/test/Analysis/element-region-address-space.c | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 0058a0ddfb0df..c82a14058de6f 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -1222,8 +1222,7 @@ MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
   // The address space must be preserved because some target-specific address
   // spaces influence the size of the pointer value which is represented by the
   // element region.
-  LangAS AS = elementType.getAddressSpace();
-  if (AS != LangAS::Default) {
+  if (LangAS AS = elementType.getAddressSpace()) {
     Qualifiers Quals;
     Quals.setAddressSpace(AS);
     T = Ctx.getQualifiedType(T, Quals);
diff --git a/clang/test/Analysis/element-region-address-space.c b/clang/test/Analysis/element-region-address-space.c
index fddc1bb840231..dd7066240fef6 100644
--- a/clang/test/Analysis/element-region-address-space.c
+++ b/clang/test/Analysis/element-region-address-space.c
@@ -1,5 +1,5 @@
 // RUN: %clang_analyze_cc1 -triple amdgcn-unknown-unknown \
-// RUN: -analyzer-checker=core,unix.Malloc -verify %s
+// RUN:   -analyzer-checker=core -verify %s
 
 // expected-no-diagnostics
 //
@@ -7,5 +7,5 @@
 #define ADDRESS_SPACE_32BITS __attribute__((address_space(3)))
 
 int test(ADDRESS_SPACE_32BITS int *p, ADDRESS_SPACE_32BITS void *q) {
-  return p == q;
+  return p == q; // no-crash
 }



More information about the cfe-commits mailing list