r175026 - [analyzer] Use Clang's evaluation for global constants and default arguments.
Jordan Rose
jordan_rose at apple.com
Tue Feb 12 19:11:06 PST 2013
Author: jrose
Date: Tue Feb 12 21:11:06 2013
New Revision: 175026
URL: http://llvm.org/viewvc/llvm-project?rev=175026&view=rev
Log:
[analyzer] Use Clang's evaluation for global constants and default arguments.
Previously, we were handling only simple integer constants for globals and
the smattering of implicitly-valued expressions handled by Environment for
default arguments. Now, we can use any integer constant expression that
Clang can evaluate, in addition to everything we handled before.
PR15094 / <rdar://problem/12830437>
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
cfe/trunk/test/Analysis/global-region-invalidation.c
cfe/trunk/test/Analysis/inline.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp?rev=175026&r1=175025&r2=175026&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp Tue Feb 12 21:11:06 2013
@@ -37,9 +37,6 @@ static const Expr *ignoreTransparentExpr
case Stmt::SubstNonTypeTemplateParmExprClass:
E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
break;
- case Stmt::CXXDefaultArgExprClass:
- E = cast<CXXDefaultArgExpr>(E)->getExpr();
- break;
default:
// This is the base case: we can't look through more than we already have.
return E;
@@ -75,7 +72,6 @@ SVal Environment::getSVal(const Environm
switch (S->getStmtClass()) {
case Stmt::CXXBindTemporaryExprClass:
- case Stmt::CXXDefaultArgExprClass:
case Stmt::ExprWithCleanupsClass:
case Stmt::GenericSelectionExprClass:
case Stmt::OpaqueValueExprClass:
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=175026&r1=175025&r2=175026&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Feb 12 21:11:06 2013
@@ -639,7 +639,6 @@ void ExprEngine::Visit(const Stmt *S, Ex
case Stmt::StringLiteralClass:
case Stmt::ObjCStringLiteralClass:
case Stmt::CXXBindTemporaryExprClass:
- case Stmt::CXXDefaultArgExprClass:
case Stmt::SubstNonTypeTemplateParmExprClass:
case Stmt::CXXNullPtrLiteralExprClass: {
Bldr.takeNodes(Pred);
@@ -649,6 +648,39 @@ void ExprEngine::Visit(const Stmt *S, Ex
Bldr.addNodes(Dst);
break;
}
+
+ case Stmt::CXXDefaultArgExprClass: {
+ Bldr.takeNodes(Pred);
+ ExplodedNodeSet PreVisit;
+ getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+ ExplodedNodeSet Tmp;
+ StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
+
+ const LocationContext *LCtx = Pred->getLocationContext();
+ const Expr *ArgE = cast<CXXDefaultArgExpr>(S)->getExpr();
+
+ // Avoid creating and destroying a lot of APSInts.
+ SVal V;
+ llvm::APSInt Result;
+
+ for (ExplodedNodeSet::iterator I = PreVisit.begin(), E = PreVisit.end();
+ I != E; ++I) {
+ ProgramStateRef State = (*I)->getState();
+
+ if (ArgE->EvaluateAsInt(Result, getContext()))
+ V = svalBuilder.makeIntVal(Result);
+ else
+ V = State->getSVal(ArgE, LCtx);
+
+ State = State->BindExpr(S, LCtx, V);
+ Bldr2.generateNode(S, *I, State);
+ }
+
+ getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
+ Bldr.addNodes(Dst);
+ break;
+ }
case Expr::ObjCArrayLiteralClass:
case Expr::ObjCDictionaryLiteralClass:
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=175026&r1=175025&r2=175026&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Tue Feb 12 21:11:06 2013
@@ -1524,11 +1524,14 @@ SVal RegionStoreManager::getBindingForVa
QualType CT = Ctx.getCanonicalType(T);
if (CT.isConstQualified()) {
if (const Expr *Init = VD->getInit()) {
- if (const IntegerLiteral *IL =
- dyn_cast<IntegerLiteral>(Init->IgnoreParenCasts())) {
- const nonloc::ConcreteInt &V = svalBuilder.makeIntVal(IL);
- return svalBuilder.evalCast(V, Init->getType(), IL->getType());
- }
+ llvm::APSInt Result;
+ if (Init->EvaluateAsInt(Result, Ctx))
+ return svalBuilder.makeIntVal(Result);
+
+ if (Init->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
+ return svalBuilder.makeNull();
+
+ // FIXME: Handle other possible constant expressions.
}
}
Modified: cfe/trunk/test/Analysis/global-region-invalidation.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/global-region-invalidation.c?rev=175026&r1=175025&r2=175026&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/global-region-invalidation.c (original)
+++ cfe/trunk/test/Analysis/global-region-invalidation.c Tue Feb 12 21:11:06 2013
@@ -67,15 +67,29 @@ int constIntGlob() {
return 3 / *m; // expected-warning {{Division by zero}}
}
-extern const int x;
+extern const int y;
int constIntGlobExtern() {
- if (x == 0) {
+ if (y == 0) {
foo();
- return 5 / x; // expected-warning {{Division by zero}}
+ return 5 / y; // expected-warning {{Division by zero}}
}
return 0;
}
+static void * const ptr = 0;
+void constPtrGlob() {
+ clang_analyzer_eval(ptr == 0); // expected-warning{{TRUE}}
+ foo();
+ clang_analyzer_eval(ptr == 0); // expected-warning{{TRUE}}
+}
+
+static const int x2 = x;
+void constIntGlob2() {
+ clang_analyzer_eval(x2 == 0); // expected-warning{{TRUE}}
+ foo();
+ clang_analyzer_eval(x2 == 0); // expected-warning{{TRUE}}
+}
+
void testAnalyzerEvalIsPure() {
extern int someGlobal;
if (someGlobal == 0) {
Modified: cfe/trunk/test/Analysis/inline.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inline.cpp?rev=175026&r1=175025&r2=175026&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inline.cpp (original)
+++ cfe/trunk/test/Analysis/inline.cpp Tue Feb 12 21:11:06 2013
@@ -216,7 +216,7 @@ namespace DefaultArgs {
class Secret {
public:
- static const int value = 42;
+ static const int value = 40 + 2;
int get(int i = value) {
return i;
}
@@ -225,16 +225,40 @@ namespace DefaultArgs {
void testMethod() {
Secret obj;
clang_analyzer_eval(obj.get(1) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(obj.get() == 42); // expected-warning{{TRUE}}
+ clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}}
+ }
- // FIXME: Should be 'TRUE'. See PR13673 or <rdar://problem/11720796>.
- clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}}
+ enum ABC {
+ A = 0,
+ B = 1,
+ C = 2
+ };
- // FIXME: Even if we constrain the variable, we still have a problem.
- // See PR13385 or <rdar://problem/12156507>.
- if (Secret::value != 42)
- return;
- clang_analyzer_eval(Secret::value == 42); // expected-warning{{TRUE}}
- clang_analyzer_eval(obj.get() == 42); // expected-warning{{UNKNOWN}}
+ int enumUser(ABC input = B) {
+ return static_cast<int>(input);
+ }
+
+ void testEnum() {
+ clang_analyzer_eval(enumUser(C) == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(enumUser() == 1); // expected-warning{{TRUE}}
+ }
+
+
+ int exprUser(int input = 2 * 4) {
+ return input;
+ }
+
+ int complicatedExprUser(int input = 2 * Secret::value) {
+ return input;
+ }
+
+ void testExprs() {
+ clang_analyzer_eval(exprUser(1) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(exprUser() == 8); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(complicatedExprUser(1) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(complicatedExprUser() == 84); // expected-warning{{TRUE}}
}
}
More information about the cfe-commits
mailing list