/// individual bug reports.
class BugReport : public llvm::ilist_node<BugReport> {
public:
- class NodeResolver {
- virtual void anchor();
-
- public:
- virtual ~NodeResolver() = default;
-
- virtual const ExplodedNode*
- getOriginalNode(const ExplodedNode *N) = 0;
- };
-
using ranges_iterator = const SourceRange *;
using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
using visitor_iterator = VisitorList::iterator;
public:
virtual ~BugReporterData() = default;
- virtual DiagnosticsEngine& getDiagnostic() = 0;
virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
virtual ASTContext &getASTContext() = 0;
virtual SourceManager &getSourceManager() = 0;
///
/// The base class is used for generating path-insensitive
class BugReporter {
-public:
- enum Kind { BasicBRKind, PathSensitiveBRKind };
-
private:
- const Kind kind;
BugReporterData& D;
/// Generate and flush the diagnostics for the given bug report.
/// A vector of BugReports for tracking the allocated pointers and cleanup.
std::vector<BugReportEquivClass *> EQClassesVector;
-protected:
- BugReporter(BugReporterData& d, Kind k)
- : kind(k), D(d) {}
-
public:
- BugReporter(BugReporterData &d) : kind(BasicBRKind), D(d) {}
+ BugReporter(BugReporterData &d) : D(d) {}
virtual ~BugReporter();
/// Generate and flush diagnostics for all bug reports.
void FlushReports();
- Kind getKind() const { return kind; }
-
- DiagnosticsEngine& getDiagnostic() {
- return D.getDiagnostic();
- }
-
ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
return D.getPathDiagnosticConsumers();
}
public:
PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng)
- : BugReporter(d, PathSensitiveBRKind), Eng(eng) {}
+ : BugReporter(d), Eng(eng) {}
/// getGraph - Get the exploded graph created by the analysis engine
/// for the analyzed method or function.
/// getStateManager - Return the state manager used by the analysis
/// engine.
- ProgramStateManager &getStateManager();
-
ProgramStateManager &getStateManager() const;
/// \p bugReports A set of bug reports within a *single* equivalence class
std::unique_ptr<DiagnosticForConsumerMapTy>
generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers,
ArrayRef<BugReport *> &bugReports) override;
-
- /// classof - Used by isa<>, cast<>, and dyn_cast<>.
- static bool classof(const BugReporter* R) {
- return R->getKind() == PathSensitiveBRKind;
- }
};
-class NodeMapClosure : public BugReport::NodeResolver {
- InterExplodedGraphMap &M;
-
-public:
- NodeMapClosure(InterExplodedGraphMap &m) : M(m) {}
-
- const ExplodedNode *getOriginalNode(const ExplodedNode *N) override {
- return M.lookup(N);
- }
-};
-
class BugReporterContext {
PathSensitiveBugReporter &BR;
- NodeMapClosure NMC;
virtual void anchor();
public:
- BugReporterContext(PathSensitiveBugReporter &br,
- InterExplodedGraphMap &Backmap)
- : BR(br), NMC(Backmap) {}
+ BugReporterContext(PathSensitiveBugReporter &br) : BR(br) {}
virtual ~BugReporterContext() = default;
PathSensitiveBugReporter& getBugReporter() { return BR; }
- const ExplodedGraph &getGraph() const { return BR.getGraph(); }
-
ProgramStateManager& getStateManager() const {
return BR.getStateManager();
}
- SValBuilder &getSValBuilder() const {
- return getStateManager().getSValBuilder();
- }
-
ASTContext &getASTContext() const {
return BR.getContext();
}
const AnalyzerOptions &getAnalyzerOptions() const {
return BR.getAnalyzerOptions();
}
-
- NodeMapClosure& getNodeResolver() { return NMC; }
};
const StackFrameContext *OriginSFC;
public:
- /// Creates a visitor for every VarDecl inside a Stmt and registers it with
- /// the BugReport.
- static void registerStatementVarDecls(BugReport &BR, const Stmt *S,
- bool EnableNullFPSuppression,
- TrackingKind TKind);
-
/// \param V We're searching for the store where \c R received this value.
/// \param R The region we're tracking.
/// \param TKind May limit the amount of notes added to the bug report.
PathPieces subPieces;
- bool containsEvent() const;
-
void flattenLocations() override {
PathDiagnosticSpotPiece::flattenLocations();
for (const auto &I : subPieces)
AnalysisDeclContextManager AnaCtxMgr;
ASTContext &Ctx;
- DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
PathDiagnosticConsumers PathConsumers;
public:
AnalyzerOptions &options;
- AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
+ AnalysisManager(ASTContext &ctx,
const PathDiagnosticConsumers &Consumers,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
return getASTContext().getSourceManager();
}
- DiagnosticsEngine &getDiagnostic() override {
- return Diags;
- }
-
const LangOptions &getLangOpts() const {
return LangOpts;
}
void AnalysisManager::anchor() { }
-AnalysisManager::AnalysisManager(ASTContext &ASTCtx, DiagnosticsEngine &diags,
+AnalysisManager::AnalysisManager(ASTContext &ASTCtx,
const PathDiagnosticConsumers &PDC,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr,
Options.ShouldElideConstructors,
/*addVirtualBaseBranches=*/true,
injector),
- Ctx(ASTCtx), Diags(diags), LangOpts(ASTCtx.getLangOpts()),
+ Ctx(ASTCtx), LangOpts(ASTCtx.getLangOpts()),
PathConsumers(PDC), CreateStoreMgr(storemgr),
CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr),
options(Options) {
// Methods for BugReport and subclasses.
//===----------------------------------------------------------------------===//
-void BugReport::NodeResolver::anchor() {}
-
void BugReport::addVisitor(std::unique_ptr<BugReporterVisitor> visitor) {
if (!visitor)
return;
return Eng.getGraph();
}
-ProgramStateManager &PathSensitiveBugReporter::getStateManager() {
- return Eng.getStateManager();
-}
-
ProgramStateManager &PathSensitiveBugReporter::getStateManager() const {
return Eng.getStateManager();
}
namespace {
/// A wrapper around an ExplodedGraph that contains a single path from the root
-/// to the error node, and a map that maps the nodes in this path to the ones in
-/// the original ExplodedGraph.
+/// to the error node.
class BugPathInfo {
public:
- InterExplodedGraphMap MapToOriginNodes;
std::unique_ptr<ExplodedGraph> BugPath;
BugReport *Report;
const ExplodedNode *ErrorNode;
class BugPathGetter {
std::unique_ptr<ExplodedGraph> TrimmedGraph;
- /// Map from the trimmed graph to the original.
- InterExplodedGraphMap InverseMap;
-
using PriorityMapTy = llvm::DenseMap<const ExplodedNode *, unsigned>;
/// Assign each node with its distance from the root.
// The trimmed graph is created in the body of the constructor to ensure
// that the DenseMaps have been initialized already.
InterExplodedGraphMap ForwardMap;
- TrimmedGraph = OriginalGraph->trim(Nodes, &ForwardMap, &InverseMap);
+ TrimmedGraph = OriginalGraph->trim(Nodes, &ForwardMap);
// Find the (first) error node in the trimmed graph. We just need to consult
// the node map which maps from nodes in the original graph to nodes
// Create a new graph with a single path. This is the graph that will be
// returned to the caller.
auto GNew = std::make_unique<ExplodedGraph>();
- CurrentBugPath.MapToOriginNodes.clear();
// Now walk from the error node up the BFS path, always taking the
// predeccessor with the lowest number.
ExplodedNode *NewN = GNew->createUncachedNode(
OrigN->getLocation(), OrigN->getState(), OrigN->isSink());
- // Store the mapping to the original node.
- InterExplodedGraphMap::const_iterator IMitr = InverseMap.find(OrigN);
- assert(IMitr != InverseMap.end() && "No mapping to original node.");
- CurrentBugPath.MapToOriginNodes[NewN] = IMitr->second;
-
// Link up the new node with the previous node.
if (Succ)
Succ->addPredecessor(NewN, *GNew);
R->addVisitor(std::make_unique<ConditionBRVisitor>());
R->addVisitor(std::make_unique<TagVisitor>());
- BugReporterContext BRC(Reporter, BugPath->MapToOriginNodes);
+ BugReporterContext BRC(Reporter);
// Run all visitors on a given graph, once.
std::unique_ptr<VisitorsDiagnosticsTy> visitorNotes =
ID.AddBoolean(EnableNullFPSuppression);
}
-void FindLastStoreBRVisitor::registerStatementVarDecls(
- BugReport &BR, const Stmt *S, bool EnableNullFPSuppression,
- TrackingKind TKind) {
-
- const ExplodedNode *N = BR.getErrorNode();
- std::deque<const Stmt *> WorkList;
- WorkList.push_back(S);
-
- while (!WorkList.empty()) {
- const Stmt *Head = WorkList.front();
- WorkList.pop_front();
-
- ProgramStateManager &StateMgr = N->getState()->getStateManager();
-
- if (const auto *DR = dyn_cast<DeclRefExpr>(Head)) {
- if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
- const VarRegion *R =
- StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
-
- // What did we load?
- SVal V = N->getSVal(S);
-
- if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
- // Register a new visitor with the BugReport.
- BR.addVisitor(std::make_unique<FindLastStoreBRVisitor>(
- V.castAs<KnownSVal>(), R, EnableNullFPSuppression, TKind));
- }
- }
- }
-
- for (const Stmt *SubStmt : Head->children())
- WorkList.push_back(SubStmt);
- }
-}
-
/// Returns true if \p N represents the DeclStmt declaring and initializing
/// \p VR.
static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
using namespace clang;
using namespace ento;
-bool PathDiagnosticMacroPiece::containsEvent() const {
- for (const auto &P : subPieces) {
- if (isa<PathDiagnosticEventPiece>(*P))
- return true;
- if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get()))
- if (MP->containsEvent())
- return true;
- }
- return false;
-}
-
static StringRef StripTrailingDots(StringRef s) {
for (StringRef::size_type i = s.size(); i != 0; --i)
if (s[i - 1] != '.')
checkerMgr = createCheckerManager(
*Ctx, *Opts, Plugins, CheckerRegistrationFns, PP.getDiagnostics());
- Mgr = std::make_unique<AnalysisManager>(
- *Ctx, PP.getDiagnostics(), PathConsumers, CreateStoreMgr,
- CreateConstraintMgr, checkerMgr.get(), *Opts, Injector);
+ Mgr = std::make_unique<AnalysisManager>(*Ctx, PathConsumers, CreateStoreMgr,
+ CreateConstraintMgr,
+ checkerMgr.get(), *Opts, Injector);
}
/// Store the top level decls in the set to be processed later on.
ExprEngineConsumer(CompilerInstance &C)
: C(C), ChkMgr(C.getASTContext(), *C.getAnalyzerOpts()), CTU(C),
Consumers(),
- AMgr(C.getASTContext(), C.getDiagnostics(), Consumers,
+ AMgr(C.getASTContext(), Consumers,
CreateRegionStoreManager, CreateRangeConstraintManager, &ChkMgr,
*C.getAnalyzerOpts()),
VisitedCallees(), FS(),