From: Ted Kremenek Date: Tue, 22 Apr 2008 16:15:03 +0000 (+0000) Subject: PathDiagnosticClients now retain ownership of passed PathDiagnostics, requiring X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5585114307b6ba4874546212cb6e5399cfff7ffb;p=clang PathDiagnosticClients now retain ownership of passed PathDiagnostics, requiring them to not be stack-allocated. HTMLDiagnostics now batches PathDiagnostics before emitting HTML in its dtor. This is a workaround for a problem when we trampled the Preprocessor state when highlighting macros (sometimes resulting in an assertion failure). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50102 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/HTMLDiagnostics.cpp b/Driver/HTMLDiagnostics.cpp index 2f1b6e3676..c850c05a58 100644 --- a/Driver/HTMLDiagnostics.cpp +++ b/Driver/HTMLDiagnostics.cpp @@ -39,18 +39,21 @@ class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient { bool createdDir, noDir; Preprocessor* PP; PreprocessorFactory* PPF; + std::vector BatchedDiags; public: HTMLDiagnostics(const std::string& prefix, Preprocessor* pp, PreprocessorFactory* ppf); - virtual ~HTMLDiagnostics() {} + virtual ~HTMLDiagnostics(); - virtual void HandlePathDiagnostic(const PathDiagnostic& D); + virtual void HandlePathDiagnostic(const PathDiagnostic* D); void HandlePiece(Rewriter& R, const PathDiagnosticPiece& P, unsigned num, unsigned max); void HighlightRange(Rewriter& R, SourceRange Range); + + void ReportDiag(const PathDiagnostic& D); }; } // end anonymous namespace @@ -75,10 +78,29 @@ clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP, // Report processing. //===----------------------------------------------------------------------===// -void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic& D) { - - if (D.empty()) +void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) { + if (!D) + return; + + if (D->empty()) { + delete D; return; + } + + BatchedDiags.push_back(D); +} + +HTMLDiagnostics::~HTMLDiagnostics() { + + while (!BatchedDiags.empty()) { + const PathDiagnostic* D = BatchedDiags.back(); + BatchedDiags.pop_back(); + ReportDiag(*D); + delete D; + } +} + +void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) { // Create the HTML directory if it is missing. @@ -127,7 +149,13 @@ void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic& D) { // for example. if (PP) html::SyntaxHighlight(R, FileID, *PP); - if (PPF) html::HighlightMacros(R, FileID, *PPF); + + // FIXME: We eventually want to use PPF to create a fresh Preprocessor, + // once we have worked out the bugs. + // + // if (PPF) html::HighlightMacros(R, FileID, *PPF); + // + if (PP) html::HighlightMacros(R, FileID, *PP); // Get the full directory name of the analyzed file. diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h index cfca94b4ca..f9bd0fd106 100644 --- a/include/clang/Analysis/PathDiagnostic.h +++ b/include/clang/Analysis/PathDiagnostic.h @@ -181,7 +181,7 @@ public: const SourceRange *Ranges, unsigned NumRanges); - virtual void HandlePathDiagnostic(const PathDiagnostic& D) = 0; + virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0; }; } //end clang namespace diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index 6b68d7f70e..be1c52d521 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -382,52 +382,51 @@ void BugReporter::EmitWarning(BugReport& R) { if (R.getBugType().isCached(R)) return; - PathDiagnostic D(R.getName()); - GeneratePathDiagnostic(D, R); + llvm::OwningPtr D(new PathDiagnostic(R.getName())); + GeneratePathDiagnostic(*D.get(), R); // Emit a full diagnostic for the path if we have a PathDiagnosticClient. - if (PD && !D.empty()) { - PD->HandlePathDiagnostic(D); + if (PD && !D->empty()) { + PD->HandlePathDiagnostic(D.take()); return; } // We don't have a PathDiagnosticClient, but we can still emit a single // line diagnostic. Determine the location. - FullSourceLoc L = D.empty() ? R.getLocation(Ctx.getSourceManager()) - : D.back()->getLocation(); + FullSourceLoc L = D->empty() ? R.getLocation(Ctx.getSourceManager()) + : D->back()->getLocation(); // Determine the range. const SourceRange *Beg, *End; - if (!D.empty()) { - Beg = D.back()->ranges_begin(); - End = D.back()->ranges_end(); + if (!D->empty()) { + Beg = D->back()->ranges_begin(); + End = D->back()->ranges_end(); } else R.getRanges(Beg, End); if (PD) { - PathDiagnostic D(R.getName()); PathDiagnosticPiece* piece = new PathDiagnosticPiece(L, R.getDescription()); for ( ; Beg != End; ++Beg) piece->addRange(*Beg); - D.push_back(piece); - PD->HandlePathDiagnostic(D); + D->push_back(piece); + PD->HandlePathDiagnostic(D.take()); } else { std::ostringstream os; os << "[CHECKER] "; - if (D.empty()) + if (D->empty()) os << R.getDescription(); else - os << D.back()->getString(); + os << D->back()->getString(); unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, diff --git a/lib/Analysis/PathDiagnostic.cpp b/lib/Analysis/PathDiagnostic.cpp index e4228c7744..28b76b38f1 100644 --- a/lib/Analysis/PathDiagnostic.cpp +++ b/lib/Analysis/PathDiagnostic.cpp @@ -31,7 +31,7 @@ void PathDiagnosticClient::HandleDiagnostic(Diagnostic &Diags, // Create a PathDiagnostic with a single piece. - PathDiagnostic D; + PathDiagnostic* D = new PathDiagnostic(); // Ripped from TextDiagnostics::FormatDiagnostic. Perhaps we should // centralize it somewhere? @@ -68,7 +68,7 @@ void PathDiagnosticClient::HandleDiagnostic(Diagnostic &Diags, ++Ranges; } - D.push_front(P); + D->push_front(P); HandlePathDiagnostic(D); }