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
#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
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.
//===----------------------------------------------------------------------===//
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();
} // 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");
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);
}
//===----------------------------------------------------------------------===//
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,
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; }
} // 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,
// 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);
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";
}