const SourceRange*& end) const;
};
+class BugReporterHelper {
+public:
+ virtual ~BugReporterHelper() {}
+
+ virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
+ ExplodedNode<ValueState>* PrevN,
+ ExplodedGraph<GRExprEngine>& G,
+ ASTContext& Ctx) = 0;
+};
+
class BugReporter {
llvm::SmallPtrSet<void*,10> CachedErrors;
void EmitPathWarning(Diagnostic& Diag, PathDiagnosticClient* PDC,
ASTContext& Ctx, const BugDescription& B,
ExplodedGraph<GRExprEngine>& G,
- ExplodedNode<ValueState>* N);
+ ExplodedNode<ValueState>* N,
+ BugReporterHelper** BegHelpers = NULL,
+ BugReporterHelper** EndHelpers = NULL);
void EmitWarning(Diagnostic& Diag, ASTContext& Ctx,
const BugDescription& B,
void GeneratePathDiagnostic(PathDiagnostic& PD, ASTContext& Ctx,
const BugDescription& B,
ExplodedGraph<GRExprEngine>& G,
- ExplodedNode<ValueState>* N);
+ ExplodedNode<ValueState>* N,
+ BugReporterHelper** BegHelpers = NULL,
+ BugReporterHelper** EndHelpers = NULL);
};
} // end clang namespace
void BugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, ASTContext& Ctx,
const BugDescription& B,
ExplodedGraph<GRExprEngine>& G,
- ExplodedNode<ValueState>* N) {
+ ExplodedNode<ValueState>* N,
+ BugReporterHelper** BegHelpers,
+ BugReporterHelper** EndHelpers) {
if (PathDiagnosticPiece* Piece = B.getEndPath(Ctx,N))
PD.push_back(Piece);
assert (NewN->getLocation() == N->getLocation());
N = NewN;
-
- while (!N->pred_empty()) {
+
+ ExplodedNode<ValueState>* NextNode = N->pred_empty()
+ ? NULL : *(N->pred_begin());
+
+ while (NextNode) {
ExplodedNode<ValueState>* LastNode = N;
- N = *(N->pred_begin());
+ N = NextNode;
+ NextNode = N->pred_empty() ? NULL : *(N->pred_begin());
ProgramPoint P = N->getLocation();
case Stmt::DefaultStmtClass: {
os << "Control jumps to the 'default' case at line "
- << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
+ << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
break;
}
break;
}
}
- }
+ }
+ else
+ for (BugReporterHelper** I = BegHelpers; I != EndHelpers; ++I) {
+
+ PathDiagnosticPiece* piece = (*I)->VisitNode(N, NextNode, G, Ctx);
+
+ if (piece)
+ PD.push_front(piece);
+ }
}
}
ASTContext& Ctx,
const BugDescription& B,
ExplodedGraph<GRExprEngine>& G,
- ExplodedNode<ValueState>* N) {
+ ExplodedNode<ValueState>* N,
+ BugReporterHelper** BegHelpers,
+ BugReporterHelper** EndHelpers) {
if (!PDC) {
EmitWarning(Diag, Ctx, B, N);
return;
PathDiagnostic D(B.getName());
- GeneratePathDiagnostic(D, Ctx, B, G, N);
+ GeneratePathDiagnostic(D, Ctx, B, G, N, BegHelpers, EndHelpers);
if (!D.empty())
PDC->HandlePathDiagnostic(D);