diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Analysis/CFG.cpp | 11 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CoreEngine.cpp | 13 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 20 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 15 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SValBuilder.cpp | 37 |
5 files changed, 82 insertions, 14 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index f50cc31e9d..e19381dcd8 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -2620,9 +2620,18 @@ CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) { CFGBlock *CatchBlock = Block; if (!CatchBlock) CatchBlock = createBlock(); - + + // CXXCatchStmt is more than just a label. They have semantic meaning + // as well, as they implicitly "initialize" the catch variable. Add + // it to the CFG as a CFGElement so that the control-flow of these + // semantics gets captured. + appendStmt(CatchBlock, CS); + + // Also add the CXXCatchStmt as a label, to mirror handling of regular + // labels. CatchBlock->setLabel(CS); + // Bail out if the CFG is bad. if (badCFG) return 0; diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index a350757a0f..326ecbfbfb 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -335,6 +335,19 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred); return; + case Stmt::CXXTryStmtClass: { + // Generate a node for each of the successors. + // Our logic for EH analysis can certainly be improved. + for (CFGBlock::const_succ_iterator it = B->succ_begin(), + et = B->succ_end(); it != et; ++it) { + if (const CFGBlock *succ = *it) { + generateNode(BlockEdge(B, succ, Pred->getLocationContext()), + Pred->State, Pred); + } + } + return; + } + case Stmt::DoStmtClass: HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred); return; diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 63027175ca..d9f9839444 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -23,6 +23,7 @@ #include "clang/AST/CharUnits.h" #include "clang/AST/ParentMap.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtCXX.h" #include "clang/AST/DeclCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" @@ -481,10 +482,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, switch (S->getStmtClass()) { // C++ and ARC stuff we don't support yet. case Expr::ObjCIndirectCopyRestoreExprClass: - case Stmt::CXXCatchStmtClass: case Stmt::CXXDependentScopeMemberExprClass: case Stmt::CXXPseudoDestructorExprClass: - case Stmt::CXXThrowExprClass: case Stmt::CXXTryStmtClass: case Stmt::CXXTypeidExprClass: case Stmt::CXXUuidofExprClass: @@ -505,7 +504,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::SEHExceptStmtClass: case Stmt::LambdaExprClass: case Stmt::SEHFinallyStmtClass: { - const ExplodedNode *node = Bldr.generateNode(S, Pred, Pred->getState()); + const ExplodedNode *node = Bldr.generateNode(S, Pred, Pred->getState(), + /* sink */ true); Engine.addAbortedBlock(node, currentBuilderContext->getBlock()); break; } @@ -600,8 +600,13 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OpaqueValueExprClass: case Stmt::AsTypeExprClass: case Stmt::AtomicExprClass: - // Fall through. + // Fall through. + // Currently all handling of 'throw' just falls to the CFG. We + // can consider doing more if necessary. + case Stmt::CXXThrowExprClass: + // Fall through. + // Cases we intentionally don't evaluate, since they don't need // to be explicitly evaluated. case Stmt::AddrLabelExprClass: @@ -720,6 +725,13 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, Bldr.addNodes(Dst); break; } + + case Stmt::CXXCatchStmtClass: { + Bldr.takeNodes(Pred); + VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst); + Bldr.addNodes(Dst); + break; + } case Stmt::CXXTemporaryObjectExprClass: case Stmt::CXXConstructExprClass: { diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index fa0245145c..72ab48ec00 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -16,6 +16,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/StmtCXX.h" using namespace clang; using namespace ento; @@ -340,6 +341,20 @@ void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, Bldr.generateNode(CDE, Pred, state); } +void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS, + ExplodedNode *Pred, + ExplodedNodeSet &Dst) { + const VarDecl *VD = CS->getExceptionDecl(); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal V = svalBuilder.getConjuredSymbolVal(CS, LCtx, VD->getType(), + currentBuilderContext->getCurrentBlockCount()); + ProgramStateRef state = Pred->getState(); + state = state->bindLoc(state->getLValue(VD, LCtx), V); + + StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); + Bldr.generateNode(CS, Pred, state); +} + void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 6f5eb375f4..9e97f5e7d1 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -106,19 +106,21 @@ SValBuilder::getRegionValueSymbolVal(const TypedValueRegion* region) { return nonloc::SymbolVal(sym); } -DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *symbolTag, - const Expr *expr, - const LocationContext *LCtx, - unsigned count) { +DefinedOrUnknownSVal +SValBuilder::getConjuredSymbolVal(const void *symbolTag, + const Expr *expr, + const LocationContext *LCtx, + unsigned count) { QualType T = expr->getType(); return getConjuredSymbolVal(symbolTag, expr, LCtx, T, count); } -DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *symbolTag, - const Expr *expr, - const LocationContext *LCtx, - QualType type, - unsigned count) { +DefinedOrUnknownSVal +SValBuilder::getConjuredSymbolVal(const void *symbolTag, + const Expr *expr, + const LocationContext *LCtx, + QualType type, + unsigned count) { if (!SymbolManager::canSymbolicate(type)) return UnknownVal(); @@ -130,6 +132,23 @@ DefinedOrUnknownSVal SValBuilder::getConjuredSymbolVal(const void *symbolTag, return nonloc::SymbolVal(sym); } + +DefinedOrUnknownSVal +SValBuilder::getConjuredSymbolVal(const Stmt *stmt, + const LocationContext *LCtx, + QualType type, + unsigned visitCount) { + if (!SymbolManager::canSymbolicate(type)) + return UnknownVal(); + + SymbolRef sym = SymMgr.getConjuredSymbol(stmt, LCtx, type, visitCount); + + if (Loc::isLocType(type)) + return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); + + return nonloc::SymbolVal(sym); +} + DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag, const MemRegion *region, const Expr *expr, QualType type, |