Skip to content

Commit ed9cc40

Browse files
committed
[analyzer][NFC] Refactoring BugReporter.cpp P2.: Clean up the construction of bug paths and finding a valid report
This patch refactors the utility functions and classes around the construction of a bug path. At a very high level, this consists of 3 steps: * For all BugReports in the same BugReportEquivClass, collect all their error nodes in a set. With that set, create a new, trimmed ExplodedGraph whose leafs are all error nodes. * Until a valid report is found, construct a bug path, which is yet another ExplodedGraph, that is linear from a given error node to the root of the graph. * Run all visitors on the constructed bug path. If in this process the report got invalidated, start over from step 2. Now, to the changes within this patch: * Do not allow the invalidation of BugReports up to the point where the trimmed graph is constructed. Checkers shouldn't add bug reports that are known to be invalid, and should use visitors and argue about the entirety of the bug path if needed. * Do not calculate indices. I may be biased, but I personally find code like this horrible. I'd like to point you to one of the comments in the original code: SmallVector<const ExplodedNode *, 32> errorNodes; for (const auto I : bugReports) { if (I->isValid()) { HasValid = true; errorNodes.push_back(I->getErrorNode()); } else { // Keep the errorNodes list in sync with the bugReports list. errorNodes.push_back(nullptr); } } Not on my watch. Instead, use a far easier to follow trick: store a pointer to the BugReport in question, not an index to it. * Add range iterators to ExplodedGraph's successors and predecessors, and a visitor range to BugReporter. * Rename TrimmedGraph to BugPathGetter. Because that is what it has always been: no sane graph type should store an iterator-like state, or have an interface not exposing a single graph-like functionalities. * Rename ReportGraph to BugPathInfo, because it is only a linear path with some other context. * Instead of having both and out and in parameter (which I think isn't ever excusable unless we use the out-param for caching), return a record object with descriptive getter methods. * Where descriptive names weren't sufficient, compliment the code with comments. Differential Revision: https://reviews.llvm.org/D65379 llvm-svn: 368694
1 parent bda73ae commit ed9cc40

File tree

3 files changed

+128
-96
lines changed

3 files changed

+128
-96
lines changed

clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class BugReport : public llvm::ilist_node<BugReport> {
8787
using ranges_iterator = const SourceRange *;
8888
using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
8989
using visitor_iterator = VisitorList::iterator;
90+
using visitor_range = llvm::iterator_range<visitor_iterator>;
9091
using ExtraTextList = SmallVector<StringRef, 2>;
9192
using NoteList = SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4>;
9293

@@ -339,6 +340,7 @@ class BugReport : public llvm::ilist_node<BugReport> {
339340
/// Iterators through the custom diagnostic visitors.
340341
visitor_iterator visitor_begin() { return Callbacks.begin(); }
341342
visitor_iterator visitor_end() { return Callbacks.end(); }
343+
visitor_range visitors() { return {visitor_begin(), visitor_end()}; }
342344

343345
/// Notes that the condition of the CFGBlock associated with \p Cond is
344346
/// being tracked.

clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,29 +219,40 @@ class ExplodedNode : public llvm::FoldingSetNode {
219219

220220
// Iterators over successor and predecessor vertices.
221221
using succ_iterator = ExplodedNode * const *;
222+
using succ_range = llvm::iterator_range<succ_iterator>;
223+
222224
using const_succ_iterator = const ExplodedNode * const *;
225+
using const_succ_range = llvm::iterator_range<const_succ_iterator>;
226+
223227
using pred_iterator = ExplodedNode * const *;
228+
using pred_range = llvm::iterator_range<pred_iterator>;
229+
224230
using const_pred_iterator = const ExplodedNode * const *;
231+
using const_pred_range = llvm::iterator_range<const_pred_iterator>;
225232

226233
pred_iterator pred_begin() { return Preds.begin(); }
227234
pred_iterator pred_end() { return Preds.end(); }
235+
pred_range preds() { return {Preds.begin(), Preds.end()}; }
228236

229237
const_pred_iterator pred_begin() const {
230238
return const_cast<ExplodedNode*>(this)->pred_begin();
231239
}
232240
const_pred_iterator pred_end() const {
233241
return const_cast<ExplodedNode*>(this)->pred_end();
234242
}
243+
const_pred_range preds() const { return {Preds.begin(), Preds.end()}; }
235244

236245
succ_iterator succ_begin() { return Succs.begin(); }
237246
succ_iterator succ_end() { return Succs.end(); }
247+
succ_range succs() { return {Succs.begin(), Succs.end()}; }
238248

239249
const_succ_iterator succ_begin() const {
240250
return const_cast<ExplodedNode*>(this)->succ_begin();
241251
}
242252
const_succ_iterator succ_end() const {
243253
return const_cast<ExplodedNode*>(this)->succ_end();
244254
}
255+
const_succ_range succs() const { return {Succs.begin(), Succs.end()}; }
245256

246257
int64_t getID(ExplodedGraph *G) const;
247258

0 commit comments

Comments
 (0)