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