]> granicus.if.org Git - clang/commitdiff
PathDiagnosticClients now retain ownership of passed PathDiagnostics, requiring
authorTed Kremenek <kremenek@apple.com>
Tue, 22 Apr 2008 16:15:03 +0000 (16:15 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 22 Apr 2008 16:15:03 +0000 (16:15 +0000)
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

Driver/HTMLDiagnostics.cpp
include/clang/Analysis/PathDiagnostic.h
lib/Analysis/BugReporter.cpp
lib/Analysis/PathDiagnostic.cpp

index 2f1b6e3676bed06b7fd665d449cede6843f73c0f..c850c05a58f7fc52c947d8878fed28776f1190cb 100644 (file)
@@ -39,18 +39,21 @@ class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
   bool createdDir, noDir;
   Preprocessor* PP;
   PreprocessorFactory* PPF;
+  std::vector<const PathDiagnostic*> 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.
 
index cfca94b4ca7cbda7848e8b46b800262e27771c66..f9bd0fd10630bbd873087ac304eeca1007153250 100644 (file)
@@ -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
index 6b68d7f70ec3db9c68d3a359a19ea3c3755051a5..be1c52d52171bacf15a7115540b36d20ec14f5b9 100644 (file)
@@ -382,52 +382,51 @@ void BugReporter::EmitWarning(BugReport& R) {
   if (R.getBugType().isCached(R))
     return;
 
-  PathDiagnostic D(R.getName());  
-  GeneratePathDiagnostic(D, R);
+  llvm::OwningPtr<PathDiagnostic> 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,
index e4228c77443c6442fb727b5fa36e5193a25b3730..28b76b38f13bfcd1fe690dfc2ae0148f114fa9c1 100644 (file)
@@ -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);  
 }