Is this a bug in AnalysisConsumer ?

In AnalysisConsumer::HandleTranslationUnit, the last statement “Mgr.reset(NULL)” would destroy the AnalysisManager which the local object BR is using. However, when existing the same function scope, the destructor of BR would get invoked, which would then invokes BugReporter::FlushReports(). The problem is, in FlushReports, the executuation path could lead to the usage of the destroyed AnalysisManager (actually, through its base class pointer which is type BugReportData), a dangling pointer. So bad things may happen, from access violation to dying message like “pure virtual function called”, depends on compiler. For the record, here is a callstack that I got it hit:

clang.exe!clang::ento::BugReporter::getPathDiagnosticClient() Line 301 + 0x12 bytes C++

clang.exe!clang::ento::BugReporter::FlushReport(clang::ento::BugReportEquivClass & EQ={…}) Line 1806 + 0x8 bytes C++

clang.exe!clang::ento::BugReporter::FlushReports() Line 1326 C++

clang.exe!clang::ento::BugReporter::~BugReporter() Line 1305 + 0x1f bytes C++

clang.exe!`anonymous namespace’::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext & C={…}) Line 247 + 0xb bytes C++

clang.exe!clang::ParseAST(clang::Sema & S={…}, bool PrintStats=false) Line 80 + 0x18 bytes C++

clang.exe!clang::ASTFrontendAction::ExecuteAction() Line 367 + 0x1f bytes C++

clang.exe!clang::FrontendAction::Execute() Line 287 + 0xf bytes C++

clang.exe!clang::CompilerInstance::ExecuteAction(clang::FrontendAction & Act={…}) Line 563 C++

clang.exe!clang::ExecuteCompilerInvocation(clang::CompilerInstance * Clang=0x0221c2a8) Line 154 + 0x11 bytes C++

I can reproduce this problem using my checker, which uses EmitBasicReport to report bugs. When my checker reports a bug, a new bug type will be added into the “BugTypes” data member of BugReporter, so in FlushReport the dangling pointer will get hit when iterating the bug types and emit report. However, I can not reproduce it using clang’s build in checkers (the vanilla Analysis tests all passed), and it looks like when using the clang’s build in checkers the BugTypes data member of BugReporter would always be empty, which will make the FlushReport return immediately without ever hitting the dangling pointer. A side note is my checker is working now after I removed the Mgr.reset(NULL), which seems is not necessary if the purpose is just to get the correct diagnostics, as all reports will get flushed when the AnalysisConsumer is destroyed, I think…

I notice this problem doesn’t exist when the checkers are registered using old approach (the ActionXXXChecker stuffJ); it just happens after I migrating my checker to use new checker registeration scheme and updating to latest revision of AnalysisConsumer.

So could any one confirm is this a bug ? Or am I misused the Emit(Basic)Report functions?