brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.1 KiB · ac2ddfa Raw
331 lines · cpp
1//===- unittests/Lex/ModuleDeclStateTest.cpp - PPCallbacks tests ------===//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/Basic/Diagnostic.h"10#include "clang/Basic/DiagnosticOptions.h"11#include "clang/Basic/FileManager.h"12#include "clang/Basic/LangOptions.h"13#include "clang/Basic/SourceManager.h"14#include "clang/Basic/TargetInfo.h"15#include "clang/Basic/TargetOptions.h"16#include "clang/Lex/HeaderSearch.h"17#include "clang/Lex/HeaderSearchOptions.h"18#include "clang/Lex/ModuleLoader.h"19#include "clang/Lex/Preprocessor.h"20#include "clang/Lex/PreprocessorOptions.h"21#include "gtest/gtest.h"22#include <cstddef>23#include <initializer_list>24 25using namespace clang;26 27namespace {28 29class CheckNamedModuleImportingCB : public PPCallbacks {30  Preprocessor &PP;31  std::vector<bool> IsImportingNamedModulesAssertions;32  std::size_t NextCheckingIndex;33 34public:35  CheckNamedModuleImportingCB(Preprocessor &PP,36                              std::initializer_list<bool> lists)37      : PP(PP), IsImportingNamedModulesAssertions(lists), NextCheckingIndex(0) {38  }39 40  void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,41                    const Module *Imported) override {42    ASSERT_TRUE(NextCheckingIndex < IsImportingNamedModulesAssertions.size());43    EXPECT_EQ(PP.isInImportingCXXNamedModules(),44              IsImportingNamedModulesAssertions[NextCheckingIndex]);45    NextCheckingIndex++;46 47    ASSERT_EQ(Imported, nullptr);48  }49 50  // Currently, only the named module will be handled by `moduleImport`51  // callback.52  std::size_t importNamedModuleNum() { return NextCheckingIndex; }53};54class ModuleDeclStateTest : public ::testing::Test {55protected:56  ModuleDeclStateTest()57      : FileMgr(FileMgrOpts),58        Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()),59        SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {60    TargetOpts->Triple = "x86_64-unknown-linux-gnu";61    Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts);62  }63 64  std::unique_ptr<Preprocessor> getPreprocessor(const char *source,65                                                Language Lang) {66    std::unique_ptr<llvm::MemoryBuffer> Buf =67        llvm::MemoryBuffer::getMemBuffer(source);68    SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));69 70    std::vector<std::string> Includes;71    LangOptions::setLangDefaults(LangOpts, Lang, Target->getTriple(), Includes,72                                 LangStandard::lang_cxx20);73    LangOpts.CPlusPlusModules = true;74    if (Lang != Language::CXX) {75      LangOpts.Modules = true;76      LangOpts.ImplicitModules = true;77    }78 79    HeaderInfo.emplace(HSOpts, SourceMgr, Diags, LangOpts, Target.get());80 81    return std::make_unique<Preprocessor>(PPOpts, Diags, LangOpts, SourceMgr,82                                          *HeaderInfo, ModLoader,83                                          /*IILookup=*/nullptr,84                                          /*OwnsHeaderSearch=*/false);85  }86 87  void preprocess(Preprocessor &PP, std::unique_ptr<PPCallbacks> C) {88    PP.Initialize(*Target);89    PP.addPPCallbacks(std::move(C));90    PP.EnterMainSourceFile();91 92    PP.LexTokensUntilEOF();93  }94 95  FileSystemOptions FileMgrOpts;96  FileManager FileMgr;97  DiagnosticOptions DiagOpts;98  DiagnosticsEngine Diags;99  SourceManager SourceMgr;100  std::shared_ptr<TargetOptions> TargetOpts;101  IntrusiveRefCntPtr<TargetInfo> Target;102  LangOptions LangOpts;103  TrivialModuleLoader ModLoader;104  HeaderSearchOptions HSOpts;105  std::optional<HeaderSearch> HeaderInfo;106  PreprocessorOptions PPOpts;107};108 109TEST_F(ModuleDeclStateTest, NamedModuleInterface) {110  const char *source = R"(111export module foo;112  )";113  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);114 115  std::initializer_list<bool> ImportKinds = {};116  auto Callback =117      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);118  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();119  preprocess(*PP, std::move(Callback));120  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0);121  EXPECT_TRUE(PP->isInNamedModule());122  EXPECT_TRUE(PP->isInNamedInterfaceUnit());123  EXPECT_FALSE(PP->isInImplementationUnit());124  EXPECT_EQ(PP->getNamedModuleName(), "foo");125}126 127TEST_F(ModuleDeclStateTest, NamedModuleImplementation) {128  const char *source = R"(129module foo;130  )";131  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);132 133  std::initializer_list<bool> ImportKinds = {};134  auto Callback =135      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);136  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();137  preprocess(*PP, std::move(Callback));138  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0);139  EXPECT_TRUE(PP->isInNamedModule());140  EXPECT_FALSE(PP->isInNamedInterfaceUnit());141  EXPECT_TRUE(PP->isInImplementationUnit());142  EXPECT_EQ(PP->getNamedModuleName(), "foo");143}144 145TEST_F(ModuleDeclStateTest, ModuleImplementationPartition) {146  const char *source = R"(147module foo:part;148  )";149  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);150 151  std::initializer_list<bool> ImportKinds = {};152  auto Callback =153      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);154  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();155  preprocess(*PP, std::move(Callback));156  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0);157  EXPECT_TRUE(PP->isInNamedModule());158  EXPECT_FALSE(PP->isInNamedInterfaceUnit());159  EXPECT_FALSE(PP->isInImplementationUnit());160  EXPECT_EQ(PP->getNamedModuleName(), "foo:part");161}162 163TEST_F(ModuleDeclStateTest, ModuleInterfacePartition) {164  const char *source = R"(165export module foo:part;166  )";167  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);168 169  std::initializer_list<bool> ImportKinds = {};170  auto Callback =171      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);172  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();173  preprocess(*PP, std::move(Callback));174  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0);175  EXPECT_TRUE(PP->isInNamedModule());176  EXPECT_TRUE(PP->isInNamedInterfaceUnit());177  EXPECT_FALSE(PP->isInImplementationUnit());178  EXPECT_EQ(PP->getNamedModuleName(), "foo:part");179}180 181TEST_F(ModuleDeclStateTest, ModuleNameWithDot) {182  const char *source = R"(183export module foo.dot:part.dot;184  )";185  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);186 187  std::initializer_list<bool> ImportKinds = {};188  auto Callback =189      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);190  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();191  preprocess(*PP, std::move(Callback));192  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0);193  EXPECT_TRUE(PP->isInNamedModule());194  EXPECT_TRUE(PP->isInNamedInterfaceUnit());195  EXPECT_FALSE(PP->isInImplementationUnit());196  EXPECT_EQ(PP->getNamedModuleName(), "foo.dot:part.dot");197}198 199TEST_F(ModuleDeclStateTest, NotModule) {200  const char *source = R"(201// export module foo:part;202  )";203  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);204 205  std::initializer_list<bool> ImportKinds = {};206  auto Callback =207      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);208  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();209  preprocess(*PP, std::move(Callback));210  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)0);211  EXPECT_FALSE(PP->isInNamedModule());212  EXPECT_FALSE(PP->isInNamedInterfaceUnit());213  EXPECT_FALSE(PP->isInImplementationUnit());214}215 216TEST_F(ModuleDeclStateTest, ModuleWithGMF) {217  const char *source = R"(218module;219#include "bar.h"220#include <zoo.h>221import "bar";222import <zoo>;223export module foo:part;224import "HU";225import M;226import :another;227  )";228  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);229 230  std::initializer_list<bool> ImportKinds = {true, true};231  auto Callback =232      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);233  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();234  preprocess(*PP, std::move(Callback));235  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)2);236  EXPECT_TRUE(PP->isInNamedModule());237  EXPECT_TRUE(PP->isInNamedInterfaceUnit());238  EXPECT_FALSE(PP->isInImplementationUnit());239  EXPECT_EQ(PP->getNamedModuleName(), "foo:part");240}241 242TEST_F(ModuleDeclStateTest, ModuleWithGMFWithClangNamedModule) {243  const char *source = R"(244module;245#include "bar.h"246#include <zoo.h>247import "bar";248import <zoo>;249export module foo:part;250import "HU";251import M;252import :another;253  )";254  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);255 256  std::initializer_list<bool> ImportKinds = {true, true};257  auto Callback =258      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);259  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();260  preprocess(*PP, std::move(Callback));261  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)2);262  EXPECT_TRUE(PP->isInNamedModule());263  EXPECT_TRUE(PP->isInNamedInterfaceUnit());264  EXPECT_FALSE(PP->isInImplementationUnit());265  EXPECT_EQ(PP->getNamedModuleName(), "foo:part");266}267 268TEST_F(ModuleDeclStateTest, ImportsInNormalTU) {269  const char *source = R"(270#include "bar.h"271#include <zoo.h>272import "bar";273import <zoo>;274import "HU";275import M;276// We can't import a partition in non-module TU.277import :another;278  )";279  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);280 281  std::initializer_list<bool> ImportKinds = {true};282  auto Callback =283      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);284  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();285  preprocess(*PP, std::move(Callback));286  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)1);287  EXPECT_FALSE(PP->isInNamedModule());288  EXPECT_FALSE(PP->isInNamedInterfaceUnit());289  EXPECT_FALSE(PP->isInImplementationUnit());290}291 292TEST_F(ModuleDeclStateTest, ImportAClangNamedModule) {293  const char *source = R"(294@import anything;295  )";296  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::ObjCXX);297 298  std::initializer_list<bool> ImportKinds = {false};299  auto Callback =300      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);301  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();302  preprocess(*PP, std::move(Callback));303  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)1);304  EXPECT_FALSE(PP->isInNamedModule());305  EXPECT_FALSE(PP->isInNamedInterfaceUnit());306  EXPECT_FALSE(PP->isInImplementationUnit());307}308 309TEST_F(ModuleDeclStateTest, ImportWixedForm) {310  const char *source = R"(311import "HU";312@import anything;313import M;314@import another;315import M2;316  )";317  std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::ObjCXX);318 319  std::initializer_list<bool> ImportKinds = {false, true, false, true};320  auto Callback =321      std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds);322  CheckNamedModuleImportingCB *CallbackPtr = Callback.get();323  preprocess(*PP, std::move(Callback));324  EXPECT_EQ(CallbackPtr->importNamedModuleNum(), (size_t)4);325  EXPECT_FALSE(PP->isInNamedModule());326  EXPECT_FALSE(PP->isInNamedInterfaceUnit());327  EXPECT_FALSE(PP->isInImplementationUnit());328}329 330} // namespace331