]> granicus.if.org Git - clang/commitdiff
[analyzer] Don't report null dereferences on address_space annotated memory
authorAnna Zaks <ganna@apple.com>
Wed, 6 Jan 2016 00:32:49 +0000 (00:32 +0000)
committerAnna Zaks <ganna@apple.com>
Wed, 6 Jan 2016 00:32:49 +0000 (00:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@256885 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
test/Analysis/null-deref-ps.c
test/Analysis/nullptr.cpp

index 5dd28320f88fa15e8820427c70ae73ff810081fc..f216f696ef65a62987aca3367c385b7867b95de7 100644 (file)
@@ -34,8 +34,7 @@ class DereferenceChecker
   mutable std::unique_ptr<BuiltinBug> BT_null;
   mutable std::unique_ptr<BuiltinBug> BT_undef;
 
-  void reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C,
-                 bool IsBind = false) const;
+  void reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C) const;
 
 public:
   void checkLocation(SVal location, bool isLoad, const Stmt* S,
@@ -89,8 +88,31 @@ DereferenceChecker::AddDerefSource(raw_ostream &os,
   }
 }
 
+static const Expr *getDereferenceExpr(const Stmt *S, bool IsBind=false){
+  const Expr *E = nullptr;
+
+  // Walk through lvalue casts to get the original expression
+  // that syntactically caused the load.
+  if (const Expr *expr = dyn_cast<Expr>(S))
+    E = expr->IgnoreParenLValueCasts();
+
+  if (IsBind) {
+    const VarDecl *VD;
+    const Expr *Init;
+    std::tie(VD, Init) = parseAssignment(S);
+    if (VD && Init)
+      E = Init;
+  }
+  return E;
+}
+
+static bool suppressReport(const Expr *E) {
+  // Do not report dereferences on memory in non-default address spaces.
+  return E->getType().getQualifiers().hasAddressSpace();
+}
+
 void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
-                                   CheckerContext &C, bool IsBind) const {
+                                   CheckerContext &C) const {
   // Generate an error node.
   ExplodedNode *N = C.generateErrorNode(State);
   if (!N)
@@ -106,19 +128,6 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
 
   SmallVector<SourceRange, 2> Ranges;
 
-  // Walk through lvalue casts to get the original expression
-  // that syntactically caused the load.
-  if (const Expr *expr = dyn_cast<Expr>(S))
-    S = expr->IgnoreParenLValueCasts();
-
-  if (IsBind) {
-    const VarDecl *VD;
-    const Expr *Init;
-    std::tie(VD, Init) = parseAssignment(S);
-    if (VD && Init)
-      S = Init;
-  }
-
   switch (S->getStmtClass()) {
   case Stmt::ArraySubscriptExprClass: {
     os << "Array access";
@@ -209,8 +218,11 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
   // The explicit NULL case.
   if (nullState) {
     if (!notNullState) {
-      reportBug(nullState, S, C);
-      return;
+      const Expr *expr = getDereferenceExpr(S);
+      if (!suppressReport(expr)) {
+        reportBug(nullState, expr, C);
+        return;
+      }
     }
 
     // Otherwise, we have the case where the location could either be
@@ -248,8 +260,11 @@ void DereferenceChecker::checkBind(SVal L, SVal V, const Stmt *S,
 
   if (StNull) {
     if (!StNonNull) {
-      reportBug(StNull, S, C, /*isBind=*/true);
-      return;
+      const Expr *expr = getDereferenceExpr(S, /*IsBind=*/true);
+      if (!suppressReport(expr)) {
+        reportBug(StNull, expr, C);
+        return;
+      }
     }
 
     // At this point the value could be either null or non-null.
index 240e8edb13d2a2ccfd7f7140148994d0e16d33be..79b3b3a5758c111cb015fa121149e8d93bbe6d30 100644 (file)
@@ -311,3 +311,21 @@ int foo10595327(int b) {
       return *p; // no-warning
   return 0;
 }
+
+#define AS_ATTRIBUTE volatile __attribute__((address_space(256)))
+#define _get_base() ((void * AS_ATTRIBUTE *)0)
+void* test_address_space_array(unsigned long slot) {
+  return _get_base()[slot]; // no-warning
+}
+void test_address_space_condition(int AS_ATTRIBUTE *cpu_data) {
+   if (cpu_data == 0) {
+    *cpu_data = 3; // no-warning
+  }
+}
+struct X { int member; };
+int test_address_space_member() {
+  struct X AS_ATTRIBUTE *data = (struct X AS_ATTRIBUTE *)0UL;
+  int ret;
+  ret = data->member; // no-warning
+  return ret;
+}
index 17320f3b9a84b4c0a2e62286e7719716c09ea446..acc525e9fef7574ffa2be654a34cac3e3fbdc004 100644 (file)
@@ -126,3 +126,22 @@ decltype(nullptr) returnsNullPtrType();
 void fromReturnType() {
   ((X *)returnsNullPtrType())->f(); // expected-warning{{Called C++ object pointer is null}}
 }
+
+#define AS_ATTRIBUTE __attribute__((address_space(256)))
+class AS1 {
+public:
+  int x;
+  ~AS1() {
+    int AS_ATTRIBUTE *x = 0;
+    *x = 3; // no-warning
+  }
+};
+void test_address_space_field_access() {
+  AS1 AS_ATTRIBUTE *pa = 0;
+  pa->x = 0; // no-warning
+}
+void test_address_space_bind() {
+  AS1 AS_ATTRIBUTE *pa = 0;
+  AS1 AS_ATTRIBUTE &r = *pa;
+  r.x = 0; // no-warning
+}