144 lines · cpp
1//===-- ModulesTests.cpp ---------------------------------------*- C++ -*-===//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 "TestFS.h"10#include "TestTU.h"11#include "llvm/ADT/StringRef.h"12#include "gmock/gmock.h"13#include "gtest/gtest.h"14 15#include <memory>16#include <string>17 18namespace clang {19namespace clangd {20namespace {21 22TEST(Modules, TextualIncludeInPreamble) {23 TestTU TU = TestTU::withCode(R"cpp(24 #include "Textual.h"25 26 void foo() {}27)cpp");28 TU.ExtraArgs.push_back("-fmodule-name=M");29 TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));30 TU.AdditionalFiles["Textual.h"] = "void foo();";31 TU.AdditionalFiles["m.modulemap"] = R"modulemap(32 module M {33 module Textual {34 textual header "Textual.h"35 }36 }37)modulemap";38 // Test that we do not crash.39 TU.index();40}41 42// Verify that visibility of AST nodes belonging to modules, but loaded from43// preamble PCH, is restored.44TEST(Modules, PreambleBuildVisibility) {45 TestTU TU = TestTU::withCode(R"cpp(46 #include "module.h"47 48 foo x;49)cpp");50 TU.OverlayRealFileSystemForModules = true;51 TU.ExtraArgs.push_back("-fmodules");52 TU.ExtraArgs.push_back("-fmodules-strict-decluse");53 TU.ExtraArgs.push_back("-Xclang");54 TU.ExtraArgs.push_back("-fmodules-local-submodule-visibility");55 TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));56 TU.AdditionalFiles["module.h"] = R"cpp(57 typedef int foo;58)cpp";59 TU.AdditionalFiles["m.modulemap"] = R"modulemap(60 module M {61 header "module.h"62 }63)modulemap";64 EXPECT_TRUE(TU.build().getDiagnostics().empty());65}66 67TEST(Modules, Diagnostic) {68 // Produce a diagnostic while building an implicit module. Use69 // -fmodules-strict-decluse, but any non-silenced diagnostic will do.70 TestTU TU = TestTU::withCode(R"cpp(71 /*error-ok*/72 #include "modular.h"73 74 void bar() {}75)cpp");76 TU.OverlayRealFileSystemForModules = true;77 TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));78 TU.ExtraArgs.push_back("-fmodules");79 TU.ExtraArgs.push_back("-fimplicit-modules");80 TU.ExtraArgs.push_back("-fmodules-strict-decluse");81 TU.AdditionalFiles["modular.h"] = R"cpp(82 #include "non-modular.h"83 )cpp";84 TU.AdditionalFiles["non-modular.h"] = "";85 TU.AdditionalFiles["m.modulemap"] = R"modulemap(86 module M {87 header "modular.h"88 }89)modulemap";90 91 // Test that we do not crash.92 TU.build();93}94 95// Unknown module formats are a fatal failure for clang. Ensure we don't crash.96TEST(Modules, UnknownFormat) {97 TestTU TU = TestTU::withCode(R"(#include "modular.h")");98 TU.OverlayRealFileSystemForModules = true;99 TU.ExtraArgs.push_back("-Xclang");100 TU.ExtraArgs.push_back("-fmodule-format=obj");101 TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap"));102 TU.ExtraArgs.push_back("-fmodules");103 TU.ExtraArgs.push_back("-fimplicit-modules");104 TU.AdditionalFiles["modular.h"] = "";105 TU.AdditionalFiles["m.modulemap"] = R"modulemap(106 module M {107 header "modular.h"108 })modulemap";109 110 // Test that we do not crash.111 TU.build();112}113 114// Test that we can build and use a preamble for a module unit.115TEST(Modules, ModulePreamble) {116 TestTU TU = TestTU::withCode(R"cpp(117 module;118 #define PREAMBLE_MACRO 1119 export module foo;120 #define MODULE_MACRO 2121 module :private;122 #define PRIVATE_MACRO 3123 )cpp");124 TU.ExtraArgs.push_back("-std=c++20");125 TU.ExtraArgs.push_back("--precompile");126 127 auto AST = TU.build();128 auto &SM = AST.getSourceManager();129 auto GetMacroFile = [&](llvm::StringRef Name) -> FileID {130 if (auto *MI = AST.getPreprocessor().getMacroInfo(131 &AST.getASTContext().Idents.get(Name)))132 return SM.getFileID(MI->getDefinitionLoc());133 return {};134 };135 136 EXPECT_EQ(GetMacroFile("PREAMBLE_MACRO"), SM.getPreambleFileID());137 EXPECT_EQ(GetMacroFile("MODULE_MACRO"), SM.getMainFileID());138 EXPECT_EQ(GetMacroFile("PRIVATE_MACRO"), SM.getMainFileID());139}140 141} // namespace142} // namespace clangd143} // namespace clang144