diff options
author | Ted Kremenek <kremenek@apple.com> | 2012-08-24 19:35:19 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2012-08-24 19:35:19 +0000 |
commit | b75e2602e246b44bb285be8cc31166302d77998f (patch) | |
tree | 3874104d9b0d49062247c4b8c0f2b5d66580ec7a | |
parent | 81e6cfddcbb32eb9bbbee5c3f5156fc19ca7e774 (diff) |
Rework how PathDiagnosticConsumers pass knowledge of what files they
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
-rw-r--r-- | include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h | 26 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 40 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/PlistDiagnostics.cpp | 21 |
4 files changed, 76 insertions, 14 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 973cfb109c..ad8a0694b4 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -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(); diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 982bcbfcdf..46adfbd795 100644 --- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -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. diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index c849778e7f..97ef906cac 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -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. //===----------------------------------------------------------------------===// diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp index d5fdd9d2bb..79b2a1ce7f 100644 --- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -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>"; } |