aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h3
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp9
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp9
-rw-r--r--test/Analysis/inline.cpp27
4 files changed, 39 insertions, 9 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 713a6d5933..bbb56885af 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -206,9 +206,6 @@ public:
/// manner.
///
/// If \p E is not a constant or cannot be modeled, returns \c None.
- ///
- /// Note that this function always treats \p E as a prvalue. Callers should
- /// check to see if \p E is a glvalue and modify their behavior accordingly.
Optional<SVal> getConstantVal(const Expr *E);
NonLoc makeCompoundVal(QualType type, llvm::ImmutableList<SVal> vals) {
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 0d5fb1785b..bfe4e15a71 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -741,6 +741,13 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
const CXXDefaultArgExpr *DefaultE = cast<CXXDefaultArgExpr>(S);
const Expr *ArgE = DefaultE->getExpr();
+ bool IsTemporary = false;
+ if (const MaterializeTemporaryExpr *MTE =
+ dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
+ ArgE = MTE->GetTemporaryExpr();
+ IsTemporary = true;
+ }
+
Optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
if (!ConstantVal)
ConstantVal = UnknownVal();
@@ -749,7 +756,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
I != E; ++I) {
ProgramStateRef State = (*I)->getState();
State = State->BindExpr(DefaultE, LCtx, *ConstantVal);
- if (DefaultE->isGLValue())
+ if (IsTemporary)
State = createTemporaryRegionIfNeeded(State, LCtx, DefaultE,
DefaultE);
Bldr2.generateNode(S, *I, State);
diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp
index 652809777c..9d77a3ef58 100644
--- a/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -268,13 +268,18 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
// If we don't have a special case, fall back to the AST's constant evaluator.
default: {
+ // Don't try to come up with a value for materialized temporaries.
+ if (E->isGLValue())
+ return None;
+
ASTContext &Ctx = getContext();
llvm::APSInt Result;
if (E->EvaluateAsInt(Result, Ctx))
return makeIntVal(Result);
- if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
- return makeNull();
+ if (Loc::isLocType(E->getType()))
+ if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
+ return makeNull();
return None;
}
diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp
index 62bce28472..909e18017b 100644
--- a/test/Analysis/inline.cpp
+++ b/test/Analysis/inline.cpp
@@ -262,12 +262,33 @@ namespace DefaultArgs {
}
int defaultReference(const int &input = 42) {
- return input;
+ return -input;
+ }
+ int defaultReferenceZero(const int &input = 0) {
+ return -input;
}
void testReference() {
- clang_analyzer_eval(defaultReference(1) == 1); // expected-warning{{TRUE}}
- clang_analyzer_eval(defaultReference() == 42); // expected-warning{{TRUE}}
+ clang_analyzer_eval(defaultReference(1) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(defaultReference() == -42); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(defaultReferenceZero(1) == -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(defaultReferenceZero() == 0); // expected-warning{{TRUE}}
+}
+
+ double defaultFloatReference(const double &i = 42) {
+ return -i;
+ }
+ double defaultFloatReferenceZero(const double &i = 0) {
+ return -i;
+ }
+
+ void testFloatReference() {
+ clang_analyzer_eval(defaultFloatReference(1) == -1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(defaultFloatReference() == -42); // expected-warning{{UNKNOWN}}
+
+ clang_analyzer_eval(defaultFloatReferenceZero(1) == -1); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(defaultFloatReferenceZero() == 0); // expected-warning{{UNKNOWN}}
}
}