From: Ted Kremenek Date: Mon, 27 Jul 2009 22:13:39 +0000 (+0000) Subject: (1) Enable PlistDiagnostics to take an option "PathDiagnosticClientFactory" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f75560670bcdd59b051149bdece3eac14e313853;p=clang (1) Enable PlistDiagnostics to take an option "PathDiagnosticClientFactory" 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 --- diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def index 9d02fd42c6..8974998b89 100644 --- a/include/clang/Frontend/Analyses.def +++ b/include/clang/Frontend/Analyses.def @@ -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 diff --git a/include/clang/Frontend/PathDiagnosticClients.h b/include/clang/Frontend/PathDiagnosticClients.h index 028cd85492..53dd32e93b 100644 --- a/include/clang/Frontend/PathDiagnosticClients.h +++ b/include/clang/Frontend/PathDiagnosticClients.h @@ -14,21 +14,41 @@ #ifndef LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLIENTS_H #define LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLiENTS_H +#include #include +#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 *FilesMade) = 0; +}; + +PathDiagnosticClient* +CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP = 0, + PreprocessorFactory* PPF = 0, + llvm::SmallVectorImpl* 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 diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp index dfbd856fc8..2031174cab 100644 --- a/lib/Frontend/AnalysisConsumer.cpp +++ b/lib/Frontend/AnalysisConsumer.cpp @@ -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. //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp index 9cfe0b2a61..160da7c097 100644 --- a/lib/Frontend/HTMLDiagnostics.cpp +++ b/lib/Frontend/HTMLDiagnostics.cpp @@ -39,9 +39,11 @@ class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient { llvm::sys::Path Directory, FilePrefix; bool createdDir, noDir; Preprocessor* PP; - std::vector BatchedDiags; + std::vector BatchedDiags; + llvm::SmallVectorImpl *FilesMade; public: - HTMLDiagnostics(const std::string& prefix, Preprocessor* pp); + HTMLDiagnostics(const std::string& prefix, Preprocessor* pp, + llvm::SmallVectorImpl *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* 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* 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 *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, diff --git a/lib/Frontend/PlistDiagnostics.cpp b/lib/Frontend/PlistDiagnostics.cpp index f3a954358e..65b3a75436 100644 --- a/lib/Frontend/PlistDiagnostics.cpp +++ b/lib/Frontend/PlistDiagnostics.cpp @@ -37,12 +37,16 @@ namespace { std::vector BatchedDiags; const std::string OutputFile; const LangOptions &LangOpts; + llvm::OwningPtr PF; + llvm::OwningPtr SubPDC; + llvm::SmallVector 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 &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 OwnedD(const_cast(D)); - + o << " \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 << " location\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 << " " << PF->getName() << "_files\n"; + o << " \n"; + for (size_t i = 0, n = FilesMade.size(); i < n ; ++i) + o << " " << FilesMade[i] << "\n"; + o << " \n"; + } + } + // Close up the entry. o << " \n"; }