1 //===- unittests/Lex/ModuleDeclStateTest.cpp - PPCallbacks tests ------===//
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 //===--------------------------------------------------------------===//
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"
23 #include <initializer_list>
25 using namespace clang
;
29 class CheckNamedModuleImportingCB
: public PPCallbacks
{
31 std::vector
<bool> IsImportingNamedModulesAssertions
;
32 std::size_t NextCheckingIndex
;
35 CheckNamedModuleImportingCB(Preprocessor
&PP
,
36 std::initializer_list
<bool> lists
)
37 : PP(PP
), IsImportingNamedModulesAssertions(lists
), NextCheckingIndex(0) {
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
]);
47 ASSERT_EQ(Imported
, nullptr);
50 // Currently, only the named module will be handled by `moduleImport`
52 std::size_t importNamedModuleNum() { return NextCheckingIndex
; }
54 class ModuleDeclStateTest
: public ::testing::Test
{
57 : FileMgr(FileMgrOpts
), DiagID(new DiagnosticIDs()),
58 Diags(DiagID
, new DiagnosticOptions
, new IgnoringDiagConsumer()),
59 SourceMgr(Diags
, FileMgr
), TargetOpts(new TargetOptions
) {
60 TargetOpts
->Triple
= "x86_64-unknown-linux-gnu";
61 Target
= TargetInfo::CreateTargetInfo(Diags
, TargetOpts
);
64 std::unique_ptr
<Preprocessor
>
65 getPreprocessor(const char *source
, Language Lang
) {
66 std::unique_ptr
<llvm::MemoryBuffer
> Buf
=
67 llvm::MemoryBuffer::getMemBuffer(source
);
68 SourceMgr
.setMainFileID(SourceMgr
.createFileID(std::move(Buf
)));
70 std::vector
<std::string
> Includes
;
71 LangOptions::setLangDefaults(LangOpts
, Lang
, Target
->getTriple(), Includes
, LangStandard::lang_cxx20
);
72 LangOpts
.CPlusPlusModules
= true;
73 if (Lang
!= Language::CXX
) {
74 LangOpts
.Modules
= true;
75 LangOpts
.ImplicitModules
= true;
78 HeaderInfo
.emplace(std::make_shared
<HeaderSearchOptions
>(), SourceMgr
,
79 Diags
, LangOpts
, Target
.get());
81 return std::make_unique
<Preprocessor
>(
82 std::make_shared
<PreprocessorOptions
>(), Diags
, LangOpts
, SourceMgr
,
83 *HeaderInfo
, ModLoader
,
84 /*IILookup =*/nullptr,
85 /*OwnsHeaderSearch =*/false);
88 void preprocess(Preprocessor
&PP
, std::unique_ptr
<PPCallbacks
> C
) {
89 PP
.Initialize(*Target
);
90 PP
.addPPCallbacks(std::move(C
));
91 PP
.EnterMainSourceFile();
93 PP
.LexTokensUntilEOF();
96 FileSystemOptions FileMgrOpts
;
98 IntrusiveRefCntPtr
<DiagnosticIDs
> DiagID
;
99 DiagnosticsEngine Diags
;
100 SourceManager SourceMgr
;
101 std::shared_ptr
<TargetOptions
> TargetOpts
;
102 IntrusiveRefCntPtr
<TargetInfo
> Target
;
103 LangOptions LangOpts
;
104 TrivialModuleLoader ModLoader
;
105 std::optional
<HeaderSearch
> HeaderInfo
;
108 TEST_F(ModuleDeclStateTest
, NamedModuleInterface
) {
109 const char *source
= R
"(
112 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
114 std::initializer_list
<bool> ImportKinds
= {};
116 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
119 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
120 EXPECT_EQ(Callback
->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");
127 TEST_F(ModuleDeclStateTest
, NamedModuleImplementation
) {
128 const char *source
= R
"(
131 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
133 std::initializer_list
<bool> ImportKinds
= {};
135 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
138 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
139 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)0);
140 EXPECT_TRUE(PP
->isInNamedModule());
141 EXPECT_FALSE(PP
->isInNamedInterfaceUnit());
142 EXPECT_TRUE(PP
->isInImplementationUnit());
143 EXPECT_EQ(PP
->getNamedModuleName(), "foo");
146 TEST_F(ModuleDeclStateTest
, ModuleImplementationPartition
) {
147 const char *source
= R
"(
150 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
152 std::initializer_list
<bool> ImportKinds
= {};
154 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
157 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
158 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)0);
159 EXPECT_TRUE(PP
->isInNamedModule());
160 EXPECT_FALSE(PP
->isInNamedInterfaceUnit());
161 EXPECT_FALSE(PP
->isInImplementationUnit());
162 EXPECT_EQ(PP
->getNamedModuleName(), "foo:part");
165 TEST_F(ModuleDeclStateTest
, ModuleInterfacePartition
) {
166 const char *source
= R
"(
167 export module foo:part;
169 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
171 std::initializer_list
<bool> ImportKinds
= {};
173 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
176 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
177 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)0);
178 EXPECT_TRUE(PP
->isInNamedModule());
179 EXPECT_TRUE(PP
->isInNamedInterfaceUnit());
180 EXPECT_FALSE(PP
->isInImplementationUnit());
181 EXPECT_EQ(PP
->getNamedModuleName(), "foo:part");
184 TEST_F(ModuleDeclStateTest
, ModuleNameWithDot
) {
185 const char *source
= R
"(
186 export module foo.dot:part.dot;
188 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
190 std::initializer_list
<bool> ImportKinds
= {};
192 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
195 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
196 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)0);
197 EXPECT_TRUE(PP
->isInNamedModule());
198 EXPECT_TRUE(PP
->isInNamedInterfaceUnit());
199 EXPECT_FALSE(PP
->isInImplementationUnit());
200 EXPECT_EQ(PP
->getNamedModuleName(), "foo.dot:part.dot");
203 TEST_F(ModuleDeclStateTest
, NotModule
) {
204 const char *source
= R
"(
205 // export module foo:part;
207 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
209 std::initializer_list
<bool> ImportKinds
= {};
211 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
214 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
215 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)0);
216 EXPECT_FALSE(PP
->isInNamedModule());
217 EXPECT_FALSE(PP
->isInNamedInterfaceUnit());
218 EXPECT_FALSE(PP
->isInImplementationUnit());
221 TEST_F(ModuleDeclStateTest
, ModuleWithGMF
) {
222 const char *source
= R
"(
228 export module foo:part;
233 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
235 std::initializer_list
<bool> ImportKinds
= {true, true};
237 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
240 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
241 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)2);
242 EXPECT_TRUE(PP
->isInNamedModule());
243 EXPECT_TRUE(PP
->isInNamedInterfaceUnit());
244 EXPECT_FALSE(PP
->isInImplementationUnit());
245 EXPECT_EQ(PP
->getNamedModuleName(), "foo:part");
248 TEST_F(ModuleDeclStateTest
, ModuleWithGMFWithClangNamedModule
) {
249 const char *source
= R
"(
255 export module foo:part;
260 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
262 std::initializer_list
<bool> ImportKinds
= {true, true};
264 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
267 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
268 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)2);
269 EXPECT_TRUE(PP
->isInNamedModule());
270 EXPECT_TRUE(PP
->isInNamedInterfaceUnit());
271 EXPECT_FALSE(PP
->isInImplementationUnit());
272 EXPECT_EQ(PP
->getNamedModuleName(), "foo:part");
275 TEST_F(ModuleDeclStateTest
, ImportsInNormalTU
) {
276 const char *source
= R
"(
283 // We can't import a partition in non-module TU.
286 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::CXX
);
288 std::initializer_list
<bool> ImportKinds
= {true};
290 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
293 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
294 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)1);
295 EXPECT_FALSE(PP
->isInNamedModule());
296 EXPECT_FALSE(PP
->isInNamedInterfaceUnit());
297 EXPECT_FALSE(PP
->isInImplementationUnit());
300 TEST_F(ModuleDeclStateTest
, ImportAClangNamedModule
) {
301 const char *source
= R
"(
304 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::ObjCXX
);
306 std::initializer_list
<bool> ImportKinds
= {false};
308 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
311 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
312 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)1);
313 EXPECT_FALSE(PP
->isInNamedModule());
314 EXPECT_FALSE(PP
->isInNamedInterfaceUnit());
315 EXPECT_FALSE(PP
->isInImplementationUnit());
318 TEST_F(ModuleDeclStateTest
, ImportWixedForm
) {
319 const char *source
= R
"(
326 std::unique_ptr
<Preprocessor
> PP
= getPreprocessor(source
, Language::ObjCXX
);
328 std::initializer_list
<bool> ImportKinds
= {false, true, false, true};
330 std::make_unique
<CheckNamedModuleImportingCB
>(*PP
, ImportKinds
));
333 static_cast<CheckNamedModuleImportingCB
*>(PP
->getPPCallbacks());
334 EXPECT_EQ(Callback
->importNamedModuleNum(), (size_t)4);
335 EXPECT_FALSE(PP
->isInNamedModule());
336 EXPECT_FALSE(PP
->isInNamedInterfaceUnit());
337 EXPECT_FALSE(PP
->isInImplementationUnit());