]> granicus.if.org Git - clang/commitdiff
Rework how PathDiagnosticConsumers pass knowledge of what files they
authorTed Kremenek <kremenek@apple.com>
Fri, 24 Aug 2012 19:35:19 +0000 (19:35 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 24 Aug 2012 19:35:19 +0000 (19:35 +0000)
generated for a given diagnostic to another.  Because PathDiagnostics
are specific to a give PathDiagnosticConsumer, store in
a FoldingSet a unique hash for a PathDiagnostic (that will be the same
for the same bug for different PathDiagnosticConsumers) that
stores a list of files generated.  This can then be read by the
other PathDiagnosticConsumers.

This fixes breakage in the PLIST-HTML output.

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

include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
lib/StaticAnalyzer/Core/PathDiagnostic.cpp
lib/StaticAnalyzer/Core/PlistDiagnostics.cpp

index 973cfb109c050e702316cec6a41b4a6cfdcce1d7..ad8a0694b41bb869024c082d9ff4726d92346b64 100644 (file)
@@ -52,7 +52,31 @@ class PathDiagnostic;
 
 class PathDiagnosticConsumer {
 public:
-  typedef std::vector<std::pair<StringRef, std::string> > FilesMade;
+  class PDFileEntry : public llvm::FoldingSetNode {
+  public:
+    PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
+
+    typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles;
+    
+    /// \brief A vector of <consumer,file> pairs.
+    ConsumerFiles files;
+    
+    /// \brief A precomputed hash tag used for uniquing PDFileEntry objects.
+    const llvm::FoldingSetNodeID NodeID;
+
+    /// \brief Used for profiling in the FoldingSet.
+    void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
+  };
+  
+  struct FilesMade : public llvm::FoldingSet<PDFileEntry> {
+    llvm::BumpPtrAllocator Alloc;
+    
+    void addDiagnostic(const PathDiagnostic &PD,
+                       StringRef ConsumerName,
+                       StringRef fileName);
+    
+    PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);
+  };
 
 private:
   virtual void anchor();
index 982bcbfcdf9aa7106a1edd8bc0d57f1c5d438215..46adfbd795a882be6bce902f21f4cb18629d9962 100644 (file)
@@ -267,8 +267,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
   }
 
   if (filesMade) {
-    filesMade->push_back(std::make_pair(StringRef(getName()),
-                                        llvm::sys::path::filename(H.str())));
+    filesMade->addDiagnostic(D, getName(), llvm::sys::path::filename(H.str()));
   }
 
   // Emit the HTML to disk.
index c849778e7f2340650936ce1a8ab8d95134a5d968..97ef906cac36479d033dff03282b59f2da2389a4 100644 (file)
@@ -271,6 +271,46 @@ void PathDiagnosticConsumer::FlushDiagnostics(
   }
 }
 
+static void ProfileDiagnostic(const PathDiagnostic &PD,
+                              llvm::FoldingSetNodeID &NodeID) {
+  NodeID.AddString(PD.getBugType());
+  NodeID.AddString(PD.getDescription());
+  NodeID.Add(PD.getLocation());
+}
+
+void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
+                                                      StringRef ConsumerName,
+                                                      StringRef FileName) {
+  llvm::FoldingSetNodeID NodeID;
+  ProfileDiagnostic(PD, NodeID);
+  void *InsertPos;
+  PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos);
+  if (!Entry) {
+    Entry = Alloc.Allocate<PDFileEntry>();
+    Entry = new (Entry) PDFileEntry(NodeID);
+    InsertNode(Entry, InsertPos);
+  }
+  
+  // Allocate persistent storage for the file name.
+  char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
+  memcpy(FileName_cstr, FileName.data(), FileName.size());
+
+  Entry->files.push_back(std::make_pair(ConsumerName,
+                                        StringRef(FileName_cstr,
+                                                  FileName.size())));
+}
+
+PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
+PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
+  llvm::FoldingSetNodeID NodeID;
+  ProfileDiagnostic(PD, NodeID);
+  void *InsertPos;
+  PDFileEntry *Entry = FindNodeOrInsertPos(NodeID, InsertPos);
+  if (!Entry)
+    return 0;
+  return &Entry->files;
+}
+
 //===----------------------------------------------------------------------===//
 // PathDiagnosticLocation methods.
 //===----------------------------------------------------------------------===//
index d5fdd9d2bb995718d86fe6f28818f0e2c513f369..79b2a1ce7f138f40ba4b42ea267c28942a5fa238 100644 (file)
@@ -499,17 +499,21 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
     // Output the diagnostic to the sub-diagnostic client, if any.
     if (!filesMade->empty()) {
       StringRef lastName;
-      for (FilesMade::iterator I = filesMade->begin(), E = filesMade->end();
-           I != E; ++I) {
-        StringRef newName = I->first;
+      PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D);
+      if (!files)
+        continue;
+      for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(),
+              CE = files->end(); CI != CE; ++CI) {
+        StringRef newName = CI->first;
         if (newName != lastName) {
-          if (!lastName.empty())
+          if (!lastName.empty()) {
             o << "  </array>\n";
+          }
           lastName = newName;
           o <<  "  <key>" << lastName << "_files</key>\n";
           o << "  <array>\n";
         }
-        o << "   <string>" << I->second << "</string>\n";
+        o << "   <string>" << CI->second << "</string>\n";
       }
       o << "  </array>\n";
     }
@@ -521,10 +525,5 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
   o << " </array>\n";
 
   // Finish.
-  o << "</dict>\n</plist>";
-  
-  if (filesMade) {
-    StringRef Name(getName());
-    filesMade->push_back(std::make_pair(Name, OutputFile));
-  }
+  o << "</dict>\n</plist>";  
 }