]> granicus.if.org Git - clang/commitdiff
(1) Enable PlistDiagnostics to take an option "PathDiagnosticClientFactory"
authorTed Kremenek <kremenek@apple.com>
Mon, 27 Jul 2009 22:13:39 +0000 (22:13 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 27 Jul 2009 22:13:39 +0000 (22:13 +0000)
object that it can use to forward PathDiagnostics for further processing. Along
with this feature, the PlistDiagnostics object logs which files are created by
the forwarding of the PathDiagnostics.

(2) Create a new PathDiagnosticClientFactory object for HTMLDiagnostics,
allowing other PathDiagnosticClients to forward PathDiagnostics through an
opaque interface.

(3) Create a "plist-html" diagnostics option in AnalysisConsumer to allow the
    logging of HTML files created in a hybrid Plist+HTML diagnostic client.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77264 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/Analyses.def
include/clang/Frontend/PathDiagnosticClients.h
lib/Frontend/AnalysisConsumer.cpp
lib/Frontend/HTMLDiagnostics.cpp
lib/Frontend/PlistDiagnostics.cpp

index 9d02fd42c68b3b43451fc20d8c3652442e5895e9..8974998b8950d636acc7e6a4908abf8a4b7468d9 100644 (file)
@@ -69,6 +69,7 @@ ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of conc
 
 ANALYSIS_DIAGNOSTICS(HTML,  "html",  "Output analysis results using HTML",   CreateHTMLDiagnosticClient, false)
 ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", CreatePlistDiagnosticClient, true)
+ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", CreatePlistHTMLDiagnosticClient, true)
 
 #undef ANALYSIS
 #undef ANALYSIS_STORE
index 028cd8549272dc0e8f8cc980696398449e7f73b0..53dd32e93b8c1af9ca47db174b4762d3c19d4c35 100644 (file)
 #ifndef LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLIENTS_H
 #define LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLiENTS_H
 
+#include <memory>
 #include <string>
+#include "llvm/ADT/SmallVector.h"
 
 namespace clang {
 
 class PathDiagnosticClient;
 class Preprocessor;
 class PreprocessorFactory;
+  
+class PathDiagnosticClientFactory {
+public:
+  PathDiagnosticClientFactory() {}
+  virtual ~PathDiagnosticClientFactory() {}
+  
+  virtual const char *getName() const = 0;
 
-PathDiagnosticClient* CreateHTMLDiagnosticClient(const std::string& prefix,
-                                                 Preprocessor* PP = 0,
-                                                 PreprocessorFactory* PPF = 0);
+  virtual PathDiagnosticClient*
+  createPathDiagnosticClient(llvm::SmallVectorImpl<std::string> *FilesMade) = 0;
+};
+
+PathDiagnosticClient*
+CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP = 0,
+                           PreprocessorFactory* PPF = 0,
+                           llvm::SmallVectorImpl<std::string>* FilesMade = 0);
+  
+PathDiagnosticClientFactory*
+CreateHTMLDiagnosticClientFactory(const std::string& prefix,
+                                  Preprocessor* PP = 0,
+                                  PreprocessorFactory* PPF = 0);
   
-PathDiagnosticClient* CreatePlistDiagnosticClient(const std::string& prefix,
-                                                  Preprocessor* PP,
-                                                  PreprocessorFactory* PPF);
-}
+PathDiagnosticClient*
+CreatePlistDiagnosticClient(const std::string& prefix, Preprocessor* PP,
+                            PreprocessorFactory* PPF,
+                            PathDiagnosticClientFactory *PF = 0);
 
+} // end clang namespace
 #endif
index dfbd856fc8d05f6dc41c6448b13c5cc5817db9f0..2031174cabdd1d188b9f05c0ea8edef4ba1cbe21 100644 (file)
@@ -49,6 +49,19 @@ namespace {
   typedef void (*CodeAction)(AnalysisManager& Mgr);
 } // end anonymous namespace
 
+//===----------------------------------------------------------------------===//
+// Special PathDiagnosticClients.
+//===----------------------------------------------------------------------===//
+
+static PathDiagnosticClient*
+CreatePlistHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
+                            PreprocessorFactory* PPF) {
+  llvm::sys::Path F(prefix);  
+  PathDiagnosticClientFactory *PF = 
+    CreateHTMLDiagnosticClientFactory(F.getDirname(), PP, PPF);
+  return CreatePlistDiagnosticClient(prefix, PP, PPF, PF);
+}
+
 //===----------------------------------------------------------------------===//
 // AnalysisConsumer declaration.
 //===----------------------------------------------------------------------===//
index 9cfe0b2a6124b21bc02fa320e6a5102456d25e49..160da7c09734756027cbfa919b3d0c6d0118a3f7 100644 (file)
@@ -39,9 +39,11 @@ class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
   llvm::sys::Path Directory, FilePrefix;
   bool createdDir, noDir;
   Preprocessor* PP;
-  std::vector<const PathDiagnostic*> BatchedDiags;  
+  std::vector<const PathDiagnostic*> BatchedDiags;
+  llvm::SmallVectorImpl<std::string> *FilesMade;  
 public:
-  HTMLDiagnostics(const std::string& prefix, Preprocessor* pp);
+  HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
+                  llvm::SmallVectorImpl<std::string> *filesMade = 0);
 
   virtual ~HTMLDiagnostics();
   
@@ -65,9 +67,10 @@ public:
   
 } // end anonymous namespace
 
-HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp)
+HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
+                                 llvm::SmallVectorImpl<std::string>* filesMade)
   : Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
-    PP(pp) {
+    PP(pp), FilesMade(filesMade) {
   
   // All html files begin with "report" 
   FilePrefix.appendComponent("report");
@@ -75,8 +78,43 @@ HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp)
 
 PathDiagnosticClient*
 clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
-                                  PreprocessorFactory*) {
-  return new HTMLDiagnostics(prefix, PP);
+                                  PreprocessorFactory*,
+                                  llvm::SmallVectorImpl<std::string>* FilesMade)
+{
+  return new HTMLDiagnostics(prefix, PP, FilesMade);
+}
+
+//===----------------------------------------------------------------------===//
+// Factory for HTMLDiagnosticClients
+//===----------------------------------------------------------------------===//
+
+namespace {
+class VISIBILITY_HIDDEN HTMLDiagnosticsFactory
+  : public PathDiagnosticClientFactory {
+
+  std::string Prefix;
+  Preprocessor *PP;
+public:
+  HTMLDiagnosticsFactory(const std::string& prefix, Preprocessor* pp)
+    : Prefix(prefix), PP(pp) {}
+
+  virtual ~HTMLDiagnosticsFactory() {}
+    
+  const char *getName() const { return "HTMLDiagnostics"; }
+    
+  PathDiagnosticClient*
+  createPathDiagnosticClient(llvm::SmallVectorImpl<std::string> *FilesMade) {
+
+  return new HTMLDiagnostics(Prefix, PP, FilesMade);
+  }
+};
+} // end anonymous namespace
+
+PathDiagnosticClientFactory*
+clang::CreateHTMLDiagnosticClientFactory(const std::string& prefix,
+                                         Preprocessor* PP,
+                                         PreprocessorFactory*) {
+  return new HTMLDiagnosticsFactory(prefix, PP);
 }
 
 //===----------------------------------------------------------------------===//
@@ -317,12 +355,14 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
       llvm::cerr << "warning: could not create file '" << F.toString() << "'\n";
       return;
     }
+
+    if (FilesMade)
+      FilesMade->push_back(H.getLast());
   }
   
   // Emit the HTML to disk.
-
   for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
-      os << *I;
+      os << *I;  
 }
 
 void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
index f3a954358ec314223567dca695340c7e162146c7..65b3a7543653751615778110329dae62e4dd95c2 100644 (file)
@@ -37,12 +37,16 @@ namespace {
     std::vector<const PathDiagnostic*> BatchedDiags;
     const std::string OutputFile;
     const LangOptions &LangOpts;
+    llvm::OwningPtr<PathDiagnosticClientFactory> PF;
+    llvm::OwningPtr<PathDiagnosticClient> SubPDC;
+    llvm::SmallVector<std::string, 1> FilesMade;
   public:
-    PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts);
+    PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
+                     PathDiagnosticClientFactory *pf);
     ~PlistDiagnostics();
     void HandlePathDiagnostic(const PathDiagnostic* D);
     
-    PathGenerationScheme getGenerationScheme() const { return Extensive; }
+    PathGenerationScheme getGenerationScheme() const;
     bool supportsLogicalOpControlFlow() const { return true; }
     bool supportsAllBlockEdges() const { return true; }
     virtual bool useVerboseDescription() const { return false; }
@@ -50,13 +54,27 @@ namespace {
 } // end anonymous namespace
 
 PlistDiagnostics::PlistDiagnostics(const std::string& output,
-                                   const LangOptions &LO)
-  : OutputFile(output), LangOpts(LO) {}
+                                   const LangOptions &LO,
+                                   PathDiagnosticClientFactory *pf)
+  : OutputFile(output), LangOpts(LO), PF(pf) {
+    
+  if (PF)
+    SubPDC.reset(PF->createPathDiagnosticClient(&FilesMade));
+}
 
 PathDiagnosticClient*
 clang::CreatePlistDiagnosticClient(const std::string& s,
-                                   Preprocessor *PP, PreprocessorFactory*) {
-  return new PlistDiagnostics(s, PP->getLangOptions());
+                                   Preprocessor *PP, PreprocessorFactory*,
+                                   PathDiagnosticClientFactory *PF) {
+  return new PlistDiagnostics(s, PP->getLangOptions(), PF);
+}
+
+PathDiagnosticClient::PathGenerationScheme
+PlistDiagnostics::getGenerationScheme() const {
+  if (const PathDiagnosticClient *PD = SubPDC.get())
+    return PD->getGenerationScheme();
+  
+  return Extensive;
 }
 
 static void AddFID(FIDMap &FIDs, llvm::SmallVectorImpl<FileID> &V,
@@ -358,9 +376,9 @@ PlistDiagnostics::~PlistDiagnostics() {
     // Create an owning smart pointer for 'D' just so that we auto-free it
     // when we exit this method.
     llvm::OwningPtr<PathDiagnostic> OwnedD(const_cast<PathDiagnostic*>(D));
-
+    
     o << "   <array>\n";
-  
+
     for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I)
       ReportDiag(o, *I, FM, *SM, LangOpts);
     
@@ -378,6 +396,24 @@ PlistDiagnostics::~PlistDiagnostics() {
     o << "  <key>location</key>\n";
     EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
     
+    // Output the diagnostic to the sub-diagnostic client, if any.
+    if (PF) {
+      if (!SubPDC.get())
+        SubPDC.reset(PF->createPathDiagnosticClient(&FilesMade));
+      
+      FilesMade.clear();
+      SubPDC->HandlePathDiagnostic(OwnedD.take());      
+      SubPDC.reset(0);
+      
+      if (!FilesMade.empty()) {
+        o << "  <key>" << PF->getName() << "_files</key>\n";
+        o << "  <array>\n";
+        for (size_t i = 0, n = FilesMade.size(); i < n ; ++i)
+          o << "   <string>" << FilesMade[i] << "</string>\n";
+        o << "  </array>\n";        
+      }
+    }
+    
     // Close up the entry.
     o << "  </dict>\n";
   }