diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-02-26 01:21:27 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-02-26 01:21:27 +0000 |
commit | 861a174018bb7c68076a4d2df241186fb0331d70 (patch) | |
tree | c174a24040f9f1838dc8778c82793fac0e8b5a41 | |
parent | c948709cda56a76cea07357db29c288235baa0ba (diff) | |
download | bcm5719-llvm-861a174018bb7c68076a4d2df241186fb0331d70.tar.gz bcm5719-llvm-861a174018bb7c68076a4d2df241186fb0331d70.zip |
[analyzer] Don't look through casts when creating pointer temporaries.
Normally, we need to look through derived-to-base casts when creating
temporary object regions (added in r175854). However, if the temporary
is a pointer (rather than a struct/class instance), we need to /preserve/
the base casts that have been applied.
This also ensures that we really do create a new temporary region when
we need to: MaterializeTemporaryExpr and lvalue CXXDefaultArgExprs.
Fixes PR15342, although the test case doesn't include the crash because
I couldn't isolate it.
llvm-svn: 176069
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 19 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 13 | ||||
-rw-r--r-- | clang/test/Analysis/temporaries.cpp | 14 |
3 files changed, 34 insertions, 12 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 8b6de132497..437af86ccfc 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -182,14 +182,16 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State, // bindings for a base type. Start by stripping and recording base casts. SmallVector<const CastExpr *, 4> Casts; const Expr *Inner = Ex->IgnoreParens(); - while (const CastExpr *CE = dyn_cast<CastExpr>(Inner)) { - if (CE->getCastKind() == CK_DerivedToBase || - CE->getCastKind() == CK_UncheckedDerivedToBase) - Casts.push_back(CE); - else if (CE->getCastKind() != CK_NoOp) - break; + if (V.getAs<NonLoc>()) { + while (const CastExpr *CE = dyn_cast<CastExpr>(Inner)) { + if (CE->getCastKind() == CK_DerivedToBase || + CE->getCastKind() == CK_UncheckedDerivedToBase) + Casts.push_back(CE); + else if (CE->getCastKind() != CK_NoOp) + break; - Inner = CE->getSubExpr()->IgnoreParens(); + Inner = CE->getSubExpr()->IgnoreParens(); + } } // Create a temporary object region for the inner expression (which may have @@ -703,7 +705,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, State = State->BindExpr(DefaultE, LCtx, V); if (DefaultE->isGLValue()) - State = createTemporaryRegionIfNeeded(State, LCtx, DefaultE); + State = createTemporaryRegionIfNeeded(State, LCtx, DefaultE, + DefaultE); Bldr2.generateNode(S, *I, State); } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index e7d59ebf576..32b522cbd5b 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -34,12 +34,17 @@ void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, // If the value is already a CXXTempObjectRegion, it is fine as it is. // Otherwise, create a new CXXTempObjectRegion, and copy the value into it. + // This is an optimization for when an rvalue is constructed and then + // immediately materialized. const MemRegion *MR = V.getAsRegion(); - if (MR && isa<CXXTempObjectRegion>(MR)) - state = state->BindExpr(ME, LCtx, V); - else - state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME); + if (const CXXTempObjectRegion *TR = + dyn_cast_or_null<CXXTempObjectRegion>(MR)) { + if (getContext().hasSameUnqualifiedType(TR->getValueType(), ME->getType())) + state = state->BindExpr(ME, LCtx, V); + } + if (state == Pred->getState()) + state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME); Bldr.generateNode(ME, Pred, state); } diff --git a/clang/test/Analysis/temporaries.cpp b/clang/test/Analysis/temporaries.cpp index 8c4e33b1793..32a4d3bef46 100644 --- a/clang/test/Analysis/temporaries.cpp +++ b/clang/test/Analysis/temporaries.cpp @@ -62,3 +62,17 @@ namespace rdar13265460 { } } +namespace rdar13281951 { + struct Derived : public Trivial { + Derived(int value) : Trivial(value), value2(-value) {} + int value2; + }; + + void test() { + Derived obj(1); + obj.value = 42; + const Trivial * const &pointerRef = &obj; + clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}} + } +} + |