brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · 3944269 Raw
194 lines · cpp
1//== unittests/Sema/SemaNoloadLookupTest.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/AST/DeclLookups.h"10#include "clang/AST/DeclarationName.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/ASTMatchers/ASTMatchers.h"13#include "clang/Driver/CreateInvocationFromArgs.h"14#include "clang/Frontend/CompilerInstance.h"15#include "clang/Frontend/FrontendAction.h"16#include "clang/Frontend/FrontendActions.h"17#include "clang/Parse/ParseAST.h"18#include "clang/Sema/Lookup.h"19#include "clang/Sema/Sema.h"20#include "clang/Sema/SemaConsumer.h"21#include "clang/Tooling/Tooling.h"22#include "gtest/gtest.h"23 24using namespace llvm;25using namespace clang;26using namespace clang::tooling;27 28namespace {29 30class NoloadLookupTest : public ::testing::Test {31  void SetUp() override {32    ASSERT_FALSE(33        sys::fs::createUniqueDirectory("modules-no-comments-test", TestDir));34  }35 36  void TearDown() override { sys::fs::remove_directories(TestDir); }37 38public:39  SmallString<256> TestDir;40 41  void addFile(StringRef Path, StringRef Contents) {42    ASSERT_FALSE(sys::path::is_absolute(Path));43 44    SmallString<256> AbsPath(TestDir);45    sys::path::append(AbsPath, Path);46 47    ASSERT_FALSE(48        sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath)));49 50    std::error_code EC;51    llvm::raw_fd_ostream OS(AbsPath, EC);52    ASSERT_FALSE(EC);53    OS << Contents;54  }55 56  std::string GenerateModuleInterface(StringRef ModuleName,57                                      StringRef Contents) {58    std::string FileName = llvm::Twine(ModuleName + ".cppm").str();59    addFile(FileName, Contents);60 61    CreateInvocationOptions CIOpts;62    CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();63    DiagnosticOptions DiagOpts;64    IntrusiveRefCntPtr<DiagnosticsEngine> Diags =65        CompilerInstance::createDiagnostics(*CIOpts.VFS, DiagOpts);66    CIOpts.Diags = Diags;67 68    std::string CacheBMIPath =69        llvm::Twine(TestDir + "/" + ModuleName + ".pcm").str();70    std::string PrebuiltModulePath =71        "-fprebuilt-module-path=" + TestDir.str().str();72    const char *Args[] = {"clang++",73                          "-std=c++20",74                          "--precompile",75                          PrebuiltModulePath.c_str(),76                          "-working-directory",77                          TestDir.c_str(),78                          "-I",79                          TestDir.c_str(),80                          FileName.c_str()};81    std::shared_ptr<CompilerInvocation> Invocation =82        createInvocation(Args, CIOpts);83    EXPECT_TRUE(Invocation);84 85    CompilerInstance Instance(std::move(Invocation));86    Instance.setDiagnostics(Diags);87    Instance.getFrontendOpts().OutputFile = CacheBMIPath;88    GenerateReducedModuleInterfaceAction Action;89    EXPECT_TRUE(Instance.ExecuteAction(Action));90    EXPECT_FALSE(Diags->hasErrorOccurred());91 92    return CacheBMIPath;93  }94};95 96struct TrivialVisibleDeclConsumer : public VisibleDeclConsumer {97  TrivialVisibleDeclConsumer() {}98  void EnteredContext(DeclContext *Ctx) override {}99  void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,100                 bool InBaseClass) override {101    FoundNum++;102  }103 104  int FoundNum = 0;105};106 107class NoloadLookupConsumer : public SemaConsumer {108public:109  void InitializeSema(Sema &S) override { SemaPtr = &S; }110 111  bool HandleTopLevelDecl(DeclGroupRef D) override {112    if (!D.isSingleDecl())113      return true;114 115    Decl *TD = D.getSingleDecl();116 117    auto *ID = dyn_cast<ImportDecl>(TD);118    if (!ID)119      return true;120 121    clang::Module *M = ID->getImportedModule();122    assert(M);123    if (M->Name != "R")124      return true;125 126    auto *Std = SemaPtr->getStdNamespace();127    EXPECT_TRUE(Std);128    TrivialVisibleDeclConsumer Consumer;129    SemaPtr->LookupVisibleDecls(Std, Sema::LookupNameKind::LookupOrdinaryName,130                                Consumer,131                                /*IncludeGlobalScope=*/true,132                                /*IncludeDependentBases=*/false,133                                /*LoadExternal=*/false);134    EXPECT_EQ(Consumer.FoundNum, 1);135    return true;136  }137 138private:139  Sema *SemaPtr = nullptr;140};141 142class NoloadLookupAction : public ASTFrontendAction {143  std::unique_ptr<ASTConsumer>144  CreateASTConsumer(CompilerInstance &CI, StringRef /*Unused*/) override {145    return std::make_unique<NoloadLookupConsumer>();146  }147};148 149TEST_F(NoloadLookupTest, NonModulesTest) {150  GenerateModuleInterface("M", R"cpp(151module;152namespace std {153  int What();154 155  void bar(int x = What()) {156  }157}158export module M;159export using std::bar;160  )cpp");161 162  GenerateModuleInterface("R", R"cpp(163module;164namespace std {165  class Another;166  int What(Another);167  int What();168}169export module R;170  )cpp");171 172  const char *test_file_contents = R"cpp(173import M;174namespace std {175  void use() {176    bar();177  }178}179import R;180  )cpp";181  std::string DepArg = "-fprebuilt-module-path=" + TestDir.str().str();182  EXPECT_TRUE(runToolOnCodeWithArgs(std::make_unique<NoloadLookupAction>(),183                                    test_file_contents,184                                    {185                                        "-std=c++20",186                                        DepArg.c_str(),187                                        "-I",188                                        TestDir.c_str(),189                                    },190                                    "test.cpp"));191}192 193} // namespace194