I'm slowly cleaning up BugReporter as a preparation for porting clang-tidy to use it exclusively as discussed in http://lists.llvm.org/pipermail/cfe-dev/2019-August/063092.html . Basically, we'll need to make a BugReport and a BugReporter that both can be compiled with CLANG_ENABLE_STATIC_ANALYZER=OFF: no "error nodes", no nothing. So we'll most likely make a clear separation between a basic bug report(er) and a path-sensitive bug report(er), having them inherit from common bug report(er) classes.
While figuring out which field/method goes where, i already made a couple of trivial commits (rC369319, rC369320). This one, however, is relatively interesting.
The BugTypes field is basically unused, and it definitely doesn't need to be implemented as an immutable set (if at all). But once i removed it i started noticing a bunch of null dereferences in generateDiagnosticForConsumerMap():
3060 std::unique_ptr<DiagnosticForConsumerMapTy> Out = 3061 generatePathDiagnostics(consumers, bugReports); 3062 3063 if (Out->empty()) // <== crash: Out is null! 3064 return Out;
This was fun to debug because it's obvious by looking at PathSensitiveBugReporter::generatePathDiagnostics() that it never returns null:
2643 std::unique_ptr<DiagnosticForConsumerMapTy> 2644 PathSensitiveBugReporter::generatePathDiagnostics(...) { ... 2649 auto Out = llvm::make_unique<DiagnosticForConsumerMapTy>(); ... 2658 return Out; 2659 }
The debugger was also sure that we're dealing with a path-sensitive bug reporter here. The answer turned out to be related to this tiny discussion. Or, rather, here's a report that's worth a thousand words:
So i decided to avoid the destructor minefield entirely, even if it means calling flush manually.
Also, ugh, why is CloneChecker subscribed to check::EndOfTranslationUnit which is a path-sensitive callback? :/