aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngineC.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-04-10 20:59:00 +0000
committerAnna Zaks <ganna@apple.com>2012-04-10 20:59:00 +0000
commite19f86edab8fb3c2c1e99e0e9815b6058504df9b (patch)
tree3e14d3f8e1a6d36ad4eb676d7f98bf79935a7e1e /lib/StaticAnalyzer/Core/ExprEngineC.cpp
parent4335a48214dcbb258e08c8867c45648e25edb2ec (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.cpp51
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);