aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-07-27 22:13:39 +0000
committerTed Kremenek <kremenek@apple.com>2009-07-27 22:13:39 +0000
commitf75560670bcdd59b051149bdece3eac14e313853 (patch)
tree1c6d28125572bc2fa46aa3abe8977d69f315a6de
parent7753b352366778d01c5cda4117356f181d3dd468 (diff)
(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
-rw-r--r--include/clang/Frontend/Analyses.def1
-rw-r--r--include/clang/Frontend/PathDiagnosticClients.h34
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp13
-rw-r--r--lib/Frontend/HTMLDiagnostics.cpp56
-rw-r--r--lib/Frontend/PlistDiagnostics.cpp52
5 files changed, 133 insertions, 23 deletions
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 <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
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
@@ -50,6 +50,19 @@ namespace {
} // 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<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,
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<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";
}