Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / unittests / Lex / ModuleDeclStateTest.cpp
blob15306ba22bf67eb56fde07c9e43266950d33753e
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-exception
6 //
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"
22 #include <cstddef>
23 #include <initializer_list>
25 using namespace clang;
27 namespace {
29 class CheckNamedModuleImportingCB : public PPCallbacks {
30 Preprocessor &PP;
31 std::vector<bool> IsImportingNamedModulesAssertions;
32 std::size_t NextCheckingIndex;
34 public:
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]);
45 NextCheckingIndex++;
47 ASSERT_EQ(Imported, nullptr);
50 // Currently, only the named module will be handled by `moduleImport`
51 // callback.
52 std::size_t importNamedModuleNum() { return NextCheckingIndex; }
54 class ModuleDeclStateTest : public ::testing::Test {
55 protected:
56 ModuleDeclStateTest()
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;
97 FileManager FileMgr;
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"(
110 export module foo;
112 std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);
114 std::initializer_list<bool> ImportKinds = {};
115 preprocess(*PP,
116 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
118 auto *Callback =
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"(
129 module foo;
131 std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);
133 std::initializer_list<bool> ImportKinds = {};
134 preprocess(*PP,
135 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
137 auto *Callback =
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"(
148 module foo:part;
150 std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);
152 std::initializer_list<bool> ImportKinds = {};
153 preprocess(*PP,
154 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
156 auto *Callback =
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 = {};
172 preprocess(*PP,
173 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
175 auto *Callback =
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 = {};
191 preprocess(*PP,
192 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
194 auto *Callback =
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 = {};
210 preprocess(*PP,
211 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
213 auto *Callback =
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"(
223 module;
224 #include "bar.h"
225 #include <zoo.h>
226 import "bar";
227 import <zoo>;
228 export module foo:part;
229 import "HU";
230 import M;
231 import :another;
233 std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);
235 std::initializer_list<bool> ImportKinds = {true, true};
236 preprocess(*PP,
237 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
239 auto *Callback =
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"(
250 module;
251 #include "bar.h"
252 #include <zoo.h>
253 import "bar";
254 import <zoo>;
255 export module foo:part;
256 import "HU";
257 import M;
258 import :another;
260 std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);
262 std::initializer_list<bool> ImportKinds = {true, true};
263 preprocess(*PP,
264 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
266 auto *Callback =
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"(
277 #include "bar.h"
278 #include <zoo.h>
279 import "bar";
280 import <zoo>;
281 import "HU";
282 import M;
283 // We can't import a partition in non-module TU.
284 import :another;
286 std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::CXX);
288 std::initializer_list<bool> ImportKinds = {true};
289 preprocess(*PP,
290 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
292 auto *Callback =
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"(
302 @import anything;
304 std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::ObjCXX);
306 std::initializer_list<bool> ImportKinds = {false};
307 preprocess(*PP,
308 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
310 auto *Callback =
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"(
320 import "HU";
321 @import anything;
322 import M;
323 @import another;
324 import M2;
326 std::unique_ptr<Preprocessor> PP = getPreprocessor(source, Language::ObjCXX);
328 std::initializer_list<bool> ImportKinds = {false, true, false, true};
329 preprocess(*PP,
330 std::make_unique<CheckNamedModuleImportingCB>(*PP, ImportKinds));
332 auto *Callback =
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());
340 } // namespace