r194164 - Introduce ClangTool::buildASTs, and buildASTFromCode.
Sean Silva
chisophugis at gmail.com
Fri Jan 30 05:46:56 PST 2015
On Fri, Jan 30, 2015 at 12:37 PM, Manuel Klimek <klimek at google.com> wrote:
> 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 ;)
>
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.
-- Sean Silva
>
>
>>
>>
>> -- 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/eddbd32e/attachment.html>
More information about the cfe-commits
mailing list