[clang] da7403e - [clang][analyzer] Add checker 'alpha.core.FixedAddressDereference' (#127191)

via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 3 01:44:09 PST 2025


Author: Balázs Kéri
Date: 2025-03-03T10:44:05+01:00
New Revision: da7403ed1d5727cd758560ffc7957bba5c395745

URL: https://github.com/llvm/llvm-project/commit/da7403ed1d5727cd758560ffc7957bba5c395745
DIFF: https://github.com/llvm/llvm-project/commit/da7403ed1d5727cd758560ffc7957bba5c395745.diff

LOG: [clang][analyzer] Add checker 'alpha.core.FixedAddressDereference' (#127191)

Added: 
    clang/test/Analysis/suppress-dereferences-from-any-address-space.c

Modified: 
    clang/docs/analyzer/checkers.rst
    clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
    clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
    clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
    clang/test/Analysis/analyzer-config.c
    clang/test/Analysis/cast-value-notes.cpp
    clang/test/Analysis/concrete-address.c
    clang/test/Analysis/misc-ps.m

Removed: 
    


################################################################################
diff  --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index c1eedb33e74d2..b817a99a1c56f 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -118,19 +118,6 @@ core.NullDereference (C, C++, ObjC)
 """""""""""""""""""""""""""""""""""
 Check for dereferences of null pointers.
 
-This checker specifically does
-not report null pointer dereferences for x86 and x86-64 targets when the
-address space is 256 (x86 GS Segment), 257 (x86 FS Segment), or 258 (x86 SS
-segment). See `X86/X86-64 Language Extensions
-<https://clang.llvm.org/docs/LanguageExtensions.html#memory-references-to-specified-segments>`__
-for reference.
-
-The ``SuppressAddressSpaces`` option suppresses
-warnings for null dereferences of all pointers with address spaces. You can
-disable this behavior with the option
-``-analyzer-config core.NullDereference:SuppressAddressSpaces=false``.
-*Defaults to true*.
-
 .. code-block:: objc
 
  // C
@@ -170,6 +157,19 @@ disable this behavior with the option
    obj->x = 1; // warn
  }
 
+Null pointer dereferences of pointers with address spaces are not always defined
+as error. Specifically on x86/x86-64 target if the pointer address space is
+256 (x86 GS Segment), 257 (x86 FS Segment), or 258 (x86 SS Segment), a null
+dereference is not defined as error. See `X86/X86-64 Language Extensions
+<https://clang.llvm.org/docs/LanguageExtensions.html#memory-references-to-specified-segments>`__
+for reference.
+	
+If the analyzer option ``suppress-dereferences-from-any-address-space`` is set
+to true (the default value), then this checker never reports dereference of
+pointers with a specified address space. If the option is set to false, then
+reports from the specific x86 address spaces 256, 257 and 258 are still
+suppressed, but null dereferences from other address spaces are reported.
+
 .. _core-StackAddressEscape:
 
 core.StackAddressEscape (C)
@@ -2919,6 +2919,41 @@ Check for assignment of a fixed address to a pointer.
    p = (int *) 0x10000; // warn
  }
 
+.. _alpha-core-FixedAddressDereference:
+
+alpha.core.FixedAddressDereference (C, C++, ObjC)
+"""""""""""""""""""""""""""""""""""""""""""""""""
+Check for dereferences of fixed addresses.
+
+A pointer contains a fixed address if it was set to a hard-coded value or it
+becomes otherwise obvious that at that point it can have only a single specific
+value.
+
+.. code-block:: c
+
+ void test1() {
+   int *p = (int *)0x020;
+   int x = p[0]; // warn
+ }
+
+ void test2(int *p) {
+   if (p == (int *)-1)
+     *p = 0; // warn
+ }
+
+ void test3() {
+   int (*p_function)(char, char);
+   p_function = (int (*)(char, char))0x04080;
+   int x = (*p_function)('x', 'y'); // NO warning yet at functon pointer calls
+ }
+
+If the analyzer option ``suppress-dereferences-from-any-address-space`` is set
+to true (the default value), then this checker never reports dereference of
+pointers with a specified address space. If the option is set to false, then
+reports from the specific x86 address spaces 256, 257 and 258 are still
+suppressed, but fixed address dereferences from other address spaces are
+reported.
+
 .. _alpha-core-PointerArithm:
 
 alpha.core.PointerArithm (C)

diff  --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 410f841630660..c8895db914d13 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -213,13 +213,6 @@ def DereferenceModeling : Checker<"DereferenceModeling">,
 
 def NullDereferenceChecker : Checker<"NullDereference">,
   HelpText<"Check for dereferences of null pointers">,
-  CheckerOptions<[
-    CmdLineOption<Boolean,
-                  "SuppressAddressSpaces",
-                  "Suppresses warning when pointer dereferences an address space",
-                  "true",
-                  Released>
-  ]>,
   Documentation<HasDocumentation>,
   Dependencies<[DereferenceModeling]>;
 
@@ -285,6 +278,12 @@ def FixedAddressChecker : Checker<"FixedAddr">,
   HelpText<"Check for assignment of a fixed address to a pointer">,
   Documentation<HasDocumentation>;
 
+def FixedAddressDereferenceChecker
+    : Checker<"FixedAddressDereference">,
+      HelpText<"Check for dereferences of fixed addresses">,
+      Documentation<HasDocumentation>,
+      Dependencies<[DereferenceModeling]>;
+
 def PointerArithChecker : Checker<"PointerArithm">,
   HelpText<"Check for pointer arithmetic on locations other than array "
            "elements">,

diff  --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
index b087ca8860690..2aa00db411844 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -395,6 +395,19 @@ ANALYZER_OPTION(
     "flex\" won't be analyzed.",
     true)
 
+ANALYZER_OPTION(
+    bool, ShouldSuppressAddressSpaceDereferences, "suppress-dereferences-from-any-address-space",
+    "The analyzer does not report dereferences on memory that use "
+    "address space #256, #257, and #258. Those address spaces are used when "
+    "dereferencing address spaces relative to the GS, FS, and SS segments on "
+    "x86/x86-64 targets. Dereferencing a null pointer in these address spaces "
+    "is not defined as an error. All other null dereferences in other address "
+    "spaces are defined as an error unless explicitly defined. "
+    "When this option is turned on, the special behavior of address spaces "
+    "#256, #257, #258 is extended to all pointers with address spaces and on "
+    "any target.",
+    true)
+
 //===----------------------------------------------------------------------===//
 // Unsigned analyzer options.
 //===----------------------------------------------------------------------===//

diff  --git a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index e9e2771c739b6..defa0701cb51f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -31,7 +31,12 @@ class DereferenceChecker
     : public Checker< check::Location,
                       check::Bind,
                       EventDispatcher<ImplicitNullDerefEvent> > {
-  enum DerefKind { NullPointer, UndefinedPointerValue, AddressOfLabel };
+  enum DerefKind {
+    NullPointer,
+    UndefinedPointerValue,
+    AddressOfLabel,
+    FixedAddress,
+  };
 
   void reportBug(DerefKind K, ProgramStateRef State, const Stmt *S,
                  CheckerContext &C) const;
@@ -49,13 +54,13 @@ class DereferenceChecker
                              const LocationContext *LCtx,
                              bool loadedFrom = false);
 
-  bool SuppressAddressSpaces = false;
-
   bool CheckNullDereference = false;
+  bool CheckFixedDereference = false;
 
   std::unique_ptr<BugType> BT_Null;
   std::unique_ptr<BugType> BT_Undef;
   std::unique_ptr<BugType> BT_Label;
+  std::unique_ptr<BugType> BT_FixedAddress;
 };
 } // end anonymous namespace
 
@@ -130,7 +135,9 @@ bool DereferenceChecker::suppressReport(CheckerContext &C,
   QualType Ty = E->getType();
   if (!Ty.hasAddressSpace())
     return false;
-  if (SuppressAddressSpaces)
+  if (C.getAnalysisManager()
+          .getAnalyzerOptions()
+          .ShouldSuppressAddressSpaceDereferences)
     return true;
 
   const llvm::Triple::ArchType Arch =
@@ -155,30 +162,47 @@ static bool isDeclRefExprToReference(const Expr *E) {
 
 void DereferenceChecker::reportBug(DerefKind K, ProgramStateRef State,
                                    const Stmt *S, CheckerContext &C) const {
-  if (!CheckNullDereference) {
-    C.addSink();
-    return;
-  }
-
   const BugType *BT = nullptr;
   llvm::StringRef DerefStr1;
   llvm::StringRef DerefStr2;
   switch (K) {
   case DerefKind::NullPointer:
+    if (!CheckNullDereference) {
+      C.addSink();
+      return;
+    }
     BT = BT_Null.get();
     DerefStr1 = " results in a null pointer dereference";
     DerefStr2 = " results in a dereference of a null pointer";
     break;
   case DerefKind::UndefinedPointerValue:
+    if (!CheckNullDereference) {
+      C.addSink();
+      return;
+    }
     BT = BT_Undef.get();
     DerefStr1 = " results in an undefined pointer dereference";
     DerefStr2 = " results in a dereference of an undefined pointer value";
     break;
   case DerefKind::AddressOfLabel:
+    if (!CheckNullDereference) {
+      C.addSink();
+      return;
+    }
     BT = BT_Label.get();
     DerefStr1 = " results in an undefined pointer dereference";
     DerefStr2 = " results in a dereference of an address of a label";
     break;
+  case DerefKind::FixedAddress:
+    // Deliberately don't add a sink node if check is disabled.
+    // This situation may be valid in special cases.
+    if (!CheckFixedDereference)
+      return;
+
+    BT = BT_FixedAddress.get();
+    DerefStr1 = " results in a dereference of a fixed address";
+    DerefStr2 = " results in a dereference of a fixed address";
+    break;
   };
 
   // Generate an error node.
@@ -289,6 +313,13 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
     }
   }
 
+  if (location.isConstant()) {
+    const Expr *DerefExpr = getDereferenceExpr(S, isLoad);
+    if (!suppressReport(C, DerefExpr))
+      reportBug(DerefKind::FixedAddress, notNullState, DerefExpr, C);
+    return;
+  }
+
   // From this point forward, we know that the location is not null.
   C.addTransition(notNullState);
 }
@@ -337,6 +368,13 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
     }
   }
 
+  if (V.isConstant()) {
+    const Expr *DerefExpr = getDereferenceExpr(S, true);
+    if (!suppressReport(C, DerefExpr))
+      reportBug(DerefKind::FixedAddress, State, DerefExpr, C);
+    return;
+  }
+
   // Unlike a regular null dereference, initializing a reference with a
   // dereferenced null pointer does not actually cause a runtime exception in
   // Clang's implementation of references.
@@ -367,8 +405,6 @@ bool ento::shouldRegisterDereferenceModeling(const CheckerManager &) {
 void ento::registerNullDereferenceChecker(CheckerManager &Mgr) {
   auto *Chk = Mgr.getChecker<DereferenceChecker>();
   Chk->CheckNullDereference = true;
-  Chk->SuppressAddressSpaces = Mgr.getAnalyzerOptions().getCheckerBooleanOption(
-      Mgr.getCurrentCheckerName(), "SuppressAddressSpaces");
   Chk->BT_Null.reset(new BugType(Mgr.getCurrentCheckerName(),
                                  "Dereference of null pointer",
                                  categories::LogicError));
@@ -383,3 +419,16 @@ void ento::registerNullDereferenceChecker(CheckerManager &Mgr) {
 bool ento::shouldRegisterNullDereferenceChecker(const CheckerManager &) {
   return true;
 }
+
+void ento::registerFixedAddressDereferenceChecker(CheckerManager &Mgr) {
+  auto *Chk = Mgr.getChecker<DereferenceChecker>();
+  Chk->CheckFixedDereference = true;
+  Chk->BT_FixedAddress.reset(new BugType(Mgr.getCurrentCheckerName(),
+                                         "Dereference of a fixed address",
+                                         categories::LogicError));
+}
+
+bool ento::shouldRegisterFixedAddressDereferenceChecker(
+    const CheckerManager &) {
+  return true;
+}

diff  --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c
index 06378b9814886..978a7509ee5e3 100644
--- a/clang/test/Analysis/analyzer-config.c
+++ b/clang/test/Analysis/analyzer-config.c
@@ -37,7 +37,6 @@
 // CHECK-NEXT: core.CallAndMessage:NilReceiver = true
 // CHECK-NEXT: core.CallAndMessage:ParameterCount = true
 // CHECK-NEXT: core.CallAndMessage:UndefReceiver = true
-// CHECK-NEXT: core.NullDereference:SuppressAddressSpaces = true
 // CHECK-NEXT: cplusplus.Move:WarnOn = KnownsAndLocals
 // CHECK-NEXT: cplusplus.SmartPtrModeling:ModelSmartPtrDereference = false
 // CHECK-NEXT: crosscheck-with-z3 = false
@@ -126,6 +125,7 @@
 // CHECK-NEXT: stable-report-filename = false
 // CHECK-NEXT: support-symbolic-integer-casts = false
 // CHECK-NEXT: suppress-c++-stdlib = true
+// CHECK-NEXT: suppress-dereferences-from-any-address-space = true
 // CHECK-NEXT: suppress-inlined-defensive-checks = true
 // CHECK-NEXT: suppress-null-return-paths = true
 // CHECK-NEXT: track-conditions = true

diff  --git a/clang/test/Analysis/cast-value-notes.cpp b/clang/test/Analysis/cast-value-notes.cpp
index 7ee224dc6e5d8..acd33e704d13a 100644
--- a/clang/test/Analysis/cast-value-notes.cpp
+++ b/clang/test/Analysis/cast-value-notes.cpp
@@ -4,12 +4,12 @@
 //
 // RUN: %clang_analyze_cc1 -std=c++14 -triple amdgcn-unknown-unknown \
 // RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
-// RUN:  -analyzer-config core.NullDereference:SuppressAddressSpaces=false\
+// RUN:  -analyzer-config suppress-dereferences-from-any-address-space=false\
 // RUN:  -analyzer-output=text -verify -DX86 -DNOT_SUPPRESSED %s 2>&1 | FileCheck %s -check-prefix=X86-CHECK
 //
 // RUN: %clang_analyze_cc1 -std=c++14 -triple amdgcn-unknown-unknown \
 // RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
-// RUN:  -analyzer-config core.NullDereference:SuppressAddressSpaces=true\
+// RUN:  -analyzer-config suppress-dereferences-from-any-address-space=true\
 // RUN:  -analyzer-output=text -verify -DX86 -DSUPPRESSED %s 2>&1 | FileCheck %s -check-prefix=X86-CHECK
 //
 // RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-unknown-unknown \
@@ -18,12 +18,12 @@
 //
 // RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-unknown-unknown \
 // RUN:  -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
-// RUN:  -analyzer-config core.NullDereference:SuppressAddressSpaces=true\
+// RUN:  -analyzer-config suppress-dereferences-from-any-address-space=true\
 // RUN:  -analyzer-output=text -verify -DX86 -DSUPPRESSED %s 2>&1 | FileCheck %s --check-prefix=X86-CHECK-SUPPRESSED
 //
 // RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-unknown-unknown \
 // RUN:  -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
-// RUN:  -analyzer-config core.NullDereference:SuppressAddressSpaces=false\
+// RUN:  -analyzer-config suppress-dereferences-from-any-address-space=false\
 // RUN:  -analyzer-output=text -verify -DX86 -DNOT_SUPPRESSED %s 2>&1 | FileCheck %s --check-prefix=X86-CHECK
 //
 // RUN: %clang_analyze_cc1 -std=c++14 -triple mips-unknown-unknown \
@@ -32,12 +32,12 @@
 //
 // RUN: %clang_analyze_cc1 -std=c++14 -triple mips-unknown-unknown \
 // RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
-// RUN: -analyzer-config core.NullDereference:SuppressAddressSpaces=false\
+// RUN: -analyzer-config suppress-dereferences-from-any-address-space=false\
 // RUN: -analyzer-output=text -verify -DMIPS %s 2>&1
 //
 // RUN: %clang_analyze_cc1 -std=c++14 -triple mips-unknown-unknown \
 // RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
-// RUN: -analyzer-config core.NullDereference:SuppressAddressSpaces=true\
+// RUN: -analyzer-config suppress-dereferences-from-any-address-space=true\
 // RUN: -analyzer-output=text -verify -DMIPS_SUPPRESSED %s
 
 #include "Inputs/llvm.h"

diff  --git a/clang/test/Analysis/concrete-address.c b/clang/test/Analysis/concrete-address.c
index 346f5093e44f7..683b7f29f4611 100644
--- a/clang/test/Analysis/concrete-address.c
+++ b/clang/test/Analysis/concrete-address.c
@@ -1,7 +1,144 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify %s
-// expected-no-diagnostics
 
-void foo(void) {
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+    unsigned int __line, __const char *__function)
+     __attribute__ ((__noreturn__));
+
+#define assert(expr) \
+  ((expr)  ? (void)(0)  : __assert_fail (#expr, __FILE__, __LINE__, __func__))
+
+typedef unsigned long long uintptr_t;
+
+void f0(void) {
   int *p = (int*) 0x10000; // Should not crash here.
-  *p = 3;
+  *p = 3; // expected-warning{{Dereference of a fixed address}}
+}
+
+void f1(int *p) {
+  if (p != (int *)-1)
+    *p = 1;
+  else
+    *p = 0; // expected-warning{{Dereference of a fixed address}}
+}
+
+struct f2_struct {
+  int x;
+};
+
+int f2(struct f2_struct* p) {
+
+  if (p != (struct f2_struct *)1)
+    p->x = 1;
+
+  return p->x++; // expected-warning{{Access to field 'x' results in a dereference of a fixed address (loaded from variable 'p')}}
+}
+
+int f3_1(char* x) {
+  int i = 2;
+
+  if (x != (char *)1)
+    return x[i - 1];
+
+  return x[i+1]; // expected-warning{{Array access (from variable 'x') results in a dereference of a fixed address}}
+}
+
+int f3_2(char* x) {
+  int i = 2;
+
+  if (x != (char *)1)
+    return x[i - 1];
+
+  return x[i+1]++; // expected-warning{{Array access (from variable 'x') results in a dereference of a fixed address}}
+}
+
+int f4_1(int *p) {
+  uintptr_t x = (uintptr_t) p;
+
+  if (x != (uintptr_t)1)
+    return 1;
+
+  int *q = (int*) x;
+  return *q; // expected-warning{{Dereference of a fixed address (loaded from variable 'q')}}
+}
+
+int f4_2(void) {
+  short array[2];
+  uintptr_t x = (uintptr_t)array;
+  short *p = (short *)x;
+
+  // The following branch should be infeasible.
+  if (!(p == &array[0])) {
+    p = (short *)1;
+    *p = 1; // no-warning
+  }
+
+  if (p != (short *)1) {
+    *p = 5; // no-warning
+    p = (short *)1; // expected-warning {{Using a fixed address is not portable}}
+  }
+  else return 1;
+
+  *p += 10; // expected-warning{{Dereference of a fixed}}
+  return 0;
+}
+
+int f5(void) {
+  char *s = "hello world";
+  return s[0]; // no-warning
+}
+
+void f6(int *p, int *q) {
+  if (p != (int *)1)
+    if (p == (int *)1)
+      *p = 1; // no-warning
+
+  if (q == (int *)1)
+    if (q != (int *)1)
+      *q = 1; // no-warning
+}
+
+int* qux(int);
+
+int f7_1(unsigned len) {
+  assert (len != 0);
+  int *p = (int *)1;
+  unsigned i;
+
+  for (i = 0; i < len; ++i)
+   p = qux(i);
+
+  return *p++; // no-warning
+}
+
+int f7_2(unsigned len) {
+  assert (len > 0);  // note use of '>'
+  int *p = (int *)1;
+  unsigned i;
+
+  for (i = 0; i < len; ++i)
+   p = qux(i);
+
+  return *p++; // no-warning
+}
+
+struct f8_s {
+  int x;
+  int y[2];
+};
+
+void f8(struct f8_s *s, int coin) {
+  if (s != (struct f8_s *)7)
+    return;
+
+  if (coin)
+    s->x = 5; // expected-warning{{Access to field 'x' results in a dereference of a fixed address (loaded from variable 's')}}
+  else
+    s->y[1] = 6; // expected-warning{{Array access (via field 'y') results in a dereference of a fixed address}}
+}
+
+void f9() {
+  int (*p_function) (char, char) = (int (*)(char, char))0x04040; // FIXME: warn at this initialization
+  p_function = (int (*)(char, char))0x04080; // expected-warning {{Using a fixed address is not portable}}
+  // FIXME: there should be a warning from calling the function pointer with fixed address
+  int x = (*p_function) ('x', 'y');
 }

diff  --git a/clang/test/Analysis/misc-ps.m b/clang/test/Analysis/misc-ps.m
index 0a8a30cb6175c..841f618fbdfab 100644
--- a/clang/test/Analysis/misc-ps.m
+++ b/clang/test/Analysis/misc-ps.m
@@ -1,6 +1,6 @@
 // NOTE: Use '-fobjc-gc' to test the analysis being run twice, and multiple reports are not issued.
-// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -Wno-strict-prototypes -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -Wno-strict-prototypes -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s
+// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-disable-checker=alpha.core.FixedAddressDereference -Wno-strict-prototypes -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-disable-checker=alpha.core.FixedAddressDereference -Wno-strict-prototypes -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s
 
 #ifndef __clang_analyzer__
 #error __clang_analyzer__ not defined

diff  --git a/clang/test/Analysis/suppress-dereferences-from-any-address-space.c b/clang/test/Analysis/suppress-dereferences-from-any-address-space.c
new file mode 100644
index 0000000000000..c1cb227994e05
--- /dev/null
+++ b/clang/test/Analysis/suppress-dereferences-from-any-address-space.c
@@ -0,0 +1,71 @@
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,alpha.core -std=gnu99 -analyzer-config suppress-dereferences-from-any-address-space=false -verify=x86-nosuppress,common %s
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,alpha.core -std=gnu99 -verify=x86-suppress,common %s
+// RUN: %clang_analyze_cc1 -triple arm-pc-linux-gnu -analyzer-checker=core,alpha.core -std=gnu99 -analyzer-config suppress-dereferences-from-any-address-space=false -verify=other-nosuppress,common %s
+// RUN: %clang_analyze_cc1 -triple arm-pc-linux-gnu -analyzer-checker=core,alpha.core -std=gnu99 -verify=other-suppress,common %s
+
+#define AS_ATTRIBUTE(_X) volatile __attribute__((address_space(_X)))
+
+#define _get_base() ((void * AS_ATTRIBUTE(256) *)0)
+
+void* test_address_space_array(unsigned long slot) {
+  return _get_base()[slot]; // other-nosuppress-warning{{Dereference}}
+}
+
+void test_address_space_condition(int AS_ATTRIBUTE(257) *cpu_data) {
+  if (cpu_data == 0) {
+    *cpu_data = 3; // other-nosuppress-warning{{Dereference}}
+  }
+}
+
+struct X { int member; };
+int test_address_space_member(void) {
+  struct X AS_ATTRIBUTE(258) *data = (struct X AS_ATTRIBUTE(258) *)0UL;
+  int ret;
+  ret = data->member; // other-nosuppress-warning{{Dereference}}
+  return ret;
+}
+
+void test_other_address_space_condition(int AS_ATTRIBUTE(259) *cpu_data) {
+  if (cpu_data == 0) {
+    *cpu_data = 3; // other-nosuppress-warning{{Dereference}} \
+                   // x86-nosuppress-warning{{Dereference}}
+  }
+}
+
+void test_no_address_space_condition(int *cpu_data) {
+  if (cpu_data == 0) {
+    *cpu_data = 3; // common-warning{{Dereference}}
+  }
+}
+
+#define _fixed_get_base() ((void * AS_ATTRIBUTE(256) *)2)
+
+void* fixed_test_address_space_array(unsigned long slot) {
+  return _fixed_get_base()[slot]; // other-nosuppress-warning{{Dereference}}
+}
+
+void fixed_test_address_space_condition(int AS_ATTRIBUTE(257) *cpu_data) {
+  if (cpu_data == (int AS_ATTRIBUTE(257) *)2) {
+    *cpu_data = 3; // other-nosuppress-warning{{Dereference}}
+  }
+}
+
+int fixed_test_address_space_member(void) {
+  struct X AS_ATTRIBUTE(258) *data = (struct X AS_ATTRIBUTE(258) *)2UL;
+  int ret;
+  ret = data->member; // other-nosuppress-warning{{Dereference}}
+  return ret;
+}
+
+void fixed_test_other_address_space_condition(int AS_ATTRIBUTE(259) *cpu_data) {
+  if (cpu_data == (int AS_ATTRIBUTE(259) *)2) {
+    *cpu_data = 3; // other-nosuppress-warning{{Dereference}} \
+                   // x86-nosuppress-warning{{Dereference}}
+  }
+}
+
+void fixed_test_no_address_space_condition(int *cpu_data) {
+  if (cpu_data == (int *)2) {
+    *cpu_data = 3; // common-warning{{Dereference}}
+  }
+}


        


More information about the cfe-commits mailing list