summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/docs/analyzer/DebugChecks.rst13
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp13
-rw-r--r--clang/test/Analysis/func.c5
-rw-r--r--clang/test/Analysis/misc-ps-region-store.cpp65
4 files changed, 54 insertions, 42 deletions
diff --git a/clang/docs/analyzer/DebugChecks.rst b/clang/docs/analyzer/DebugChecks.rst
index a0f2a07a00b..14d6ae4c4c9 100644
--- a/clang/docs/analyzer/DebugChecks.rst
+++ b/clang/docs/analyzer/DebugChecks.rst
@@ -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
==========
diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 9522d1d6387..3ed2435b92e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -22,6 +22,7 @@ class ExprInspectionChecker : public Checker< eval::Call > {
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(const CallExpr *CE,
.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(const CallExpr *CE,
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();
diff --git a/clang/test/Analysis/func.c b/clang/test/Analysis/func.c
index 275a82da2e7..78afb45da69 100644
--- a/clang/test/Analysis/func.c
+++ b/clang/test/Analysis/func.c
@@ -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
}
diff --git a/clang/test/Analysis/misc-ps-region-store.cpp b/clang/test/Analysis/misc-ps-region-store.cpp
index 902a5e52711..6a873f01b3d 100644
--- a/clang/test/Analysis/misc-ps-region-store.cpp
+++ b/clang/test/Analysis/misc-ps-region-store.cpp
@@ -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[], int index, int index2) {
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
}
}
OpenPOWER on IntegriCloud