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