<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 30, 2015 at 12:37 PM, Manuel Klimek <span dir="ltr"><<a href="mailto:klimek@google.com" target="_blank">klimek@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><span class="">On Fri Jan 30 2015 at 1:18:46 PM Sean Silva <<a href="mailto:chisophugis@gmail.com" target="_blank">chisophugis@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><span style="font-size:13px">Wow, I'm just seeing this through its use on D7289. This is so great! Is there some way we can draw more attention to this? Docs?</span></div></div></blockquote><div><br></div></span><div>Awesome! A volunteer :)</div><div><br></div><div>Yes, we definitely could need more docs here - best in the form of small tutorials ;)</div></div></div></blockquote><div><br></div><div>I'll probably get around to it next time I'm doing something using clang as a library. If it wasn't obvious.... I've been pretty out of the loop here.</div><div><br></div><div>-- Sean Silva</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><br></div></div><div dir="ltr"><div><span style="font-size:13px"><br></span></div><div><span style="font-size:13px">-- Sean Silva</span></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 6, 2013 at 8:12 PM, Peter Collingbourne <span dir="ltr"><<a href="mailto:peter@pcc.me.uk" target="_blank">peter@pcc.me.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: pcc<br>
Date: Wed Nov 6 14:12:45 2013<br>
New Revision: 194164<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=194164&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=194164&view=rev</a><br>
Log:<br>
Introduce ClangTool::buildASTs, and buildASTFromCode.<br>
<br>
These allow clients to retrieve persistent AST objects (ASTUnits) which<br>
can be used in an ad-hoc manner after parsing.<br>
<br>
To accommodate this change, the code for processing a CompilerInvocation<br>
using a FrontendAction has been factored out to FrontendActionFactory, and<br>
a new base class, ToolAction, has been introduced, allowing the tool to do<br>
arbitrary things with each CompilerInvocation. This change was necessary<br>
because ASTUnit does not use the FrontendAction interface directly.<br>
<br>
This change also causes the FileManager in ClangTool to use shared ownership.<br>
This will become necessary because ASTUnit takes shared ownership of<br>
FileManager (ClangTool's FileManager is currently unused by ASTUnit; this<br>
is a FIXME). As shown in the tests, any client of ToolInvocation will<br>
need to be modified to use shared ownership for FileManager.<br>
<br>
Differential Revision: <a href="http://llvm-reviews.chandlerc.com/D2097" target="_blank">http://llvm-reviews.chandlerc.com/D2097</a><br>
<br>
Modified:<br>
cfe/trunk/include/clang/Tooling/Tooling.h<br>
cfe/trunk/lib/Tooling/Tooling.cpp<br>
cfe/trunk/unittests/Tooling/ToolingTest.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Tooling/Tooling.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Tooling.h?rev=194164&r1=194163&r2=194164&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Tooling.h?rev=194164&r1=194163&r2=194164&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Tooling/Tooling.h (original)<br>
+++ cfe/trunk/include/clang/Tooling/Tooling.h Wed Nov 6 14:12:45 2013<br>
@@ -53,14 +53,33 @@ class FrontendAction;<br>
<br>
namespace tooling {<br>
<br>
+/// \brief Interface to process a clang::CompilerInvocation.<br>
+///<br>
+/// If your tool is based on FrontendAction, you should be deriving from<br>
+/// FrontendActionFactory instead.<br>
+class ToolAction {<br>
+public:<br>
+ virtual ~ToolAction();<br>
+<br>
+ /// \brief Perform an action for an invocation.<br>
+ virtual bool runInvocation(clang::CompilerInvocation *Invocation,<br>
+ FileManager *Files) = 0;<br>
+};<br>
+<br>
/// \brief Interface to generate clang::FrontendActions.<br>
///<br>
/// Having a factory interface allows, for example, a new FrontendAction to be<br>
-/// created for each translation unit processed by ClangTool.<br>
-class FrontendActionFactory {<br>
+/// created for each translation unit processed by ClangTool. This class is<br>
+/// also a ToolAction which uses the FrontendActions created by create() to<br>
+/// process each translation unit.<br>
+class FrontendActionFactory : public ToolAction {<br>
public:<br>
virtual ~FrontendActionFactory();<br>
<br>
+ /// \brief Invokes the compiler with a FrontendAction created by create().<br>
+ bool runInvocation(clang::CompilerInvocation *Invocation,<br>
+ FileManager *Files);<br>
+<br>
/// \brief Returns a new clang::FrontendAction.<br>
///<br>
/// The caller takes ownership of the returned action.<br>
@@ -133,6 +152,26 @@ bool runToolOnCodeWithArgs(clang::Fronte<br>
const std::vector<std::string> &Args,<br>
const Twine &FileName = "input.cc");<br>
<br>
+/// \brief Builds an AST for 'Code'.<br>
+///<br>
+/// \param Code C++ code.<br>
+/// \param FileName The file name which 'Code' will be mapped as.<br>
+///<br>
+/// \return The resulting AST or null if an error occurred.<br>
+ASTUnit *buildASTFromCode(const Twine &Code,<br>
+ const Twine &FileName = "input.cc");<br>
+<br>
+/// \brief Builds an AST for 'Code' with additional flags.<br>
+///<br>
+/// \param Code C++ code.<br>
+/// \param Args Additional flags to pass on.<br>
+/// \param FileName The file name which 'Code' will be mapped as.<br>
+///<br>
+/// \return The resulting AST or null if an error occurred.<br>
+ASTUnit *buildASTFromCodeWithArgs(const Twine &Code,<br>
+ const std::vector<std::string> &Args,<br>
+ const Twine &FileName = "input.cc");<br>
+<br>
/// \brief Utility to run a FrontendAction in a single clang invocation.<br>
class ToolInvocation {<br>
public:<br>
@@ -145,9 +184,19 @@ class ToolInvocation {<br>
/// \param ToolAction The action to be executed. Class takes ownership.<br>
/// \param Files The FileManager used for the execution. Class does not take<br>
/// ownership.<br>
- ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,<br>
+ ToolInvocation(ArrayRef<std::string> CommandLine, FrontendAction *FAction,<br>
FileManager *Files);<br>
<br>
+ /// \brief Create a tool invocation.<br>
+ ///<br>
+ /// \param CommandLine The command line arguments to clang.<br>
+ /// \param Action The action to be executed.<br>
+ /// \param Files The FileManager used for the execution.<br>
+ ToolInvocation(ArrayRef<std::string> CommandLine, ToolAction *Action,<br>
+ FileManager *Files);<br>
+<br>
+ ~ToolInvocation();<br>
+<br>
/// \brief Map a virtual file to be used while running the tool.<br>
///<br>
/// \param FilePath The path at which the content will be mapped.<br>
@@ -167,7 +216,8 @@ class ToolInvocation {<br>
clang::CompilerInvocation *Invocation);<br>
<br>
std::vector<std::string> CommandLine;<br>
- OwningPtr<FrontendAction> ToolAction;<br>
+ ToolAction *Action;<br>
+ bool OwnsAction;<br>
FileManager *Files;<br>
// Maps <file name> -> <file content>.<br>
llvm::StringMap<StringRef> MappedFileContents;<br>
@@ -216,23 +266,25 @@ class ClangTool {<br>
/// \brief Clear the command line arguments adjuster chain.<br>
void clearArgumentsAdjusters();<br>
<br>
- /// Runs a frontend action over all files specified in the command line.<br>
+ /// Runs an action over all files specified in the command line.<br>
///<br>
- /// \param ActionFactory Factory generating the frontend actions. The function<br>
- /// takes ownership of this parameter. A new action is generated for every<br>
- /// processed translation unit.<br>
- virtual int run(FrontendActionFactory *ActionFactory);<br>
+ /// \param Action Tool action.<br>
+ int run(ToolAction *Action);<br>
+<br>
+ /// \brief Create an AST for each file specified in the command line and<br>
+ /// append them to ASTs.<br>
+ int buildASTs(std::vector<ASTUnit *> &ASTs);<br>
<br>
/// \brief Returns the file manager used in the tool.<br>
///<br>
/// The file manager is shared between all translation units.<br>
- FileManager &getFiles() { return Files; }<br>
+ FileManager &getFiles() { return *Files; }<br>
<br>
private:<br>
// We store compile commands as pair (file name, compile command).<br>
std::vector< std::pair<std::string, CompileCommand> > CompileCommands;<br>
<br>
- FileManager Files;<br>
+ llvm::IntrusiveRefCntPtr<FileManager> Files;<br>
// Contains a list of pairs (<file name>, <file content>).<br>
std::vector< std::pair<StringRef, StringRef> > MappedFileContents;<br>
<br>
<br>
Modified: cfe/trunk/lib/Tooling/Tooling.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Tooling.cpp?rev=194164&r1=194163&r2=194164&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Tooling.cpp?rev=194164&r1=194163&r2=194164&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Tooling/Tooling.cpp (original)<br>
+++ cfe/trunk/lib/Tooling/Tooling.cpp Wed Nov 6 14:12:45 2013<br>
@@ -13,9 +13,11 @@<br>
//===----------------------------------------------------------------------===//<br>
<br>
#include "clang/Tooling/Tooling.h"<br>
+#include "clang/AST/ASTConsumer.h"<br>
#include "clang/Driver/Compilation.h"<br>
#include "clang/Driver/Driver.h"<br>
#include "clang/Driver/Tool.h"<br>
+#include "clang/Frontend/ASTUnit.h"<br>
#include "clang/Frontend/CompilerInstance.h"<br>
#include "clang/Frontend/FrontendDiagnostic.h"<br>
#include "clang/Frontend/TextDiagnosticPrinter.h"<br>
@@ -38,6 +40,8 @@<br>
namespace clang {<br>
namespace tooling {<br>
<br>
+ToolAction::~ToolAction() {}<br>
+<br>
FrontendActionFactory::~FrontendActionFactory() {}<br>
<br>
// FIXME: This file contains structural duplication with other parts of the<br>
@@ -104,18 +108,26 @@ bool runToolOnCode(clang::FrontendAction<br>
ToolAction, Code, std::vector<std::string>(), FileName);<br>
}<br>
<br>
+static std::vector<std::string><br>
+getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs,<br>
+ StringRef FileName) {<br>
+ std::vector<std::string> Args;<br>
+ Args.push_back("clang-tool");<br>
+ Args.push_back("-fsyntax-only");<br>
+ Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());<br>
+ Args.push_back(FileName.str());<br>
+ return Args;<br>
+}<br>
+<br>
bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,<br>
const std::vector<std::string> &Args,<br>
const Twine &FileName) {<br>
SmallString<16> FileNameStorage;<br>
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);<br>
- std::vector<std::string> Commands;<br>
- Commands.push_back("clang-tool");<br>
- Commands.push_back("-fsyntax-only");<br>
- Commands.insert(Commands.end(), Args.begin(), Args.end());<br>
- Commands.push_back(FileNameRef.data());<br>
- FileManager Files((FileSystemOptions()));<br>
- ToolInvocation Invocation(Commands, ToolAction, &Files);<br>
+ llvm::IntrusiveRefCntPtr<FileManager> Files(<br>
+ new FileManager(FileSystemOptions()));<br>
+ ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction,<br>
+ Files.getPtr());<br>
<br>
SmallString<1024> CodeStorage;<br>
Invocation.mapVirtualFile(FileNameRef,<br>
@@ -138,10 +150,33 @@ std::string getAbsolutePath(StringRef Fi<br>
return AbsolutePath.str();<br>
}<br>
<br>
-ToolInvocation::ToolInvocation(<br>
- ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,<br>
- FileManager *Files)<br>
- : CommandLine(CommandLine.vec()), ToolAction(ToolAction), Files(Files) {<br>
+namespace {<br>
+<br>
+class SingleFrontendActionFactory : public FrontendActionFactory {<br>
+ FrontendAction *Action;<br>
+<br>
+public:<br>
+ SingleFrontendActionFactory(FrontendAction *Action) : Action(Action) {}<br>
+<br>
+ FrontendAction *create() { return Action; }<br>
+};<br>
+<br>
+}<br>
+<br>
+ToolInvocation::ToolInvocation(ArrayRef<std::string> CommandLine,<br>
+ ToolAction *Action, FileManager *Files)<br>
+ : CommandLine(CommandLine.vec()), Action(Action), OwnsAction(false),<br>
+ Files(Files) {}<br>
+<br>
+ToolInvocation::ToolInvocation(ArrayRef<std::string> CommandLine,<br>
+ FrontendAction *FAction, FileManager *Files)<br>
+ : CommandLine(CommandLine.vec()),<br>
+ Action(new SingleFrontendActionFactory(FAction)), OwnsAction(true),<br>
+ Files(Files) {}<br>
+<br>
+ToolInvocation::~ToolInvocation() {<br>
+ if (OwnsAction)<br>
+ delete Action;<br>
}<br>
<br>
void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {<br>
@@ -175,6 +210,14 @@ bool ToolInvocation::run() {<br>
}<br>
OwningPtr<clang::CompilerInvocation> Invocation(<br>
newInvocation(&Diagnostics, *CC1Args));<br>
+ for (llvm::StringMap<StringRef>::const_iterator<br>
+ It = MappedFileContents.begin(), End = MappedFileContents.end();<br>
+ It != End; ++It) {<br>
+ // Inject the code as the given file name into the preprocessor options.<br>
+ const llvm::MemoryBuffer *Input =<br>
+ llvm::MemoryBuffer::getMemBuffer(It->getValue());<br>
+ Invocation->getPreprocessorOpts().addRemappedFile(It->getKey(), Input);<br>
+ }<br>
return runInvocation(BinaryName, Compilation.get(), Invocation.take());<br>
}<br>
<br>
@@ -189,16 +232,20 @@ bool ToolInvocation::runInvocation(<br>
llvm::errs() << "\n";<br>
}<br>
<br>
+ return Action->runInvocation(Invocation, Files);<br>
+}<br>
+<br>
+bool FrontendActionFactory::runInvocation(CompilerInvocation *Invocation,<br>
+ FileManager *Files) {<br>
// Create a compiler instance to handle the actual work.<br>
clang::CompilerInstance Compiler;<br>
Compiler.setInvocation(Invocation);<br>
Compiler.setFileManager(Files);<br>
- // FIXME: What about LangOpts?<br>
<br>
- // ToolAction can have lifetime requirements for Compiler or its members, and<br>
- // we need to ensure it's deleted earlier than Compiler. So we pass it to an<br>
- // OwningPtr declared after the Compiler variable.<br>
- OwningPtr<FrontendAction> ScopedToolAction(ToolAction.take());<br>
+ // The FrontendAction can have lifetime requirements for Compiler or its<br>
+ // members, and we need to ensure it's deleted earlier than Compiler. So we<br>
+ // pass it to an OwningPtr declared after the Compiler variable.<br>
+ OwningPtr<FrontendAction> ScopedToolAction(create());<br>
<br>
// Create the compilers actual diagnostics engine.<br>
Compiler.createDiagnostics();<br>
@@ -206,32 +253,16 @@ bool ToolInvocation::runInvocation(<br>
return false;<br>
<br>
Compiler.createSourceManager(*Files);<br>
- addFileMappingsTo(Compiler.getSourceManager());<br>
<br>
const bool Success = Compiler.ExecuteAction(*ScopedToolAction);<br>
<br>
- Compiler.resetAndLeakFileManager();<br>
Files->clearStatCaches();<br>
return Success;<br>
}<br>
<br>
-void ToolInvocation::addFileMappingsTo(SourceManager &Sources) {<br>
- for (llvm::StringMap<StringRef>::const_iterator<br>
- It = MappedFileContents.begin(), End = MappedFileContents.end();<br>
- It != End; ++It) {<br>
- // Inject the code as the given file name into the preprocessor options.<br>
- const llvm::MemoryBuffer *Input =<br>
- llvm::MemoryBuffer::getMemBuffer(It->getValue());<br>
- // FIXME: figure out what '0' stands for.<br>
- const FileEntry *FromFile = Files->getVirtualFile(<br>
- It->getKey(), Input->getBufferSize(), 0);<br>
- Sources.overrideFileContents(FromFile, Input);<br>
- }<br>
-}<br>
-<br>
ClangTool::ClangTool(const CompilationDatabase &Compilations,<br>
ArrayRef<std::string> SourcePaths)<br>
- : Files((FileSystemOptions())) {<br>
+ : Files(new FileManager(FileSystemOptions())) {<br>
ArgsAdjusters.push_back(new ClangStripOutputAdjuster());<br>
ArgsAdjusters.push_back(new ClangSyntaxOnlyAdjuster());<br>
for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) {<br>
@@ -274,7 +305,7 @@ void ClangTool::clearArgumentsAdjusters(<br>
ArgsAdjusters.clear();<br>
}<br>
<br>
-int ClangTool::run(FrontendActionFactory *ActionFactory) {<br>
+int ClangTool::run(ToolAction *Action) {<br>
// Exists solely for the purpose of lookup of the resource path.<br>
// This just needs to be some symbol in the binary.<br>
static int StaticSymbol;<br>
@@ -309,7 +340,7 @@ int ClangTool::run(FrontendActionFactory<br>
DEBUG({<br>
llvm::dbgs() << "Processing: " << File << ".\n";<br>
});<br>
- ToolInvocation Invocation(CommandLine, ActionFactory->create(), &Files);<br>
+ ToolInvocation Invocation(CommandLine, Action, Files.getPtr());<br>
for (int I = 0, E = MappedFileContents.size(); I != E; ++I) {<br>
Invocation.mapVirtualFile(MappedFileContents[I].first,<br>
MappedFileContents[I].second);<br>
@@ -323,5 +354,58 @@ int ClangTool::run(FrontendActionFactory<br>
return ProcessingFailed ? 1 : 0;<br>
}<br>
<br>
+namespace {<br>
+<br>
+class ASTBuilderAction : public ToolAction {<br>
+ std::vector<ASTUnit *> &ASTs;<br>
+<br>
+public:<br>
+ ASTBuilderAction(std::vector<ASTUnit *> &ASTs) : ASTs(ASTs) {}<br>
+<br>
+ bool runInvocation(CompilerInvocation *Invocation,<br>
+ FileManager *Files) {<br>
+ // FIXME: This should use the provided FileManager.<br>
+ ASTUnit *AST = ASTUnit::LoadFromCompilerInvocation(<br>
+ Invocation,<br>
+ CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts()));<br>
+ if (!AST)<br>
+ return false;<br>
+<br>
+ ASTs.push_back(AST);<br>
+ return true;<br>
+ }<br>
+};<br>
+<br>
+}<br>
+<br>
+int ClangTool::buildASTs(std::vector<ASTUnit *> &ASTs) {<br>
+ ASTBuilderAction Action(ASTs);<br>
+ return run(&Action);<br>
+}<br>
+<br>
+ASTUnit *buildASTFromCode(const Twine &Code, const Twine &FileName) {<br>
+ return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName);<br>
+}<br>
+<br>
+ASTUnit *buildASTFromCodeWithArgs(const Twine &Code,<br>
+ const std::vector<std::string> &Args,<br>
+ const Twine &FileName) {<br>
+ SmallString<16> FileNameStorage;<br>
+ StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);<br>
+<br>
+ std::vector<ASTUnit *> ASTs;<br>
+ ASTBuilderAction Action(ASTs);<br>
+ ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action, 0);<br>
+<br>
+ SmallString<1024> CodeStorage;<br>
+ Invocation.mapVirtualFile(FileNameRef,<br>
+ Code.toNullTerminatedStringRef(CodeStorage));<br>
+ if (!Invocation.run())<br>
+ return 0;<br>
+<br>
+ assert(ASTs.size() == 1);<br>
+ return ASTs[0];<br>
+}<br>
+<br>
} // end namespace tooling<br>
} // end namespace clang<br>
<br>
Modified: cfe/trunk/unittests/Tooling/ToolingTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ToolingTest.cpp?rev=194164&r1=194163&r2=194164&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ToolingTest.cpp?rev=194164&r1=194163&r2=194164&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/unittests/Tooling/ToolingTest.cpp (original)<br>
+++ cfe/trunk/unittests/Tooling/ToolingTest.cpp Wed Nov 6 14:12:45 2013<br>
@@ -10,12 +10,14 @@<br>
#include "clang/AST/ASTConsumer.h"<br>
#include "clang/AST/DeclCXX.h"<br>
#include "clang/AST/DeclGroup.h"<br>
+#include "clang/Frontend/ASTUnit.h"<br>
#include "clang/Frontend/CompilerInstance.h"<br>
#include "clang/Frontend/FrontendAction.h"<br>
#include "clang/Frontend/FrontendActions.h"<br>
#include "clang/Tooling/CompilationDatabase.h"<br>
#include "clang/Tooling/Tooling.h"<br>
#include "gtest/gtest.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
#include <string><br>
<br>
namespace clang {<br>
@@ -83,6 +85,18 @@ class FindClassDeclXConsumer : public cl<br>
private:<br>
bool *FoundClassDeclX;<br>
};<br>
+bool FindClassDeclX(ASTUnit *AST) {<br>
+ for (std::vector<Decl *>::iterator i = AST->top_level_begin(),<br>
+ e = AST->top_level_end();<br>
+ i != e; ++i) {<br>
+ if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(*i)) {<br>
+ if (Record->getName() == "X") {<br>
+ return true;<br>
+ }<br>
+ }<br>
+ }<br>
+ return false;<br>
+}<br>
} // end namespace<br>
<br>
TEST(runToolOnCode, FindsClassDecl) {<br>
@@ -97,6 +111,16 @@ TEST(runToolOnCode, FindsClassDecl) {<br>
EXPECT_FALSE(FoundClassDeclX);<br>
}<br>
<br>
+TEST(buildASTFromCode, FindsClassDecl) {<br>
+ OwningPtr<ASTUnit> AST(buildASTFromCode("class X;"));<br>
+ ASSERT_TRUE(AST.get());<br>
+ EXPECT_TRUE(FindClassDeclX(AST.get()));<br>
+<br>
+ AST.reset(buildASTFromCode("class Y;"));<br>
+ ASSERT_TRUE(AST.get());<br>
+ EXPECT_FALSE(FindClassDeclX(AST.get()));<br>
+}<br>
+<br>
TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {<br>
OwningPtr<FrontendActionFactory> Factory(<br>
newFrontendActionFactory<SyntaxOnlyAction>());<br>
@@ -119,13 +143,15 @@ TEST(newFrontendActionFactory, CreatesFr<br>
}<br>
<br>
TEST(ToolInvocation, TestMapVirtualFile) {<br>
- clang::FileManager Files((clang::FileSystemOptions()));<br>
+ IntrusiveRefCntPtr<clang::FileManager> Files(<br>
+ new clang::FileManager(clang::FileSystemOptions()));<br>
std::vector<std::string> Args;<br>
Args.push_back("tool-executable");<br>
Args.push_back("-Idef");<br>
Args.push_back("-fsyntax-only");<br>
Args.push_back("test.cpp");<br>
- clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction, &Files);<br>
+ clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,<br>
+ Files.getPtr());<br>
Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");<br>
Invocation.mapVirtualFile("def/abc", "\n");<br>
EXPECT_TRUE(Invocation.run());<br>
@@ -136,13 +162,15 @@ TEST(ToolInvocation, TestVirtualModulesC<br>
// mapped module.map is found on the include path. In the future, expand this<br>
// test to run a full modules enabled compilation, so we make sure we can<br>
// rerun modules compilations with a virtual file system.<br>
- clang::FileManager Files((clang::FileSystemOptions()));<br>
+ IntrusiveRefCntPtr<clang::FileManager> Files(<br>
+ new clang::FileManager(clang::FileSystemOptions()));<br>
std::vector<std::string> Args;<br>
Args.push_back("tool-executable");<br>
Args.push_back("-Idef");<br>
Args.push_back("-fsyntax-only");<br>
Args.push_back("test.cpp");<br>
- clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction, &Files);<br>
+ clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,<br>
+ Files.getPtr());<br>
Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");<br>
Invocation.mapVirtualFile("def/abc", "\n");<br>
// Add a module.map file in the include directory of our header, so we trigger<br>
@@ -254,5 +282,23 @@ TEST(ClangToolTest, ArgumentAdjusters) {<br>
EXPECT_FALSE(Found);<br>
}<br>
<br>
+TEST(ClangToolTest, BuildASTs) {<br>
+ FixedCompilationDatabase Compilations("/", std::vector<std::string>());<br>
+<br>
+ std::vector<std::string> Sources;<br>
+ Sources.push_back("/a.cc");<br>
+ Sources.push_back("/b.cc");<br>
+ ClangTool Tool(Compilations, Sources);<br>
+<br>
+ Tool.mapVirtualFile("/a.cc", "void a() {}");<br>
+ Tool.mapVirtualFile("/b.cc", "void b() {}");<br>
+<br>
+ std::vector<ASTUnit *> ASTs;<br>
+ EXPECT_EQ(0, Tool.buildASTs(ASTs));<br>
+ EXPECT_EQ(2u, ASTs.size());<br>
+<br>
+ llvm::DeleteContainerPointers(ASTs);<br>
+}<br>
+<br>
} // end namespace tooling<br>
} // end namespace clang<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
______________________________<u></u>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div></div></div>
</blockquote></div><br></div></div>