[cfe-commits] r109286 - in /cfe/trunk: lib/Checker/CMakeLists.txt lib/Checker/GRExprEngineExperimentalChecks.cpp lib/Checker/GRExprEngineExperimentalChecks.h lib/Checker/UnreachableCodeChecker.cpp test/Analysis/additive-folding.c test/Analysis/bstring.c test/Analysis/malloc.c test/Analysis/unreachable-code-path.c
Tom Care
tcare at apple.com
Fri Jul 23 16:04:53 PDT 2010
Author: tcare
Date: Fri Jul 23 18:04:53 2010
New Revision: 109286
URL: http://llvm.org/viewvc/llvm-project?rev=109286&view=rev
Log:
Added an path-sensitive unreachable code checker to the experimental analyzer checks.
- Created a new class to do post-analysis
- Updated several test cases with unreachable code to expect a warning
- Added some general tests
Added:
cfe/trunk/lib/Checker/UnreachableCodeChecker.cpp
cfe/trunk/test/Analysis/unreachable-code-path.c
Modified:
cfe/trunk/lib/Checker/CMakeLists.txt
cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp
cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h
cfe/trunk/test/Analysis/additive-folding.c
cfe/trunk/test/Analysis/bstring.c
cfe/trunk/test/Analysis/malloc.c
Modified: cfe/trunk/lib/Checker/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/CMakeLists.txt?rev=109286&r1=109285&r2=109286&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/CMakeLists.txt (original)
+++ cfe/trunk/lib/Checker/CMakeLists.txt Fri Jul 23 18:04:53 2010
@@ -74,6 +74,7 @@
UndefinedArraySubscriptChecker.cpp
UndefinedAssignmentChecker.cpp
UnixAPIChecker.cpp
+ UnreachableCodeChecker.cpp
VLASizeChecker.cpp
ValueManager.cpp
)
Modified: cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp?rev=109286&r1=109285&r2=109286&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp Fri Jul 23 18:04:53 2010
@@ -18,13 +18,14 @@
using namespace clang;
-void clang::RegisterExperimentalChecks(GRExprEngine &Eng) {
+void clang::RegisterExperimentalChecks(GRExprEngine &Eng) {
// These are checks that never belong as internal checks
// within GRExprEngine.
- RegisterPthreadLockChecker(Eng);
+ RegisterCStringChecker(Eng);
RegisterMallocChecker(Eng);
+ RegisterPthreadLockChecker(Eng);
RegisterStreamChecker(Eng);
- RegisterCStringChecker(Eng);
+ RegisterUnreachableCodeChecker(Eng);
}
void clang::RegisterExperimentalInternalChecks(GRExprEngine &Eng) {
@@ -34,11 +35,10 @@
// Note that this must be registered after ReturnStackAddresEngsChecker.
RegisterReturnPointerRangeChecker(Eng);
+ RegisterArrayBoundChecker(Eng);
+ RegisterCastSizeChecker(Eng);
+ RegisterCastToStructChecker(Eng);
RegisterFixedAddressChecker(Eng);
- RegisterPointerSubChecker(Eng);
RegisterPointerArithChecker(Eng);
- RegisterCastToStructChecker(Eng);
- RegisterCastSizeChecker(Eng);
- RegisterArrayBoundChecker(Eng);
-
+ RegisterPointerSubChecker(Eng);
}
Modified: cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h?rev=109286&r1=109285&r2=109286&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h (original)
+++ cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h Fri Jul 23 18:04:53 2010
@@ -20,9 +20,10 @@
class GRExprEngine;
void RegisterCStringChecker(GRExprEngine &Eng);
-void RegisterPthreadLockChecker(GRExprEngine &Eng);
void RegisterMallocChecker(GRExprEngine &Eng);
+void RegisterPthreadLockChecker(GRExprEngine &Eng);
void RegisterStreamChecker(GRExprEngine &Eng);
+void RegisterUnreachableCodeChecker(GRExprEngine &Eng);
} // end clang namespace
#endif
Added: cfe/trunk/lib/Checker/UnreachableCodeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/UnreachableCodeChecker.cpp?rev=109286&view=auto
==============================================================================
--- cfe/trunk/lib/Checker/UnreachableCodeChecker.cpp (added)
+++ cfe/trunk/lib/Checker/UnreachableCodeChecker.cpp Fri Jul 23 18:04:53 2010
@@ -0,0 +1,143 @@
+//==- UnreachableCodeChecker.cpp - Generalized dead code checker -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This file implements a generalized unreachable code checker using a
+// path-sensitive analysis. We mark any path visited, and then walk the CFG as a
+// post-analysis to determine what was never visited.
+//
+// A similar flow-sensitive only check exists in Analysis/UnreachableCode.cpp
+//===----------------------------------------------------------------------===//
+
+#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/ExplodedGraph.h"
+#include "clang/Checker/PathSensitive/SVals.h"
+#include "clang/Checker/BugReporter/BugReporter.h"
+#include "GRExprEngineExperimentalChecks.h"
+#include "clang/AST/StmtCXX.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+// The number of CFGBlock pointers we want to reserve memory for. This is used
+// once for each function we analyze.
+#define DEFAULT_CFGBLOCKS 256
+
+using namespace clang;
+
+namespace {
+class UnreachableCodeChecker : public CheckerVisitor<UnreachableCodeChecker> {
+public:
+ static void *getTag();
+ void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
+ bool hasWorkRemaining);
+private:
+ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R);
+ void FindUnreachableEntryPoints(const CFGBlock *CB);
+ void MarkSuccessorsReachable(const CFGBlock *CB);
+
+ llvm::SmallPtrSet<const CFGBlock*, DEFAULT_CFGBLOCKS> reachable;
+ llvm::SmallPtrSet<const CFGBlock*, DEFAULT_CFGBLOCKS> visited;
+};
+}
+
+void *UnreachableCodeChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void clang::RegisterUnreachableCodeChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new UnreachableCodeChecker());
+}
+
+void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
+ BugReporter &B,
+ bool hasWorkRemaining) {
+ // Bail out if we didn't cover all paths
+ if (hasWorkRemaining)
+ return;
+
+ CFG *C = 0;
+ // Iterate over ExplodedGraph
+ for (ExplodedGraph::node_iterator I = G.nodes_begin(); I != G.nodes_end();
+ ++I) {
+ const ProgramPoint &P = I->getLocation();
+
+ // Save the CFG if we don't have it already
+ if (!C)
+ C = P.getLocationContext()->getCFG();
+
+ if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
+ const CFGBlock *CB = BE->getBlock();
+ reachable.insert(CB);
+ }
+ }
+
+ // Bail out if we didn't get the CFG
+ if (!C)
+ return;
+
+ // Find CFGBlocks that were not covered by any node
+ for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
+ const CFGBlock *CB = *I;
+ // Check if the block is unreachable
+ if (!reachable.count(CB)) {
+ // Find the entry points for this block
+ FindUnreachableEntryPoints(CB);
+ // This block may have been pruned; check if we still want to report it
+ if (reachable.count(CB))
+ continue;
+
+ // We found a statement that wasn't covered
+ SourceRange S;
+ SourceLocation SL = GetUnreachableLoc(*CB, S);
+ if (S.getBegin().isMacroID() || S.getEnd().isMacroID() || S.isInvalid()
+ || SL.isInvalid())
+ continue;
+ B.EmitBasicReport("Unreachable code", "This statement is never executed",
+ SL, S);
+ }
+ }
+}
+
+// Recursively finds the entry point(s) for this dead CFGBlock.
+void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
+ bool allPredecessorsReachable = true;
+
+ visited.insert(CB);
+
+ for (CFGBlock::const_pred_iterator I = CB->pred_begin(); I != CB->pred_end();
+ ++I) {
+ // Recurse over all unreachable blocks
+ if (!reachable.count(*I) && !visited.count(*I)) {
+ FindUnreachableEntryPoints(*I);
+ allPredecessorsReachable = false;
+ }
+ }
+
+ // If at least one predecessor is unreachable, mark this block as reachable
+ // so we don't report this block.
+ if (!allPredecessorsReachable) {
+ reachable.insert(CB);
+ }
+}
+
+// Find the SourceLocation and SourceRange to report this CFGBlock
+SourceLocation UnreachableCodeChecker::GetUnreachableLoc(const CFGBlock &b,
+ SourceRange &R) {
+ const Stmt *S = 0;
+ unsigned sn = 0;
+ R = SourceRange();
+
+ if (sn < b.size())
+ S = b[sn].getStmt();
+ else if (b.getTerminator())
+ S = b.getTerminator();
+ else
+ return SourceLocation();
+
+ R = S->getSourceRange();
+ return S->getLocStart();
+}
Modified: cfe/trunk/test/Analysis/additive-folding.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/additive-folding.c?rev=109286&r1=109285&r2=109286&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/additive-folding.c (original)
+++ cfe/trunk/test/Analysis/additive-folding.c Fri Jul 23 18:04:53 2010
@@ -18,7 +18,7 @@
char* buf = malloc(1);
if (a != 0 && b == 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(buf);
}
@@ -29,7 +29,7 @@
char* buf = malloc(1);
if (a != 0 && b == 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(buf);
}
@@ -40,11 +40,11 @@
// This is part of PR7406.
int b = a + 1LL;
if (a != 0 && (b-1) == 0) // not crash
- return; // no warning
+ return; // expected-warning{{never executed}}
int c = a + 1U;
if (a != 0 && (c-1) == 0) // not crash
- return; // no warning
+ return; // expected-warning{{never executed}}
free(buf);
}
@@ -61,7 +61,7 @@
if (a+1 != 0)
return; // no-warning
if (a-1 != UINT_MAX-1)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
@@ -72,7 +72,7 @@
if (a+1 == 0)
return; // no-warning
if (a-1 == UINT_MAX-1)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
@@ -85,7 +85,7 @@
if (a+1U != 2)
return; // no-warning
if (a-1U != 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
@@ -96,7 +96,7 @@
if (a+1U == 2)
return; // no-warning
if (a-1U == 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
@@ -177,7 +177,7 @@
void tautologyGT (unsigned a) {
char* b = malloc(1);
if (a > UINT_MAX)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
@@ -191,7 +191,7 @@
void tautologyLT (unsigned a) {
char* b = malloc(1);
if (a < 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
Modified: cfe/trunk/test/Analysis/bstring.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/bstring.c?rev=109286&r1=109285&r2=109286&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/bstring.c (original)
+++ cfe/trunk/test/Analysis/bstring.c Fri Jul 23 18:04:53 2010
@@ -53,7 +53,7 @@
memcpy(dst, src, 4); // no-warning
if (memcpy(dst, src, 4) != dst) {
- (void)*(char*)0; // no-warning -- should be unreachable
+ (void)*(char*)0; // expected-warning{{never executed}}
}
}
@@ -155,7 +155,7 @@
memmove(dst, src, 4); // no-warning
if (memmove(dst, src, 4) != dst) {
- (void)*(char*)0; // no-warning -- should be unreachable
+ (void)*(char*)0; // expected-warning{{never executed}}
}
}
@@ -217,7 +217,7 @@
char a[] = {1, 2, 3, 4};
if (memcmp(a, a, 4))
- (void)*(char*)0; // no-warning
+ (void)*(char*)0; // expected-warning{{never executed}}
}
void memcmp4 (char *input) {
@@ -231,11 +231,11 @@
char a[] = {1, 2, 3, 4};
if (memcmp(a, 0, 0)) // no-warning
- (void)*(char*)0; // no-warning
+ (void)*(char*)0; // expected-warning{{never executed}}
if (memcmp(0, a, 0)) // no-warning
- (void)*(char*)0; // no-warning
+ (void)*(char*)0; // expected-warning{{never executed}}
if (memcmp(a, input, 0)) // no-warning
- (void)*(char*)0; // no-warning
+ (void)*(char*)0; // expected-warning{{never executed}}
}
void memcmp6 (char *a, char *b, size_t n) {
Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=109286&r1=109285&r2=109286&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Fri Jul 23 18:04:53 2010
@@ -117,7 +117,7 @@
char *buf = calloc(2,2);
char result = buf[3]; // no-warning
if (buf[1] != 0) {
- free(buf);
+ free(buf); // expected-warning{{never executed}}
}
return result; // expected-warning{{never released}}
}
Added: cfe/trunk/test/Analysis/unreachable-code-path.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/unreachable-code-path.c?rev=109286&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/unreachable-code-path.c (added)
+++ cfe/trunk/test/Analysis/unreachable-code-path.c Fri Jul 23 18:04:53 2010
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-check-objc-mem -analyzer-check-dead-stores -verify -analyzer-opt-analyze-nested-blocks %s
+
+extern void foo(int a);
+
+void test(unsigned a) {
+ switch (a) {
+ a += 5; // expected-warning{{never executed}}
+ case 2:
+ a *= 10;
+ case 3:
+ a %= 2;
+ }
+ foo(a);
+}
+
+void test2(unsigned a) {
+ help:
+ if (a > 0)
+ return;
+ if (a == 0)
+ return;
+ foo(a); // expected-warning{{never executed}}
+ goto help;
+}
+
+void test3() {
+ int a = 5;
+
+ while (a > 1)
+ a -= 2;
+
+ if (a > 1) {
+ a = a + 56; // expected-warning{{never executed}}
+ }
+
+ foo(a);
+}
+
+void test4(unsigned a) {
+ while(1);
+ if (a > 5) { // expected-warning{{never executed}}
+ return;
+ }
+}
+
+extern void bar(char c);
+
+void test5(const char *c) {
+ foo(c[0]);
+
+ if (!c) {
+ bar(1); // expected-warning{{never executed}}
+ }
+}
+
More information about the cfe-commits
mailing list