1 //===-- ModulesTests.cpp ---------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
11 #include "llvm/ADT/StringRef.h"
12 #include "gmock/gmock.h"
13 #include "gtest/gtest.h"
22 TEST(Modules
, TextualIncludeInPreamble
) {
23 TestTU TU
= TestTU::withCode(R
"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(
34 textual header "Textual
.h
"
38 // Test that we do not crash.
42 // Verify that visibility of AST nodes belonging to modules, but loaded from
43 // preamble PCH, is restored.
44 TEST(Modules
, PreambleBuildVisibility
) {
45 TestTU TU
= TestTU::withCode(R
"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(
59 TU
.AdditionalFiles
["m.modulemap"] = R
"modulemap(
64 EXPECT_TRUE(TU
.build().getDiagnostics().empty());
67 TEST(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(R
"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
"
84 TU
.AdditionalFiles
["non-modular.h"] = "";
85 TU
.AdditionalFiles
["m.modulemap"] = R
"modulemap(
91 // Test that we do not crash.
95 // Unknown module formats are a fatal failure for clang. Ensure we don't crash.
96 TEST(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(
110 // Test that we do not crash.
114 // Test that we can build and use a preamble for a module unit.
115 TEST(Modules
, ModulePreamble
) {
116 TestTU TU
= TestTU::withCode(R
"cpp(
118 #define PREAMBLE_MACRO 1
120 #define MODULE_MACRO 2
122 #define PRIVATE_MACRO 3
124 TU
.ExtraArgs
.push_back("-std=c++20");
125 TU
.ExtraArgs
.push_back("--precompile");
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());
136 EXPECT_EQ(GetMacroFile("PREAMBLE_MACRO"), SM
.getPreambleFileID());
137 EXPECT_EQ(GetMacroFile("MODULE_MACRO"), SM
.getMainFileID());
138 EXPECT_EQ(GetMacroFile("PRIVATE_MACRO"), SM
.getMainFileID());
142 } // namespace clangd