1b7bdb8cfSRichard Smith //===--- SemaModule.cpp - Semantic Analysis for Modules -------------------===//
2b7bdb8cfSRichard Smith //
3b7bdb8cfSRichard Smith // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b7bdb8cfSRichard Smith // See https://llvm.org/LICENSE.txt for license information.
5b7bdb8cfSRichard Smith // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b7bdb8cfSRichard Smith //
7b7bdb8cfSRichard Smith //===----------------------------------------------------------------------===//
8b7bdb8cfSRichard Smith //
9b7bdb8cfSRichard Smith // This file implements semantic analysis for modules (C++ modules syntax,
10b7bdb8cfSRichard Smith // Objective-C modules syntax, and Clang header modules).
11b7bdb8cfSRichard Smith //
12b7bdb8cfSRichard Smith //===----------------------------------------------------------------------===//
13b7bdb8cfSRichard Smith
14b7bdb8cfSRichard Smith #include "clang/AST/ASTConsumer.h"
15b7bdb8cfSRichard Smith #include "clang/Lex/HeaderSearch.h"
16b7bdb8cfSRichard Smith #include "clang/Lex/Preprocessor.h"
17b7bdb8cfSRichard Smith #include "clang/Sema/SemaInternal.h"
18b7bdb8cfSRichard Smith
19b7bdb8cfSRichard Smith using namespace clang;
20b7bdb8cfSRichard Smith using namespace sema;
21b7bdb8cfSRichard Smith
checkModuleImportContext(Sema & S,Module * M,SourceLocation ImportLoc,DeclContext * DC,bool FromInclude=false)22b7bdb8cfSRichard Smith static void checkModuleImportContext(Sema &S, Module *M,
23b7bdb8cfSRichard Smith SourceLocation ImportLoc, DeclContext *DC,
24b7bdb8cfSRichard Smith bool FromInclude = false) {
25b7bdb8cfSRichard Smith SourceLocation ExternCLoc;
26b7bdb8cfSRichard Smith
27b7bdb8cfSRichard Smith if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) {
28b7bdb8cfSRichard Smith switch (LSD->getLanguage()) {
29b7bdb8cfSRichard Smith case LinkageSpecDecl::lang_c:
30b7bdb8cfSRichard Smith if (ExternCLoc.isInvalid())
31b7bdb8cfSRichard Smith ExternCLoc = LSD->getBeginLoc();
32b7bdb8cfSRichard Smith break;
33b7bdb8cfSRichard Smith case LinkageSpecDecl::lang_cxx:
34b7bdb8cfSRichard Smith break;
35b7bdb8cfSRichard Smith }
36b7bdb8cfSRichard Smith DC = LSD->getParent();
37b7bdb8cfSRichard Smith }
38b7bdb8cfSRichard Smith
39b7bdb8cfSRichard Smith while (isa<LinkageSpecDecl>(DC) || isa<ExportDecl>(DC))
40b7bdb8cfSRichard Smith DC = DC->getParent();
41b7bdb8cfSRichard Smith
42b7bdb8cfSRichard Smith if (!isa<TranslationUnitDecl>(DC)) {
43b7bdb8cfSRichard Smith S.Diag(ImportLoc, (FromInclude && S.isModuleVisible(M))
44b7bdb8cfSRichard Smith ? diag::ext_module_import_not_at_top_level_noop
45b7bdb8cfSRichard Smith : diag::err_module_import_not_at_top_level_fatal)
46b7bdb8cfSRichard Smith << M->getFullModuleName() << DC;
47b7bdb8cfSRichard Smith S.Diag(cast<Decl>(DC)->getBeginLoc(),
48b7bdb8cfSRichard Smith diag::note_module_import_not_at_top_level)
49b7bdb8cfSRichard Smith << DC;
50b7bdb8cfSRichard Smith } else if (!M->IsExternC && ExternCLoc.isValid()) {
51b7bdb8cfSRichard Smith S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)
52b7bdb8cfSRichard Smith << M->getFullModuleName();
53b7bdb8cfSRichard Smith S.Diag(ExternCLoc, diag::note_extern_c_begins_here);
54b7bdb8cfSRichard Smith }
55b7bdb8cfSRichard Smith }
56b7bdb8cfSRichard Smith
5769350e56SIain Sandoe // We represent the primary and partition names as 'Paths' which are sections
5869350e56SIain Sandoe // of the hierarchical access path for a clang module. However for C++20
5969350e56SIain Sandoe // the periods in a name are just another character, and we will need to
6069350e56SIain Sandoe // flatten them into a string.
stringFromPath(ModuleIdPath Path)6169350e56SIain Sandoe static std::string stringFromPath(ModuleIdPath Path) {
6269350e56SIain Sandoe std::string Name;
6369350e56SIain Sandoe if (Path.empty())
6469350e56SIain Sandoe return Name;
6569350e56SIain Sandoe
6669350e56SIain Sandoe for (auto &Piece : Path) {
6769350e56SIain Sandoe if (!Name.empty())
6869350e56SIain Sandoe Name += ".";
6969350e56SIain Sandoe Name += Piece.first->getName();
7069350e56SIain Sandoe }
7169350e56SIain Sandoe return Name;
7269350e56SIain Sandoe }
7369350e56SIain Sandoe
74b7bdb8cfSRichard Smith Sema::DeclGroupPtrTy
ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc)75b7bdb8cfSRichard Smith Sema::ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc) {
76b7bdb8cfSRichard Smith if (!ModuleScopes.empty() &&
77b7bdb8cfSRichard Smith ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment) {
78b7bdb8cfSRichard Smith // Under -std=c++2a -fmodules-ts, we can find an explicit 'module;' after
79b7bdb8cfSRichard Smith // already implicitly entering the global module fragment. That's OK.
80b7bdb8cfSRichard Smith assert(getLangOpts().CPlusPlusModules && getLangOpts().ModulesTS &&
81b7bdb8cfSRichard Smith "unexpectedly encountered multiple global module fragment decls");
82b7bdb8cfSRichard Smith ModuleScopes.back().BeginLoc = ModuleLoc;
83b7bdb8cfSRichard Smith return nullptr;
84b7bdb8cfSRichard Smith }
85b7bdb8cfSRichard Smith
86b7bdb8cfSRichard Smith // We start in the global module; all those declarations are implicitly
87b7bdb8cfSRichard Smith // module-private (though they do not have module linkage).
88e587372fSChuanqi Xu Module *GlobalModule =
89e587372fSChuanqi Xu PushGlobalModuleFragment(ModuleLoc, /*IsImplicit=*/false);
90b7bdb8cfSRichard Smith
91b7bdb8cfSRichard Smith // All declarations created from now on are owned by the global module.
92b7bdb8cfSRichard Smith auto *TU = Context.getTranslationUnitDecl();
939c04851cSChuanqi Xu // [module.global.frag]p2
949c04851cSChuanqi Xu // A global-module-fragment specifies the contents of the global module
959c04851cSChuanqi Xu // fragment for a module unit. The global module fragment can be used to
969c04851cSChuanqi Xu // provide declarations that are attached to the global module and usable
979c04851cSChuanqi Xu // within the module unit.
989c04851cSChuanqi Xu //
999c04851cSChuanqi Xu // So the declations in the global module shouldn't be visible by default.
1009c04851cSChuanqi Xu TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);
101b7bdb8cfSRichard Smith TU->setLocalOwningModule(GlobalModule);
102b7bdb8cfSRichard Smith
103b7bdb8cfSRichard Smith // FIXME: Consider creating an explicit representation of this declaration.
104b7bdb8cfSRichard Smith return nullptr;
105b7bdb8cfSRichard Smith }
106b7bdb8cfSRichard Smith
HandleStartOfHeaderUnit()1076c0e60e8SIain Sandoe void Sema::HandleStartOfHeaderUnit() {
1086c0e60e8SIain Sandoe assert(getLangOpts().CPlusPlusModules &&
1096c0e60e8SIain Sandoe "Header units are only valid for C++20 modules");
1106c0e60e8SIain Sandoe SourceLocation StartOfTU =
1116c0e60e8SIain Sandoe SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
1126c0e60e8SIain Sandoe
1136c0e60e8SIain Sandoe StringRef HUName = getLangOpts().CurrentModule;
1146c0e60e8SIain Sandoe if (HUName.empty()) {
1156c0e60e8SIain Sandoe HUName = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())->getName();
1166c0e60e8SIain Sandoe const_cast<LangOptions &>(getLangOpts()).CurrentModule = HUName.str();
1176c0e60e8SIain Sandoe }
1186c0e60e8SIain Sandoe
1196c0e60e8SIain Sandoe // TODO: Make the C++20 header lookup independent.
120d9cea8d3SIain Sandoe // When the input is pre-processed source, we need a file ref to the original
121d9cea8d3SIain Sandoe // file for the header map.
122d9cea8d3SIain Sandoe auto F = SourceMgr.getFileManager().getFile(HUName);
123d9cea8d3SIain Sandoe // For the sake of error recovery (if someone has moved the original header
124d9cea8d3SIain Sandoe // after creating the pre-processed output) fall back to obtaining the file
125d9cea8d3SIain Sandoe // ref for the input file, which must be present.
126d9cea8d3SIain Sandoe if (!F)
127d9cea8d3SIain Sandoe F = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
128d9cea8d3SIain Sandoe assert(F && "failed to find the header unit source?");
129d9cea8d3SIain Sandoe Module::Header H{HUName.str(), HUName.str(), *F};
130d9cea8d3SIain Sandoe auto &Map = PP.getHeaderSearchInfo().getModuleMap();
1316c0e60e8SIain Sandoe Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);
1326c0e60e8SIain Sandoe assert(Mod && "module creation should not fail");
1336c0e60e8SIain Sandoe ModuleScopes.push_back({}); // No GMF
1346c0e60e8SIain Sandoe ModuleScopes.back().BeginLoc = StartOfTU;
1356c0e60e8SIain Sandoe ModuleScopes.back().Module = Mod;
1366c0e60e8SIain Sandoe ModuleScopes.back().ModuleInterface = true;
1376c0e60e8SIain Sandoe ModuleScopes.back().IsPartition = false;
1386c0e60e8SIain Sandoe VisibleModules.setVisible(Mod, StartOfTU);
1396c0e60e8SIain Sandoe
1406c0e60e8SIain Sandoe // From now on, we have an owning module for all declarations we see.
1416c0e60e8SIain Sandoe // All of these are implicitly exported.
1426c0e60e8SIain Sandoe auto *TU = Context.getTranslationUnitDecl();
1436c0e60e8SIain Sandoe TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Visible);
1446c0e60e8SIain Sandoe TU->setLocalOwningModule(Mod);
1456c0e60e8SIain Sandoe }
1466c0e60e8SIain Sandoe
14769350e56SIain Sandoe Sema::DeclGroupPtrTy
ActOnModuleDecl(SourceLocation StartLoc,SourceLocation ModuleLoc,ModuleDeclKind MDK,ModuleIdPath Path,ModuleIdPath Partition,ModuleImportState & ImportState)14869350e56SIain Sandoe Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
14969350e56SIain Sandoe ModuleDeclKind MDK, ModuleIdPath Path,
15069350e56SIain Sandoe ModuleIdPath Partition, ModuleImportState &ImportState) {
151b7bdb8cfSRichard Smith assert((getLangOpts().ModulesTS || getLangOpts().CPlusPlusModules) &&
152b7bdb8cfSRichard Smith "should only have module decl in Modules TS or C++20");
153b7bdb8cfSRichard Smith
154ab28488eSIain Sandoe bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl;
155ab28488eSIain Sandoe bool SeenGMF = ImportState == ModuleImportState::GlobalFragment;
156ab28488eSIain Sandoe // If any of the steps here fail, we count that as invalidating C++20
157ab28488eSIain Sandoe // module state;
158ab28488eSIain Sandoe ImportState = ModuleImportState::NotACXX20Module;
159ab28488eSIain Sandoe
16061144914SIain Sandoe bool IsPartition = !Partition.empty();
16161144914SIain Sandoe if (IsPartition)
16261144914SIain Sandoe switch (MDK) {
16361144914SIain Sandoe case ModuleDeclKind::Implementation:
16461144914SIain Sandoe MDK = ModuleDeclKind::PartitionImplementation;
16561144914SIain Sandoe break;
16661144914SIain Sandoe case ModuleDeclKind::Interface:
16761144914SIain Sandoe MDK = ModuleDeclKind::PartitionInterface;
16861144914SIain Sandoe break;
16961144914SIain Sandoe default:
17061144914SIain Sandoe llvm_unreachable("how did we get a partition type set?");
17161144914SIain Sandoe }
17261144914SIain Sandoe
17361144914SIain Sandoe // A (non-partition) module implementation unit requires that we are not
17461144914SIain Sandoe // compiling a module of any kind. A partition implementation emits an
17561144914SIain Sandoe // interface (and the AST for the implementation), which will subsequently
17661144914SIain Sandoe // be consumed to emit a binary.
17761144914SIain Sandoe // A module interface unit requires that we are not compiling a module map.
178b7bdb8cfSRichard Smith switch (getLangOpts().getCompilingModule()) {
179b7bdb8cfSRichard Smith case LangOptions::CMK_None:
180b7bdb8cfSRichard Smith // It's OK to compile a module interface as a normal translation unit.
181b7bdb8cfSRichard Smith break;
182b7bdb8cfSRichard Smith
183b7bdb8cfSRichard Smith case LangOptions::CMK_ModuleInterface:
184b7bdb8cfSRichard Smith if (MDK != ModuleDeclKind::Implementation)
185b7bdb8cfSRichard Smith break;
186b7bdb8cfSRichard Smith
187b7bdb8cfSRichard Smith // We were asked to compile a module interface unit but this is a module
18861144914SIain Sandoe // implementation unit.
189b7bdb8cfSRichard Smith Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
190b7bdb8cfSRichard Smith << FixItHint::CreateInsertion(ModuleLoc, "export ");
191b7bdb8cfSRichard Smith MDK = ModuleDeclKind::Interface;
192b7bdb8cfSRichard Smith break;
193b7bdb8cfSRichard Smith
194b7bdb8cfSRichard Smith case LangOptions::CMK_ModuleMap:
195b7bdb8cfSRichard Smith Diag(ModuleLoc, diag::err_module_decl_in_module_map_module);
196b7bdb8cfSRichard Smith return nullptr;
197b7bdb8cfSRichard Smith
198b7bdb8cfSRichard Smith case LangOptions::CMK_HeaderModule:
1996c0e60e8SIain Sandoe case LangOptions::CMK_HeaderUnit:
200b7bdb8cfSRichard Smith Diag(ModuleLoc, diag::err_module_decl_in_header_module);
201b7bdb8cfSRichard Smith return nullptr;
202b7bdb8cfSRichard Smith }
203b7bdb8cfSRichard Smith
204b7bdb8cfSRichard Smith assert(ModuleScopes.size() <= 1 && "expected to be at global module scope");
205b7bdb8cfSRichard Smith
206b7bdb8cfSRichard Smith // FIXME: Most of this work should be done by the preprocessor rather than
207b7bdb8cfSRichard Smith // here, in order to support macro import.
208b7bdb8cfSRichard Smith
209b7bdb8cfSRichard Smith // Only one module-declaration is permitted per source file.
210b7bdb8cfSRichard Smith if (!ModuleScopes.empty() &&
211a5bbbfefSRichard Smith ModuleScopes.back().Module->isModulePurview()) {
212b7bdb8cfSRichard Smith Diag(ModuleLoc, diag::err_module_redeclaration);
213b7bdb8cfSRichard Smith Diag(VisibleModules.getImportLoc(ModuleScopes.back().Module),
214b7bdb8cfSRichard Smith diag::note_prev_module_declaration);
215b7bdb8cfSRichard Smith return nullptr;
216b7bdb8cfSRichard Smith }
217b7bdb8cfSRichard Smith
218b7bdb8cfSRichard Smith // Find the global module fragment we're adopting into this module, if any.
219b7bdb8cfSRichard Smith Module *GlobalModuleFragment = nullptr;
220b7bdb8cfSRichard Smith if (!ModuleScopes.empty() &&
221b7bdb8cfSRichard Smith ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment)
222b7bdb8cfSRichard Smith GlobalModuleFragment = ModuleScopes.back().Module;
223b7bdb8cfSRichard Smith
224cf396c56SIain Sandoe assert((!getLangOpts().CPlusPlusModules || getLangOpts().ModulesTS ||
225ab28488eSIain Sandoe SeenGMF == (bool)GlobalModuleFragment) &&
226ab28488eSIain Sandoe "mismatched global module state");
227ab28488eSIain Sandoe
228b7bdb8cfSRichard Smith // In C++20, the module-declaration must be the first declaration if there
229b7bdb8cfSRichard Smith // is no global module fragment.
230ab28488eSIain Sandoe if (getLangOpts().CPlusPlusModules && !IsFirstDecl && !SeenGMF) {
231b7bdb8cfSRichard Smith Diag(ModuleLoc, diag::err_module_decl_not_at_start);
232b7bdb8cfSRichard Smith SourceLocation BeginLoc =
233b7bdb8cfSRichard Smith ModuleScopes.empty()
234b7bdb8cfSRichard Smith ? SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID())
235b7bdb8cfSRichard Smith : ModuleScopes.back().BeginLoc;
236b7bdb8cfSRichard Smith if (BeginLoc.isValid()) {
237b7bdb8cfSRichard Smith Diag(BeginLoc, diag::note_global_module_introducer_missing)
238b7bdb8cfSRichard Smith << FixItHint::CreateInsertion(BeginLoc, "module;\n");
239b7bdb8cfSRichard Smith }
240b7bdb8cfSRichard Smith }
241b7bdb8cfSRichard Smith
242b7bdb8cfSRichard Smith // Flatten the dots in a module name. Unlike Clang's hierarchical module map
243b7bdb8cfSRichard Smith // modules, the dots here are just another character that can appear in a
244b7bdb8cfSRichard Smith // module name.
24569350e56SIain Sandoe std::string ModuleName = stringFromPath(Path);
24669350e56SIain Sandoe if (IsPartition) {
24769350e56SIain Sandoe ModuleName += ":";
24869350e56SIain Sandoe ModuleName += stringFromPath(Partition);
249b7bdb8cfSRichard Smith }
250b7bdb8cfSRichard Smith // If a module name was explicitly specified on the command line, it must be
251b7bdb8cfSRichard Smith // correct.
252b7bdb8cfSRichard Smith if (!getLangOpts().CurrentModule.empty() &&
253b7bdb8cfSRichard Smith getLangOpts().CurrentModule != ModuleName) {
254b7bdb8cfSRichard Smith Diag(Path.front().second, diag::err_current_module_name_mismatch)
25569350e56SIain Sandoe << SourceRange(Path.front().second, IsPartition
25669350e56SIain Sandoe ? Partition.back().second
25769350e56SIain Sandoe : Path.back().second)
258b7bdb8cfSRichard Smith << getLangOpts().CurrentModule;
259b7bdb8cfSRichard Smith return nullptr;
260b7bdb8cfSRichard Smith }
261b7bdb8cfSRichard Smith const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;
262b7bdb8cfSRichard Smith
263b7bdb8cfSRichard Smith auto &Map = PP.getHeaderSearchInfo().getModuleMap();
264b7bdb8cfSRichard Smith Module *Mod;
265b7bdb8cfSRichard Smith
266b7bdb8cfSRichard Smith switch (MDK) {
26761144914SIain Sandoe case ModuleDeclKind::Interface:
26861144914SIain Sandoe case ModuleDeclKind::PartitionInterface: {
269b7bdb8cfSRichard Smith // We can't have parsed or imported a definition of this module or parsed a
270b7bdb8cfSRichard Smith // module map defining it already.
271b7bdb8cfSRichard Smith if (auto *M = Map.findModule(ModuleName)) {
272b7bdb8cfSRichard Smith Diag(Path[0].second, diag::err_module_redefinition) << ModuleName;
273b7bdb8cfSRichard Smith if (M->DefinitionLoc.isValid())
274b7bdb8cfSRichard Smith Diag(M->DefinitionLoc, diag::note_prev_module_definition);
2759f151df1SDuncan P. N. Exon Smith else if (Optional<FileEntryRef> FE = M->getASTFile())
276b7bdb8cfSRichard Smith Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file)
277b7bdb8cfSRichard Smith << FE->getName();
278b7bdb8cfSRichard Smith Mod = M;
279b7bdb8cfSRichard Smith break;
280b7bdb8cfSRichard Smith }
281b7bdb8cfSRichard Smith
282b7bdb8cfSRichard Smith // Create a Module for the module that we're defining.
283b7bdb8cfSRichard Smith Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
284b7bdb8cfSRichard Smith GlobalModuleFragment);
28561144914SIain Sandoe if (MDK == ModuleDeclKind::PartitionInterface)
28669350e56SIain Sandoe Mod->Kind = Module::ModulePartitionInterface;
287b7bdb8cfSRichard Smith assert(Mod && "module creation should not fail");
288b7bdb8cfSRichard Smith break;
289b7bdb8cfSRichard Smith }
290b7bdb8cfSRichard Smith
29161144914SIain Sandoe case ModuleDeclKind::Implementation: {
292b7bdb8cfSRichard Smith std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc(
293b7bdb8cfSRichard Smith PP.getIdentifierInfo(ModuleName), Path[0].second);
29469350e56SIain Sandoe // C++20 A module-declaration that contains neither an export-
29569350e56SIain Sandoe // keyword nor a module-partition implicitly imports the primary
29669350e56SIain Sandoe // module interface unit of the module as if by a module-import-
29769350e56SIain Sandoe // declaration.
298b7bdb8cfSRichard Smith Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
299b7bdb8cfSRichard Smith Module::AllVisible,
30049a3ad21SRui Ueyama /*IsInclusionDirective=*/false);
301b7bdb8cfSRichard Smith if (!Mod) {
302b7bdb8cfSRichard Smith Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
303b7bdb8cfSRichard Smith // Create an empty module interface unit for error recovery.
304b7bdb8cfSRichard Smith Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
305b7bdb8cfSRichard Smith GlobalModuleFragment);
306b7bdb8cfSRichard Smith }
30761144914SIain Sandoe } break;
30861144914SIain Sandoe
30961144914SIain Sandoe case ModuleDeclKind::PartitionImplementation:
31061144914SIain Sandoe // Create an interface, but note that it is an implementation
31161144914SIain Sandoe // unit.
31261144914SIain Sandoe Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
31361144914SIain Sandoe GlobalModuleFragment);
31461144914SIain Sandoe Mod->Kind = Module::ModulePartitionImplementation;
315b7bdb8cfSRichard Smith break;
316b7bdb8cfSRichard Smith }
317b7bdb8cfSRichard Smith
318b7bdb8cfSRichard Smith if (!GlobalModuleFragment) {
319b7bdb8cfSRichard Smith ModuleScopes.push_back({});
320b7bdb8cfSRichard Smith if (getLangOpts().ModulesLocalVisibility)
321b7bdb8cfSRichard Smith ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
322a5bbbfefSRichard Smith } else {
323a5bbbfefSRichard Smith // We're done with the global module fragment now.
324a5bbbfefSRichard Smith ActOnEndOfTranslationUnitFragment(TUFragmentKind::Global);
325b7bdb8cfSRichard Smith }
326b7bdb8cfSRichard Smith
327b7bdb8cfSRichard Smith // Switch from the global module fragment (if any) to the named module.
328b7bdb8cfSRichard Smith ModuleScopes.back().BeginLoc = StartLoc;
329b7bdb8cfSRichard Smith ModuleScopes.back().Module = Mod;
33061144914SIain Sandoe ModuleScopes.back().ModuleInterface = MDK != ModuleDeclKind::Implementation;
33169350e56SIain Sandoe ModuleScopes.back().IsPartition = IsPartition;
332b7bdb8cfSRichard Smith VisibleModules.setVisible(Mod, ModuleLoc);
333b7bdb8cfSRichard Smith
334b7bdb8cfSRichard Smith // From now on, we have an owning module for all declarations we see.
3359c04851cSChuanqi Xu // In C++20 modules, those declaration would be reachable when imported
3369c04851cSChuanqi Xu // unless explicitily exported.
3379c04851cSChuanqi Xu // Otherwise, those declarations are module-private unless explicitly
338b7bdb8cfSRichard Smith // exported.
339b7bdb8cfSRichard Smith auto *TU = Context.getTranslationUnitDecl();
3409c04851cSChuanqi Xu TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);
341b7bdb8cfSRichard Smith TU->setLocalOwningModule(Mod);
342b7bdb8cfSRichard Smith
343ab28488eSIain Sandoe // We are in the module purview, but before any other (non import)
344ab28488eSIain Sandoe // statements, so imports are allowed.
345ab28488eSIain Sandoe ImportState = ModuleImportState::ImportAllowed;
346ab28488eSIain Sandoe
347*afda39a5SIain Sandoe // For an implementation, We already made an implicit import (its interface).
348*afda39a5SIain Sandoe // Make and return the import decl to be added to the current TU.
349*afda39a5SIain Sandoe if (MDK == ModuleDeclKind::Implementation) {
350*afda39a5SIain Sandoe // Make the import decl for the interface.
351*afda39a5SIain Sandoe ImportDecl *Import =
352*afda39a5SIain Sandoe ImportDecl::Create(Context, CurContext, ModuleLoc, Mod, Path[0].second);
353*afda39a5SIain Sandoe // and return it to be added.
354*afda39a5SIain Sandoe return ConvertDeclToDeclGroup(Import);
355*afda39a5SIain Sandoe }
356*afda39a5SIain Sandoe
357b7bdb8cfSRichard Smith // FIXME: Create a ModuleDecl.
358b7bdb8cfSRichard Smith return nullptr;
359b7bdb8cfSRichard Smith }
360b7bdb8cfSRichard Smith
361a5bbbfefSRichard Smith Sema::DeclGroupPtrTy
ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,SourceLocation PrivateLoc)362a5bbbfefSRichard Smith Sema::ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,
363a5bbbfefSRichard Smith SourceLocation PrivateLoc) {
364a5bbbfefSRichard Smith // C++20 [basic.link]/2:
365a5bbbfefSRichard Smith // A private-module-fragment shall appear only in a primary module
366a5bbbfefSRichard Smith // interface unit.
367a5bbbfefSRichard Smith switch (ModuleScopes.empty() ? Module::GlobalModuleFragment
368a5bbbfefSRichard Smith : ModuleScopes.back().Module->Kind) {
369a5bbbfefSRichard Smith case Module::ModuleMapModule:
370a5bbbfefSRichard Smith case Module::GlobalModuleFragment:
371c9cc8035SIain Sandoe case Module::ModulePartitionImplementation:
372c9cc8035SIain Sandoe case Module::ModulePartitionInterface:
3736c0e60e8SIain Sandoe case Module::ModuleHeaderUnit:
374a5bbbfefSRichard Smith Diag(PrivateLoc, diag::err_private_module_fragment_not_module);
375a5bbbfefSRichard Smith return nullptr;
376a5bbbfefSRichard Smith
377a5bbbfefSRichard Smith case Module::PrivateModuleFragment:
378a5bbbfefSRichard Smith Diag(PrivateLoc, diag::err_private_module_fragment_redefined);
379a5bbbfefSRichard Smith Diag(ModuleScopes.back().BeginLoc, diag::note_previous_definition);
380a5bbbfefSRichard Smith return nullptr;
381a5bbbfefSRichard Smith
382a5bbbfefSRichard Smith case Module::ModuleInterfaceUnit:
383a5bbbfefSRichard Smith break;
384a5bbbfefSRichard Smith }
385a5bbbfefSRichard Smith
386a5bbbfefSRichard Smith if (!ModuleScopes.back().ModuleInterface) {
387a5bbbfefSRichard Smith Diag(PrivateLoc, diag::err_private_module_fragment_not_module_interface);
388a5bbbfefSRichard Smith Diag(ModuleScopes.back().BeginLoc,
389a5bbbfefSRichard Smith diag::note_not_module_interface_add_export)
390a5bbbfefSRichard Smith << FixItHint::CreateInsertion(ModuleScopes.back().BeginLoc, "export ");
391a5bbbfefSRichard Smith return nullptr;
392a5bbbfefSRichard Smith }
393a5bbbfefSRichard Smith
394a5bbbfefSRichard Smith // FIXME: Check this isn't a module interface partition.
395a5bbbfefSRichard Smith // FIXME: Check that this translation unit does not import any partitions;
396a5bbbfefSRichard Smith // such imports would violate [basic.link]/2's "shall be the only module unit"
397a5bbbfefSRichard Smith // restriction.
398a5bbbfefSRichard Smith
399a5bbbfefSRichard Smith // We've finished the public fragment of the translation unit.
400a5bbbfefSRichard Smith ActOnEndOfTranslationUnitFragment(TUFragmentKind::Normal);
401a5bbbfefSRichard Smith
402a5bbbfefSRichard Smith auto &Map = PP.getHeaderSearchInfo().getModuleMap();
403a5bbbfefSRichard Smith Module *PrivateModuleFragment =
404a5bbbfefSRichard Smith Map.createPrivateModuleFragmentForInterfaceUnit(
405a5bbbfefSRichard Smith ModuleScopes.back().Module, PrivateLoc);
406a5bbbfefSRichard Smith assert(PrivateModuleFragment && "module creation should not fail");
407a5bbbfefSRichard Smith
408a5bbbfefSRichard Smith // Enter the scope of the private module fragment.
409a5bbbfefSRichard Smith ModuleScopes.push_back({});
410a5bbbfefSRichard Smith ModuleScopes.back().BeginLoc = ModuleLoc;
411a5bbbfefSRichard Smith ModuleScopes.back().Module = PrivateModuleFragment;
412a5bbbfefSRichard Smith ModuleScopes.back().ModuleInterface = true;
413a5bbbfefSRichard Smith VisibleModules.setVisible(PrivateModuleFragment, ModuleLoc);
414a5bbbfefSRichard Smith
415a5bbbfefSRichard Smith // All declarations created from now on are scoped to the private module
416a5bbbfefSRichard Smith // fragment (and are neither visible nor reachable in importers of the module
417a5bbbfefSRichard Smith // interface).
418a5bbbfefSRichard Smith auto *TU = Context.getTranslationUnitDecl();
419a5bbbfefSRichard Smith TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate);
420a5bbbfefSRichard Smith TU->setLocalOwningModule(PrivateModuleFragment);
421a5bbbfefSRichard Smith
422a5bbbfefSRichard Smith // FIXME: Consider creating an explicit representation of this declaration.
423a5bbbfefSRichard Smith return nullptr;
424a5bbbfefSRichard Smith }
425a5bbbfefSRichard Smith
ActOnModuleImport(SourceLocation StartLoc,SourceLocation ExportLoc,SourceLocation ImportLoc,ModuleIdPath Path,bool IsPartition)426b7bdb8cfSRichard Smith DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
427b7bdb8cfSRichard Smith SourceLocation ExportLoc,
42869350e56SIain Sandoe SourceLocation ImportLoc, ModuleIdPath Path,
4293eb2da76SChuanqi Xu bool IsPartition) {
43069350e56SIain Sandoe
43169350e56SIain Sandoe bool Cxx20Mode = getLangOpts().CPlusPlusModules || getLangOpts().ModulesTS;
43269350e56SIain Sandoe assert((!IsPartition || Cxx20Mode) && "partition seen in non-C++20 code?");
43369350e56SIain Sandoe
43469350e56SIain Sandoe // For a C++20 module name, flatten into a single identifier with the source
43569350e56SIain Sandoe // location of the first component.
436b7bdb8cfSRichard Smith std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc;
43769350e56SIain Sandoe
438b7bdb8cfSRichard Smith std::string ModuleName;
43969350e56SIain Sandoe if (IsPartition) {
44069350e56SIain Sandoe // We already checked that we are in a module purview in the parser.
44169350e56SIain Sandoe assert(!ModuleScopes.empty() && "in a module purview, but no module?");
44269350e56SIain Sandoe Module *NamedMod = ModuleScopes.back().Module;
443b3fcfcb9SIain Sandoe // If we are importing into a partition, find the owning named module,
444b3fcfcb9SIain Sandoe // otherwise, the name of the importing named module.
445b3fcfcb9SIain Sandoe ModuleName = NamedMod->getPrimaryModuleInterfaceName().str();
44669350e56SIain Sandoe ModuleName += ":";
4473eb2da76SChuanqi Xu ModuleName += stringFromPath(Path);
4483eb2da76SChuanqi Xu ModuleNameLoc = {PP.getIdentifierInfo(ModuleName), Path[0].second};
4493eb2da76SChuanqi Xu Path = ModuleIdPath(ModuleNameLoc);
45069350e56SIain Sandoe } else if (Cxx20Mode) {
45169350e56SIain Sandoe ModuleName = stringFromPath(Path);
452b7bdb8cfSRichard Smith ModuleNameLoc = {PP.getIdentifierInfo(ModuleName), Path[0].second};
453b7bdb8cfSRichard Smith Path = ModuleIdPath(ModuleNameLoc);
454b7bdb8cfSRichard Smith }
455b7bdb8cfSRichard Smith
456ab28488eSIain Sandoe // Diagnose self-import before attempting a load.
4571a76d256SIain Sandoe // [module.import]/9
4581a76d256SIain Sandoe // A module implementation unit of a module M that is not a module partition
4591a76d256SIain Sandoe // shall not contain a module-import-declaration nominating M.
4601a76d256SIain Sandoe // (for an implementation, the module interface is imported implicitly,
4611a76d256SIain Sandoe // but that's handled in the module decl code).
4621a76d256SIain Sandoe
463ab28488eSIain Sandoe if (getLangOpts().CPlusPlusModules && isCurrentModulePurview() &&
464ab28488eSIain Sandoe getCurrentModule()->Name == ModuleName) {
4651a76d256SIain Sandoe Diag(ImportLoc, diag::err_module_self_import_cxx20)
4661a76d256SIain Sandoe << ModuleName << !ModuleScopes.back().ModuleInterface;
467ab28488eSIain Sandoe return true;
468ab28488eSIain Sandoe }
469ab28488eSIain Sandoe
47069350e56SIain Sandoe Module *Mod = getModuleLoader().loadModule(
4713eb2da76SChuanqi Xu ImportLoc, Path, Module::AllVisible, /*IsInclusionDirective=*/false);
472b7bdb8cfSRichard Smith if (!Mod)
473b7bdb8cfSRichard Smith return true;
474b7bdb8cfSRichard Smith
4753eb2da76SChuanqi Xu return ActOnModuleImport(StartLoc, ExportLoc, ImportLoc, Mod, Path);
476b7bdb8cfSRichard Smith }
477b7bdb8cfSRichard Smith
478e181de7fSRichard Smith /// Determine whether \p D is lexically within an export-declaration.
getEnclosingExportDecl(const Decl * D)479e181de7fSRichard Smith static const ExportDecl *getEnclosingExportDecl(const Decl *D) {
480e181de7fSRichard Smith for (auto *DC = D->getLexicalDeclContext(); DC; DC = DC->getLexicalParent())
481e181de7fSRichard Smith if (auto *ED = dyn_cast<ExportDecl>(DC))
482e181de7fSRichard Smith return ED;
483e181de7fSRichard Smith return nullptr;
484e181de7fSRichard Smith }
485e181de7fSRichard Smith
ActOnModuleImport(SourceLocation StartLoc,SourceLocation ExportLoc,SourceLocation ImportLoc,Module * Mod,ModuleIdPath Path)486b7bdb8cfSRichard Smith DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
487b7bdb8cfSRichard Smith SourceLocation ExportLoc,
48869350e56SIain Sandoe SourceLocation ImportLoc, Module *Mod,
48969350e56SIain Sandoe ModuleIdPath Path) {
490b7bdb8cfSRichard Smith VisibleModules.setVisible(Mod, ImportLoc);
491b7bdb8cfSRichard Smith
492b7bdb8cfSRichard Smith checkModuleImportContext(*this, Mod, ImportLoc, CurContext);
493b7bdb8cfSRichard Smith
494b7bdb8cfSRichard Smith // FIXME: we should support importing a submodule within a different submodule
495b7bdb8cfSRichard Smith // of the same top-level module. Until we do, make it an error rather than
496b7bdb8cfSRichard Smith // silently ignoring the import.
497ab28488eSIain Sandoe // FIXME: Should we warn on a redundant import of the current module?
4981a76d256SIain Sandoe if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule &&
499b7bdb8cfSRichard Smith (getLangOpts().isCompilingModule() || !getLangOpts().ModulesTS)) {
500b7bdb8cfSRichard Smith Diag(ImportLoc, getLangOpts().isCompilingModule()
501b7bdb8cfSRichard Smith ? diag::err_module_self_import
502b7bdb8cfSRichard Smith : diag::err_module_import_in_implementation)
503b7bdb8cfSRichard Smith << Mod->getFullModuleName() << getLangOpts().CurrentModule;
504b7bdb8cfSRichard Smith }
505b7bdb8cfSRichard Smith
506b7bdb8cfSRichard Smith SmallVector<SourceLocation, 2> IdentifierLocs;
50769350e56SIain Sandoe
50869350e56SIain Sandoe if (Path.empty()) {
50969350e56SIain Sandoe // If this was a header import, pad out with dummy locations.
51069350e56SIain Sandoe // FIXME: Pass in and use the location of the header-name token in this
51169350e56SIain Sandoe // case.
51269350e56SIain Sandoe for (Module *ModCheck = Mod; ModCheck; ModCheck = ModCheck->Parent)
51369350e56SIain Sandoe IdentifierLocs.push_back(SourceLocation());
51469350e56SIain Sandoe } else if (getLangOpts().CPlusPlusModules && !Mod->Parent) {
51569350e56SIain Sandoe // A single identifier for the whole name.
51669350e56SIain Sandoe IdentifierLocs.push_back(Path[0].second);
51769350e56SIain Sandoe } else {
518b7bdb8cfSRichard Smith Module *ModCheck = Mod;
519b7bdb8cfSRichard Smith for (unsigned I = 0, N = Path.size(); I != N; ++I) {
52069350e56SIain Sandoe // If we've run out of module parents, just drop the remaining
52169350e56SIain Sandoe // identifiers. We need the length to be consistent.
522b7bdb8cfSRichard Smith if (!ModCheck)
523b7bdb8cfSRichard Smith break;
524b7bdb8cfSRichard Smith ModCheck = ModCheck->Parent;
525b7bdb8cfSRichard Smith
526b7bdb8cfSRichard Smith IdentifierLocs.push_back(Path[I].second);
527b7bdb8cfSRichard Smith }
528b7bdb8cfSRichard Smith }
529b7bdb8cfSRichard Smith
530b7bdb8cfSRichard Smith ImportDecl *Import = ImportDecl::Create(Context, CurContext, StartLoc,
531b7bdb8cfSRichard Smith Mod, IdentifierLocs);
532b7bdb8cfSRichard Smith CurContext->addDecl(Import);
533b7bdb8cfSRichard Smith
534b7bdb8cfSRichard Smith // Sequence initialization of the imported module before that of the current
535b7bdb8cfSRichard Smith // module, if any.
536b7bdb8cfSRichard Smith if (!ModuleScopes.empty())
537b7bdb8cfSRichard Smith Context.addModuleInitializer(ModuleScopes.back().Module, Import);
538b7bdb8cfSRichard Smith
5391a76d256SIain Sandoe // A module (partition) implementation unit shall not be exported.
5408d093111SSimon Pilgrim if (getLangOpts().CPlusPlusModules && ExportLoc.isValid() &&
5411a76d256SIain Sandoe Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) {
5421a76d256SIain Sandoe Diag(ExportLoc, diag::err_export_partition_impl)
5431a76d256SIain Sandoe << SourceRange(ExportLoc, Path.back().second);
5446c0e60e8SIain Sandoe } else if (!ModuleScopes.empty() &&
5456c0e60e8SIain Sandoe (ModuleScopes.back().ModuleInterface ||
5466c0e60e8SIain Sandoe (getLangOpts().CPlusPlusModules &&
5476c0e60e8SIain Sandoe ModuleScopes.back().Module->isGlobalModule()))) {
5486c0e60e8SIain Sandoe assert((!ModuleScopes.back().Module->isGlobalModule() ||
5496c0e60e8SIain Sandoe Mod->Kind == Module::ModuleKind::ModuleHeaderUnit) &&
5506c0e60e8SIain Sandoe "should only be importing a header unit into the GMF");
55186b001a9SChuanqi Xu // Re-export the module if the imported module is exported.
55286b001a9SChuanqi Xu // Note that we don't need to add re-exported module to Imports field
55386b001a9SChuanqi Xu // since `Exports` implies the module is imported already.
554e181de7fSRichard Smith if (ExportLoc.isValid() || getEnclosingExportDecl(Import))
555b7bdb8cfSRichard Smith getCurrentModule()->Exports.emplace_back(Mod, false);
55686b001a9SChuanqi Xu else
55786b001a9SChuanqi Xu getCurrentModule()->Imports.insert(Mod);
558b7bdb8cfSRichard Smith } else if (ExportLoc.isValid()) {
55986b001a9SChuanqi Xu // [module.interface]p1:
56086b001a9SChuanqi Xu // An export-declaration shall inhabit a namespace scope and appear in the
56186b001a9SChuanqi Xu // purview of a module interface unit.
5621a76d256SIain Sandoe Diag(ExportLoc, diag::err_export_not_in_module_interface)
5631a76d256SIain Sandoe << (!ModuleScopes.empty() &&
5641a76d256SIain Sandoe !ModuleScopes.back().ImplicitGlobalModuleFragment);
56569350e56SIain Sandoe } else if (getLangOpts().isCompilingModule()) {
56669350e56SIain Sandoe Module *ThisModule = PP.getHeaderSearchInfo().lookupModule(
56769350e56SIain Sandoe getLangOpts().CurrentModule, ExportLoc, false, false);
568fb3a2d45SBenjamin Kramer (void)ThisModule;
56969350e56SIain Sandoe assert(ThisModule && "was expecting a module if building one");
570b7bdb8cfSRichard Smith }
571b7bdb8cfSRichard Smith
572853ca547SIain Sandoe // In some cases we need to know if an entity was present in a directly-
573853ca547SIain Sandoe // imported module (as opposed to a transitive import). This avoids
574853ca547SIain Sandoe // searching both Imports and Exports.
575853ca547SIain Sandoe DirectModuleImports.insert(Mod);
576853ca547SIain Sandoe
577b7bdb8cfSRichard Smith return Import;
578b7bdb8cfSRichard Smith }
579b7bdb8cfSRichard Smith
ActOnModuleInclude(SourceLocation DirectiveLoc,Module * Mod)580b7bdb8cfSRichard Smith void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
581b7bdb8cfSRichard Smith checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);
582b7bdb8cfSRichard Smith BuildModuleInclude(DirectiveLoc, Mod);
583b7bdb8cfSRichard Smith }
584b7bdb8cfSRichard Smith
BuildModuleInclude(SourceLocation DirectiveLoc,Module * Mod)585b7bdb8cfSRichard Smith void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
586b7bdb8cfSRichard Smith // Determine whether we're in the #include buffer for a module. The #includes
587b7bdb8cfSRichard Smith // in that buffer do not qualify as module imports; they're just an
588b7bdb8cfSRichard Smith // implementation detail of us building the module.
589b7bdb8cfSRichard Smith //
590b7bdb8cfSRichard Smith // FIXME: Should we even get ActOnModuleInclude calls for those?
591b7bdb8cfSRichard Smith bool IsInModuleIncludes =
592b7bdb8cfSRichard Smith TUKind == TU_Module &&
593b7bdb8cfSRichard Smith getSourceManager().isWrittenInMainFile(DirectiveLoc);
594b7bdb8cfSRichard Smith
595b7bdb8cfSRichard Smith bool ShouldAddImport = !IsInModuleIncludes;
596b7bdb8cfSRichard Smith
597b7bdb8cfSRichard Smith // If this module import was due to an inclusion directive, create an
598b7bdb8cfSRichard Smith // implicit import declaration to capture it in the AST.
599b7bdb8cfSRichard Smith if (ShouldAddImport) {
600b7bdb8cfSRichard Smith TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
601b7bdb8cfSRichard Smith ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
602b7bdb8cfSRichard Smith DirectiveLoc, Mod,
603b7bdb8cfSRichard Smith DirectiveLoc);
604b7bdb8cfSRichard Smith if (!ModuleScopes.empty())
605b7bdb8cfSRichard Smith Context.addModuleInitializer(ModuleScopes.back().Module, ImportD);
606b7bdb8cfSRichard Smith TU->addDecl(ImportD);
607b7bdb8cfSRichard Smith Consumer.HandleImplicitImportDecl(ImportD);
608b7bdb8cfSRichard Smith }
609b7bdb8cfSRichard Smith
610b7bdb8cfSRichard Smith getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc);
611b7bdb8cfSRichard Smith VisibleModules.setVisible(Mod, DirectiveLoc);
61269350e56SIain Sandoe
61369350e56SIain Sandoe if (getLangOpts().isCompilingModule()) {
61469350e56SIain Sandoe Module *ThisModule = PP.getHeaderSearchInfo().lookupModule(
61569350e56SIain Sandoe getLangOpts().CurrentModule, DirectiveLoc, false, false);
616fb3a2d45SBenjamin Kramer (void)ThisModule;
61769350e56SIain Sandoe assert(ThisModule && "was expecting a module if building one");
61869350e56SIain Sandoe }
619b7bdb8cfSRichard Smith }
620b7bdb8cfSRichard Smith
ActOnModuleBegin(SourceLocation DirectiveLoc,Module * Mod)621b7bdb8cfSRichard Smith void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {
622b7bdb8cfSRichard Smith checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);
623b7bdb8cfSRichard Smith
624b7bdb8cfSRichard Smith ModuleScopes.push_back({});
625b7bdb8cfSRichard Smith ModuleScopes.back().Module = Mod;
626b7bdb8cfSRichard Smith if (getLangOpts().ModulesLocalVisibility)
627b7bdb8cfSRichard Smith ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
628b7bdb8cfSRichard Smith
629b7bdb8cfSRichard Smith VisibleModules.setVisible(Mod, DirectiveLoc);
630b7bdb8cfSRichard Smith
631b7bdb8cfSRichard Smith // The enclosing context is now part of this module.
632b7bdb8cfSRichard Smith // FIXME: Consider creating a child DeclContext to hold the entities
633b7bdb8cfSRichard Smith // lexically within the module.
634b7bdb8cfSRichard Smith if (getLangOpts().trackLocalOwningModule()) {
635b7bdb8cfSRichard Smith for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
636b7bdb8cfSRichard Smith cast<Decl>(DC)->setModuleOwnershipKind(
637b7bdb8cfSRichard Smith getLangOpts().ModulesLocalVisibility
638b7bdb8cfSRichard Smith ? Decl::ModuleOwnershipKind::VisibleWhenImported
639b7bdb8cfSRichard Smith : Decl::ModuleOwnershipKind::Visible);
640b7bdb8cfSRichard Smith cast<Decl>(DC)->setLocalOwningModule(Mod);
641b7bdb8cfSRichard Smith }
642b7bdb8cfSRichard Smith }
643b7bdb8cfSRichard Smith }
644b7bdb8cfSRichard Smith
ActOnModuleEnd(SourceLocation EomLoc,Module * Mod)645b7bdb8cfSRichard Smith void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) {
646b7bdb8cfSRichard Smith if (getLangOpts().ModulesLocalVisibility) {
647b7bdb8cfSRichard Smith VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules);
648b7bdb8cfSRichard Smith // Leaving a module hides namespace names, so our visible namespace cache
649b7bdb8cfSRichard Smith // is now out of date.
650b7bdb8cfSRichard Smith VisibleNamespaceCache.clear();
651b7bdb8cfSRichard Smith }
652b7bdb8cfSRichard Smith
653b7bdb8cfSRichard Smith assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod &&
654b7bdb8cfSRichard Smith "left the wrong module scope");
655b7bdb8cfSRichard Smith ModuleScopes.pop_back();
656b7bdb8cfSRichard Smith
657b7bdb8cfSRichard Smith // We got to the end of processing a local module. Create an
658b7bdb8cfSRichard Smith // ImportDecl as we would for an imported module.
659b7bdb8cfSRichard Smith FileID File = getSourceManager().getFileID(EomLoc);
660b7bdb8cfSRichard Smith SourceLocation DirectiveLoc;
661b7bdb8cfSRichard Smith if (EomLoc == getSourceManager().getLocForEndOfFile(File)) {
662b7bdb8cfSRichard Smith // We reached the end of a #included module header. Use the #include loc.
663b7bdb8cfSRichard Smith assert(File != getSourceManager().getMainFileID() &&
664b7bdb8cfSRichard Smith "end of submodule in main source file");
665b7bdb8cfSRichard Smith DirectiveLoc = getSourceManager().getIncludeLoc(File);
666b7bdb8cfSRichard Smith } else {
667b7bdb8cfSRichard Smith // We reached an EOM pragma. Use the pragma location.
668b7bdb8cfSRichard Smith DirectiveLoc = EomLoc;
669b7bdb8cfSRichard Smith }
670b7bdb8cfSRichard Smith BuildModuleInclude(DirectiveLoc, Mod);
671b7bdb8cfSRichard Smith
672b7bdb8cfSRichard Smith // Any further declarations are in whatever module we returned to.
673b7bdb8cfSRichard Smith if (getLangOpts().trackLocalOwningModule()) {
674b7bdb8cfSRichard Smith // The parser guarantees that this is the same context that we entered
675b7bdb8cfSRichard Smith // the module within.
676b7bdb8cfSRichard Smith for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
677b7bdb8cfSRichard Smith cast<Decl>(DC)->setLocalOwningModule(getCurrentModule());
678b7bdb8cfSRichard Smith if (!getCurrentModule())
679b7bdb8cfSRichard Smith cast<Decl>(DC)->setModuleOwnershipKind(
680b7bdb8cfSRichard Smith Decl::ModuleOwnershipKind::Unowned);
681b7bdb8cfSRichard Smith }
682b7bdb8cfSRichard Smith }
683b7bdb8cfSRichard Smith }
684b7bdb8cfSRichard Smith
createImplicitModuleImportForErrorRecovery(SourceLocation Loc,Module * Mod)685b7bdb8cfSRichard Smith void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
686b7bdb8cfSRichard Smith Module *Mod) {
687b7bdb8cfSRichard Smith // Bail if we're not allowed to implicitly import a module here.
688b7bdb8cfSRichard Smith if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery ||
689b7bdb8cfSRichard Smith VisibleModules.isVisible(Mod))
690b7bdb8cfSRichard Smith return;
691b7bdb8cfSRichard Smith
692b7bdb8cfSRichard Smith // Create the implicit import declaration.
693b7bdb8cfSRichard Smith TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
694b7bdb8cfSRichard Smith ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
695b7bdb8cfSRichard Smith Loc, Mod, Loc);
696b7bdb8cfSRichard Smith TU->addDecl(ImportD);
697b7bdb8cfSRichard Smith Consumer.HandleImplicitImportDecl(ImportD);
698b7bdb8cfSRichard Smith
699b7bdb8cfSRichard Smith // Make the module visible.
700b7bdb8cfSRichard Smith getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc);
701b7bdb8cfSRichard Smith VisibleModules.setVisible(Mod, Loc);
702b7bdb8cfSRichard Smith }
703b7bdb8cfSRichard Smith
704b7bdb8cfSRichard Smith /// We have parsed the start of an export declaration, including the '{'
705b7bdb8cfSRichard Smith /// (if present).
ActOnStartExportDecl(Scope * S,SourceLocation ExportLoc,SourceLocation LBraceLoc)706b7bdb8cfSRichard Smith Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
707b7bdb8cfSRichard Smith SourceLocation LBraceLoc) {
708b7bdb8cfSRichard Smith ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc);
709b7bdb8cfSRichard Smith
710e181de7fSRichard Smith // Set this temporarily so we know the export-declaration was braced.
711e181de7fSRichard Smith D->setRBraceLoc(LBraceLoc);
712e181de7fSRichard Smith
7134f8916cfSChuanqi Xu CurContext->addDecl(D);
7144f8916cfSChuanqi Xu PushDeclContext(S, D);
7154f8916cfSChuanqi Xu
716e181de7fSRichard Smith // C++2a [module.interface]p1:
717a5bbbfefSRichard Smith // An export-declaration shall appear only [...] in the purview of a module
718a5bbbfefSRichard Smith // interface unit. An export-declaration shall not appear directly or
719e181de7fSRichard Smith // indirectly within [...] a private-module-fragment.
720a5bbbfefSRichard Smith if (ModuleScopes.empty() || !ModuleScopes.back().Module->isModulePurview()) {
721a5bbbfefSRichard Smith Diag(ExportLoc, diag::err_export_not_in_module_interface) << 0;
7224f8916cfSChuanqi Xu D->setInvalidDecl();
7234f8916cfSChuanqi Xu return D;
724a5bbbfefSRichard Smith } else if (!ModuleScopes.back().ModuleInterface) {
725a5bbbfefSRichard Smith Diag(ExportLoc, diag::err_export_not_in_module_interface) << 1;
726a5bbbfefSRichard Smith Diag(ModuleScopes.back().BeginLoc,
727a5bbbfefSRichard Smith diag::note_not_module_interface_add_export)
728a5bbbfefSRichard Smith << FixItHint::CreateInsertion(ModuleScopes.back().BeginLoc, "export ");
7294f8916cfSChuanqi Xu D->setInvalidDecl();
7304f8916cfSChuanqi Xu return D;
731a5bbbfefSRichard Smith } else if (ModuleScopes.back().Module->Kind ==
732a5bbbfefSRichard Smith Module::PrivateModuleFragment) {
733a5bbbfefSRichard Smith Diag(ExportLoc, diag::err_export_in_private_module_fragment);
734a5bbbfefSRichard Smith Diag(ModuleScopes.back().BeginLoc, diag::note_private_module_fragment);
7354f8916cfSChuanqi Xu D->setInvalidDecl();
7364f8916cfSChuanqi Xu return D;
737a5bbbfefSRichard Smith }
738b7bdb8cfSRichard Smith
739e181de7fSRichard Smith for (const DeclContext *DC = CurContext; DC; DC = DC->getLexicalParent()) {
740e181de7fSRichard Smith if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) {
741e181de7fSRichard Smith // An export-declaration shall not appear directly or indirectly within
742e181de7fSRichard Smith // an unnamed namespace [...]
743e181de7fSRichard Smith if (ND->isAnonymousNamespace()) {
744e181de7fSRichard Smith Diag(ExportLoc, diag::err_export_within_anonymous_namespace);
745e181de7fSRichard Smith Diag(ND->getLocation(), diag::note_anonymous_namespace);
746e181de7fSRichard Smith // Don't diagnose internal-linkage declarations in this region.
747e181de7fSRichard Smith D->setInvalidDecl();
7484f8916cfSChuanqi Xu return D;
749e181de7fSRichard Smith }
750e181de7fSRichard Smith
751e181de7fSRichard Smith // A declaration is exported if it is [...] a namespace-definition
752e181de7fSRichard Smith // that contains an exported declaration.
753e181de7fSRichard Smith //
754e181de7fSRichard Smith // Defer exporting the namespace until after we leave it, in order to
755e181de7fSRichard Smith // avoid marking all subsequent declarations in the namespace as exported.
756e181de7fSRichard Smith if (!DeferredExportedNamespaces.insert(ND).second)
757e181de7fSRichard Smith break;
758e181de7fSRichard Smith }
759e181de7fSRichard Smith }
760e181de7fSRichard Smith
761a5bbbfefSRichard Smith // [...] its declaration or declaration-seq shall not contain an
762b7bdb8cfSRichard Smith // export-declaration.
763e181de7fSRichard Smith if (auto *ED = getEnclosingExportDecl(D)) {
764b7bdb8cfSRichard Smith Diag(ExportLoc, diag::err_export_within_export);
765e181de7fSRichard Smith if (ED->hasBraces())
766e181de7fSRichard Smith Diag(ED->getLocation(), diag::note_export);
7674f8916cfSChuanqi Xu D->setInvalidDecl();
7684f8916cfSChuanqi Xu return D;
769e181de7fSRichard Smith }
770b7bdb8cfSRichard Smith
771b7bdb8cfSRichard Smith D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::VisibleWhenImported);
772b7bdb8cfSRichard Smith return D;
773b7bdb8cfSRichard Smith }
774b7bdb8cfSRichard Smith
775e181de7fSRichard Smith static bool checkExportedDeclContext(Sema &S, DeclContext *DC,
776e181de7fSRichard Smith SourceLocation BlockStart);
777e181de7fSRichard Smith
778e181de7fSRichard Smith namespace {
779e181de7fSRichard Smith enum class UnnamedDeclKind {
780e181de7fSRichard Smith Empty,
781e181de7fSRichard Smith StaticAssert,
782e181de7fSRichard Smith Asm,
783e181de7fSRichard Smith UsingDirective,
784f60dc3caSIain Sandoe Namespace,
785e181de7fSRichard Smith Context
786e181de7fSRichard Smith };
787e181de7fSRichard Smith }
788e181de7fSRichard Smith
getUnnamedDeclKind(Decl * D)789e181de7fSRichard Smith static llvm::Optional<UnnamedDeclKind> getUnnamedDeclKind(Decl *D) {
790e181de7fSRichard Smith if (isa<EmptyDecl>(D))
791e181de7fSRichard Smith return UnnamedDeclKind::Empty;
792e181de7fSRichard Smith if (isa<StaticAssertDecl>(D))
793e181de7fSRichard Smith return UnnamedDeclKind::StaticAssert;
794e181de7fSRichard Smith if (isa<FileScopeAsmDecl>(D))
795e181de7fSRichard Smith return UnnamedDeclKind::Asm;
796e181de7fSRichard Smith if (isa<UsingDirectiveDecl>(D))
797e181de7fSRichard Smith return UnnamedDeclKind::UsingDirective;
798e181de7fSRichard Smith // Everything else either introduces one or more names or is ill-formed.
799e181de7fSRichard Smith return llvm::None;
800e181de7fSRichard Smith }
801e181de7fSRichard Smith
getUnnamedDeclDiag(UnnamedDeclKind UDK,bool InBlock)802e181de7fSRichard Smith unsigned getUnnamedDeclDiag(UnnamedDeclKind UDK, bool InBlock) {
803e181de7fSRichard Smith switch (UDK) {
804e181de7fSRichard Smith case UnnamedDeclKind::Empty:
805e181de7fSRichard Smith case UnnamedDeclKind::StaticAssert:
806e181de7fSRichard Smith // Allow empty-declarations and static_asserts in an export block as an
807e181de7fSRichard Smith // extension.
808e181de7fSRichard Smith return InBlock ? diag::ext_export_no_name_block : diag::err_export_no_name;
809e181de7fSRichard Smith
810e181de7fSRichard Smith case UnnamedDeclKind::UsingDirective:
811e181de7fSRichard Smith // Allow exporting using-directives as an extension.
812e181de7fSRichard Smith return diag::ext_export_using_directive;
813e181de7fSRichard Smith
814f60dc3caSIain Sandoe case UnnamedDeclKind::Namespace:
815f60dc3caSIain Sandoe // Anonymous namespace with no content.
816f60dc3caSIain Sandoe return diag::introduces_no_names;
817f60dc3caSIain Sandoe
818e181de7fSRichard Smith case UnnamedDeclKind::Context:
819e181de7fSRichard Smith // Allow exporting DeclContexts that transitively contain no declarations
820e181de7fSRichard Smith // as an extension.
821e181de7fSRichard Smith return diag::ext_export_no_names;
822e181de7fSRichard Smith
823e181de7fSRichard Smith case UnnamedDeclKind::Asm:
824e181de7fSRichard Smith return diag::err_export_no_name;
825e181de7fSRichard Smith }
826e181de7fSRichard Smith llvm_unreachable("unknown kind");
827e181de7fSRichard Smith }
828e181de7fSRichard Smith
diagExportedUnnamedDecl(Sema & S,UnnamedDeclKind UDK,Decl * D,SourceLocation BlockStart)829e181de7fSRichard Smith static void diagExportedUnnamedDecl(Sema &S, UnnamedDeclKind UDK, Decl *D,
830e181de7fSRichard Smith SourceLocation BlockStart) {
831e181de7fSRichard Smith S.Diag(D->getLocation(), getUnnamedDeclDiag(UDK, BlockStart.isValid()))
832e181de7fSRichard Smith << (unsigned)UDK;
833e181de7fSRichard Smith if (BlockStart.isValid())
834e181de7fSRichard Smith S.Diag(BlockStart, diag::note_export);
835e181de7fSRichard Smith }
836e181de7fSRichard Smith
837e181de7fSRichard Smith /// Check that it's valid to export \p D.
checkExportedDecl(Sema & S,Decl * D,SourceLocation BlockStart)838e181de7fSRichard Smith static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) {
839e181de7fSRichard Smith // C++2a [module.interface]p3:
840e181de7fSRichard Smith // An exported declaration shall declare at least one name
841e181de7fSRichard Smith if (auto UDK = getUnnamedDeclKind(D))
842e181de7fSRichard Smith diagExportedUnnamedDecl(S, *UDK, D, BlockStart);
843e181de7fSRichard Smith
844e181de7fSRichard Smith // [...] shall not declare a name with internal linkage.
845f60dc3caSIain Sandoe bool HasName = false;
846e181de7fSRichard Smith if (auto *ND = dyn_cast<NamedDecl>(D)) {
847e181de7fSRichard Smith // Don't diagnose anonymous union objects; we'll diagnose their members
848e181de7fSRichard Smith // instead.
849f60dc3caSIain Sandoe HasName = (bool)ND->getDeclName();
850f60dc3caSIain Sandoe if (HasName && ND->getFormalLinkage() == InternalLinkage) {
851e181de7fSRichard Smith S.Diag(ND->getLocation(), diag::err_export_internal) << ND;
852e181de7fSRichard Smith if (BlockStart.isValid())
853e181de7fSRichard Smith S.Diag(BlockStart, diag::note_export);
854e181de7fSRichard Smith }
855e181de7fSRichard Smith }
856e181de7fSRichard Smith
857e181de7fSRichard Smith // C++2a [module.interface]p5:
858e181de7fSRichard Smith // all entities to which all of the using-declarators ultimately refer
859e181de7fSRichard Smith // shall have been introduced with a name having external linkage
860e181de7fSRichard Smith if (auto *USD = dyn_cast<UsingShadowDecl>(D)) {
861e181de7fSRichard Smith NamedDecl *Target = USD->getUnderlyingDecl();
862f60dc3caSIain Sandoe Linkage Lk = Target->getFormalLinkage();
863f60dc3caSIain Sandoe if (Lk == InternalLinkage || Lk == ModuleLinkage) {
864f60dc3caSIain Sandoe S.Diag(USD->getLocation(), diag::err_export_using_internal)
865f60dc3caSIain Sandoe << (Lk == InternalLinkage ? 0 : 1) << Target;
866e181de7fSRichard Smith S.Diag(Target->getLocation(), diag::note_using_decl_target);
867e181de7fSRichard Smith if (BlockStart.isValid())
868e181de7fSRichard Smith S.Diag(BlockStart, diag::note_export);
869e181de7fSRichard Smith }
870e181de7fSRichard Smith }
871e181de7fSRichard Smith
872e181de7fSRichard Smith // Recurse into namespace-scope DeclContexts. (Only namespace-scope
873f60dc3caSIain Sandoe // declarations are exported.).
874f60dc3caSIain Sandoe if (auto *DC = dyn_cast<DeclContext>(D)) {
875f60dc3caSIain Sandoe if (isa<NamespaceDecl>(D) && DC->decls().empty()) {
876f60dc3caSIain Sandoe if (!HasName)
877f60dc3caSIain Sandoe // We don't allow an empty anonymous namespace (we don't allow decls
878f60dc3caSIain Sandoe // in them either, but that's handled in the recursion).
879f60dc3caSIain Sandoe diagExportedUnnamedDecl(S, UnnamedDeclKind::Namespace, D, BlockStart);
88092fed06fSIain Sandoe // We allow an empty named namespace decl.
881f60dc3caSIain Sandoe } else if (DC->getRedeclContext()->isFileContext() && !isa<EnumDecl>(D))
882e181de7fSRichard Smith return checkExportedDeclContext(S, DC, BlockStart);
883f60dc3caSIain Sandoe }
884e181de7fSRichard Smith return false;
885e181de7fSRichard Smith }
886e181de7fSRichard Smith
887e181de7fSRichard Smith /// Check that it's valid to export all the declarations in \p DC.
checkExportedDeclContext(Sema & S,DeclContext * DC,SourceLocation BlockStart)888e181de7fSRichard Smith static bool checkExportedDeclContext(Sema &S, DeclContext *DC,
889e181de7fSRichard Smith SourceLocation BlockStart) {
890e181de7fSRichard Smith bool AllUnnamed = true;
891e181de7fSRichard Smith for (auto *D : DC->decls())
892e181de7fSRichard Smith AllUnnamed &= checkExportedDecl(S, D, BlockStart);
893e181de7fSRichard Smith return AllUnnamed;
894e181de7fSRichard Smith }
895e181de7fSRichard Smith
896b7bdb8cfSRichard Smith /// Complete the definition of an export declaration.
ActOnFinishExportDecl(Scope * S,Decl * D,SourceLocation RBraceLoc)897b7bdb8cfSRichard Smith Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) {
898b7bdb8cfSRichard Smith auto *ED = cast<ExportDecl>(D);
899b7bdb8cfSRichard Smith if (RBraceLoc.isValid())
900b7bdb8cfSRichard Smith ED->setRBraceLoc(RBraceLoc);
901b7bdb8cfSRichard Smith
902b7bdb8cfSRichard Smith PopDeclContext();
903e181de7fSRichard Smith
904e181de7fSRichard Smith if (!D->isInvalidDecl()) {
905e181de7fSRichard Smith SourceLocation BlockStart =
906e181de7fSRichard Smith ED->hasBraces() ? ED->getBeginLoc() : SourceLocation();
907e181de7fSRichard Smith for (auto *Child : ED->decls()) {
908e181de7fSRichard Smith if (checkExportedDecl(*this, Child, BlockStart)) {
909e181de7fSRichard Smith // If a top-level child is a linkage-spec declaration, it might contain
910e181de7fSRichard Smith // no declarations (transitively), in which case it's ill-formed.
911e181de7fSRichard Smith diagExportedUnnamedDecl(*this, UnnamedDeclKind::Context, Child,
912e181de7fSRichard Smith BlockStart);
913e181de7fSRichard Smith }
914e181de7fSRichard Smith }
915e181de7fSRichard Smith }
916e181de7fSRichard Smith
917b7bdb8cfSRichard Smith return D;
918b7bdb8cfSRichard Smith }
919e587372fSChuanqi Xu
PushGlobalModuleFragment(SourceLocation BeginLoc,bool IsImplicit)920e587372fSChuanqi Xu Module *Sema::PushGlobalModuleFragment(SourceLocation BeginLoc,
921e587372fSChuanqi Xu bool IsImplicit) {
9223504937dSChuanqi Xu // We shouldn't create new global module fragment if there is already
9233504937dSChuanqi Xu // one.
9243504937dSChuanqi Xu if (!GlobalModuleFragment) {
925e587372fSChuanqi Xu ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();
9263504937dSChuanqi Xu GlobalModuleFragment = Map.createGlobalModuleFragmentForModuleUnit(
9273504937dSChuanqi Xu BeginLoc, getCurrentModule());
9283504937dSChuanqi Xu }
9293504937dSChuanqi Xu
9303504937dSChuanqi Xu assert(GlobalModuleFragment && "module creation should not fail");
931e587372fSChuanqi Xu
932e587372fSChuanqi Xu // Enter the scope of the global module.
9333504937dSChuanqi Xu ModuleScopes.push_back({BeginLoc, GlobalModuleFragment,
934e587372fSChuanqi Xu /*ModuleInterface=*/false,
93569350e56SIain Sandoe /*IsPartition=*/false,
9364168efe1SChuanqi Xu /*ImplicitGlobalModuleFragment=*/IsImplicit,
93769350e56SIain Sandoe /*OuterVisibleModules=*/{}});
9383504937dSChuanqi Xu VisibleModules.setVisible(GlobalModuleFragment, BeginLoc);
939e587372fSChuanqi Xu
9403504937dSChuanqi Xu return GlobalModuleFragment;
941e587372fSChuanqi Xu }
942e587372fSChuanqi Xu
PopGlobalModuleFragment()943e587372fSChuanqi Xu void Sema::PopGlobalModuleFragment() {
944e587372fSChuanqi Xu assert(!ModuleScopes.empty() && getCurrentModule()->isGlobalModule() &&
945e587372fSChuanqi Xu "left the wrong module scope, which is not global module fragment");
946e587372fSChuanqi Xu ModuleScopes.pop_back();
947e587372fSChuanqi Xu }
948354a597bSChuanqi Xu
isModuleUnitOfCurrentTU(const Module * M) const949354a597bSChuanqi Xu bool Sema::isModuleUnitOfCurrentTU(const Module *M) const {
950354a597bSChuanqi Xu assert(M);
951354a597bSChuanqi Xu
952354a597bSChuanqi Xu Module *CurrentModuleUnit = getCurrentModule();
953354a597bSChuanqi Xu
954354a597bSChuanqi Xu // If we are not in a module currently, M must not be the module unit of
955354a597bSChuanqi Xu // current TU.
956354a597bSChuanqi Xu if (!CurrentModuleUnit)
957354a597bSChuanqi Xu return false;
958354a597bSChuanqi Xu
959354a597bSChuanqi Xu return M->isSubModuleOf(CurrentModuleUnit->getTopLevelModule());
960354a597bSChuanqi Xu }
961