VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred,
BugReporterContext &BRC, BugReport &BR) = 0;
+ /// Last function called on the visitor, no further calls to VisitNode
+ /// would follow.
+ virtual void finalizeVisitor(BugReporterContext &BRC,
+ const ExplodedNode *EndPathNode,
+ BugReport &BR);
+
/// Provide custom definition for the final diagnostic piece on the
/// path - the piece, which is displayed before the path is expanded.
///
- /// If returns NULL the default implementation will be used.
- /// Also note that at most one visitor of a BugReport should generate a
- /// non-NULL end of path diagnostic piece.
+ /// NOTE that this function can be implemented on at most one used visitor,
+ /// and otherwise it crahes at runtime.
virtual std::unique_ptr<PathDiagnosticPiece>
getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR);
return nullptr;
}
- std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) override;
+ void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
+ BugReport &BR) override;
};
/// When a region containing undefined value or '0' value is passed
PathDiagnostic &PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N,
LocationContextMap &LCM,
ArrayRef<std::unique_ptr<BugReporterVisitor>> visitors,
+ BugReport *R,
PathDiagnosticConsumer::PathGenerationScheme ActiveScheme) {
+ const ExplodedNode *LastNode = N;
BugReport *report = PDB.getBugReport();
StackDiagVector CallStack;
InterestingExprs IE;
generatePathDiagnosticsForNode(
N, PD, PrevLoc, PDB, LCM, CallStack, IE, AddPathEdges);
- if (!NextNode)
+ if (!NextNode) {
+ for (auto &V : visitors) {
+ V->finalizeVisitor(PDB, LastNode, *R);
+ }
continue;
+ }
// Add pieces from custom visitors.
llvm::FoldingSet<PathDiagnosticPiece> DeduplicationSet;
// hold onto old mappings.
LCM.clear();
- generatePathDiagnostics(PD, PDB, N, LCM, visitors, ActiveScheme);
+ generatePathDiagnostics(PD, PDB, N, LCM, visitors, R, ActiveScheme);
// Clean up the visitors we used.
visitors.clear();
return nullptr;
}
+void
+BugReporterVisitor::finalizeVisitor(BugReporterContext &BRC,
+ const ExplodedNode *EndPathNode,
+ BugReport &BR) {};
+
std::unique_ptr<PathDiagnosticPiece> BugReporterVisitor::getDefaultEndPath(
BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {
PathDiagnosticLocation L =
llvm_unreachable("Invalid visit mode!");
}
- std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) override {
+ void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
+ BugReport &BR) override {
if (EnableNullFPSuppression)
BR.markInvalid(ReturnVisitor::getTag(), StackFrame);
- return nullptr;
}
};
Piece->getString() == GenericFalseMessage;
}
-std::unique_ptr<PathDiagnosticPiece>
-LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) {
+void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
+ BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) {
// Here we suppress false positives coming from system headers. This list is
// based on known issues.
ExprEngine &Eng = BRC.getBugReporter().getEngine();
// TR1, Boost, or llvm/ADT.
if (Options.shouldSuppressFromCXXStandardLibrary()) {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
} else {
// If the complete 'std' suppression is not enabled, suppress reports
// from the 'std' namespace that are known to produce false positives.
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "list") {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
}
const CXXRecordDecl *CD = MD->getParent();
if (CD->getName() == "__independent_bits_engine") {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
}
// data structure.
if (CD->getName() == "basic_string") {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
// The analyzer issues a false positive on
// because it does not reason properly about temporary destructors.
if (CD->getName() == "shared_ptr") {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
}
}
Loc = Loc.getSpellingLoc();
if (SM.getFilename(Loc).endswith("sys/queue.h")) {
BR.markInvalid(getTag(), nullptr);
- return nullptr;
+ return;
}
}
-
- return nullptr;
}
std::shared_ptr<PathDiagnosticPiece>