diff options
Diffstat (limited to 'lib/Analysis/BugReporter.cpp')
-rw-r--r-- | lib/Analysis/BugReporter.cpp | 641 |
1 files changed, 320 insertions, 321 deletions
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index e54a50078e..23ca53d6e9 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -53,7 +53,7 @@ static inline const Stmt* GetStmt(ProgramPoint P) { return SP->getStmt(); else if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) return BE->getSrc()->getTerminator(); - + return 0; } @@ -71,7 +71,7 @@ static const Stmt* GetPreviousStmt(const ExplodedNode* N) { for (N = GetPredecessorNode(N); N; N = GetPredecessorNode(N)) if (const Stmt *S = GetStmt(N->getLocation())) return S; - + return 0; } @@ -92,30 +92,30 @@ static const Stmt* GetNextStmt(const ExplodedNode* N) { default: break; } - + // Some expressions don't have locations. if (S->getLocStart().isInvalid()) continue; - + return S; } - + return 0; } static inline const Stmt* -GetCurrentOrPreviousStmt(const ExplodedNode* N) { +GetCurrentOrPreviousStmt(const ExplodedNode* N) { if (const Stmt *S = GetStmt(N->getLocation())) return S; - + return GetPreviousStmt(N); } - + static inline const Stmt* -GetCurrentOrNextStmt(const ExplodedNode* N) { +GetCurrentOrNextStmt(const ExplodedNode* N) { if (const Stmt *S = GetStmt(N->getLocation())) return S; - + return GetNextStmt(N); } @@ -132,63 +132,62 @@ class VISIBILITY_HIDDEN NodeMapClosure : public BugReport::NodeResolver { public: NodeMapClosure(NodeBackMap *m) : M(*m) {} ~NodeMapClosure() {} - + const ExplodedNode* getOriginalNode(const ExplodedNode* N) { NodeBackMap::iterator I = M.find(N); return I == M.end() ? 0 : I->second; } }; - + class VISIBILITY_HIDDEN PathDiagnosticBuilder : public BugReporterContext { BugReport *R; PathDiagnosticClient *PDC; llvm::OwningPtr<ParentMap> PM; NodeMapClosure NMC; -public: +public: PathDiagnosticBuilder(GRBugReporter &br, - BugReport *r, NodeBackMap *Backmap, + BugReport *r, NodeBackMap *Backmap, PathDiagnosticClient *pdc) : BugReporterContext(br), - R(r), PDC(pdc), NMC(Backmap) - { + R(r), PDC(pdc), NMC(Backmap) { addVisitor(R); } - + PathDiagnosticLocation ExecutionContinues(const ExplodedNode* N); - + PathDiagnosticLocation ExecutionContinues(llvm::raw_string_ostream& os, const ExplodedNode* N); - + ParentMap& getParentMap() { if (PM.get() == 0) PM.reset(new ParentMap(getCodeDecl().getBody())); return *PM.get(); } - + const Stmt *getParent(const Stmt *S) { return getParentMap().getParent(S); } - + virtual NodeMapClosure& getNodeResolver() { return NMC; } BugReport& getReport() { return *R; } PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S); - + PathDiagnosticLocation getEnclosingStmtLocation(const PathDiagnosticLocation &L) { if (const Stmt *S = L.asStmt()) return getEnclosingStmtLocation(S); - + return L; } - + PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const { return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive; } bool supportsLogicalOpControlFlow() const { return PDC ? PDC->supportsLogicalOpControlFlow() : true; - } + } }; } // end anonymous namespace @@ -197,10 +196,10 @@ PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode* N) { if (const Stmt *S = GetNextStmt(N)) return PathDiagnosticLocation(S, getSourceManager()); - return FullSourceLoc(N->getLocationContext()->getDecl()->getBodyRBrace(), + return FullSourceLoc(N->getLocationContext()->getDecl()->getBodyRBrace(), getSourceManager()); } - + PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os, const ExplodedNode* N) { @@ -208,9 +207,9 @@ PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os, // Slow, but probably doesn't matter. if (os.str().empty()) os << ' '; - + const PathDiagnosticLocation &Loc = ExecutionContinues(N); - + if (Loc.asStmt()) os << "Execution continues on line " << getSourceManager().getInstantiationLineNumber(Loc.asLocation()) @@ -219,16 +218,16 @@ PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream& os, os << "Execution jumps to the end of the " << (isa<ObjCMethodDecl>(N->getLocationContext()->getDecl()) ? "method" : "function") << '.'; - + return Loc; } static bool IsNested(const Stmt *S, ParentMap &PM) { if (isa<Expr>(S) && PM.isConsumedExpr(cast<Expr>(S))) return true; - + const Stmt *Parent = PM.getParentIgnoreParens(S); - + if (Parent) switch (Parent->getStmtClass()) { case Stmt::ForStmtClass: @@ -238,29 +237,29 @@ static bool IsNested(const Stmt *S, ParentMap &PM) { default: break; } - - return false; + + return false; } PathDiagnosticLocation PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { assert(S && "Null Stmt* passed to getEnclosingStmtLocation"); - ParentMap &P = getParentMap(); + ParentMap &P = getParentMap(); SourceManager &SMgr = getSourceManager(); while (IsNested(S, P)) { const Stmt *Parent = P.getParentIgnoreParens(S); - + if (!Parent) break; - + switch (Parent->getStmtClass()) { case Stmt::BinaryOperatorClass: { const BinaryOperator *B = cast<BinaryOperator>(Parent); if (B->isLogicalOp()) return PathDiagnosticLocation(S, SMgr); break; - } + } case Stmt::CompoundStmtClass: case Stmt::StmtExprClass: return PathDiagnosticLocation(S, SMgr); @@ -270,20 +269,20 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { if (cast<ChooseExpr>(Parent)->getCond() == S) return PathDiagnosticLocation(Parent, SMgr); else - return PathDiagnosticLocation(S, SMgr); + return PathDiagnosticLocation(S, SMgr); case Stmt::ConditionalOperatorClass: // For '?', if we are referring to condition, just have the edge point // to the entire '?' expression. if (cast<ConditionalOperator>(Parent)->getCond() == S) return PathDiagnosticLocation(Parent, SMgr); else - return PathDiagnosticLocation(S, SMgr); + return PathDiagnosticLocation(S, SMgr); case Stmt::DoStmtClass: - return PathDiagnosticLocation(S, SMgr); + return PathDiagnosticLocation(S, SMgr); case Stmt::ForStmtClass: if (cast<ForStmt>(Parent)->getBody() == S) - return PathDiagnosticLocation(S, SMgr); - break; + return PathDiagnosticLocation(S, SMgr); + break; case Stmt::IfStmtClass: if (cast<IfStmt>(Parent)->getCond() != S) return PathDiagnosticLocation(S, SMgr); @@ -302,7 +301,7 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { S = Parent; } - + assert(S && "Cannot have null Stmt for PathDiagnosticLocation"); // Special case: DeclStmts can appear in for statement declarations, in which @@ -315,8 +314,8 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { return PathDiagnosticLocation(Parent, SMgr); default: break; - } - } + } + } } else if (isa<BinaryOperator>(S)) { // Special case: the binary operator represents the initialization @@ -339,84 +338,84 @@ PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt *S) { static const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode* N, GRStateManager& VMgr, SVal X) { - + for ( ; N ; N = N->pred_empty() ? 0 : *N->pred_begin()) { - + ProgramPoint P = N->getLocation(); - + if (!isa<PostStmt>(P)) continue; - + const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(cast<PostStmt>(P).getStmt()); - + if (!DR) continue; - + SVal Y = N->getState()->getSVal(DR); - + if (X != Y) continue; - + const VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()); - + if (!VD) continue; - + return VD; } - + return 0; } namespace { -class VISIBILITY_HIDDEN NotableSymbolHandler +class VISIBILITY_HIDDEN NotableSymbolHandler : public StoreManager::BindingsHandler { - + SymbolRef Sym; const GRState* PrevSt; const Stmt* S; GRStateManager& VMgr; const ExplodedNode* Pred; - PathDiagnostic& PD; + PathDiagnostic& PD; BugReporter& BR; - + public: - + NotableSymbolHandler(SymbolRef sym, const GRState* prevst, const Stmt* s, GRStateManager& vmgr, const ExplodedNode* pred, PathDiagnostic& pd, BugReporter& br) : Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {} - + bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal V) { - + SymbolRef ScanSym = V.getAsSymbol(); - + if (ScanSym != Sym) return true; - - // Check if the previous state has this binding. + + // Check if the previous state has this binding. SVal X = PrevSt->getSVal(loc::MemRegionVal(R)); - + if (X == V) // Same binding? return true; - + // Different binding. Only handle assignments for now. We don't pull - // this check out of the loop because we will eventually handle other + // this check out of the loop because we will eventually handle other // cases. - + VarDecl *VD = 0; - + if (const BinaryOperator* B = dyn_cast<BinaryOperator>(S)) { if (!B->isAssignmentOp()) return true; - + // What variable did we assign to? DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts()); - + if (!DR) return true; - + VD = dyn_cast<VarDecl>(DR->getDecl()); } else if (const DeclStmt* DS = dyn_cast<DeclStmt>(S)) { @@ -425,28 +424,28 @@ public: // holds by contruction in the CFG. VD = dyn_cast<VarDecl>(*DS->decl_begin()); } - + if (!VD) return true; - + // What is the most recently referenced variable with this binding? const VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V); - + if (!MostRecent) return true; - + // Create the diagnostic. FullSourceLoc L(S->getLocStart(), BR.getSourceManager()); - + if (Loc::IsLocType(VD->getType())) { std::string msg = "'" + std::string(VD->getNameAsString()) + "' now aliases '" + MostRecent->getNameAsString() + "'"; - + PD.push_front(new PathDiagnosticEventPiece(L, msg)); } - + return true; - } + } }; } @@ -454,13 +453,13 @@ static void HandleNotableSymbol(const ExplodedNode* N, const Stmt* S, SymbolRef Sym, BugReporter& BR, PathDiagnostic& PD) { - + const ExplodedNode* Pred = N->pred_empty() ? 0 : *N->pred_begin(); const GRState* PrevSt = Pred ? Pred->getState() : 0; - + if (!PrevSt) return; - + // Look at the region bindings of the current state that map to the // specified symbol. Are any of them not in the previous state? GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager(); @@ -471,34 +470,34 @@ static void HandleNotableSymbol(const ExplodedNode* N, namespace { class VISIBILITY_HIDDEN ScanNotableSymbols : public StoreManager::BindingsHandler { - + llvm::SmallSet<SymbolRef, 10> AlreadyProcessed; const ExplodedNode* N; const Stmt* S; GRBugReporter& BR; PathDiagnostic& PD; - + public: ScanNotableSymbols(const ExplodedNode* n, const Stmt* s, GRBugReporter& br, PathDiagnostic& pd) : N(n), S(s), BR(br), PD(pd) {} - + bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal V) { - + SymbolRef ScanSym = V.getAsSymbol(); - + if (!ScanSym) return true; - + if (!BR.isNotable(ScanSym)) return true; - + if (AlreadyProcessed.count(ScanSym)) return true; - + AlreadyProcessed.insert(ScanSym); - + HandleNotableSymbol(N, S, ScanSym, BR, PD); return true; } @@ -516,54 +515,54 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, const ExplodedNode *N) { SourceManager& SMgr = PDB.getSourceManager(); - const ExplodedNode* NextNode = N->pred_empty() + const ExplodedNode* NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); while (NextNode) { - N = NextNode; + N = NextNode; NextNode = GetPredecessorNode(N); - + ProgramPoint P = N->getLocation(); - + if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) { CFGBlock* Src = BE->getSrc(); CFGBlock* Dst = BE->getDst(); Stmt* T = Src->getTerminator(); - + if (!T) continue; - + FullSourceLoc Start(T->getLocStart(), SMgr); - + switch (T->getStmtClass()) { default: break; - + case Stmt::GotoStmtClass: - case Stmt::IndirectGotoStmtClass: { + case Stmt::IndirectGotoStmtClass: { const Stmt* S = GetNextStmt(N); - + if (!S) continue; - + std::string sbuf; - llvm::raw_string_ostream os(sbuf); + llvm::raw_string_ostream os(sbuf); const PathDiagnosticLocation &End = PDB.getEnclosingStmtLocation(S); - + os << "Control jumps to line " << End.asLocation().getInstantiationLineNumber(); PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, os.str())); break; } - - case Stmt::SwitchStmtClass: { + + case Stmt::SwitchStmtClass: { // Figure out what case arm we took. std::string sbuf; llvm::raw_string_ostream os(sbuf); - + if (Stmt* S = Dst->getLabel()) { PathDiagnosticLocation End(S, SMgr); - + switch (S->getStmtClass()) { default: os << "No cases match in the switch statement. " @@ -574,21 +573,21 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, os << "Control jumps to the 'default' case at line " << End.asLocation().getInstantiationLineNumber(); break; - + case Stmt::CaseStmtClass: { - os << "Control jumps to 'case "; - CaseStmt* Case = cast<CaseStmt>(S); + os << "Control jumps to 'case "; + CaseStmt* Case = cast<CaseStmt>(S); Expr* LHS = Case->getLHS()->IgnoreParenCasts(); - - // Determine if it is an enum. + + // Determine if it is an enum. bool GetRawInt = true; - + if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) { // FIXME: Maybe this should be an assertion. Are there cases // were it is not an EnumConstantDecl? EnumConstantDecl* D = dyn_cast<EnumConstantDecl>(DR->getDecl()); - + if (D) { GetRawInt = false; os << D->getNameAsString(); @@ -608,14 +607,14 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, } else { os << "'Default' branch taken. "; - const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); + const PathDiagnosticLocation &End = PDB.ExecutionContinues(os, N); PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, os.str())); } - + break; } - + case Stmt::BreakStmtClass: case Stmt::ContinueStmtClass: { std::string sbuf; @@ -625,117 +624,117 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, os.str())); break; } - + // Determine control-flow for ternary '?'. case Stmt::ConditionalOperatorClass: { std::string sbuf; llvm::raw_string_ostream os(sbuf); os << "'?' condition is "; - + if (*(Src->succ_begin()+1) == Dst) os << "false"; else os << "true"; - + PathDiagnosticLocation End = PDB.ExecutionContinues(N); - + if (const Stmt *S = End.asStmt()) End = PDB.getEnclosingStmtLocation(S); - + PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, os.str())); break; } - + // Determine control-flow for short-circuited '&&' and '||'. case Stmt::BinaryOperatorClass: { if (!PDB.supportsLogicalOpControlFlow()) break; - + BinaryOperator *B = cast<BinaryOperator>(T); std::string sbuf; llvm::raw_string_ostream os(sbuf); os << "Left side of '"; - + if (B->getOpcode() == BinaryOperator::LAnd) { os << "&&" << "' is "; - + if (*(Src->succ_begin()+1) == Dst) { os << "false"; PathDiagnosticLocation End(B->getLHS(), SMgr); PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr); PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, os.str())); - } + } else { os << "true"; PathDiagnosticLocation Start(B->getLHS(), SMgr); PathDiagnosticLocation End = PDB.ExecutionContinues(N); PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, os.str())); - } + } } else { assert(B->getOpcode() == BinaryOperator::LOr); os << "||" << "' is "; - + if (*(Src->succ_begin()+1) == Dst) { os << "false"; PathDiagnosticLocation Start(B->getLHS(), SMgr); PathDiagnosticLocation End = PDB.ExecutionContinues(N); PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, - os.str())); + os.str())); } else { os << "true"; PathDiagnosticLocation End(B->getLHS(), SMgr); PathDiagnosticLocation Start(B->getOperatorLoc(), SMgr); PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, - os.str())); + os.str())); } } - + break; } - - case Stmt::DoStmtClass: { + + case Stmt::DoStmtClass: { if (*(Src->succ_begin()) == Dst) { std::string sbuf; llvm::raw_string_ostream os(sbuf); - + os << "Loop condition is true. "; PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); - + if (const Stmt *S = End.asStmt()) End = PDB.getEnclosingStmtLocation(S); - + PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, os.str())); } else { PathDiagnosticLocation End = PDB.ExecutionContinues(N); - + if (const Stmt *S = End.asStmt()) End = PDB.getEnclosingStmtLocation(S); - + PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, "Loop condition is false. Exiting loop")); } - + break; } - + case Stmt::WhileStmtClass: - case Stmt::ForStmtClass: { + case Stmt::ForStmtClass: { if (*(Src->succ_begin()+1) == Dst) { std::string sbuf; llvm::raw_string_ostream os(sbuf); - + os << "Loop condition is false. "; PathDiagnosticLocation End = PDB.ExecutionContinues(os, N); if (const Stmt *S = End.asStmt()) End = PDB.getEnclosingStmtLocation(S); - + PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, os.str())); } @@ -743,32 +742,32 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, PathDiagnosticLocation End = PDB.ExecutionContinues(N); if (const Stmt *S = End.asStmt()) End = PDB.getEnclosingStmtLocation(S); - + PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, "Loop condition is true. Entering loop body")); } - + break; } - + case Stmt::IfStmtClass: { PathDiagnosticLocation End = PDB.ExecutionContinues(N); - + if (const Stmt *S = End.asStmt()) End = PDB.getEnclosingStmtLocation(S); - + if (*(Src->succ_begin()+1) == Dst) PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, "Taking false branch")); - else + else PD.push_front(new PathDiagnosticControlFlowPiece(Start, End, "Taking true branch")); - + break; } } } - + if (NextNode) { for (BugReporterContext::visitor_iterator I = PDB.visitor_begin(), E = PDB.visitor_end(); I!=E; ++I) { @@ -776,15 +775,15 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, PD.push_front(p); } } - - if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) { + + if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) { // Scan the region bindings, and see if a "notable" symbol has a new // lval binding. ScanNotableSymbols SNS(N, PS->getStmt(), PDB.getBugReporter(), PD); PDB.getStateManager().iterBindings(N->getState(), SNS); } } - + // After constructing the full PathDiagnostic, do a pass over it to compact // PathDiagnosticPieces that occur within a macro. CompactPathDiagnostic(PD, PDB.getSourceManager()); @@ -796,20 +795,20 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, static bool IsControlFlowExpr(const Stmt *S) { const Expr *E = dyn_cast<Expr>(S); - + if (!E) return false; - - E = E->IgnoreParenCasts(); - + + E = E->IgnoreParenCasts(); + if (isa<ConditionalOperator>(E)) return true; - + if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) if (B->isLogicalOp()) return true; - - return false; + + return false; } namespace { @@ -818,25 +817,25 @@ class VISIBILITY_HIDDEN ContextLocation : public PathDiagnosticLocation { public: ContextLocation(const PathDiagnosticLocation &L, bool isdead = false) : PathDiagnosticLocation(L), IsDead(isdead) {} - - void markDead() { IsDead = true; } + + void markDead() { IsDead = true; } bool isDead() const { return IsDead; } }; - + class VISIBILITY_HIDDEN EdgeBuilder { std::vector<ContextLocation> CLocs; typedef std::vector<ContextLocation>::iterator iterator; PathDiagnostic &PD; PathDiagnosticBuilder &PDB; PathDiagnosticLocation PrevLoc; - + bool IsConsumedExpr(const PathDiagnosticLocation &L); - + bool containsLocation(const PathDiagnosticLocation &Container, const PathDiagnosticLocation &Containee); - + PathDiagnosticLocation getContextLocation(const PathDiagnosticLocation &L); - + PathDiagnosticLocation cleanUpLocation(PathDiagnosticLocation L, bool firstCharOnly = false) { if (const Stmt *S = L.asStmt()) { @@ -864,20 +863,20 @@ class VISIBILITY_HIDDEN EdgeBuilder { firstCharOnly = true; continue; } - + break; } - + if (S != Original) L = PathDiagnosticLocation(S, L.getManager()); } - + if (firstCharOnly) L = PathDiagnosticLocation(L.asLocation()); return L; } - + void popLocation() { if (!CLocs.back().isDead() && CLocs.back().asLocation().isFileID()) { // For contexts, we only one the first character as the range. @@ -885,18 +884,18 @@ class VISIBILITY_HIDDEN EdgeBuilder { } CLocs.pop_back(); } - - PathDiagnosticLocation IgnoreParens(const PathDiagnosticLocation &L); + + PathDiagnosticLocation IgnoreParens(const PathDiagnosticLocation &L); public: EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb) : PD(pd), PDB(pdb) { - + // If the PathDiagnostic already has pieces, add the enclosing statement // of the first piece as a context as well. if (!PD.empty()) { PrevLoc = PD.begin()->getLocation(); - + if (const Stmt *S = PrevLoc.asStmt()) addExtendedContext(PDB.getEnclosingStmtLocation(S).asStmt()); } @@ -904,7 +903,7 @@ public: ~EdgeBuilder() { while (!CLocs.empty()) popLocation(); - + // Finally, add an initial edge from the start location of the first // statement (if it doesn't already exist). // FIXME: Should handle CXXTryStmt if analyser starts supporting C++. @@ -914,20 +913,20 @@ public: SourceLocation Loc = (*CS->body_begin())->getLocStart(); rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager())); } - + } void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false); - + void addEdge(const Stmt *S, bool alwaysAdd = false) { addEdge(PathDiagnosticLocation(S, PDB.getSourceManager()), alwaysAdd); } - + void rawAddEdge(PathDiagnosticLocation NewLoc); - + void addContext(const Stmt *S); void addExtendedContext(const Stmt *S); -}; +}; } // end anonymous namespace @@ -936,10 +935,10 @@ EdgeBuilder::getContextLocation(const PathDiagnosticLocation &L) { if (const Stmt *S = L.asStmt()) { if (IsControlFlowExpr(S)) return L; - - return PDB.getEnclosingStmtLocation(S); + + return PDB.getEnclosingStmtLocation(S); } - + return L; } @@ -948,10 +947,10 @@ bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, if (Container == Containee) return true; - + if (Container.asDecl()) return true; - + if (const Stmt *S = Containee.asStmt()) if (const Stmt *ContainerS = Container.asStmt()) { while (S) { @@ -965,25 +964,25 @@ bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container, // Less accurate: compare using source ranges. SourceRange ContainerR = Container.asRange(); SourceRange ContaineeR = Containee.asRange(); - + SourceManager &SM = PDB.getSourceManager(); SourceLocation ContainerRBeg = SM.getInstantiationLoc(ContainerR.getBegin()); SourceLocation ContainerREnd = SM.getInstantiationLoc(ContainerR.getEnd()); SourceLocation ContaineeRBeg = SM.getInstantiationLoc(ContaineeR.getBegin()); SourceLocation ContaineeREnd = SM.getInstantiationLoc(ContaineeR.getEnd()); - + unsigned ContainerBegLine = SM.getInstantiationLineNumber(ContainerRBeg); unsigned ContainerEndLine = SM.getInstantiationLineNumber(ContainerREnd); unsigned ContaineeBegLine = SM.getInstantiationLineNumber(ContaineeRBeg); unsigned ContaineeEndLine = SM.getInstantiationLineNumber(ContaineeREnd); - + assert(ContainerBegLine <= ContainerEndLine); - assert(ContaineeBegLine <= ContaineeEndLine); - + assert(ContaineeBegLine <= ContaineeEndLine); + return (ContainerBegLine <= ContaineeBegLine && ContainerEndLine >= ContaineeEndLine && (ContainerBegLine != ContaineeBegLine || - SM.getInstantiationColumnNumber(ContainerRBeg) <= + SM.getInstantiationColumnNumber(ContainerRBeg) <= SM.getInstantiationColumnNumber(ContaineeRBeg)) && (ContainerEndLine != ContaineeEndLine || SM.getInstantiationColumnNumber(ContainerREnd) >= @@ -1003,13 +1002,13 @@ void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { PrevLoc = NewLoc; return; } - + const PathDiagnosticLocation &NewLocClean = cleanUpLocation(NewLoc); const PathDiagnosticLocation &PrevLocClean = cleanUpLocation(PrevLoc); - + if (NewLocClean.asLocation() == PrevLocClean.asLocation()) return; - + // FIXME: Ignore intra-macro edges for now. if (NewLocClean.asLocation().getInstantiationLoc() == PrevLocClean.asLocation().getInstantiationLoc()) @@ -1020,15 +1019,15 @@ void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) { } void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { - + if (!alwaysAdd && NewLoc.asLocation().isMacroID()) return; - + const PathDiagnosticLocation &CLoc = getContextLocation(NewLoc); while (!CLocs.empty()) { ContextLocation &TopContextLoc = CLocs.back(); - + // Is the top location context the same as the one for the new location? if (TopContextLoc == CLoc) { if (alwaysAdd) { @@ -1045,21 +1044,21 @@ void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { if (containsLocation(TopContextLoc, CLoc)) { if (alwaysAdd) { rawAddEdge(NewLoc); - + if (IsConsumedExpr(CLoc) && !IsControlFlowExpr(CLoc.asStmt())) { CLocs.push_back(ContextLocation(CLoc, true)); return; } } - + CLocs.push_back(CLoc); - return; + return; } // Context does not contain the location. Flush it. popLocation(); } - + // If we reach here, there is no enclosing context. Just add the edge. rawAddEdge(NewLoc); } @@ -1067,15 +1066,15 @@ void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd) { bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation &L) { if (const Expr *X = dyn_cast_or_null<Expr>(L.asStmt())) return PDB.getParentMap().isConsumedExpr(X) && !IsControlFlowExpr(X); - + return false; } - + void EdgeBuilder::addExtendedContext(const Stmt *S) { if (!S) return; - - const Stmt *Parent = PDB.getParent(S); + + const Stmt *Parent = PDB.getParent(S); while (Parent) { if (isa<CompoundStmt>(Parent)) Parent = PDB.getParent(Parent); @@ -1092,16 +1091,16 @@ void EdgeBuilder::addExtendedContext(const Stmt *S) { break; } } - + addContext(S); } - + void EdgeBuilder::addContext(const Stmt *S) { if (!S) return; PathDiagnosticLocation L(S, PDB.getSourceManager()); - + while (!CLocs.empty()) { const PathDiagnosticLocation &TopContextLoc = CLocs.back(); @@ -1111,7 +1110,7 @@ void EdgeBuilder::addContext(const Stmt *S) { if (containsLocation(TopContextLoc, L)) { CLocs.push_back(L); - return; + return; } // Context does not contain the location. Flush it. @@ -1124,11 +1123,11 @@ void EdgeBuilder::addContext(const Stmt *S) { static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N) { - - + + EdgeBuilder EB(PD, PDB); - const ExplodedNode* NextNode = N->pred_empty() + const ExplodedNode* NextNode = N->pred_empty() ? NULL : *(N->pred_begin()); while (NextNode) { N = NextNode; @@ -1140,26 +1139,26 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { const CFGBlock &Blk = *BE->getSrc(); const Stmt *Term = Blk.getTerminator(); - + // Are we jumping to the head of a loop? Add a special diagnostic. if (const Stmt *Loop = BE->getDst()->getLoopTarget()) { PathDiagnosticLocation L(Loop, PDB.getSourceManager()); const CompoundStmt *CS = NULL; - + if (!Term) { |