diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Analysis/CFG.cpp | 75 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 61 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 10 |
3 files changed, 108 insertions, 38 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index cd0ff0a4922..1cbaaee4a1c 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -233,6 +233,43 @@ public: } }; +class reverse_children { + llvm::SmallVector<Stmt *, 12> childrenBuf; + ArrayRef<Stmt*> children; +public: + reverse_children(Stmt *S); + + typedef ArrayRef<Stmt*>::reverse_iterator iterator; + iterator begin() const { return children.rbegin(); } + iterator end() const { return children.rend(); } +}; + + +reverse_children::reverse_children(Stmt *S) { + if (CallExpr *CE = dyn_cast<CallExpr>(S)) { + children = CE->getRawSubExprs(); + return; + } + switch (S->getStmtClass()) { + case Stmt::InitListExprClass: { + InitListExpr *IE = cast<InitListExpr>(S); + children = llvm::makeArrayRef(reinterpret_cast<Stmt**>(IE->getInits()), + IE->getNumInits()); + return; + } + default: + break; + } + + // Default case for all other statements. + for (Stmt::child_range I = S->children(); I; ++I) { + childrenBuf.push_back(*I); + } + + // This needs to be done *after* childrenBuf has been populated. + children = childrenBuf; +} + /// CFGBuilder - This class implements CFG construction from an AST. /// The builder is stateful: an instance of the builder should be used to only /// construct a single CFG. @@ -1166,14 +1203,19 @@ CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { } /// VisitChildren - Visit the children of a Stmt. -CFGBlock *CFGBuilder::VisitChildren(Stmt *Terminator) { - CFGBlock *lastBlock = Block; - for (Stmt::child_range I = Terminator->children(); I; ++I) - if (Stmt *child = *I) - if (CFGBlock *b = Visit(child)) - lastBlock = b; +CFGBlock *CFGBuilder::VisitChildren(Stmt *S) { + CFGBlock *B = Block; - return lastBlock; + // Visit the children in their reverse order so that they appear in + // left-to-right (natural) order in the CFG. + reverse_children RChildren(S); + for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end(); + I != E; ++I) { + if (Stmt *Child = *I) + if (CFGBlock *R = Visit(Child)) + B = R; + } + return B; } CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, @@ -3093,19 +3135,14 @@ tryAgain: CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E) { // When visiting children for destructors we want to visit them in reverse - // order. Because there's no reverse iterator for children must to reverse - // them in helper vector. - typedef SmallVector<Stmt *, 4> ChildrenVect; - ChildrenVect ChildrenRev; - for (Stmt::child_range I = E->children(); I; ++I) { - if (*I) ChildrenRev.push_back(*I); - } - + // order that they will appear in the CFG. Because the CFG is built + // bottom-up, this means we visit them in their natural order, which + // reverses them in the CFG. CFGBlock *B = Block; - for (ChildrenVect::reverse_iterator I = ChildrenRev.rbegin(), - L = ChildrenRev.rend(); I != L; ++I) { - if (CFGBlock *R = VisitForTemporaryDtors(*I)) - B = R; + for (Stmt::child_range I = E->children(); I; ++I) { + if (Stmt *Child = *I) + if (CFGBlock *R = VisitForTemporaryDtors(Child)) + B = R; } return B; } diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 3aa351527f3..17dd772a688 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -433,42 +433,65 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, llvm::raw_svector_ostream os(sbuf); if (const PostStmt *PS = StoreSite->getLocationAs<PostStmt>()) { - if (const DeclStmt *DS = PS->getStmtAs<DeclStmt>()) { - - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { - os << "Variable '" << *VR->getDecl() << "' "; + const Stmt *S = PS->getStmt(); + const char *action = 0; + const DeclStmt *DS = dyn_cast<DeclStmt>(S); + const VarRegion *VR = dyn_cast<VarRegion>(R); + + if (DS) { + action = "initialized to "; + } else if (isa<BlockExpr>(S)) { + action = "captured by block as "; + if (VR) { + // See if we can get the BlockVarRegion. + ProgramStateRef State = StoreSite->getState(); + SVal V = State->getSVal(S, PS->getLocationContext()); + if (const BlockDataRegion *BDR = + dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { + if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) { + V = State->getSVal(OriginalR); + BR.addVisitor(new FindLastStoreBRVisitor(V, OriginalR)); + } + } } - else - return NULL; + } + + if (action) { + if (!R) + return 0; + + os << "Variable '" << *VR->getDecl() << "' "; if (isa<loc::ConcreteInt>(V)) { bool b = false; if (R->isBoundable()) { if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { if (TR->getValueType()->isObjCObjectPointerType()) { - os << "initialized to nil"; + os << action << "nil"; b = true; } } } if (!b) - os << "initialized to a null pointer value"; + os << action << "a null pointer value"; } else if (isa<nonloc::ConcreteInt>(V)) { - os << "initialized to " << cast<nonloc::ConcreteInt>(V).getValue(); + os << action << cast<nonloc::ConcreteInt>(V).getValue(); } - else if (V.isUndef()) { - if (isa<VarRegion>(R)) { - const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); - if (VD->getInit()) - os << "initialized to a garbage value"; - else - os << "declared without an initial value"; + else if (DS) { + if (V.isUndef()) { + if (isa<VarRegion>(R)) { + const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); + if (VD->getInit()) + os << "initialized to a garbage value"; + else + os << "declared without an initial value"; + } + } + else { + os << "initialized here"; } - } - else { - os << "initialized here"; } } } else if (isa<CallEnter>(StoreSite->getLocation())) { diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 70bb9658593..687c7c0188a 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -1302,3 +1302,13 @@ BlockDataRegion::referenced_vars_end() const { return BlockDataRegion::referenced_vars_iterator(Vec->end(), VecOriginal->end()); } + +const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const { + for (referenced_vars_iterator I = referenced_vars_begin(), + E = referenced_vars_end(); + I != E; ++I) { + if (I.getCapturedRegion() == R) + return I.getOriginalRegion(); + } + return 0; +} |

