aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-02-25 19:45:34 +0000
committerJordan Rose <jordan_rose@apple.com>2013-02-25 19:45:34 +0000
commitfbdbed3bde8577815826b9d15790e5effb913f7b (patch)
treefdc192c69de3661cf8efffcaaa9c98b988ab34c4
parent59c900304a390b11c4efcad2924bf6373979db73 (diff)
[analyzer] Handle reference parameters with default values.
r175026 added support for default values, but didn't take reference parameters into account, which expect the default argument to be an lvalue. Use createTemporaryRegionIfNeeded if we can evaluate the default expr as an rvalue but the expected result is an lvalue. Fixes the most recent report of PR12915. The original report predates default argument support, so that can't be it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176042 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp7
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp2
-rw-r--r--test/Analysis/global_region_invalidation.mm9
-rw-r--r--test/Analysis/inline.cpp9
4 files changed, 23 insertions, 4 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index eb83e202b7..8b6de13249 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -685,7 +685,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
const LocationContext *LCtx = Pred->getLocationContext();
- const Expr *ArgE = cast<CXXDefaultArgExpr>(S)->getExpr();
+ const CXXDefaultArgExpr *DefaultE = cast<CXXDefaultArgExpr>(S);
+ const Expr *ArgE = DefaultE->getExpr();
// Avoid creating and destroying a lot of APSInts.
SVal V;
@@ -700,7 +701,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
else
V = State->getSVal(ArgE, LCtx);
- State = State->BindExpr(S, LCtx, V);
+ State = State->BindExpr(DefaultE, LCtx, V);
+ if (DefaultE->isGLValue())
+ State = createTemporaryRegionIfNeeded(State, LCtx, DefaultE);
Bldr2.generateNode(S, *I, State);
}
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 310c080faf..acda9e0af3 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1578,7 +1578,7 @@ static Optional<SVal> getConstValue(SValBuilder &SVB, const VarDecl *VD) {
return None;
llvm::APSInt Result;
- if (Init->EvaluateAsInt(Result, Ctx))
+ if (!Init->isGLValue() && Init->EvaluateAsInt(Result, Ctx))
return SVB.makeIntVal(Result);
if (Init->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
diff --git a/test/Analysis/global_region_invalidation.mm b/test/Analysis/global_region_invalidation.mm
index 0d7f172b3f..be337edab1 100644
--- a/test/Analysis/global_region_invalidation.mm
+++ b/test/Analysis/global_region_invalidation.mm
@@ -9,4 +9,11 @@ id foo(int x) {
static id p = foo(1);
clang_analyzer_eval(p == 0); // expected-warning{{TRUE}}
return p;
-} \ No newline at end of file
+}
+
+const int &globalInt = 42;
+
+void testGlobal() {
+ // FIXME: Should be TRUE, but should at least not crash.
+ clang_analyzer_eval(globalInt == 42); // expected-warning{{UNKNOWN}}
+}
diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp
index f0e69ddfc2..27853dc2aa 100644
--- a/test/Analysis/inline.cpp
+++ b/test/Analysis/inline.cpp
@@ -260,6 +260,15 @@ namespace DefaultArgs {
clang_analyzer_eval(complicatedExprUser(1) == 1); // expected-warning{{TRUE}}
clang_analyzer_eval(complicatedExprUser() == 84); // expected-warning{{TRUE}}
}
+
+ int defaultReference(const int &input = 42) {
+ return input;
+ }
+
+ void testReference() {
+ clang_analyzer_eval(defaultReference(1) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(defaultReference() == 42); // expected-warning{{TRUE}}
+ }
}
namespace OperatorNew {