#ifndef LLVM_CLANG_TOOLING_TOOLING_H
#define LLVM_CLANG_TOOLING_TOOLING_H
+#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Util.h"
/// \brief Perform an action for an invocation.
virtual bool runInvocation(clang::CompilerInvocation *Invocation,
- FileManager *Files) = 0;
+ FileManager *Files,
+ DiagnosticConsumer *DiagConsumer) = 0;
};
/// \brief Interface to generate clang::FrontendActions.
virtual ~FrontendActionFactory();
/// \brief Invokes the compiler with a FrontendAction created by create().
- bool runInvocation(clang::CompilerInvocation *Invocation,
- FileManager *Files);
+ bool runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files,
+ DiagnosticConsumer *DiagConsumer);
/// \brief Returns a new clang::FrontendAction.
///
~ToolInvocation();
+ /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer);
+
/// \brief Map a virtual file to be used while running the tool.
///
/// \param FilePath The path at which the content will be mapped.
FileManager *Files;
// Maps <file name> -> <file content>.
llvm::StringMap<StringRef> MappedFileContents;
+ DiagnosticConsumer *DiagConsumer;
};
/// \brief Utility to run a FrontendAction over a set of files.
virtual ~ClangTool() { clearArgumentsAdjusters(); }
+ /// \brief Set a \c DiagnosticConsumer to use during parsing.
+ void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer);
+
/// \brief Map a virtual file to be used while running the tool.
///
/// \param FilePath The path at which the content will be mapped.
std::vector< std::pair<StringRef, StringRef> > MappedFileContents;
SmallVector<ArgumentsAdjuster *, 2> ArgsAdjusters;
+
+ DiagnosticConsumer *DiagConsumer;
};
template <typename T>
ToolInvocation::ToolInvocation(ArrayRef<std::string> CommandLine,
ToolAction *Action, FileManager *Files)
- : CommandLine(CommandLine.vec()), Action(Action), OwnsAction(false),
- Files(Files) {}
+ : CommandLine(CommandLine.vec()),
+ Action(Action),
+ OwnsAction(false),
+ Files(Files),
+ DiagConsumer(NULL) {}
ToolInvocation::ToolInvocation(ArrayRef<std::string> CommandLine,
FrontendAction *FAction, FileManager *Files)
: CommandLine(CommandLine.vec()),
- Action(new SingleFrontendActionFactory(FAction)), OwnsAction(true),
- Files(Files) {}
+ Action(new SingleFrontendActionFactory(FAction)),
+ OwnsAction(true),
+ Files(Files),
+ DiagConsumer(NULL) {}
ToolInvocation::~ToolInvocation() {
if (OwnsAction)
delete Action;
}
+void ToolInvocation::setDiagnosticConsumer(DiagnosticConsumer *D) {
+ DiagConsumer = D;
+}
+
void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {
SmallString<1024> PathStorage;
llvm::sys::path::native(FilePath, PathStorage);
TextDiagnosticPrinter DiagnosticPrinter(
llvm::errs(), &*DiagOpts);
DiagnosticsEngine Diagnostics(
- IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
- &*DiagOpts, &DiagnosticPrinter, false);
+ IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
+ DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
const OwningPtr<clang::driver::Driver> Driver(
newDriver(&Diagnostics, BinaryName));
llvm::errs() << "\n";
}
- return Action->runInvocation(Invocation, Files);
+ return Action->runInvocation(Invocation, Files, DiagConsumer);
}
bool FrontendActionFactory::runInvocation(CompilerInvocation *Invocation,
- FileManager *Files) {
+ FileManager *Files,
+ DiagnosticConsumer *DiagConsumer) {
// Create a compiler instance to handle the actual work.
clang::CompilerInstance Compiler;
Compiler.setInvocation(Invocation);
OwningPtr<FrontendAction> ScopedToolAction(create());
// Create the compilers actual diagnostics engine.
- Compiler.createDiagnostics();
+ Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
if (!Compiler.hasDiagnostics())
return false;
ClangTool::ClangTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths)
- : Files(new FileManager(FileSystemOptions())) {
+ : Files(new FileManager(FileSystemOptions())), DiagConsumer(NULL) {
ArgsAdjusters.push_back(new ClangStripOutputAdjuster());
ArgsAdjusters.push_back(new ClangSyntaxOnlyAdjuster());
for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) {
}
}
+void ClangTool::setDiagnosticConsumer(DiagnosticConsumer *D) {
+ DiagConsumer = D;
+}
+
void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
MappedFileContents.push_back(std::make_pair(FilePath, Content));
}
llvm::dbgs() << "Processing: " << File << ".\n";
});
ToolInvocation Invocation(CommandLine, Action, Files.getPtr());
+ Invocation.setDiagnosticConsumer(DiagConsumer);
for (int I = 0, E = MappedFileContents.size(); I != E; ++I) {
Invocation.mapVirtualFile(MappedFileContents[I].first,
MappedFileContents[I].second);
public:
ASTBuilderAction(std::vector<ASTUnit *> &ASTs) : ASTs(ASTs) {}
- bool runInvocation(CompilerInvocation *Invocation,
- FileManager *Files) {
+ bool runInvocation(CompilerInvocation *Invocation, FileManager *Files,
+ DiagnosticConsumer *DiagConsumer) {
// FIXME: This should use the provided FileManager.
ASTUnit *AST = ASTUnit::LoadFromCompilerInvocation(
- Invocation,
- CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts()));
+ Invocation, CompilerInstance::createDiagnostics(
+ &Invocation->getDiagnosticOpts(), DiagConsumer,
+ /*ShouldOwnClient=*/false));
if (!AST)
return false;
}
#endif
+struct TestDiagnosticConsumer : public DiagnosticConsumer {
+ TestDiagnosticConsumer() : NumDiagnosticsSeen(0) {}
+ virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+ const Diagnostic &Info) {
+ ++NumDiagnosticsSeen;
+ }
+ unsigned NumDiagnosticsSeen;
+};
+
+TEST(ClangToolTest, InjectDiagnosticConsumer) {
+ FixedCompilationDatabase Compilations("/", std::vector<std::string>());
+ ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
+ Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
+ TestDiagnosticConsumer Consumer;
+ Tool.setDiagnosticConsumer(&Consumer);
+ Tool.run(newFrontendActionFactory<SyntaxOnlyAction>());
+ EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
+}
+
} // end namespace tooling
} // end namespace clang