[analyzer] Don't try to evaluate MaterializeTemporaryExpr as a constant.
...and don't consider '0' to be a null pointer constant if it's the initializer for a float! Apparently null pointer constant evaluation looks through both MaterializeTemporaryExpr and ImplicitCastExpr, so we have to be more careful about types in the callers. For RegionStore this just means giving up a little more; for ExprEngine this means handling the MaterializeTemporaryExpr case explicitly. Follow-up to r180894. llvm-svn: 180944
This commit is contained in:
parent
f380515753
commit
c76d7e3d96
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue