r191909 - [analyzer] Add new debug helper clang_analyzer_warnIfReached.

Jordan Rose jordan_rose at apple.com
Thu Oct 3 09:57:04 PDT 2013


Author: jrose
Date: Thu Oct  3 11:57:03 2013
New Revision: 191909

URL: http://llvm.org/viewvc/llvm-project?rev=191909&view=rev
Log:
[analyzer] Add new debug helper clang_analyzer_warnIfReached.

This will emit a warning if a call to clang_analyzer_warnIfReached is
executed, printing REACHABLE. This is a more explicit way to declare
expected reachability than using clang_analyzer_eval or triggering
a bug (divide-by-zero or null dereference), and unlike the former will
work the same in inlined functions and top-level functions. Like the
other debug helpers, it is part of the debug.ExprInspection checker.

Patch by Jared Grubb!

Modified:
    cfe/trunk/docs/analyzer/DebugChecks.rst
    cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
    cfe/trunk/test/Analysis/func.c
    cfe/trunk/test/Analysis/misc-ps-region-store.cpp

Modified: cfe/trunk/docs/analyzer/DebugChecks.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/analyzer/DebugChecks.rst?rev=191909&r1=191908&r2=191909&view=diff
==============================================================================
--- cfe/trunk/docs/analyzer/DebugChecks.rst (original)
+++ cfe/trunk/docs/analyzer/DebugChecks.rst Thu Oct  3 11:57:03 2013
@@ -125,6 +125,19 @@ ExprInspection checks
       clang_analyzer_eval(value == 42); // expected-warning{{TRUE}}
     }
 
+- void clang_analyzer_warnIfReached();
+
+  Generate a warning if this line of code gets reached by the analyzer.
+
+  Example usage::
+
+    if (true) {
+      clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
+    }
+    else {
+      clang_analyzer_warnIfReached();  // no-warning
+    }
+
 
 Statistics
 ==========

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp?rev=191909&r1=191908&r2=191909&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp Thu Oct  3 11:57:03 2013
@@ -22,6 +22,7 @@ class ExprInspectionChecker : public Che
 
   void analyzerEval(const CallExpr *CE, CheckerContext &C) const;
   void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const;
+  void analyzerWarnIfReached(const CallExpr *CE, CheckerContext &C) const;
   void analyzerCrash(const CallExpr *CE, CheckerContext &C) const;
 
   typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
@@ -41,6 +42,7 @@ bool ExprInspectionChecker::evalCall(con
     .Case("clang_analyzer_checkInlined",
           &ExprInspectionChecker::analyzerCheckInlined)
     .Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
+    .Case("clang_analyzer_warnIfReached", &ExprInspectionChecker::analyzerWarnIfReached)
     .Default(0);
 
   if (!Handler)
@@ -99,6 +101,17 @@ void ExprInspectionChecker::analyzerEval
   C.emitReport(R);
 }
 
+void ExprInspectionChecker::analyzerWarnIfReached(const CallExpr *CE,
+                                                  CheckerContext &C) const {
+  ExplodedNode *N = C.getPredecessor();
+
+  if (!BT)
+    BT.reset(new BugType("Checking analyzer assumptions", "debug"));
+
+  BugReport *R = new BugReport(*BT, "REACHABLE", N);
+  C.emitReport(R);
+}
+
 void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
                                                  CheckerContext &C) const {
   ExplodedNode *N = C.getPredecessor();

Modified: cfe/trunk/test/Analysis/func.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/func.c?rev=191909&r1=191908&r2=191909&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/func.c (original)
+++ cfe/trunk/test/Analysis/func.c Thu Oct  3 11:57:03 2013
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify %s
 
 void clang_analyzer_eval(int);
+void clang_analyzer_warnIfReached();
 
 void f(void) {
   void (*p)(void);
@@ -29,12 +30,12 @@ void f3(void (*f)(void), void (*g)(void)
 void nullFunctionPointerConstant() {
   void (*f)(void) = 0;
   f(); // expected-warning{{Called function pointer is null}}
-  clang_analyzer_eval(0); // no-warning
+  clang_analyzer_warnIfReached(); // no-warning
 }
 
 void nullFunctionPointerConstraint(void (*f)(void)) {
   if (f)
     return;
   f(); // expected-warning{{Called function pointer is null}}
-  clang_analyzer_eval(0); // no-warning
+  clang_analyzer_warnIfReached(); // no-warning
 }

Modified: cfe/trunk/test/Analysis/misc-ps-region-store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.cpp?rev=191909&r1=191908&r2=191909&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.cpp (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.cpp Thu Oct  3 11:57:03 2013
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions
-// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s -fexceptions -fcxx-exceptions
+
+void clang_analyzer_warnIfReached();
 
 // Test basic handling of references.
 char &test1_aux();
@@ -54,9 +56,7 @@ int test_init_in_condition_switch() {
       if (x == 2)
         return 0;
       else {
-        // Unreachable.
-        int *p = 0;
-        *p = 0xDEADBEEF; // no-warning
+        clang_analyzer_warnIfReached();  // unreachable
       }
     default:
       break;
@@ -74,8 +74,7 @@ int test_init_in_condition_while() {
   if (z == 2)
     return 0;
   
-  int *p = 0;
-  *p = 0xDEADBEEF; // no-warning
+  clang_analyzer_warnIfReached();  // unreachable
   return 0;
 }
 
@@ -89,8 +88,7 @@ int test_init_in_condition_for() {
   if (z == 1)
     return 0;
     
-  int *p = 0;
-  *p = 0xDEADBEEF; // no-warning
+  clang_analyzer_warnIfReached();  // unreachable
   return 0;
 }
 
@@ -117,8 +115,7 @@ int TestHandleThis::null_deref_negative(
   if (x == 10) {
     return 1;
   }
-  int *p = 0;
-  *p = 0xDEADBEEF; // no-warning
+  clang_analyzer_warnIfReached();  // unreachable
   return 0;  
 }
 
@@ -127,8 +124,7 @@ int TestHandleThis::null_deref_positive(
   if (x == 9) {
     return 1;
   }
-  int *p = 0;
-  *p = 0xDEADBEEF; // expected-warning{{null pointer}}
+  clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
   return 0;  
 }
 
@@ -143,9 +139,9 @@ void pr7675_test() {
   pr7675(10);
   pr7675('c');
   pr7675_i(4.0i);
-  // Add null deref to ensure we are analyzing the code up to this point.
-  int *p = 0;
-  *p = 0xDEADBEEF; // expected-warning{{null pointer}}
+
+  // Add check to ensure we are analyzing the code up to this point.
+  clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 }
 
 // <rdar://problem/8375510> - CFGBuilder should handle temporaries.
@@ -328,26 +324,23 @@ class RDar9267815 {
 };
 
 void RDar9267815::test_pos() {
-  int *p = 0;
   if (x == 42)
     return;
-  *p = 0xDEADBEEF; // expected-warning {{null}}
+  clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 }
 void RDar9267815::test() {
-  int *p = 0;
   if (x == 42)
     return;
   if (x == 42)
-    *p = 0xDEADBEEF; // no-warning
+    clang_analyzer_warnIfReached();  // no-warning
 }
 
 void RDar9267815::test2() {
-  int *p = 0;
   if (x == 42)
     return;
   invalidate();
   if (x == 42)
-    *p = 0xDEADBEEF; // expected-warning {{null}}
+    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 }
 
 // Test reference parameters.
@@ -440,8 +433,7 @@ int rdar9948787_negative() {
     unsigned value = classWithStatic.value;
     if (value == 1)
       return 1;
-    int *p = 0;
-    *p = 0xDEADBEEF; // no-warning
+    clang_analyzer_warnIfReached();  // no-warning
     return 0;
 }
 
@@ -450,8 +442,7 @@ int rdar9948787_positive() {
     unsigned value = classWithStatic.value;
     if (value == 0)
       return 1;
-    int *p = 0;
-    *p = 0xDEADBEEF; // expected-warning {{null}}
+    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
     return 0;
 }
 
@@ -467,8 +458,7 @@ void rdar10202899_test1() {
 void rdar10202899_test2() {
   if (val == rdar10202899_ValTA)
    return;
-  int *p = 0;
-  *p = 0xDEADBEEF;
+  clang_analyzer_warnIfReached();  // no-warning
 }
 
 void rdar10202899_test3() {
@@ -476,8 +466,7 @@ void rdar10202899_test3() {
     case rdar10202899_ValTA: return;
     default: ;
   };
-  int *p = 0;
-  *p = 0xDEADBEEF;
+  clang_analyzer_warnIfReached();  // no-warning
 }
 
 // This used to crash the analyzer because of the unnamed bitfield.
@@ -489,13 +478,12 @@ void PR11249()
     char f2[1];
     char f3;
   } V = { 1, {2}, 3 };
-  int *p = 0;
   if (V.f1 != 1)
-    *p = 0xDEADBEEF;  // no-warning
+    clang_analyzer_warnIfReached();  // no-warning
   if (V.f2[0] != 2)
-    *p = 0xDEADBEEF;  // no-warning
+    clang_analyzer_warnIfReached();  // no-warning
   if (V.f3 != 3)
-    *p = 0xDEADBEEF;  // no-warning
+    clang_analyzer_warnIfReached();  // no-warning
 }
 
 // Handle doing a load from the memory associated with the code for
@@ -599,12 +587,10 @@ void rdar10924675(unsigned short x[], in
 void rdar11401827() {
   int x = int();
   if (!x) {
-    int *p = 0;
-    *p = 0xDEADBEEF; // expected-warning {{null pointer}}
+    clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
   }
   else {
-    int *p = 0;
-    *p = 0xDEADBEEF;
+    clang_analyzer_warnIfReached();  // no-warning
   }
 }
 
@@ -701,8 +687,7 @@ const Rdar12755044_foo *radar12755044()
 void rdar12759044() {
   int flag = 512;
   if (!(flag & 512)) {
-   int *p = 0;
-   *p = 0xDEADBEEF; // no-warning
+    clang_analyzer_warnIfReached();  // no-warning
   }
 }
 





More information about the cfe-commits mailing list