1 //===- unittest/AST/ExternalASTSourceTest.cpp -----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains tests for Clang's ExternalASTSource. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/ASTConsumer.h" 14 #include "clang/AST/ASTContext.h" 15 #include "clang/AST/ExternalASTSource.h" 16 #include "clang/Frontend/CompilerInstance.h" 17 #include "clang/Frontend/CompilerInvocation.h" 18 #include "clang/Frontend/FrontendActions.h" 19 #include "clang/Lex/PreprocessorOptions.h" 20 #include "gtest/gtest.h" 21 22 using namespace clang; 23 using namespace llvm; 24 25 26 class TestFrontendAction : public ASTFrontendAction { 27 public: 28 TestFrontendAction(ExternalASTSource *Source) : Source(Source) {} 29 30 private: 31 void ExecuteAction() override { 32 getCompilerInstance().getASTContext().setExternalSource(Source); 33 getCompilerInstance().getASTContext().getTranslationUnitDecl() 34 ->setHasExternalVisibleStorage(); 35 return ASTFrontendAction::ExecuteAction(); 36 } 37 38 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 39 StringRef InFile) override { 40 return std::make_unique<ASTConsumer>(); 41 } 42 43 IntrusiveRefCntPtr<ExternalASTSource> Source; 44 }; 45 46 bool testExternalASTSource(ExternalASTSource *Source, 47 StringRef FileContents) { 48 CompilerInstance Compiler; 49 Compiler.createDiagnostics(); 50 51 auto Invocation = std::make_shared<CompilerInvocation>(); 52 Invocation->getPreprocessorOpts().addRemappedFile( 53 "test.cc", MemoryBuffer::getMemBuffer(FileContents).release()); 54 const char *Args[] = { "test.cc" }; 55 CompilerInvocation::CreateFromArgs(*Invocation, Args, 56 Compiler.getDiagnostics()); 57 Compiler.setInvocation(std::move(Invocation)); 58 59 TestFrontendAction Action(Source); 60 return Compiler.ExecuteAction(Action); 61 } 62 63 64 // Ensure that a failed name lookup into an external source only occurs once. 65 TEST(ExternalASTSourceTest, FailedLookupOccursOnce) { 66 struct TestSource : ExternalASTSource { 67 TestSource(unsigned &Calls) : Calls(Calls) {} 68 69 bool FindExternalVisibleDeclsByName(const DeclContext *, 70 DeclarationName Name) override { 71 if (Name.getAsString() == "j") 72 ++Calls; 73 return false; 74 } 75 76 unsigned &Calls; 77 }; 78 79 unsigned Calls = 0; 80 ASSERT_TRUE(testExternalASTSource(new TestSource(Calls), "int j, k = j;")); 81 EXPECT_EQ(1u, Calls); 82 } 83