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-exception
6//
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(Code: R"cpp(
24 #include "Textual.h"
25
26 void foo() {}
27)cpp");
28 TU.ExtraArgs.push_back(x: "-fmodule-name=M");
29 TU.ExtraArgs.push_back(x: "-fmodule-map-file=" + testPath(File: "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 from
43// preamble PCH, is restored.
44TEST(Modules, PreambleBuildVisibility) {
45 TestTU TU = TestTU::withCode(Code: R"cpp(
46 #include "module.h"
47
48 foo x;
49)cpp");
50 TU.OverlayRealFileSystemForModules = true;
51 TU.ExtraArgs.push_back(x: "-fmodules");
52 TU.ExtraArgs.push_back(x: "-fmodules-strict-decluse");
53 TU.ExtraArgs.push_back(x: "-Xclang");
54 TU.ExtraArgs.push_back(x: "-fmodules-local-submodule-visibility");
55 TU.ExtraArgs.push_back(x: "-fmodule-map-file=" + testPath(File: "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. Use
69 // -fmodules-strict-decluse, but any non-silenced diagnostic will do.
70 TestTU TU = TestTU::withCode(Code: R"cpp(
71 /*error-ok*/
72 #include "modular.h"
73
74 void bar() {}
75)cpp");
76 TU.OverlayRealFileSystemForModules = true;
77 TU.ExtraArgs.push_back(x: "-fmodule-map-file=" + testPath(File: "m.modulemap"));
78 TU.ExtraArgs.push_back(x: "-fmodules");
79 TU.ExtraArgs.push_back(x: "-fimplicit-modules");
80 TU.ExtraArgs.push_back(x: "-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(Code: R"(#include "modular.h")");
98 TU.OverlayRealFileSystemForModules = true;
99 TU.ExtraArgs.push_back(x: "-Xclang");
100 TU.ExtraArgs.push_back(x: "-fmodule-format=obj");
101 TU.ExtraArgs.push_back(x: "-fmodule-map-file=" + testPath(File: "m.modulemap"));
102 TU.ExtraArgs.push_back(x: "-fmodules");
103 TU.ExtraArgs.push_back(x: "-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(Code: R"cpp(
117 module;
118 #define PREAMBLE_MACRO 1
119 export module foo;
120 #define MODULE_MACRO 2
121 module :private;
122 #define PRIVATE_MACRO 3
123 )cpp");
124 TU.ExtraArgs.push_back(x: "-std=c++20");
125 TU.ExtraArgs.push_back(x: "--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 II: &AST.getASTContext().Idents.get(Name)))
132 return SM.getFileID(SpellingLoc: 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} // namespace
142} // namespace clangd
143} // namespace clang
144

source code of clang-tools-extra/clangd/unittests/ModulesTests.cpp