diff options
author | Anna Zaks <ganna@apple.com> | 2012-04-10 20:59:00 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-04-10 20:59:00 +0000 |
commit | e19f86edab8fb3c2c1e99e0e9815b6058504df9b (patch) | |
tree | 3e14d3f8e1a6d36ad4eb676d7f98bf79935a7e1e /lib/StaticAnalyzer/Core/ExprEngineC.cpp | |
parent | 4335a48214dcbb258e08c8867c45648e25edb2ec (diff) |
[analyzer] Add support for C++ dynamic_cast.
Simulate the C++ dynamic_cast in the analyzer.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154434 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 5ec3bc749e..5070e9d111 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -283,8 +283,50 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, Bldr.generateNode(CastE, Pred, state); continue; } - // Various C++ casts that are not handled yet. - case CK_Dynamic: + // Handle C++ dyn_cast. + case CK_Dynamic: { + ProgramStateRef state = Pred->getState(); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal val = state->getSVal(Ex, LCtx); + + // Compute the type of the result. + QualType resultType = CastE->getType(); + if (CastE->isLValue()) + resultType = getContext().getPointerType(resultType); + + bool Failed = false; + + // Check if the value being cast evaluates to 0. + if (val.isZeroConstant()) + Failed = true; + // Else, evaluate the cast. + else + val = getStoreManager().evalDynamicCast(val, T, Failed); + + if (Failed) { + // If the cast fails, conjure symbol constrained to 0. + DefinedOrUnknownSVal NewSym = svalBuilder.getConjuredSymbolVal(NULL, + CastE, LCtx, resultType, + currentBuilderContext->getCurrentBlockCount()); + DefinedOrUnknownSVal Constraint = svalBuilder.evalEQ(state, + NewSym, svalBuilder.makeZeroVal(resultType)); + state = state->assume(Constraint, true); + state = state->BindExpr(CastE, LCtx, NewSym); + } else { + // If we don't know if the cast succeeded, conjure a new symbol. + if (val.isUnknown()) { + DefinedOrUnknownSVal NewSym = svalBuilder.getConjuredSymbolVal(NULL, + CastE, LCtx, resultType, + currentBuilderContext->getCurrentBlockCount()); + state = state->BindExpr(CastE, LCtx, NewSym); + } else + // Else, bind to the derived region value. + state = state->BindExpr(CastE, LCtx, val); + } + Bldr.generateNode(CastE, Pred, state); + continue; + } + // Various C++ casts that are not handled yet. case CK_ToUnion: case CK_BaseToDerived: case CK_NullToMemberPointer: @@ -300,9 +342,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, if (CastE->isLValue()) resultType = getContext().getPointerType(resultType); const LocationContext *LCtx = Pred->getLocationContext(); - SVal result = - svalBuilder.getConjuredSymbolVal(NULL, CastE, LCtx, resultType, - currentBuilderContext->getCurrentBlockCount()); + SVal result = svalBuilder.getConjuredSymbolVal(NULL, CastE, LCtx, + resultType, currentBuilderContext->getCurrentBlockCount()); ProgramStateRef state = Pred->getState()->BindExpr(CastE, LCtx, result); Bldr.generateNode(CastE, Pred, state); |