diff options
author | Gabor Horvath <xazax.hun@gmail.com> | 2016-08-08 09:22:59 +0000 |
---|---|---|
committer | Gabor Horvath <xazax.hun@gmail.com> | 2016-08-08 09:22:59 +0000 |
commit | 44583ce65a81c4e6e4e629d259e9e2851c0c6e6e (patch) | |
tree | 6ad1d0715baa7d4fb8d032eb2dbb35204aaea89d /clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | |
parent | 2ab623b5a31db5fecb08f822cc59433cfb7ccb58 (diff) | |
download | bcm5719-llvm-44583ce65a81c4e6e4e629d259e9e2851c0c6e6e.tar.gz bcm5719-llvm-44583ce65a81c4e6e4e629d259e9e2851c0c6e6e.zip |
[analyzer] Model base to derived casts more precisely.
Dynamic casts are handled relatively well by the static analyzer.
BaseToDerived casts however are treated conservatively. This can cause some
false positives with the NewDeleteLeaks checker.
This patch alters the behavior of BaseToDerived casts. In case a dynamic cast
would succeed use the same semantics. Otherwise fall back to the conservative
approach.
Differential Revision: https://reviews.llvm.org/D23014
llvm-svn: 277989
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 542399d4bcb..0f40739e1fc 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -386,7 +386,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, Failed = true; // Else, evaluate the cast. else - val = getStoreManager().evalDynamicCast(val, T, Failed); + val = getStoreManager().attemptDownCast(val, T, Failed); if (Failed) { if (T->isReferenceType()) { @@ -412,6 +412,28 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, Bldr.generateNode(CastE, Pred, state); continue; } + case CK_BaseToDerived: { + SVal val = state->getSVal(Ex, LCtx); + QualType resultType = CastE->getType(); + if (CastE->isGLValue()) + resultType = getContext().getPointerType(resultType); + + bool Failed = false; + + if (!val.isConstant()) { + val = getStoreManager().attemptDownCast(val, T, Failed); + } + + // Failed to cast or the result is unknown, fall back to conservative. + if (Failed || val.isUnknown()) { + val = + svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, + currBldrCtx->blockCount()); + } + state = state->BindExpr(CastE, LCtx, val); + Bldr.generateNode(CastE, Pred, state); + continue; + } case CK_NullToMemberPointer: { // FIXME: For now, member pointers are represented by void *. SVal V = svalBuilder.makeNull(); @@ -421,7 +443,6 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, } // Various C++ casts that are not handled yet. case CK_ToUnion: - case CK_BaseToDerived: case CK_BaseToDerivedMemberPointer: case CK_DerivedToBaseMemberPointer: case CK_ReinterpretMemberPointer: |