|  | //===- unittest/AST/ExternalASTSourceTest.cpp -----------------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file contains tests for Clang's ExternalASTSource. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "clang/AST/ExternalASTSource.h" | 
|  | #include "clang/AST/ASTConsumer.h" | 
|  | #include "clang/AST/ASTContext.h" | 
|  | #include "clang/Frontend/CompilerInstance.h" | 
|  | #include "clang/Frontend/CompilerInvocation.h" | 
|  | #include "clang/Frontend/FrontendActions.h" | 
|  | #include "clang/Lex/PreprocessorOptions.h" | 
|  | #include "llvm/Support/VirtualFileSystem.h" | 
|  | #include "gtest/gtest.h" | 
|  |  | 
|  | using namespace clang; | 
|  | using namespace llvm; | 
|  |  | 
|  |  | 
|  | class TestFrontendAction : public ASTFrontendAction { | 
|  | public: | 
|  | TestFrontendAction(IntrusiveRefCntPtr<ExternalASTSource> Source) | 
|  | : Source(std::move(Source)) {} | 
|  |  | 
|  | private: | 
|  | void ExecuteAction() override { | 
|  | getCompilerInstance().getASTContext().setExternalSource(Source); | 
|  | getCompilerInstance().getASTContext().getTranslationUnitDecl() | 
|  | ->setHasExternalVisibleStorage(); | 
|  | return ASTFrontendAction::ExecuteAction(); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, | 
|  | StringRef InFile) override { | 
|  | return std::make_unique<ASTConsumer>(); | 
|  | } | 
|  |  | 
|  | IntrusiveRefCntPtr<ExternalASTSource> Source; | 
|  | }; | 
|  |  | 
|  | bool testExternalASTSource(llvm::IntrusiveRefCntPtr<ExternalASTSource> Source, | 
|  | StringRef FileContents) { | 
|  |  | 
|  | auto Invocation = std::make_shared<CompilerInvocation>(); | 
|  | Invocation->getPreprocessorOpts().addRemappedFile( | 
|  | "test.cc", MemoryBuffer::getMemBuffer(FileContents).release()); | 
|  | const char *Args[] = { "test.cc" }; | 
|  |  | 
|  | DiagnosticOptions InvocationDiagOpts; | 
|  | auto InvocationDiags = CompilerInstance::createDiagnostics( | 
|  | *llvm::vfs::getRealFileSystem(), InvocationDiagOpts); | 
|  | CompilerInvocation::CreateFromArgs(*Invocation, Args, *InvocationDiags); | 
|  |  | 
|  | CompilerInstance Compiler(std::move(Invocation)); | 
|  | Compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem()); | 
|  | Compiler.createDiagnostics(); | 
|  |  | 
|  | TestFrontendAction Action(Source); | 
|  | return Compiler.ExecuteAction(Action); | 
|  | } | 
|  |  | 
|  | // Ensure that a failed name lookup into an external source only occurs once. | 
|  | TEST(ExternalASTSourceTest, FailedLookupOccursOnce) { | 
|  | struct TestSource : ExternalASTSource { | 
|  | TestSource(unsigned &Calls) : Calls(Calls) {} | 
|  |  | 
|  | bool | 
|  | FindExternalVisibleDeclsByName(const DeclContext *, DeclarationName Name, | 
|  | const DeclContext *OriginalDC) override { | 
|  | if (Name.getAsString() == "j") | 
|  | ++Calls; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | unsigned &Calls; | 
|  | }; | 
|  |  | 
|  | unsigned Calls = 0; | 
|  | ASSERT_TRUE(testExternalASTSource( | 
|  | llvm::makeIntrusiveRefCnt<TestSource>(Calls), "int j, k = j;")); | 
|  | EXPECT_EQ(1u, Calls); | 
|  | } |