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; +}