1 // BugReporter.cpp - Generate PathDiagnostics for Bugs ------------*- C++ -*--//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines BugReporter, a utility class for generating
13 //===----------------------------------------------------------------------===//
15 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
16 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
18 #include "clang/AST/ASTContext.h"
19 #include "clang/Analysis/CFG.h"
20 #include "clang/AST/DeclObjC.h"
21 #include "clang/AST/Expr.h"
22 #include "clang/AST/ParentMap.h"
23 #include "clang/AST/StmtObjC.h"
24 #include "clang/Basic/SourceManager.h"
25 #include "clang/Analysis/ProgramPoint.h"
26 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/ADT/DenseMap.h"
29 #include "llvm/ADT/SmallString.h"
30 #include "llvm/ADT/STLExtras.h"
31 #include "llvm/ADT/OwningPtr.h"
32 #include "llvm/ADT/IntrusiveRefCntPtr.h"
35 using namespace clang
;
38 BugReporterVisitor::~BugReporterVisitor() {}
40 void BugReporterContext::anchor() {}
42 //===----------------------------------------------------------------------===//
43 // Helper routines for walking the ExplodedGraph and fetching statements.
44 //===----------------------------------------------------------------------===//
46 static inline const Stmt
*GetStmt(const ProgramPoint
&P
) {
47 if (const StmtPoint
* SP
= dyn_cast
<StmtPoint
>(&P
))
49 else if (const BlockEdge
*BE
= dyn_cast
<BlockEdge
>(&P
))
50 return BE
->getSrc()->getTerminator();
51 else if (const CallEnter
*CE
= dyn_cast
<CallEnter
>(&P
))
52 return CE
->getCallExpr();
53 else if (const CallExitEnd
*CEE
= dyn_cast
<CallExitEnd
>(&P
))
54 return CEE
->getCalleeContext()->getCallSite();
59 static inline const ExplodedNode
*
60 GetPredecessorNode(const ExplodedNode
*N
) {
61 return N
->pred_empty() ? NULL
: *(N
->pred_begin());
64 static inline const ExplodedNode
*
65 GetSuccessorNode(const ExplodedNode
*N
) {
66 return N
->succ_empty() ? NULL
: *(N
->succ_begin());
69 static const Stmt
*GetPreviousStmt(const ExplodedNode
*N
) {
70 for (N
= GetPredecessorNode(N
); N
; N
= GetPredecessorNode(N
))
71 if (const Stmt
*S
= GetStmt(N
->getLocation()))
77 static const Stmt
*GetNextStmt(const ExplodedNode
*N
) {
78 for (N
= GetSuccessorNode(N
); N
; N
= GetSuccessorNode(N
))
79 if (const Stmt
*S
= GetStmt(N
->getLocation())) {
80 // Check if the statement is '?' or '&&'/'||'. These are "merges",
81 // not actual statement points.
82 switch (S
->getStmtClass()) {
83 case Stmt::ChooseExprClass
:
84 case Stmt::BinaryConditionalOperatorClass
: continue;
85 case Stmt::ConditionalOperatorClass
: continue;
86 case Stmt::BinaryOperatorClass
: {
87 BinaryOperatorKind Op
= cast
<BinaryOperator
>(S
)->getOpcode();
88 if (Op
== BO_LAnd
|| Op
== BO_LOr
)
101 static inline const Stmt
*
102 GetCurrentOrPreviousStmt(const ExplodedNode
*N
) {
103 if (const Stmt
*S
= GetStmt(N
->getLocation()))
106 return GetPreviousStmt(N
);
109 static inline const Stmt
*
110 GetCurrentOrNextStmt(const ExplodedNode
*N
) {
111 if (const Stmt
*S
= GetStmt(N
->getLocation()))
114 return GetNextStmt(N
);
117 //===----------------------------------------------------------------------===//
118 // Diagnostic cleanup.
119 //===----------------------------------------------------------------------===//
121 /// Recursively scan through a path and prune out calls and macros pieces
122 /// that aren't needed. Return true if afterwards the path contains
123 /// "interesting stuff" which means it should be pruned from the parent path.
124 bool BugReporter::RemoveUneededCalls(PathPieces
&pieces
, BugReport
*R
,
125 PathDiagnosticCallPiece
*CallWithLoc
) {
126 bool containsSomethingInteresting
= false;
127 const unsigned N
= pieces
.size();
129 for (unsigned i
= 0 ; i
< N
; ++i
) {
130 // Remove the front piece from the path. If it is still something we
131 // want to keep once we are done, we will push it back on the end.
132 IntrusiveRefCntPtr
<PathDiagnosticPiece
> piece(pieces
.front());
135 // Throw away pieces with invalid locations.
136 if (piece
->getKind() != PathDiagnosticPiece::Call
&&
137 piece
->getLocation().asLocation().isInvalid())
140 switch (piece
->getKind()) {
141 case PathDiagnosticPiece::Call
: {
142 PathDiagnosticCallPiece
*call
= cast
<PathDiagnosticCallPiece
>(piece
);
143 // Check if the location context is interesting.
144 assert(LocationContextMap
.count(call
));
145 if (R
->isInteresting(LocationContextMap
[call
])) {
146 containsSomethingInteresting
= true;
149 // Recursively clean out the subclass. Keep this call around if
150 // it contains any informative diagnostics.
151 PathDiagnosticCallPiece
*NewCallWithLoc
=
152 call
->getLocation().asLocation().isValid()
153 ? call
: CallWithLoc
;
155 if (!RemoveUneededCalls(call
->path
, R
, NewCallWithLoc
))
158 if (NewCallWithLoc
== CallWithLoc
&& CallWithLoc
) {
159 call
->callEnter
= CallWithLoc
->callEnter
;
162 containsSomethingInteresting
= true;
165 case PathDiagnosticPiece::Macro
: {
166 PathDiagnosticMacroPiece
*macro
= cast
<PathDiagnosticMacroPiece
>(piece
);
167 if (!RemoveUneededCalls(macro
->subPieces
, R
))
169 containsSomethingInteresting
= true;
172 case PathDiagnosticPiece::Event
: {
173 PathDiagnosticEventPiece
*event
= cast
<PathDiagnosticEventPiece
>(piece
);
175 // We never throw away an event, but we do throw it away wholesale
176 // as part of a path if we throw the entire path away.
177 containsSomethingInteresting
|= !event
->isPrunable();
180 case PathDiagnosticPiece::ControlFlow
:
184 pieces
.push_back(piece
);
187 return containsSomethingInteresting
;
190 //===----------------------------------------------------------------------===//
191 // PathDiagnosticBuilder and its associated routines and helper objects.
192 //===----------------------------------------------------------------------===//
194 typedef llvm::DenseMap
<const ExplodedNode
*,
195 const ExplodedNode
*> NodeBackMap
;
198 class NodeMapClosure
: public BugReport::NodeResolver
{
201 NodeMapClosure(NodeBackMap
*m
) : M(*m
) {}
204 const ExplodedNode
*getOriginalNode(const ExplodedNode
*N
) {
205 NodeBackMap::iterator I
= M
.find(N
);
206 return I
== M
.end() ? 0 : I
->second
;
210 class PathDiagnosticBuilder
: public BugReporterContext
{
212 PathDiagnosticConsumer
*PDC
;
213 OwningPtr
<ParentMap
> PM
;
216 const LocationContext
*LC
;
218 PathDiagnosticBuilder(GRBugReporter
&br
,
219 BugReport
*r
, NodeBackMap
*Backmap
,
220 PathDiagnosticConsumer
*pdc
)
221 : BugReporterContext(br
),
222 R(r
), PDC(pdc
), NMC(Backmap
), LC(r
->getErrorNode()->getLocationContext())
225 PathDiagnosticLocation
ExecutionContinues(const ExplodedNode
*N
);
227 PathDiagnosticLocation
ExecutionContinues(llvm::raw_string_ostream
&os
,
228 const ExplodedNode
*N
);
230 BugReport
*getBugReport() { return R
; }
232 Decl
const &getCodeDecl() { return R
->getErrorNode()->getCodeDecl(); }
234 ParentMap
& getParentMap() { return LC
->getParentMap(); }
236 const Stmt
*getParent(const Stmt
*S
) {
237 return getParentMap().getParent(S
);
240 virtual NodeMapClosure
& getNodeResolver() { return NMC
; }
242 PathDiagnosticLocation
getEnclosingStmtLocation(const Stmt
*S
);
244 PathDiagnosticConsumer::PathGenerationScheme
getGenerationScheme() const {
245 return PDC
? PDC
->getGenerationScheme() : PathDiagnosticConsumer::Extensive
;
248 bool supportsLogicalOpControlFlow() const {
249 return PDC
? PDC
->supportsLogicalOpControlFlow() : true;
252 } // end anonymous namespace
254 PathDiagnosticLocation
255 PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode
*N
) {
256 if (const Stmt
*S
= GetNextStmt(N
))
257 return PathDiagnosticLocation(S
, getSourceManager(), LC
);
259 return PathDiagnosticLocation::createDeclEnd(N
->getLocationContext(),
263 PathDiagnosticLocation
264 PathDiagnosticBuilder::ExecutionContinues(llvm::raw_string_ostream
&os
,
265 const ExplodedNode
*N
) {
267 // Slow, but probably doesn't matter.
268 if (os
.str().empty())
271 const PathDiagnosticLocation
&Loc
= ExecutionContinues(N
);
274 os
<< "Execution continues on line "
275 << getSourceManager().getExpansionLineNumber(Loc
.asLocation())
278 os
<< "Execution jumps to the end of the ";
279 const Decl
*D
= N
->getLocationContext()->getDecl();
280 if (isa
<ObjCMethodDecl
>(D
))
282 else if (isa
<FunctionDecl
>(D
))
285 assert(isa
<BlockDecl
>(D
));
286 os
<< "anonymous block";
294 static bool IsNested(const Stmt
*S
, ParentMap
&PM
) {
295 if (isa
<Expr
>(S
) && PM
.isConsumedExpr(cast
<Expr
>(S
)))
298 const Stmt
*Parent
= PM
.getParentIgnoreParens(S
);
301 switch (Parent
->getStmtClass()) {
302 case Stmt::ForStmtClass
:
303 case Stmt::DoStmtClass
:
304 case Stmt::WhileStmtClass
:
313 PathDiagnosticLocation
314 PathDiagnosticBuilder::getEnclosingStmtLocation(const Stmt
*S
) {
315 assert(S
&& "Null Stmt *passed to getEnclosingStmtLocation");
316 ParentMap
&P
= getParentMap();
317 SourceManager
&SMgr
= getSourceManager();
319 while (IsNested(S
, P
)) {
320 const Stmt
*Parent
= P
.getParentIgnoreParens(S
);
325 switch (Parent
->getStmtClass()) {
326 case Stmt::BinaryOperatorClass
: {
327 const BinaryOperator
*B
= cast
<BinaryOperator
>(Parent
);
328 if (B
->isLogicalOp())
329 return PathDiagnosticLocation(S
, SMgr
, LC
);
332 case Stmt::CompoundStmtClass
:
333 case Stmt::StmtExprClass
:
334 return PathDiagnosticLocation(S
, SMgr
, LC
);
335 case Stmt::ChooseExprClass
:
336 // Similar to '?' if we are referring to condition, just have the edge
337 // point to the entire choose expression.
338 if (cast
<ChooseExpr
>(Parent
)->getCond() == S
)
339 return PathDiagnosticLocation(Parent
, SMgr
, LC
);
341 return PathDiagnosticLocation(S
, SMgr
, LC
);
342 case Stmt::BinaryConditionalOperatorClass
:
343 case Stmt::ConditionalOperatorClass
:
344 // For '?', if we are referring to condition, just have the edge point
345 // to the entire '?' expression.
346 if (cast
<AbstractConditionalOperator
>(Parent
)->getCond() == S
)
347 return PathDiagnosticLocation(Parent
, SMgr
, LC
);
349 return PathDiagnosticLocation(S
, SMgr
, LC
);
350 case Stmt::DoStmtClass
:
351 return PathDiagnosticLocation(S
, SMgr
, LC
);
352 case Stmt::ForStmtClass
:
353 if (cast
<ForStmt
>(Parent
)->getBody() == S
)
354 return PathDiagnosticLocation(S
, SMgr
, LC
);
356 case Stmt::IfStmtClass
:
357 if (cast
<IfStmt
>(Parent
)->getCond() != S
)
358 return PathDiagnosticLocation(S
, SMgr
, LC
);
360 case Stmt::ObjCForCollectionStmtClass
:
361 if (cast
<ObjCForCollectionStmt
>(Parent
)->getBody() == S
)
362 return PathDiagnosticLocation(S
, SMgr
, LC
);
364 case Stmt::WhileStmtClass
:
365 if (cast
<WhileStmt
>(Parent
)->getCond() != S
)
366 return PathDiagnosticLocation(S
, SMgr
, LC
);
375 assert(S
&& "Cannot have null Stmt for PathDiagnosticLocation");
377 // Special case: DeclStmts can appear in for statement declarations, in which
378 // case the ForStmt is the context.
379 if (isa
<DeclStmt
>(S
)) {
380 if (const Stmt
*Parent
= P
.getParent(S
)) {
381 switch (Parent
->getStmtClass()) {
382 case Stmt::ForStmtClass
:
383 case Stmt::ObjCForCollectionStmtClass
:
384 return PathDiagnosticLocation(Parent
, SMgr
, LC
);
390 else if (isa
<BinaryOperator
>(S
)) {
391 // Special case: the binary operator represents the initialization
392 // code in a for statement (this can happen when the variable being
393 // initialized is an old variable.
394 if (const ForStmt
*FS
=
395 dyn_cast_or_null
<ForStmt
>(P
.getParentIgnoreParens(S
))) {
396 if (FS
->getInit() == S
)
397 return PathDiagnosticLocation(FS
, SMgr
, LC
);
401 return PathDiagnosticLocation(S
, SMgr
, LC
);
404 //===----------------------------------------------------------------------===//
405 // "Visitors only" path diagnostic generation algorithm.
406 //===----------------------------------------------------------------------===//
407 static bool GenerateVisitorsOnlyPathDiagnostic(PathDiagnostic
&PD
,
408 PathDiagnosticBuilder
&PDB
,
409 const ExplodedNode
*N
,
410 ArrayRef
<BugReporterVisitor
*> visitors
) {
411 // All path generation skips the very first node (the error node).
412 // This is because there is special handling for the end-of-path note.
413 N
= N
->getFirstPred();
417 BugReport
*R
= PDB
.getBugReport();
418 while (const ExplodedNode
*Pred
= N
->getFirstPred()) {
419 for (ArrayRef
<BugReporterVisitor
*>::iterator I
= visitors
.begin(),
422 // Visit all the node pairs, but throw the path pieces away.
423 PathDiagnosticPiece
*Piece
= (*I
)->VisitNode(N
, Pred
, PDB
, *R
);
433 //===----------------------------------------------------------------------===//
434 // "Minimal" path diagnostic generation algorithm.
435 //===----------------------------------------------------------------------===//
436 typedef std::pair
<PathDiagnosticCallPiece
*, const ExplodedNode
*> StackDiagPair
;
437 typedef SmallVector
<StackDiagPair
, 6> StackDiagVector
;
439 static void updateStackPiecesWithMessage(PathDiagnosticPiece
*P
,
440 StackDiagVector
&CallStack
) {
441 // If the piece contains a special message, add it to all the call
442 // pieces on the active stack.
443 if (PathDiagnosticEventPiece
*ep
=
444 dyn_cast
<PathDiagnosticEventPiece
>(P
)) {
446 if (ep
->hasCallStackHint())
447 for (StackDiagVector::iterator I
= CallStack
.begin(),
448 E
= CallStack
.end(); I
!= E
; ++I
) {
449 PathDiagnosticCallPiece
*CP
= I
->first
;
450 const ExplodedNode
*N
= I
->second
;
451 std::string stackMsg
= ep
->getCallStackMessage(N
);
453 // The last message on the path to final bug is the most important
454 // one. Since we traverse the path backwards, do not add the message
455 // if one has been previously added.
456 if (!CP
->hasCallStackMessage())
457 CP
->setCallStackMessage(stackMsg
);
462 static void CompactPathDiagnostic(PathPieces
&path
, const SourceManager
& SM
);
464 static bool GenerateMinimalPathDiagnostic(PathDiagnostic
& PD
,
465 PathDiagnosticBuilder
&PDB
,
466 const ExplodedNode
*N
,
467 ArrayRef
<BugReporterVisitor
*> visitors
) {
469 SourceManager
& SMgr
= PDB
.getSourceManager();
470 const LocationContext
*LC
= PDB
.LC
;
471 const ExplodedNode
*NextNode
= N
->pred_empty()
472 ? NULL
: *(N
->pred_begin());
474 StackDiagVector CallStack
;
478 PDB
.LC
= N
->getLocationContext();
479 NextNode
= GetPredecessorNode(N
);
481 ProgramPoint P
= N
->getLocation();
484 if (const CallExitEnd
*CE
= dyn_cast
<CallExitEnd
>(&P
)) {
485 PathDiagnosticCallPiece
*C
=
486 PathDiagnosticCallPiece::construct(N
, *CE
, SMgr
);
487 GRBugReporter
& BR
= PDB
.getBugReporter();
488 BR
.addCallPieceLocationContextPair(C
, CE
->getCalleeContext());
489 PD
.getActivePath().push_front(C
);
490 PD
.pushActivePath(&C
->path
);
491 CallStack
.push_back(StackDiagPair(C
, N
));
495 if (const CallEnter
*CE
= dyn_cast
<CallEnter
>(&P
)) {
496 // Flush all locations, and pop the active path.
497 bool VisitedEntireCall
= PD
.isWithinCall();
500 // Either we just added a bunch of stuff to the top-level path, or
501 // we have a previous CallExitEnd. If the former, it means that the
502 // path terminated within a function call. We must then take the
503 // current contents of the active path and place it within
504 // a new PathDiagnosticCallPiece.
505 PathDiagnosticCallPiece
*C
;
506 if (VisitedEntireCall
) {
507 C
= cast
<PathDiagnosticCallPiece
>(PD
.getActivePath().front());
509 const Decl
*Caller
= CE
->getLocationContext()->getDecl();
510 C
= PathDiagnosticCallPiece::construct(PD
.getActivePath(), Caller
);
511 GRBugReporter
& BR
= PDB
.getBugReporter();
512 BR
.addCallPieceLocationContextPair(C
, CE
->getCalleeContext());
515 C
->setCallee(*CE
, SMgr
);
516 if (!CallStack
.empty()) {
517 assert(CallStack
.back().first
== C
);
518 CallStack
.pop_back();
523 if (const BlockEdge
*BE
= dyn_cast
<BlockEdge
>(&P
)) {
524 const CFGBlock
*Src
= BE
->getSrc();
525 const CFGBlock
*Dst
= BE
->getDst();
526 const Stmt
*T
= Src
->getTerminator();
531 PathDiagnosticLocation Start
=
532 PathDiagnosticLocation::createBegin(T
, SMgr
,
533 N
->getLocationContext());
535 switch (T
->getStmtClass()) {
539 case Stmt::GotoStmtClass
:
540 case Stmt::IndirectGotoStmtClass
: {
541 const Stmt
*S
= GetNextStmt(N
);
547 llvm::raw_string_ostream
os(sbuf
);
548 const PathDiagnosticLocation
&End
= PDB
.getEnclosingStmtLocation(S
);
550 os
<< "Control jumps to line "
551 << End
.asLocation().getExpansionLineNumber();
552 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
553 Start
, End
, os
.str()));
557 case Stmt::SwitchStmtClass
: {
558 // Figure out what case arm we took.
560 llvm::raw_string_ostream
os(sbuf
);
562 if (const Stmt
*S
= Dst
->getLabel()) {
563 PathDiagnosticLocation
End(S
, SMgr
, LC
);
565 switch (S
->getStmtClass()) {
567 os
<< "No cases match in the switch statement. "
568 "Control jumps to line "
569 << End
.asLocation().getExpansionLineNumber();
571 case Stmt::DefaultStmtClass
:
572 os
<< "Control jumps to the 'default' case at line "
573 << End
.asLocation().getExpansionLineNumber();
576 case Stmt::CaseStmtClass
: {
577 os
<< "Control jumps to 'case ";
578 const CaseStmt
*Case
= cast
<CaseStmt
>(S
);
579 const Expr
*LHS
= Case
->getLHS()->IgnoreParenCasts();
581 // Determine if it is an enum.
582 bool GetRawInt
= true;
584 if (const DeclRefExpr
*DR
= dyn_cast
<DeclRefExpr
>(LHS
)) {
585 // FIXME: Maybe this should be an assertion. Are there cases
586 // were it is not an EnumConstantDecl?
587 const EnumConstantDecl
*D
=
588 dyn_cast
<EnumConstantDecl
>(DR
->getDecl());
597 os
<< LHS
->EvaluateKnownConstInt(PDB
.getASTContext());
600 << End
.asLocation().getExpansionLineNumber();
604 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
605 Start
, End
, os
.str()));
608 os
<< "'Default' branch taken. ";
609 const PathDiagnosticLocation
&End
= PDB
.ExecutionContinues(os
, N
);
610 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
611 Start
, End
, os
.str()));
617 case Stmt::BreakStmtClass
:
618 case Stmt::ContinueStmtClass
: {
620 llvm::raw_string_ostream
os(sbuf
);
621 PathDiagnosticLocation End
= PDB
.ExecutionContinues(os
, N
);
622 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
623 Start
, End
, os
.str()));
627 // Determine control-flow for ternary '?'.
628 case Stmt::BinaryConditionalOperatorClass
:
629 case Stmt::ConditionalOperatorClass
: {
631 llvm::raw_string_ostream
os(sbuf
);
632 os
<< "'?' condition is ";
634 if (*(Src
->succ_begin()+1) == Dst
)
639 PathDiagnosticLocation End
= PDB
.ExecutionContinues(N
);
641 if (const Stmt
*S
= End
.asStmt())
642 End
= PDB
.getEnclosingStmtLocation(S
);
644 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
645 Start
, End
, os
.str()));
649 // Determine control-flow for short-circuited '&&' and '||'.
650 case Stmt::BinaryOperatorClass
: {
651 if (!PDB
.supportsLogicalOpControlFlow())
654 const BinaryOperator
*B
= cast
<BinaryOperator
>(T
);
656 llvm::raw_string_ostream
os(sbuf
);
657 os
<< "Left side of '";
659 if (B
->getOpcode() == BO_LAnd
) {
660 os
<< "&&" << "' is ";
662 if (*(Src
->succ_begin()+1) == Dst
) {
664 PathDiagnosticLocation
End(B
->getLHS(), SMgr
, LC
);
665 PathDiagnosticLocation Start
=
666 PathDiagnosticLocation::createOperatorLoc(B
, SMgr
);
667 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
668 Start
, End
, os
.str()));
672 PathDiagnosticLocation
Start(B
->getLHS(), SMgr
, LC
);
673 PathDiagnosticLocation End
= PDB
.ExecutionContinues(N
);
674 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
675 Start
, End
, os
.str()));
679 assert(B
->getOpcode() == BO_LOr
);
680 os
<< "||" << "' is ";
682 if (*(Src
->succ_begin()+1) == Dst
) {
684 PathDiagnosticLocation
Start(B
->getLHS(), SMgr
, LC
);
685 PathDiagnosticLocation End
= PDB
.ExecutionContinues(N
);
686 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
687 Start
, End
, os
.str()));
691 PathDiagnosticLocation
End(B
->getLHS(), SMgr
, LC
);
692 PathDiagnosticLocation Start
=
693 PathDiagnosticLocation::createOperatorLoc(B
, SMgr
);
694 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
695 Start
, End
, os
.str()));
702 case Stmt::DoStmtClass
: {
703 if (*(Src
->succ_begin()) == Dst
) {
705 llvm::raw_string_ostream
os(sbuf
);
707 os
<< "Loop condition is true. ";
708 PathDiagnosticLocation End
= PDB
.ExecutionContinues(os
, N
);
710 if (const Stmt
*S
= End
.asStmt())
711 End
= PDB
.getEnclosingStmtLocation(S
);
713 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
714 Start
, End
, os
.str()));
717 PathDiagnosticLocation End
= PDB
.ExecutionContinues(N
);
719 if (const Stmt
*S
= End
.asStmt())
720 End
= PDB
.getEnclosingStmtLocation(S
);
722 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
723 Start
, End
, "Loop condition is false. Exiting loop"));
729 case Stmt::WhileStmtClass
:
730 case Stmt::ForStmtClass
: {
731 if (*(Src
->succ_begin()+1) == Dst
) {
733 llvm::raw_string_ostream
os(sbuf
);
735 os
<< "Loop condition is false. ";
736 PathDiagnosticLocation End
= PDB
.ExecutionContinues(os
, N
);
737 if (const Stmt
*S
= End
.asStmt())
738 End
= PDB
.getEnclosingStmtLocation(S
);
740 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
741 Start
, End
, os
.str()));
744 PathDiagnosticLocation End
= PDB
.ExecutionContinues(N
);
745 if (const Stmt
*S
= End
.asStmt())
746 End
= PDB
.getEnclosingStmtLocation(S
);
748 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
749 Start
, End
, "Loop condition is true. Entering loop body"));
755 case Stmt::IfStmtClass
: {
756 PathDiagnosticLocation End
= PDB
.ExecutionContinues(N
);
758 if (const Stmt
*S
= End
.asStmt())
759 End
= PDB
.getEnclosingStmtLocation(S
);
761 if (*(Src
->succ_begin()+1) == Dst
)
762 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
763 Start
, End
, "Taking false branch"));
765 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(
766 Start
, End
, "Taking true branch"));
775 // Add diagnostic pieces from custom visitors.
776 BugReport
*R
= PDB
.getBugReport();
777 for (ArrayRef
<BugReporterVisitor
*>::iterator I
= visitors
.begin(),
780 if (PathDiagnosticPiece
*p
= (*I
)->VisitNode(N
, NextNode
, PDB
, *R
)) {
781 PD
.getActivePath().push_front(p
);
782 updateStackPiecesWithMessage(p
, CallStack
);
788 if (!PDB
.getBugReport()->isValid())
791 // After constructing the full PathDiagnostic, do a pass over it to compact
792 // PathDiagnosticPieces that occur within a macro.
793 CompactPathDiagnostic(PD
.getMutablePieces(), PDB
.getSourceManager());
797 //===----------------------------------------------------------------------===//
798 // "Extensive" PathDiagnostic generation.
799 //===----------------------------------------------------------------------===//
801 static bool IsControlFlowExpr(const Stmt
*S
) {
802 const Expr
*E
= dyn_cast
<Expr
>(S
);
807 E
= E
->IgnoreParenCasts();
809 if (isa
<AbstractConditionalOperator
>(E
))
812 if (const BinaryOperator
*B
= dyn_cast
<BinaryOperator
>(E
))
813 if (B
->isLogicalOp())
820 class ContextLocation
: public PathDiagnosticLocation
{
823 ContextLocation(const PathDiagnosticLocation
&L
, bool isdead
= false)
824 : PathDiagnosticLocation(L
), IsDead(isdead
) {}
826 void markDead() { IsDead
= true; }
827 bool isDead() const { return IsDead
; }
831 std::vector
<ContextLocation
> CLocs
;
832 typedef std::vector
<ContextLocation
>::iterator iterator
;
834 PathDiagnosticBuilder
&PDB
;
835 PathDiagnosticLocation PrevLoc
;
837 bool IsConsumedExpr(const PathDiagnosticLocation
&L
);
839 bool containsLocation(const PathDiagnosticLocation
&Container
,
840 const PathDiagnosticLocation
&Containee
);
842 PathDiagnosticLocation
getContextLocation(const PathDiagnosticLocation
&L
);
844 PathDiagnosticLocation
cleanUpLocation(PathDiagnosticLocation L
,
845 bool firstCharOnly
= false) {
846 if (const Stmt
*S
= L
.asStmt()) {
847 const Stmt
*Original
= S
;
849 // Adjust the location for some expressions that are best referenced
850 // by one of their subexpressions.
851 switch (S
->getStmtClass()) {
854 case Stmt::ParenExprClass
:
855 case Stmt::GenericSelectionExprClass
:
856 S
= cast
<Expr
>(S
)->IgnoreParens();
857 firstCharOnly
= true;
859 case Stmt::BinaryConditionalOperatorClass
:
860 case Stmt::ConditionalOperatorClass
:
861 S
= cast
<AbstractConditionalOperator
>(S
)->getCond();
862 firstCharOnly
= true;
864 case Stmt::ChooseExprClass
:
865 S
= cast
<ChooseExpr
>(S
)->getCond();
866 firstCharOnly
= true;
868 case Stmt::BinaryOperatorClass
:
869 S
= cast
<BinaryOperator
>(S
)->getLHS();
870 firstCharOnly
= true;
878 L
= PathDiagnosticLocation(S
, L
.getManager(), PDB
.LC
);
882 L
= PathDiagnosticLocation::createSingleLocation(L
);
888 if (!CLocs
.back().isDead() && CLocs
.back().asLocation().isFileID()) {
889 // For contexts, we only one the first character as the range.
890 rawAddEdge(cleanUpLocation(CLocs
.back(), true));
896 EdgeBuilder(PathDiagnostic
&pd
, PathDiagnosticBuilder
&pdb
)
899 // If the PathDiagnostic already has pieces, add the enclosing statement
900 // of the first piece as a context as well.
901 if (!PD
.path
.empty()) {
902 PrevLoc
= (*PD
.path
.begin())->getLocation();
904 if (const Stmt
*S
= PrevLoc
.asStmt())
905 addExtendedContext(PDB
.getEnclosingStmtLocation(S
).asStmt());
910 while (!CLocs
.empty()) popLocation();
912 // Finally, add an initial edge from the start location of the first
913 // statement (if it doesn't already exist).
914 PathDiagnosticLocation L
= PathDiagnosticLocation::createDeclBegin(
916 PDB
.getSourceManager());
921 void flushLocations() {
922 while (!CLocs
.empty())
924 PrevLoc
= PathDiagnosticLocation();
927 void addEdge(PathDiagnosticLocation NewLoc
, bool alwaysAdd
= false);
929 void rawAddEdge(PathDiagnosticLocation NewLoc
);
931 void addContext(const Stmt
*S
);
932 void addContext(const PathDiagnosticLocation
&L
);
933 void addExtendedContext(const Stmt
*S
);
935 } // end anonymous namespace
938 PathDiagnosticLocation
939 EdgeBuilder::getContextLocation(const PathDiagnosticLocation
&L
) {
940 if (const Stmt
*S
= L
.asStmt()) {
941 if (IsControlFlowExpr(S
))
944 return PDB
.getEnclosingStmtLocation(S
);
950 bool EdgeBuilder::containsLocation(const PathDiagnosticLocation
&Container
,
951 const PathDiagnosticLocation
&Containee
) {
953 if (Container
== Containee
)
956 if (Container
.asDecl())
959 if (const Stmt
*S
= Containee
.asStmt())
960 if (const Stmt
*ContainerS
= Container
.asStmt()) {
964 S
= PDB
.getParent(S
);
969 // Less accurate: compare using source ranges.
970 SourceRange ContainerR
= Container
.asRange();
971 SourceRange ContaineeR
= Containee
.asRange();
973 SourceManager
&SM
= PDB
.getSourceManager();
974 SourceLocation ContainerRBeg
= SM
.getExpansionLoc(ContainerR
.getBegin());
975 SourceLocation ContainerREnd
= SM
.getExpansionLoc(ContainerR
.getEnd());
976 SourceLocation ContaineeRBeg
= SM
.getExpansionLoc(ContaineeR
.getBegin());
977 SourceLocation ContaineeREnd
= SM
.getExpansionLoc(ContaineeR
.getEnd());
979 unsigned ContainerBegLine
= SM
.getExpansionLineNumber(ContainerRBeg
);
980 unsigned ContainerEndLine
= SM
.getExpansionLineNumber(ContainerREnd
);
981 unsigned ContaineeBegLine
= SM
.getExpansionLineNumber(ContaineeRBeg
);
982 unsigned ContaineeEndLine
= SM
.getExpansionLineNumber(ContaineeREnd
);
984 assert(ContainerBegLine
<= ContainerEndLine
);
985 assert(ContaineeBegLine
<= ContaineeEndLine
);
987 return (ContainerBegLine
<= ContaineeBegLine
&&
988 ContainerEndLine
>= ContaineeEndLine
&&
989 (ContainerBegLine
!= ContaineeBegLine
||
990 SM
.getExpansionColumnNumber(ContainerRBeg
) <=
991 SM
.getExpansionColumnNumber(ContaineeRBeg
)) &&
992 (ContainerEndLine
!= ContaineeEndLine
||
993 SM
.getExpansionColumnNumber(ContainerREnd
) >=
994 SM
.getExpansionColumnNumber(ContaineeREnd
)));
997 void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc
) {
998 if (!PrevLoc
.isValid()) {
1003 const PathDiagnosticLocation
&NewLocClean
= cleanUpLocation(NewLoc
);
1004 const PathDiagnosticLocation
&PrevLocClean
= cleanUpLocation(PrevLoc
);
1006 if (PrevLocClean
.asLocation().isInvalid()) {
1011 if (NewLocClean
.asLocation() == PrevLocClean
.asLocation())
1014 // FIXME: Ignore intra-macro edges for now.
1015 if (NewLocClean
.asLocation().getExpansionLoc() ==
1016 PrevLocClean
.asLocation().getExpansionLoc())
1019 PD
.getActivePath().push_front(new PathDiagnosticControlFlowPiece(NewLocClean
, PrevLocClean
));
1023 void EdgeBuilder::addEdge(PathDiagnosticLocation NewLoc
, bool alwaysAdd
) {
1025 if (!alwaysAdd
&& NewLoc
.asLocation().isMacroID())
1028 const PathDiagnosticLocation
&CLoc
= getContextLocation(NewLoc
);
1030 while (!CLocs
.empty()) {
1031 ContextLocation
&TopContextLoc
= CLocs
.back();
1033 // Is the top location context the same as the one for the new location?
1034 if (TopContextLoc
== CLoc
) {
1036 if (IsConsumedExpr(TopContextLoc
) &&
1037 !IsControlFlowExpr(TopContextLoc
.asStmt()))
1038 TopContextLoc
.markDead();
1046 if (containsLocation(TopContextLoc
, CLoc
)) {
1050 if (IsConsumedExpr(CLoc
) && !IsControlFlowExpr(CLoc
.asStmt())) {
1051 CLocs
.push_back(ContextLocation(CLoc
, true));
1056 CLocs
.push_back(CLoc
);
1060 // Context does not contain the location. Flush it.
1064 // If we reach here, there is no enclosing context. Just add the edge.
1068 bool EdgeBuilder::IsConsumedExpr(const PathDiagnosticLocation
&L
) {
1069 if (const Expr
*X
= dyn_cast_or_null
<Expr
>(L
.asStmt()))
1070 return PDB
.getParentMap().isConsumedExpr(X
) && !IsControlFlowExpr(X
);
1075 void EdgeBuilder::addExtendedContext(const Stmt
*S
) {
1079 const Stmt
*Parent
= PDB
.getParent(S
);
1081 if (isa
<CompoundStmt
>(Parent
))
1082 Parent
= PDB
.getParent(Parent
);
1088 switch (Parent
->getStmtClass()) {
1089 case Stmt::DoStmtClass
:
1090 case Stmt::ObjCAtSynchronizedStmtClass
:
1100 void EdgeBuilder::addContext(const Stmt
*S
) {
1104 PathDiagnosticLocation
L(S
, PDB
.getSourceManager(), PDB
.LC
);
1108 void EdgeBuilder::addContext(const PathDiagnosticLocation
&L
) {
1109 while (!CLocs
.empty()) {
1110 const PathDiagnosticLocation
&TopContextLoc
= CLocs
.back();
1112 // Is the top location context the same as the one for the new location?
1113 if (TopContextLoc
== L
)
1116 if (containsLocation(TopContextLoc
, L
)) {
1121 // Context does not contain the location. Flush it.
1128 // Cone-of-influence: support the reverse propagation of "interesting" symbols
1129 // and values by tracing interesting calculations backwards through evaluated
1130 // expressions along a path. This is probably overly complicated, but the idea
1131 // is that if an expression computed an "interesting" value, the child
1132 // expressions are are also likely to be "interesting" as well (which then
1133 // propagates to the values they in turn compute). This reverse propagation
1134 // is needed to track interesting correlations across function call boundaries,
1135 // where formal arguments bind to actual arguments, etc. This is also needed
1136 // because the constraint solver sometimes simplifies certain symbolic values
1137 // into constants when appropriate, and this complicates reasoning about
1138 // interesting values.
1139 typedef llvm::DenseSet
<const Expr
*> InterestingExprs
;
1141 static void reversePropagateIntererstingSymbols(BugReport
&R
,
1142 InterestingExprs
&IE
,
1143 const ProgramState
*State
,
1145 const LocationContext
*LCtx
) {
1146 SVal V
= State
->getSVal(Ex
, LCtx
);
1147 if (!(R
.isInteresting(V
) || IE
.count(Ex
)))
1150 switch (Ex
->getStmtClass()) {
1152 if (!isa
<CastExpr
>(Ex
))
1155 case Stmt::BinaryOperatorClass
:
1156 case Stmt::UnaryOperatorClass
: {
1157 for (Stmt::const_child_iterator CI
= Ex
->child_begin(),
1158 CE
= Ex
->child_end();
1160 if (const Expr
*child
= dyn_cast_or_null
<Expr
>(*CI
)) {
1162 SVal ChildV
= State
->getSVal(child
, LCtx
);
1163 R
.markInteresting(ChildV
);
1170 R
.markInteresting(V
);
1173 static void reversePropagateInterestingSymbols(BugReport
&R
,
1174 InterestingExprs
&IE
,
1175 const ProgramState
*State
,
1176 const LocationContext
*CalleeCtx
,
1177 const LocationContext
*CallerCtx
)
1179 // FIXME: Handle non-CallExpr-based CallEvents.
1180 const StackFrameContext
*Callee
= CalleeCtx
->getCurrentStackFrame();
1181 const Stmt
*CallSite
= Callee
->getCallSite();
1182 if (const CallExpr
*CE
= dyn_cast_or_null
<CallExpr
>(CallSite
)) {
1183 if (const FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(CalleeCtx
->getDecl())) {
1184 FunctionDecl::param_const_iterator PI
= FD
->param_begin(),
1185 PE
= FD
->param_end();
1186 CallExpr::const_arg_iterator AI
= CE
->arg_begin(), AE
= CE
->arg_end();
1187 for (; AI
!= AE
&& PI
!= PE
; ++AI
, ++PI
) {
1188 if (const Expr
*ArgE
= *AI
) {
1189 if (const ParmVarDecl
*PD
= *PI
) {
1190 Loc LV
= State
->getLValue(PD
, CalleeCtx
);
1191 if (R
.isInteresting(LV
) || R
.isInteresting(State
->getRawSVal(LV
)))
1200 static bool GenerateExtensivePathDiagnostic(PathDiagnostic
& PD
,
1201 PathDiagnosticBuilder
&PDB
,
1202 const ExplodedNode
*N
,
1203 ArrayRef
<BugReporterVisitor
*> visitors
) {
1204 EdgeBuilder
EB(PD
, PDB
);
1205 const SourceManager
& SM
= PDB
.getSourceManager();
1206 StackDiagVector CallStack
;
1207 InterestingExprs IE
;
1209 const ExplodedNode
*NextNode
= N
->pred_empty() ? NULL
: *(N
->pred_begin());
1212 NextNode
= GetPredecessorNode(N
);
1213 ProgramPoint P
= N
->getLocation();
1216 if (const PostStmt
*PS
= dyn_cast
<PostStmt
>(&P
)) {
1217 if (const Expr
*Ex
= PS
->getStmtAs
<Expr
>())
1218 reversePropagateIntererstingSymbols(*PDB
.getBugReport(), IE
,
1219 N
->getState().getPtr(), Ex
,
1220 N
->getLocationContext());
1223 if (const CallExitEnd
*CE
= dyn_cast
<CallExitEnd
>(&P
)) {
1224 const Stmt
*S
= CE
->getCalleeContext()->getCallSite();
1225 if (const Expr
*Ex
= dyn_cast_or_null
<Expr
>(S
)) {
1226 reversePropagateIntererstingSymbols(*PDB
.getBugReport(), IE
,
1227 N
->getState().getPtr(), Ex
,
1228 N
->getLocationContext());
1231 PathDiagnosticCallPiece
*C
=
1232 PathDiagnosticCallPiece::construct(N
, *CE
, SM
);
1233 GRBugReporter
& BR
= PDB
.getBugReporter();
1234 BR
.addCallPieceLocationContextPair(C
, CE
->getCalleeContext());
1236 EB
.addEdge(C
->callReturn
, true);
1237 EB
.flushLocations();
1239 PD
.getActivePath().push_front(C
);
1240 PD
.pushActivePath(&C
->path
);
1241 CallStack
.push_back(StackDiagPair(C
, N
));
1245 // Pop the call hierarchy if we are done walking the contents
1246 // of a function call.
1247 if (const CallEnter
*CE
= dyn_cast
<CallEnter
>(&P
)) {
1248 // Add an edge to the start of the function.
1249 const Decl
*D
= CE
->getCalleeContext()->getDecl();
1250 PathDiagnosticLocation pos
=
1251 PathDiagnosticLocation::createBegin(D
, SM
);
1254 // Flush all locations, and pop the active path.
1255 bool VisitedEntireCall
= PD
.isWithinCall();
1256 EB
.flushLocations();
1258 PDB
.LC
= N
->getLocationContext();
1260 // Either we just added a bunch of stuff to the top-level path, or
1261 // we have a previous CallExitEnd. If the former, it means that the
1262 // path terminated within a function call. We must then take the
1263 // current contents of the active path and place it within
1264 // a new PathDiagnosticCallPiece.
1265 PathDiagnosticCallPiece
*C
;
1266 if (VisitedEntireCall
) {
1267 C
= cast
<PathDiagnosticCallPiece
>(PD
.getActivePath().front());
1269 const Decl
*Caller
= CE
->getLocationContext()->getDecl();
1270 C
= PathDiagnosticCallPiece::construct(PD
.getActivePath(), Caller
);
1271 GRBugReporter
& BR
= PDB
.getBugReporter();
1272 BR
.addCallPieceLocationContextPair(C
, CE
->getCalleeContext());
1275 C
->setCallee(*CE
, SM
);
1276 EB
.addContext(C
->getLocation());
1278 if (!CallStack
.empty()) {
1279 assert(CallStack
.back().first
== C
);
1280 CallStack
.pop_back();
1285 // Note that is important that we update the LocationContext
1286 // after looking at CallExits. CallExit basically adds an
1287 // edge in the *caller*, so we don't want to update the LocationContext
1289 PDB
.LC
= N
->getLocationContext();
1292 if (const BlockEdge
*BE
= dyn_cast
<BlockEdge
>(&P
)) {
1293 // Does this represent entering a call? If so, look at propagating
1294 // interesting symbols across call boundaries.
1296 const LocationContext
*CallerCtx
= NextNode
->getLocationContext();
1297 const LocationContext
*CalleeCtx
= PDB
.LC
;
1298 if (CallerCtx
!= CalleeCtx
) {
1299 reversePropagateInterestingSymbols(*PDB
.getBugReport(), IE
,
1300 N
->getState().getPtr(),
1301 CalleeCtx
, CallerCtx
);
1305 // Are we jumping to the head of a loop? Add a special diagnostic.
1306 if (const Stmt
*Loop
= BE
->getSrc()->getLoopTarget()) {
1307 PathDiagnosticLocation
L(Loop
, SM
, PDB
.LC
);
1308 const CompoundStmt
*CS
= NULL
;
1310 if (const ForStmt
*FS
= dyn_cast
<ForStmt
>(Loop
))
1311 CS
= dyn_cast
<CompoundStmt
>(FS
->getBody());
1312 else if (const WhileStmt
*WS
= dyn_cast
<WhileStmt
>(Loop
))
1313 CS
= dyn_cast
<CompoundStmt
>(WS
->getBody());
1315 PathDiagnosticEventPiece
*p
=
1316 new PathDiagnosticEventPiece(L
,
1317 "Looping back to the head of the loop");
1318 p
->setPrunable(true);
1320 EB
.addEdge(p
->getLocation(), true);
1321 PD
.getActivePath().push_front(p
);
1324 PathDiagnosticLocation BL
=
1325 PathDiagnosticLocation::createEndBrace(CS
, SM
);
1330 if (const Stmt
*Term
= BE
->getSrc()->getTerminator())
1331 EB
.addContext(Term
);
1336 if (const BlockEntrance
*BE
= dyn_cast
<BlockEntrance
>(&P
)) {
1337 CFGElement First
= BE
->getFirstElement();
1338 if (const CFGStmt
*S
= First
.getAs
<CFGStmt
>()) {
1339 const Stmt
*stmt
= S
->getStmt();
1340 if (IsControlFlowExpr(stmt
)) {
1341 // Add the proper context for '&&', '||', and '?'.
1342 EB
.addContext(stmt
);
1345 EB
.addExtendedContext(PDB
.getEnclosingStmtLocation(stmt
).asStmt());
1357 // Add pieces from custom visitors.
1358 BugReport
*R
= PDB
.getBugReport();
1359 for (ArrayRef
<BugReporterVisitor
*>::iterator I
= visitors
.begin(),
1362 if (PathDiagnosticPiece
*p
= (*I
)->VisitNode(N
, NextNode
, PDB
, *R
)) {
1363 const PathDiagnosticLocation
&Loc
= p
->getLocation();
1364 EB
.addEdge(Loc
, true);
1365 PD
.getActivePath().push_front(p
);
1366 updateStackPiecesWithMessage(p
, CallStack
);
1368 if (const Stmt
*S
= Loc
.asStmt())
1369 EB
.addExtendedContext(PDB
.getEnclosingStmtLocation(S
).asStmt());
1374 return PDB
.getBugReport()->isValid();
1377 //===----------------------------------------------------------------------===//
1378 // Methods for BugType and subclasses.
1379 //===----------------------------------------------------------------------===//
1380 BugType::~BugType() { }
1382 void BugType::FlushReports(BugReporter
&BR
) {}
1384 void BuiltinBug::anchor() {}
1386 //===----------------------------------------------------------------------===//
1387 // Methods for BugReport and subclasses.
1388 //===----------------------------------------------------------------------===//
1390 void BugReport::NodeResolver::anchor() {}
1392 void BugReport::addVisitor(BugReporterVisitor
* visitor
) {
1396 llvm::FoldingSetNodeID ID
;
1397 visitor
->Profile(ID
);
1400 if (CallbacksSet
.FindNodeOrInsertPos(ID
, InsertPos
)) {
1405 CallbacksSet
.InsertNode(visitor
, InsertPos
);
1406 Callbacks
.push_back(visitor
);
1407 ++ConfigurationChangeToken
;
1410 BugReport::~BugReport() {
1411 for (visitor_iterator I
= visitor_begin(), E
= visitor_end(); I
!= E
; ++I
) {
1414 while (!interestingSymbols
.empty()) {
1415 popInterestingSymbolsAndRegions();
1419 const Decl
*BugReport::getDeclWithIssue() const {
1421 return DeclWithIssue
;
1423 const ExplodedNode
*N
= getErrorNode();
1427 const LocationContext
*LC
= N
->getLocationContext();
1428 return LC
->getCurrentStackFrame()->getDecl();
1431 void BugReport::Profile(llvm::FoldingSetNodeID
& hash
) const {
1432 hash
.AddPointer(&BT
);
1433 hash
.AddString(Description
);
1434 if (UniqueingLocation
.isValid()) {
1435 UniqueingLocation
.Profile(hash
);
1436 } else if (Location
.isValid()) {
1437 Location
.Profile(hash
);
1440 hash
.AddPointer(GetCurrentOrPreviousStmt(ErrorNode
));
1443 for (SmallVectorImpl
<SourceRange
>::const_iterator I
=
1444 Ranges
.begin(), E
= Ranges
.end(); I
!= E
; ++I
) {
1445 const SourceRange range
= *I
;
1446 if (!range
.isValid())
1448 hash
.AddInteger(range
.getBegin().getRawEncoding());
1449 hash
.AddInteger(range
.getEnd().getRawEncoding());
1453 void BugReport::markInteresting(SymbolRef sym
) {
1457 // If the symbol wasn't already in our set, note a configuration change.
1458 if (getInterestingSymbols().insert(sym
).second
)
1459 ++ConfigurationChangeToken
;
1461 if (const SymbolMetadata
*meta
= dyn_cast
<SymbolMetadata
>(sym
))
1462 getInterestingRegions().insert(meta
->getRegion());
1465 void BugReport::markInteresting(const MemRegion
*R
) {
1469 // If the base region wasn't already in our set, note a configuration change.
1470 R
= R
->getBaseRegion();
1471 if (getInterestingRegions().insert(R
).second
)
1472 ++ConfigurationChangeToken
;
1474 if (const SymbolicRegion
*SR
= dyn_cast
<SymbolicRegion
>(R
))
1475 getInterestingSymbols().insert(SR
->getSymbol());
1478 void BugReport::markInteresting(SVal V
) {
1479 markInteresting(V
.getAsRegion());
1480 markInteresting(V
.getAsSymbol());
1483 void BugReport::markInteresting(const LocationContext
*LC
) {
1486 InterestingLocationContexts
.insert(LC
);
1489 bool BugReport::isInteresting(SVal V
) {
1490 return isInteresting(V
.getAsRegion()) || isInteresting(V
.getAsSymbol());
1493 bool BugReport::isInteresting(SymbolRef sym
) {
1496 // We don't currently consider metadata symbols to be interesting
1497 // even if we know their region is interesting. Is that correct behavior?
1498 return getInterestingSymbols().count(sym
);
1501 bool BugReport::isInteresting(const MemRegion
*R
) {
1504 R
= R
->getBaseRegion();
1505 bool b
= getInterestingRegions().count(R
);
1508 if (const SymbolicRegion
*SR
= dyn_cast
<SymbolicRegion
>(R
))
1509 return getInterestingSymbols().count(SR
->getSymbol());
1513 bool BugReport::isInteresting(const LocationContext
*LC
) {
1516 return InterestingLocationContexts
.count(LC
);
1519 void BugReport::lazyInitializeInterestingSets() {
1520 if (interestingSymbols
.empty()) {
1521 interestingSymbols
.push_back(new Symbols());
1522 interestingRegions
.push_back(new Regions());
1526 BugReport::Symbols
&BugReport::getInterestingSymbols() {
1527 lazyInitializeInterestingSets();
1528 return *interestingSymbols
.back();
1531 BugReport::Regions
&BugReport::getInterestingRegions() {
1532 lazyInitializeInterestingSets();
1533 return *interestingRegions
.back();
1536 void BugReport::pushInterestingSymbolsAndRegions() {
1537 interestingSymbols
.push_back(new Symbols(getInterestingSymbols()));
1538 interestingRegions
.push_back(new Regions(getInterestingRegions()));
1541 void BugReport::popInterestingSymbolsAndRegions() {
1542 delete interestingSymbols
.back();
1543 interestingSymbols
.pop_back();
1544 delete interestingRegions
.back();
1545 interestingRegions
.pop_back();
1548 const Stmt
*BugReport::getStmt() const {
1552 ProgramPoint ProgP
= ErrorNode
->getLocation();
1553 const Stmt
*S
= NULL
;
1555 if (BlockEntrance
*BE
= dyn_cast
<BlockEntrance
>(&ProgP
)) {
1556 CFGBlock
&Exit
= ProgP
.getLocationContext()->getCFG()->getExit();
1557 if (BE
->getBlock() == &Exit
)
1558 S
= GetPreviousStmt(ErrorNode
);
1566 std::pair
<BugReport::ranges_iterator
, BugReport::ranges_iterator
>
1567 BugReport::getRanges() {
1568 // If no custom ranges, add the range of the statement corresponding to
1570 if (Ranges
.empty()) {
1571 if (const Expr
*E
= dyn_cast_or_null
<Expr
>(getStmt()))
1572 addRange(E
->getSourceRange());
1574 return std::make_pair(ranges_iterator(), ranges_iterator());
1577 // User-specified absence of range info.
1578 if (Ranges
.size() == 1 && !Ranges
.begin()->isValid())
1579 return std::make_pair(ranges_iterator(), ranges_iterator());
1581 return std::make_pair(Ranges
.begin(), Ranges
.end());
1584 PathDiagnosticLocation
BugReport::getLocation(const SourceManager
&SM
) const {
1586 assert(!Location
.isValid() &&
1587 "Either Location or ErrorNode should be specified but not both.");
1589 if (const Stmt
*S
= GetCurrentOrPreviousStmt(ErrorNode
)) {
1590 const LocationContext
*LC
= ErrorNode
->getLocationContext();
1592 // For member expressions, return the location of the '.' or '->'.
1593 if (const MemberExpr
*ME
= dyn_cast
<MemberExpr
>(S
))
1594 return PathDiagnosticLocation::createMemberLoc(ME
, SM
);
1595 // For binary operators, return the location of the operator.
1596 if (const BinaryOperator
*B
= dyn_cast
<BinaryOperator
>(S
))
1597 return PathDiagnosticLocation::createOperatorLoc(B
, SM
);
1599 return PathDiagnosticLocation::createBegin(S
, SM
, LC
);
1602 assert(Location
.isValid());
1606 return PathDiagnosticLocation();
1609 //===----------------------------------------------------------------------===//
1610 // Methods for BugReporter and subclasses.
1611 //===----------------------------------------------------------------------===//
1613 BugReportEquivClass::~BugReportEquivClass() { }
1614 GRBugReporter::~GRBugReporter() { }
1615 BugReporterData::~BugReporterData() {}
1617 ExplodedGraph
&GRBugReporter::getGraph() { return Eng
.getGraph(); }
1619 ProgramStateManager
&
1620 GRBugReporter::getStateManager() { return Eng
.getStateManager(); }
1622 BugReporter::~BugReporter() {
1625 // Free the bug reports we are tracking.
1626 typedef std::vector
<BugReportEquivClass
*> ContTy
;
1627 for (ContTy::iterator I
= EQClassesVector
.begin(), E
= EQClassesVector
.end();
1633 void BugReporter::FlushReports() {
1634 if (BugTypes
.isEmpty())
1637 // First flush the warnings for each BugType. This may end up creating new
1638 // warnings and new BugTypes.
1639 // FIXME: Only NSErrorChecker needs BugType's FlushReports.
1640 // Turn NSErrorChecker into a proper checker and remove this.
1641 SmallVector
<const BugType
*, 16> bugTypes
;
1642 for (BugTypesTy::iterator I
=BugTypes
.begin(), E
=BugTypes
.end(); I
!=E
; ++I
)
1643 bugTypes
.push_back(*I
);
1644 for (SmallVector
<const BugType
*, 16>::iterator
1645 I
= bugTypes
.begin(), E
= bugTypes
.end(); I
!= E
; ++I
)
1646 const_cast<BugType
*>(*I
)->FlushReports(*this);
1648 // We need to flush reports in deterministic order to ensure the order
1649 // of the reports is consistent between runs.
1650 typedef std::vector
<BugReportEquivClass
*> ContVecTy
;
1651 for (ContVecTy::iterator EI
=EQClassesVector
.begin(), EE
=EQClassesVector
.end();
1653 BugReportEquivClass
& EQ
= **EI
;
1657 // BugReporter owns and deletes only BugTypes created implicitly through
1659 // FIXME: There are leaks from checkers that assume that the BugTypes they
1660 // create will be destroyed by the BugReporter.
1661 for (llvm::StringMap
<BugType
*>::iterator
1662 I
= StrBugTypes
.begin(), E
= StrBugTypes
.end(); I
!= E
; ++I
)
1665 // Remove all references to the BugType objects.
1666 BugTypes
= F
.getEmptySet();
1669 //===----------------------------------------------------------------------===//
1670 // PathDiagnostics generation.
1671 //===----------------------------------------------------------------------===//
1673 static std::pair
<std::pair
<ExplodedGraph
*, NodeBackMap
*>,
1674 std::pair
<ExplodedNode
*, unsigned> >
1675 MakeReportGraph(const ExplodedGraph
* G
,
1676 SmallVectorImpl
<const ExplodedNode
*> &nodes
) {
1678 // Create the trimmed graph. It will contain the shortest paths from the
1679 // error nodes to the root. In the new graph we should only have one
1680 // error node unless there are two or more error nodes with the same minimum
1682 ExplodedGraph
* GTrim
;
1683 InterExplodedGraphMap
* NMap
;
1685 llvm::DenseMap
<const void*, const void*> InverseMap
;
1686 llvm::tie(GTrim
, NMap
) = G
->Trim(nodes
.data(), nodes
.data() + nodes
.size(),
1689 // Create owning pointers for GTrim and NMap just to ensure that they are
1690 // released when this function exists.
1691 OwningPtr
<ExplodedGraph
> AutoReleaseGTrim(GTrim
);
1692 OwningPtr
<InterExplodedGraphMap
> AutoReleaseNMap(NMap
);
1694 // Find the (first) error node in the trimmed graph. We just need to consult
1695 // the node map (NMap) which maps from nodes in the original graph to nodes
1696 // in the new graph.
1698 std::queue
<const ExplodedNode
*> WS
;
1699 typedef llvm::DenseMap
<const ExplodedNode
*, unsigned> IndexMapTy
;
1700 IndexMapTy IndexMap
;
1702 for (unsigned nodeIndex
= 0 ; nodeIndex
< nodes
.size(); ++nodeIndex
) {
1703 const ExplodedNode
*originalNode
= nodes
[nodeIndex
];
1704 if (const ExplodedNode
*N
= NMap
->getMappedNode(originalNode
)) {
1706 IndexMap
[originalNode
] = nodeIndex
;
1710 assert(!WS
.empty() && "No error node found in the trimmed graph.");
1712 // Create a new (third!) graph with a single path. This is the graph
1713 // that will be returned to the caller.
1714 ExplodedGraph
*GNew
= new ExplodedGraph();
1716 // Sometimes the trimmed graph can contain a cycle. Perform a reverse BFS
1717 // to the root node, and then construct a new graph that contains only
1719 llvm::DenseMap
<const void*,unsigned> Visited
;
1722 const ExplodedNode
*Root
= 0;
1724 while (!WS
.empty()) {
1725 const ExplodedNode
*Node
= WS
.front();
1728 if (Visited
.find(Node
) != Visited
.end())
1731 Visited
[Node
] = cnt
++;
1733 if (Node
->pred_empty()) {
1738 for (ExplodedNode::const_pred_iterator I
=Node
->pred_begin(),
1739 E
=Node
->pred_end(); I
!=E
; ++I
)
1745 // Now walk from the root down the BFS path, always taking the successor
1746 // with the lowest number.
1747 ExplodedNode
*Last
= 0, *First
= 0;
1748 NodeBackMap
*BM
= new NodeBackMap();
1749 unsigned NodeIndex
= 0;
1751 for ( const ExplodedNode
*N
= Root
;;) {
1752 // Lookup the number associated with the current node.
1753 llvm::DenseMap
<const void*,unsigned>::iterator I
= Visited
.find(N
);
1754 assert(I
!= Visited
.end());
1756 // Create the equivalent node in the new graph with the same state
1758 ExplodedNode
*NewN
= GNew
->getNode(N
->getLocation(), N
->getState());
1760 // Store the mapping to the original node.
1761 llvm::DenseMap
<const void*, const void*>::iterator IMitr
=InverseMap
.find(N
);
1762 assert(IMitr
!= InverseMap
.end() && "No mapping to original node.");
1763 (*BM
)[NewN
] = (const ExplodedNode
*) IMitr
->second
;
1765 // Link up the new node with the previous node.
1767 NewN
->addPredecessor(Last
, *GNew
);
1771 // Are we at the final node?
1772 IndexMapTy::iterator IMI
=
1773 IndexMap
.find((const ExplodedNode
*)(IMitr
->second
));
1774 if (IMI
!= IndexMap
.end()) {
1776 NodeIndex
= IMI
->second
;
1780 // Find the next successor node. We choose the node that is marked
1781 // with the lowest DFS number.
1782 ExplodedNode::const_succ_iterator SI
= N
->succ_begin();
1783 ExplodedNode::const_succ_iterator SE
= N
->succ_end();
1786 for (unsigned MinVal
= 0; SI
!= SE
; ++SI
) {
1788 I
= Visited
.find(*SI
);
1790 if (I
== Visited
.end())
1793 if (!N
|| I
->second
< MinVal
) {
1804 return std::make_pair(std::make_pair(GNew
, BM
),
1805 std::make_pair(First
, NodeIndex
));
1808 /// CompactPathDiagnostic - This function postprocesses a PathDiagnostic object
1809 /// and collapses PathDiagosticPieces that are expanded by macros.
1810 static void CompactPathDiagnostic(PathPieces
&path
, const SourceManager
& SM
) {
1811 typedef std::vector
<std::pair
<IntrusiveRefCntPtr
<PathDiagnosticMacroPiece
>,
1812 SourceLocation
> > MacroStackTy
;
1814 typedef std::vector
<IntrusiveRefCntPtr
<PathDiagnosticPiece
> >
1817 MacroStackTy MacroStack
;
1820 for (PathPieces::const_iterator I
= path
.begin(), E
= path
.end();
1823 PathDiagnosticPiece
*piece
= I
->getPtr();
1825 // Recursively compact calls.
1826 if (PathDiagnosticCallPiece
*call
=dyn_cast
<PathDiagnosticCallPiece
>(piece
)){
1827 CompactPathDiagnostic(call
->path
, SM
);
1830 // Get the location of the PathDiagnosticPiece.
1831 const FullSourceLoc Loc
= piece
->getLocation().asLocation();
1833 // Determine the instantiation location, which is the location we group
1834 // related PathDiagnosticPieces.
1835 SourceLocation InstantiationLoc
= Loc
.isMacroID() ?
1836 SM
.getExpansionLoc(Loc
) :
1839 if (Loc
.isFileID()) {
1841 Pieces
.push_back(piece
);
1845 assert(Loc
.isMacroID());
1847 // Is the PathDiagnosticPiece within the same macro group?
1848 if (!MacroStack
.empty() && InstantiationLoc
== MacroStack
.back().second
) {
1849 MacroStack
.back().first
->subPieces
.push_back(piece
);
1853 // We aren't in the same group. Are we descending into a new macro
1854 // or are part of an old one?
1855 IntrusiveRefCntPtr
<PathDiagnosticMacroPiece
> MacroGroup
;
1857 SourceLocation ParentInstantiationLoc
= InstantiationLoc
.isMacroID() ?
1858 SM
.getExpansionLoc(Loc
) :
1861 // Walk the entire macro stack.
1862 while (!MacroStack
.empty()) {
1863 if (InstantiationLoc
== MacroStack
.back().second
) {
1864 MacroGroup
= MacroStack
.back().first
;
1868 if (ParentInstantiationLoc
== MacroStack
.back().second
) {
1869 MacroGroup
= MacroStack
.back().first
;
1873 MacroStack
.pop_back();
1876 if (!MacroGroup
|| ParentInstantiationLoc
== MacroStack
.back().second
) {
1877 // Create a new macro group and add it to the stack.
1878 PathDiagnosticMacroPiece
*NewGroup
=
1879 new PathDiagnosticMacroPiece(
1880 PathDiagnosticLocation::createSingleLocation(piece
->getLocation()));
1883 MacroGroup
->subPieces
.push_back(NewGroup
);
1885 assert(InstantiationLoc
.isFileID());
1886 Pieces
.push_back(NewGroup
);
1889 MacroGroup
= NewGroup
;
1890 MacroStack
.push_back(std::make_pair(MacroGroup
, InstantiationLoc
));
1893 // Finally, add the PathDiagnosticPiece to the group.
1894 MacroGroup
->subPieces
.push_back(piece
);
1897 // Now take the pieces and construct a new PathDiagnostic.
1900 for (PiecesTy::iterator I
=Pieces
.begin(), E
=Pieces
.end(); I
!=E
; ++I
)
1904 bool GRBugReporter::generatePathDiagnostic(PathDiagnostic
& PD
,
1905 PathDiagnosticConsumer
&PC
,
1906 ArrayRef
<BugReport
*> &bugReports
) {
1907 assert(!bugReports
.empty());
1909 bool HasValid
= false;
1910 SmallVector
<const ExplodedNode
*, 10> errorNodes
;
1911 for (ArrayRef
<BugReport
*>::iterator I
= bugReports
.begin(),
1912 E
= bugReports
.end(); I
!= E
; ++I
) {
1913 if ((*I
)->isValid()) {
1915 errorNodes
.push_back((*I
)->getErrorNode());
1917 errorNodes
.push_back(0);
1921 // If all the reports have been marked invalid, we're done.
1925 // Construct a new graph that contains only a single path from the error
1927 const std::pair
<std::pair
<ExplodedGraph
*, NodeBackMap
*>,
1928 std::pair
<ExplodedNode
*, unsigned> >&
1929 GPair
= MakeReportGraph(&getGraph(), errorNodes
);
1931 // Find the BugReport with the original location.
1932 assert(GPair
.second
.second
< bugReports
.size());
1933 BugReport
*R
= bugReports
[GPair
.second
.second
];
1934 assert(R
&& "No original report found for sliced graph.");
1935 assert(R
->isValid() && "Report selected from trimmed graph marked invalid.");
1937 OwningPtr
<ExplodedGraph
> ReportGraph(GPair
.first
.first
);
1938 OwningPtr
<NodeBackMap
> BackMap(GPair
.first
.second
);
1939 const ExplodedNode
*N
= GPair
.second
.first
;
1941 // Start building the path diagnostic...
1942 PathDiagnosticBuilder
PDB(*this, R
, BackMap
.get(), &PC
);
1944 // Register additional node visitors.
1945 R
->addVisitor(new NilReceiverBRVisitor());
1946 R
->addVisitor(new ConditionBRVisitor());
1948 BugReport::VisitorList visitors
;
1949 unsigned originalReportConfigToken
, finalReportConfigToken
;
1951 // While generating diagnostics, it's possible the visitors will decide
1952 // new symbols and regions are interesting, or add other visitors based on
1953 // the information they find. If they do, we need to regenerate the path
1954 // based on our new report configuration.
1956 // Get a clean copy of all the visitors.
1957 for (BugReport::visitor_iterator I
= R
->visitor_begin(),
1958 E
= R
->visitor_end(); I
!= E
; ++I
)
1959 visitors
.push_back((*I
)->clone());
1961 // Clear out the active path from any previous work.
1963 originalReportConfigToken
= R
->getConfigurationChangeToken();
1965 // Generate the very last diagnostic piece - the piece is visible before
1966 // the trace is expanded.
1967 if (PDB
.getGenerationScheme() != PathDiagnosticConsumer::None
) {
1968 PathDiagnosticPiece
*LastPiece
= 0;
1969 for (BugReport::visitor_iterator I
= visitors
.begin(), E
= visitors
.end();
1971 if (PathDiagnosticPiece
*Piece
= (*I
)->getEndPath(PDB
, N
, *R
)) {
1972 assert (!LastPiece
&&
1973 "There can only be one final piece in a diagnostic.");
1978 LastPiece
= BugReporterVisitor::getDefaultEndPath(PDB
, N
, *R
);
1980 PD
.setEndOfPath(LastPiece
);
1985 switch (PDB
.getGenerationScheme()) {
1986 case PathDiagnosticConsumer::Extensive
:
1987 if (!GenerateExtensivePathDiagnostic(PD
, PDB
, N
, visitors
)) {
1988 assert(!R
->isValid() && "Failed on valid report");
1989 // Try again. We'll filter out the bad report when we trim the graph.
1990 // FIXME: It would be more efficient to use the same intermediate
1991 // trimmed graph, and just repeat the shortest-path search.
1992 return generatePathDiagnostic(PD
, PC
, bugReports
);
1995 case PathDiagnosticConsumer::Minimal
:
1996 if (!GenerateMinimalPathDiagnostic(PD
, PDB
, N
, visitors
)) {
1997 assert(!R
->isValid() && "Failed on valid report");
1998 // Try again. We'll filter out the bad report when we trim the graph.
1999 return generatePathDiagnostic(PD
, PC
, bugReports
);
2002 case PathDiagnosticConsumer::None
:
2003 if (!GenerateVisitorsOnlyPathDiagnostic(PD
, PDB
, N
, visitors
)) {
2004 assert(!R
->isValid() && "Failed on valid report");
2005 // Try again. We'll filter out the bad report when we trim the graph.
2006 return generatePathDiagnostic(PD
, PC
, bugReports
);
2011 // Clean up the visitors we used.
2012 llvm::DeleteContainerPointers(visitors
);
2014 // Did anything change while generating this path?
2015 finalReportConfigToken
= R
->getConfigurationChangeToken();
2016 } while(finalReportConfigToken
!= originalReportConfigToken
);
2018 // Finally, prune the diagnostic path of uninteresting stuff.
2019 if (!PD
.path
.empty() && R
->shouldPrunePath()) {
2020 bool hasSomethingInteresting
= RemoveUneededCalls(PD
.getMutablePieces(), R
);
2021 assert(hasSomethingInteresting
);
2022 (void) hasSomethingInteresting
;
2028 void BugReporter::Register(BugType
*BT
) {
2029 BugTypes
= F
.add(BugTypes
, BT
);
2032 void BugReporter::EmitReport(BugReport
* R
) {
2033 // Compute the bug report's hash to determine its equivalence class.
2034 llvm::FoldingSetNodeID ID
;
2037 // Lookup the equivance class. If there isn't one, create it.
2038 BugType
& BT
= R
->getBugType();
2041 BugReportEquivClass
* EQ
= EQClasses
.FindNodeOrInsertPos(ID
, InsertPos
);
2044 EQ
= new BugReportEquivClass(R
);
2045 EQClasses
.InsertNode(EQ
, InsertPos
);
2046 EQClassesVector
.push_back(EQ
);
2053 //===----------------------------------------------------------------------===//
2054 // Emitting reports in equivalence classes.
2055 //===----------------------------------------------------------------------===//
2058 struct FRIEC_WLItem
{
2059 const ExplodedNode
*N
;
2060 ExplodedNode::const_succ_iterator I
, E
;
2062 FRIEC_WLItem(const ExplodedNode
*n
)
2063 : N(n
), I(N
->succ_begin()), E(N
->succ_end()) {}
2068 FindReportInEquivalenceClass(BugReportEquivClass
& EQ
,
2069 SmallVectorImpl
<BugReport
*> &bugReports
) {
2071 BugReportEquivClass::iterator I
= EQ
.begin(), E
= EQ
.end();
2073 BugType
& BT
= I
->getBugType();
2075 // If we don't need to suppress any of the nodes because they are
2076 // post-dominated by a sink, simply add all the nodes in the equivalence class
2077 // to 'Nodes'. Any of the reports will serve as a "representative" report.
2078 if (!BT
.isSuppressOnSink()) {
2080 for (BugReportEquivClass::iterator I
=EQ
.begin(), E
=EQ
.end(); I
!=E
; ++I
) {
2081 const ExplodedNode
*N
= I
->getErrorNode();
2084 bugReports
.push_back(R
);
2090 // For bug reports that should be suppressed when all paths are post-dominated
2091 // by a sink node, iterate through the reports in the equivalence class
2092 // until we find one that isn't post-dominated (if one exists). We use a
2093 // DFS traversal of the ExplodedGraph to find a non-sink node. We could write
2094 // this as a recursive function, but we don't want to risk blowing out the
2095 // stack for very long paths.
2096 BugReport
*exampleReport
= 0;
2098 for (; I
!= E
; ++I
) {
2099 const ExplodedNode
*errorNode
= I
->getErrorNode();
2103 if (errorNode
->isSink()) {
2105 "BugType::isSuppressSink() should not be 'true' for sink end nodes");
2107 // No successors? By definition this nodes isn't post-dominated by a sink.
2108 if (errorNode
->succ_empty()) {
2109 bugReports
.push_back(I
);
2115 // At this point we know that 'N' is not a sink and it has at least one
2116 // successor. Use a DFS worklist to find a non-sink end-of-path node.
2117 typedef FRIEC_WLItem WLItem
;
2118 typedef SmallVector
<WLItem
, 10> DFSWorkList
;
2119 llvm::DenseMap
<const ExplodedNode
*, unsigned> Visited
;
2122 WL
.push_back(errorNode
);
2123 Visited
[errorNode
] = 1;
2125 while (!WL
.empty()) {
2126 WLItem
&WI
= WL
.back();
2127 assert(!WI
.N
->succ_empty());
2129 for (; WI
.I
!= WI
.E
; ++WI
.I
) {
2130 const ExplodedNode
*Succ
= *WI
.I
;
2131 // End-of-path node?
2132 if (Succ
->succ_empty()) {
2133 // If we found an end-of-path node that is not a sink.
2134 if (!Succ
->isSink()) {
2135 bugReports
.push_back(I
);
2141 // Found a sink? Continue on to the next successor.
2144 // Mark the successor as visited. If it hasn't been explored,
2145 // enqueue it to the DFS worklist.
2146 unsigned &mark
= Visited
[Succ
];
2154 // The worklist may have been cleared at this point. First
2155 // check if it is empty before checking the last item.
2156 if (!WL
.empty() && &WL
.back() == &WI
)
2161 // ExampleReport will be NULL if all the nodes in the equivalence class
2162 // were post-dominated by sinks.
2163 return exampleReport
;
2166 void BugReporter::FlushReport(BugReportEquivClass
& EQ
) {
2167 SmallVector
<BugReport
*, 10> bugReports
;
2168 BugReport
*exampleReport
= FindReportInEquivalenceClass(EQ
, bugReports
);
2169 if (exampleReport
) {
2170 const PathDiagnosticConsumers
&C
= getPathDiagnosticConsumers();
2171 for (PathDiagnosticConsumers::const_iterator I
=C
.begin(),
2172 E
=C
.end(); I
!= E
; ++I
) {
2173 FlushReport(exampleReport
, **I
, bugReports
);
2178 void BugReporter::FlushReport(BugReport
*exampleReport
,
2179 PathDiagnosticConsumer
&PD
,
2180 ArrayRef
<BugReport
*> bugReports
) {
2182 // FIXME: Make sure we use the 'R' for the path that was actually used.
2183 // Probably doesn't make a difference in practice.
2184 BugType
& BT
= exampleReport
->getBugType();
2186 OwningPtr
<PathDiagnostic
>
2187 D(new PathDiagnostic(exampleReport
->getDeclWithIssue(),
2188 exampleReport
->getBugType().getName(),
2189 exampleReport
->getDescription(),
2190 exampleReport
->getShortDescription(/*Fallback=*/false),
2193 // Generate the full path diagnostic, using the generation scheme
2194 // specified by the PathDiagnosticConsumer. Note that we have to generate
2195 // path diagnostics even for consumers which do not support paths, because
2196 // the BugReporterVisitors may mark this bug as a false positive.
2197 if (!bugReports
.empty())
2198 if (!generatePathDiagnostic(*D
.get(), PD
, bugReports
))
2201 // If the path is empty, generate a single step path with the location
2203 if (D
->path
.empty()) {
2204 PathDiagnosticLocation L
= exampleReport
->getLocation(getSourceManager());
2205 PathDiagnosticPiece
*piece
=
2206 new PathDiagnosticEventPiece(L
, exampleReport
->getDescription());
2207 BugReport::ranges_iterator Beg
, End
;
2208 llvm::tie(Beg
, End
) = exampleReport
->getRanges();
2209 for ( ; Beg
!= End
; ++Beg
)
2210 piece
->addRange(*Beg
);
2211 D
->setEndOfPath(piece
);
2214 // Get the meta data.
2215 const BugReport::ExtraTextList
&Meta
= exampleReport
->getExtraText();
2216 for (BugReport::ExtraTextList::const_iterator i
= Meta
.begin(),
2217 e
= Meta
.end(); i
!= e
; ++i
) {
2221 PD
.HandlePathDiagnostic(D
.take());
2224 void BugReporter::EmitBasicReport(const Decl
*DeclWithIssue
,
2227 StringRef str
, PathDiagnosticLocation Loc
,
2228 SourceRange
* RBeg
, unsigned NumRanges
) {
2230 // 'BT' is owned by BugReporter.
2231 BugType
*BT
= getBugTypeForName(name
, category
);
2232 BugReport
*R
= new BugReport(*BT
, str
, Loc
);
2233 R
->setDeclWithIssue(DeclWithIssue
);
2234 for ( ; NumRanges
> 0 ; --NumRanges
, ++RBeg
) R
->addRange(*RBeg
);
2238 BugType
*BugReporter::getBugTypeForName(StringRef name
,
2239 StringRef category
) {
2240 SmallString
<136> fullDesc
;
2241 llvm::raw_svector_ostream(fullDesc
) << name
<< ":" << category
;
2242 llvm::StringMapEntry
<BugType
*> &
2243 entry
= StrBugTypes
.GetOrCreateValue(fullDesc
);
2244 BugType
*BT
= entry
.getValue();
2246 BT
= new BugType(name
, category
);