1600 lines · cpp
1//===--- SemaModule.cpp - Semantic Analysis for Modules -------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements semantic analysis for modules (C++ modules syntax,10// Objective-C modules syntax, and Clang header modules).11//12//===----------------------------------------------------------------------===//13 14#include "clang/AST/ASTConsumer.h"15#include "clang/AST/ASTMutationListener.h"16#include "clang/AST/DynamicRecursiveASTVisitor.h"17#include "clang/Lex/HeaderSearch.h"18#include "clang/Lex/Preprocessor.h"19#include "clang/Sema/ParsedAttr.h"20#include "clang/Sema/SemaInternal.h"21#include "llvm/ADT/StringExtras.h"22 23using namespace clang;24using namespace sema;25 26static void checkModuleImportContext(Sema &S, Module *M,27 SourceLocation ImportLoc, DeclContext *DC,28 bool FromInclude = false) {29 SourceLocation ExternCLoc;30 31 if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) {32 switch (LSD->getLanguage()) {33 case LinkageSpecLanguageIDs::C:34 if (ExternCLoc.isInvalid())35 ExternCLoc = LSD->getBeginLoc();36 break;37 case LinkageSpecLanguageIDs::CXX:38 break;39 }40 DC = LSD->getParent();41 }42 43 while (isa<LinkageSpecDecl>(DC) || isa<ExportDecl>(DC))44 DC = DC->getParent();45 46 if (!isa<TranslationUnitDecl>(DC)) {47 S.Diag(ImportLoc, (FromInclude && S.isModuleVisible(M))48 ? diag::ext_module_import_not_at_top_level_noop49 : diag::err_module_import_not_at_top_level_fatal)50 << M->getFullModuleName() << DC;51 S.Diag(cast<Decl>(DC)->getBeginLoc(),52 diag::note_module_import_not_at_top_level)53 << DC;54 } else if (!M->IsExternC && ExternCLoc.isValid()) {55 S.Diag(ImportLoc, diag::ext_module_import_in_extern_c)56 << M->getFullModuleName();57 S.Diag(ExternCLoc, diag::note_extern_c_begins_here);58 }59}60 61// We represent the primary and partition names as 'Paths' which are sections62// of the hierarchical access path for a clang module. However for C++2063// the periods in a name are just another character, and we will need to64// flatten them into a string.65static std::string stringFromPath(ModuleIdPath Path) {66 std::string Name;67 if (Path.empty())68 return Name;69 70 for (auto &Piece : Path) {71 if (!Name.empty())72 Name += ".";73 Name += Piece.getIdentifierInfo()->getName();74 }75 return Name;76}77 78/// Helper function for makeTransitiveImportsVisible to decide whether79/// the \param Imported module unit is in the same module with the \param80/// CurrentModule.81/// \param FoundPrimaryModuleInterface is a helper parameter to record the82/// primary module interface unit corresponding to the module \param83/// CurrentModule. Since currently it is expensive to decide whether two module84/// units come from the same module by comparing the module name.85static bool86isImportingModuleUnitFromSameModule(ASTContext &Ctx, Module *Imported,87 Module *CurrentModule,88 Module *&FoundPrimaryModuleInterface) {89 if (!Imported->isNamedModule())90 return false;91 92 // The a partition unit we're importing must be in the same module of the93 // current module.94 if (Imported->isModulePartition())95 return true;96 97 // If we found the primary module interface during the search process, we can98 // return quickly to avoid expensive string comparison.99 if (FoundPrimaryModuleInterface)100 return Imported == FoundPrimaryModuleInterface;101 102 if (!CurrentModule)103 return false;104 105 // Then the imported module must be a primary module interface unit. It106 // is only allowed to import the primary module interface unit from the same107 // module in the implementation unit and the implementation partition unit.108 109 // Since we'll handle implementation unit above. We can only care110 // about the implementation partition unit here.111 if (!CurrentModule->isModulePartitionImplementation())112 return false;113 114 if (Ctx.isInSameModule(Imported, CurrentModule)) {115 assert(!FoundPrimaryModuleInterface ||116 FoundPrimaryModuleInterface == Imported);117 FoundPrimaryModuleInterface = Imported;118 return true;119 }120 121 return false;122}123 124/// [module.import]p7:125/// Additionally, when a module-import-declaration in a module unit of some126/// module M imports another module unit U of M, it also imports all127/// translation units imported by non-exported module-import-declarations in128/// the module unit purview of U. These rules can in turn lead to the129/// importation of yet more translation units.130static void131makeTransitiveImportsVisible(ASTContext &Ctx, VisibleModuleSet &VisibleModules,132 Module *Imported, Module *CurrentModule,133 SourceLocation ImportLoc,134 bool IsImportingPrimaryModuleInterface = false) {135 assert(Imported->isNamedModule() &&136 "'makeTransitiveImportsVisible()' is intended for standard C++ named "137 "modules only.");138 139 llvm::SmallVector<Module *, 4> Worklist;140 llvm::SmallPtrSet<Module *, 16> Visited;141 Worklist.push_back(Imported);142 143 Module *FoundPrimaryModuleInterface =144 IsImportingPrimaryModuleInterface ? Imported : nullptr;145 146 while (!Worklist.empty()) {147 Module *Importing = Worklist.pop_back_val();148 149 if (Visited.count(Importing))150 continue;151 Visited.insert(Importing);152 153 // FIXME: The ImportLoc here is not meaningful. It may be problematic if we154 // use the sourcelocation loaded from the visible modules.155 VisibleModules.setVisible(Importing, ImportLoc);156 157 if (isImportingModuleUnitFromSameModule(Ctx, Importing, CurrentModule,158 FoundPrimaryModuleInterface)) {159 for (Module *TransImported : Importing->Imports)160 Worklist.push_back(TransImported);161 162 for (auto [Exports, _] : Importing->Exports)163 Worklist.push_back(Exports);164 }165 }166}167 168Sema::DeclGroupPtrTy169Sema::ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc) {170 // We start in the global module;171 Module *GlobalModule =172 PushGlobalModuleFragment(ModuleLoc);173 174 // All declarations created from now on are owned by the global module.175 auto *TU = Context.getTranslationUnitDecl();176 // [module.global.frag]p2177 // A global-module-fragment specifies the contents of the global module178 // fragment for a module unit. The global module fragment can be used to179 // provide declarations that are attached to the global module and usable180 // within the module unit.181 //182 // So the declations in the global module shouldn't be visible by default.183 TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);184 TU->setLocalOwningModule(GlobalModule);185 186 // FIXME: Consider creating an explicit representation of this declaration.187 return nullptr;188}189 190void Sema::HandleStartOfHeaderUnit() {191 assert(getLangOpts().CPlusPlusModules &&192 "Header units are only valid for C++20 modules");193 SourceLocation StartOfTU =194 SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());195 196 StringRef HUName = getLangOpts().CurrentModule;197 if (HUName.empty()) {198 HUName =199 SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID())->getName();200 const_cast<LangOptions &>(getLangOpts()).CurrentModule = HUName.str();201 }202 203 // TODO: Make the C++20 header lookup independent.204 // When the input is pre-processed source, we need a file ref to the original205 // file for the header map.206 auto F = SourceMgr.getFileManager().getOptionalFileRef(HUName);207 // For the sake of error recovery (if someone has moved the original header208 // after creating the pre-processed output) fall back to obtaining the file209 // ref for the input file, which must be present.210 if (!F)211 F = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());212 assert(F && "failed to find the header unit source?");213 Module::Header H{HUName.str(), HUName.str(), *F};214 auto &Map = PP.getHeaderSearchInfo().getModuleMap();215 Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);216 assert(Mod && "module creation should not fail");217 ModuleScopes.push_back({}); // No GMF218 ModuleScopes.back().BeginLoc = StartOfTU;219 ModuleScopes.back().Module = Mod;220 VisibleModules.setVisible(Mod, StartOfTU);221 222 // From now on, we have an owning module for all declarations we see.223 // All of these are implicitly exported.224 auto *TU = Context.getTranslationUnitDecl();225 TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Visible);226 TU->setLocalOwningModule(Mod);227}228 229/// Tests whether the given identifier is reserved as a module name and230/// diagnoses if it is. Returns true if a diagnostic is emitted and false231/// otherwise.232static bool DiagReservedModuleName(Sema &S, const IdentifierInfo *II,233 SourceLocation Loc) {234 enum {235 Valid = -1,236 Invalid = 0,237 Reserved = 1,238 } Reason = Valid;239 240 if (II->isStr("module") || II->isStr("import"))241 Reason = Invalid;242 else if (II->isReserved(S.getLangOpts()) !=243 ReservedIdentifierStatus::NotReserved)244 Reason = Reserved;245 246 // If the identifier is reserved (not invalid) but is in a system header,247 // we do not diagnose (because we expect system headers to use reserved248 // identifiers).249 if (Reason == Reserved && S.getSourceManager().isInSystemHeader(Loc))250 Reason = Valid;251 252 switch (Reason) {253 case Valid:254 return false;255 case Invalid:256 return S.Diag(Loc, diag::err_invalid_module_name) << II;257 case Reserved:258 S.Diag(Loc, diag::warn_reserved_module_name) << II;259 return false;260 }261 llvm_unreachable("fell off a fully covered switch");262}263 264Sema::DeclGroupPtrTy265Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,266 ModuleDeclKind MDK, ModuleIdPath Path,267 ModuleIdPath Partition, ModuleImportState &ImportState,268 bool SeenNoTrivialPPDirective) {269 assert(getLangOpts().CPlusPlusModules &&270 "should only have module decl in standard C++ modules");271 272 bool IsFirstDecl = ImportState == ModuleImportState::FirstDecl;273 bool SeenGMF = ImportState == ModuleImportState::GlobalFragment;274 // If any of the steps here fail, we count that as invalidating C++20275 // module state;276 ImportState = ModuleImportState::NotACXX20Module;277 278 bool IsPartition = !Partition.empty();279 if (IsPartition)280 switch (MDK) {281 case ModuleDeclKind::Implementation:282 MDK = ModuleDeclKind::PartitionImplementation;283 break;284 case ModuleDeclKind::Interface:285 MDK = ModuleDeclKind::PartitionInterface;286 break;287 default:288 llvm_unreachable("how did we get a partition type set?");289 }290 291 // A (non-partition) module implementation unit requires that we are not292 // compiling a module of any kind. A partition implementation emits an293 // interface (and the AST for the implementation), which will subsequently294 // be consumed to emit a binary.295 // A module interface unit requires that we are not compiling a module map.296 switch (getLangOpts().getCompilingModule()) {297 case LangOptions::CMK_None:298 // It's OK to compile a module interface as a normal translation unit.299 break;300 301 case LangOptions::CMK_ModuleInterface:302 if (MDK != ModuleDeclKind::Implementation)303 break;304 305 // We were asked to compile a module interface unit but this is a module306 // implementation unit.307 Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)308 << FixItHint::CreateInsertion(ModuleLoc, "export ");309 MDK = ModuleDeclKind::Interface;310 break;311 312 case LangOptions::CMK_ModuleMap:313 Diag(ModuleLoc, diag::err_module_decl_in_module_map_module);314 return nullptr;315 316 case LangOptions::CMK_HeaderUnit:317 Diag(ModuleLoc, diag::err_module_decl_in_header_unit);318 return nullptr;319 }320 321 assert(ModuleScopes.size() <= 1 && "expected to be at global module scope");322 323 // FIXME: Most of this work should be done by the preprocessor rather than324 // here, in order to support macro import.325 326 // Only one module-declaration is permitted per source file.327 if (isCurrentModulePurview()) {328 Diag(ModuleLoc, diag::err_module_redeclaration);329 Diag(VisibleModules.getImportLoc(ModuleScopes.back().Module),330 diag::note_prev_module_declaration);331 return nullptr;332 }333 334 assert((!getLangOpts().CPlusPlusModules ||335 SeenGMF == (bool)this->TheGlobalModuleFragment) &&336 "mismatched global module state");337 338 // In C++20, A module directive may only appear as the first preprocessing339 // tokens in a file (excluding the global module fragment.).340 if (getLangOpts().CPlusPlusModules &&341 (!IsFirstDecl || SeenNoTrivialPPDirective) && !SeenGMF) {342 Diag(ModuleLoc, diag::err_module_decl_not_at_start);343 SourceLocation BeginLoc = PP.getMainFileFirstPPTokenLoc();344 Diag(BeginLoc, diag::note_global_module_introducer_missing)345 << FixItHint::CreateInsertion(BeginLoc, "module;\n");346 }347 348 // C++23 [module.unit]p1: ... The identifiers module and import shall not349 // appear as identifiers in a module-name or module-partition. All350 // module-names either beginning with an identifier consisting of std351 // followed by zero or more digits or containing a reserved identifier352 // ([lex.name]) are reserved and shall not be specified in a353 // module-declaration; no diagnostic is required.354 355 // Test the first part of the path to see if it's std[0-9]+ but allow the356 // name in a system header.357 StringRef FirstComponentName = Path[0].getIdentifierInfo()->getName();358 if (!getSourceManager().isInSystemHeader(Path[0].getLoc()) &&359 (FirstComponentName == "std" ||360 (FirstComponentName.starts_with("std") &&361 llvm::all_of(FirstComponentName.drop_front(3), &llvm::isDigit))))362 Diag(Path[0].getLoc(), diag::warn_reserved_module_name)363 << Path[0].getIdentifierInfo();364 365 // Then test all of the components in the path to see if any of them are366 // using another kind of reserved or invalid identifier.367 for (auto Part : Path) {368 if (DiagReservedModuleName(*this, Part.getIdentifierInfo(), Part.getLoc()))369 return nullptr;370 }371 372 // Flatten the dots in a module name. Unlike Clang's hierarchical module map373 // modules, the dots here are just another character that can appear in a374 // module name.375 std::string ModuleName = stringFromPath(Path);376 if (IsPartition) {377 ModuleName += ":";378 ModuleName += stringFromPath(Partition);379 }380 // If a module name was explicitly specified on the command line, it must be381 // correct.382 if (!getLangOpts().CurrentModule.empty() &&383 getLangOpts().CurrentModule != ModuleName) {384 Diag(Path.front().getLoc(), diag::err_current_module_name_mismatch)385 << SourceRange(Path.front().getLoc(), IsPartition386 ? Partition.back().getLoc()387 : Path.back().getLoc())388 << getLangOpts().CurrentModule;389 return nullptr;390 }391 const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;392 393 auto &Map = PP.getHeaderSearchInfo().getModuleMap();394 Module *Mod; // The module we are creating.395 Module *Interface = nullptr; // The interface for an implementation.396 switch (MDK) {397 case ModuleDeclKind::Interface:398 case ModuleDeclKind::PartitionInterface: {399 // We can't have parsed or imported a definition of this module or parsed a400 // module map defining it already.401 if (auto *M = Map.findOrLoadModule(ModuleName)) {402 Diag(Path[0].getLoc(), diag::err_module_redefinition) << ModuleName;403 if (M->DefinitionLoc.isValid())404 Diag(M->DefinitionLoc, diag::note_prev_module_definition);405 else if (OptionalFileEntryRef FE = M->getASTFile())406 Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file)407 << FE->getName();408 Mod = M;409 break;410 }411 412 // Create a Module for the module that we're defining.413 Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);414 if (MDK == ModuleDeclKind::PartitionInterface)415 Mod->Kind = Module::ModulePartitionInterface;416 assert(Mod && "module creation should not fail");417 break;418 }419 420 case ModuleDeclKind::Implementation: {421 // C++20 A module-declaration that contains neither an export-422 // keyword nor a module-partition implicitly imports the primary423 // module interface unit of the module as if by a module-import-424 // declaration.425 IdentifierLoc ModuleNameLoc(Path[0].getLoc(),426 PP.getIdentifierInfo(ModuleName));427 428 // The module loader will assume we're trying to import the module that429 // we're building if `LangOpts.CurrentModule` equals to 'ModuleName'.430 // Change the value for `LangOpts.CurrentModule` temporarily to make the431 // module loader work properly.432 const_cast<LangOptions &>(getLangOpts()).CurrentModule = "";433 Interface = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},434 Module::AllVisible,435 /*IsInclusionDirective=*/false);436 const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;437 438 if (!Interface) {439 Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;440 // Create an empty module interface unit for error recovery.441 Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);442 } else {443 Mod = Map.createModuleForImplementationUnit(ModuleLoc, ModuleName);444 }445 } break;446 447 case ModuleDeclKind::PartitionImplementation:448 // Create an interface, but note that it is an implementation449 // unit.450 Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);451 Mod->Kind = Module::ModulePartitionImplementation;452 break;453 }454 455 if (!this->TheGlobalModuleFragment) {456 ModuleScopes.push_back({});457 if (getLangOpts().ModulesLocalVisibility)458 ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);459 } else {460 // We're done with the global module fragment now.461 ActOnEndOfTranslationUnitFragment(TUFragmentKind::Global);462 }463 464 // Switch from the global module fragment (if any) to the named module.465 ModuleScopes.back().BeginLoc = StartLoc;466 ModuleScopes.back().Module = Mod;467 VisibleModules.setVisible(Mod, ModuleLoc);468 469 // From now on, we have an owning module for all declarations we see.470 // In C++20 modules, those declaration would be reachable when imported471 // unless explicitily exported.472 // Otherwise, those declarations are module-private unless explicitly473 // exported.474 auto *TU = Context.getTranslationUnitDecl();475 TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);476 TU->setLocalOwningModule(Mod);477 478 // We are in the module purview, but before any other (non import)479 // statements, so imports are allowed.480 ImportState = ModuleImportState::ImportAllowed;481 482 getASTContext().setCurrentNamedModule(Mod);483 484 if (auto *Listener = getASTMutationListener())485 Listener->EnteringModulePurview();486 487 // We already potentially made an implicit import (in the case of a module488 // implementation unit importing its interface). Make this module visible489 // and return the import decl to be added to the current TU.490 if (Interface) {491 HadImportedNamedModules = true;492 493 makeTransitiveImportsVisible(getASTContext(), VisibleModules, Interface,494 Mod, ModuleLoc,495 /*IsImportingPrimaryModuleInterface=*/true);496 497 // Make the import decl for the interface in the impl module.498 ImportDecl *Import = ImportDecl::Create(Context, CurContext, ModuleLoc,499 Interface, Path[0].getLoc());500 CurContext->addDecl(Import);501 502 // Sequence initialization of the imported module before that of the current503 // module, if any.504 Context.addModuleInitializer(ModuleScopes.back().Module, Import);505 Mod->Imports.insert(Interface); // As if we imported it.506 // Also save this as a shortcut to checking for decls in the interface507 ThePrimaryInterface = Interface;508 // If we made an implicit import of the module interface, then return the509 // imported module decl.510 return ConvertDeclToDeclGroup(Import);511 }512 513 return nullptr;514}515 516Sema::DeclGroupPtrTy517Sema::ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,518 SourceLocation PrivateLoc) {519 // C++20 [basic.link]/2:520 // A private-module-fragment shall appear only in a primary module521 // interface unit.522 switch (ModuleScopes.empty() ? Module::ExplicitGlobalModuleFragment523 : ModuleScopes.back().Module->Kind) {524 case Module::ModuleMapModule:525 case Module::ExplicitGlobalModuleFragment:526 case Module::ImplicitGlobalModuleFragment:527 case Module::ModulePartitionImplementation:528 case Module::ModulePartitionInterface:529 case Module::ModuleHeaderUnit:530 Diag(PrivateLoc, diag::err_private_module_fragment_not_module);531 return nullptr;532 533 case Module::PrivateModuleFragment:534 Diag(PrivateLoc, diag::err_private_module_fragment_redefined);535 Diag(ModuleScopes.back().BeginLoc, diag::note_previous_definition);536 return nullptr;537 538 case Module::ModuleImplementationUnit:539 Diag(PrivateLoc, diag::err_private_module_fragment_not_module_interface);540 Diag(ModuleScopes.back().BeginLoc,541 diag::note_not_module_interface_add_export)542 << FixItHint::CreateInsertion(ModuleScopes.back().BeginLoc, "export ");543 return nullptr;544 545 case Module::ModuleInterfaceUnit:546 break;547 }548 549 // FIXME: Check that this translation unit does not import any partitions;550 // such imports would violate [basic.link]/2's "shall be the only module unit"551 // restriction.552 553 // We've finished the public fragment of the translation unit.554 ActOnEndOfTranslationUnitFragment(TUFragmentKind::Normal);555 556 auto &Map = PP.getHeaderSearchInfo().getModuleMap();557 Module *PrivateModuleFragment =558 Map.createPrivateModuleFragmentForInterfaceUnit(559 ModuleScopes.back().Module, PrivateLoc);560 assert(PrivateModuleFragment && "module creation should not fail");561 562 // Enter the scope of the private module fragment.563 ModuleScopes.push_back({});564 ModuleScopes.back().BeginLoc = ModuleLoc;565 ModuleScopes.back().Module = PrivateModuleFragment;566 VisibleModules.setVisible(PrivateModuleFragment, ModuleLoc);567 568 // All declarations created from now on are scoped to the private module569 // fragment (and are neither visible nor reachable in importers of the module570 // interface).571 auto *TU = Context.getTranslationUnitDecl();572 TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate);573 TU->setLocalOwningModule(PrivateModuleFragment);574 575 // FIXME: Consider creating an explicit representation of this declaration.576 return nullptr;577}578 579DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,580 SourceLocation ExportLoc,581 SourceLocation ImportLoc, ModuleIdPath Path,582 bool IsPartition) {583 assert((!IsPartition || getLangOpts().CPlusPlusModules) &&584 "partition seen in non-C++20 code?");585 586 // For a C++20 module name, flatten into a single identifier with the source587 // location of the first component.588 IdentifierLoc ModuleNameLoc;589 590 std::string ModuleName;591 if (IsPartition) {592 // We already checked that we are in a module purview in the parser.593 assert(!ModuleScopes.empty() && "in a module purview, but no module?");594 Module *NamedMod = ModuleScopes.back().Module;595 // If we are importing into a partition, find the owning named module,596 // otherwise, the name of the importing named module.597 ModuleName = NamedMod->getPrimaryModuleInterfaceName().str();598 ModuleName += ":";599 ModuleName += stringFromPath(Path);600 ModuleNameLoc =601 IdentifierLoc(Path[0].getLoc(), PP.getIdentifierInfo(ModuleName));602 Path = ModuleIdPath(ModuleNameLoc);603 } else if (getLangOpts().CPlusPlusModules) {604 ModuleName = stringFromPath(Path);605 ModuleNameLoc =606 IdentifierLoc(Path[0].getLoc(), PP.getIdentifierInfo(ModuleName));607 Path = ModuleIdPath(ModuleNameLoc);608 }609 610 // Diagnose self-import before attempting a load.611 // [module.import]/9612 // A module implementation unit of a module M that is not a module partition613 // shall not contain a module-import-declaration nominating M.614 // (for an implementation, the module interface is imported implicitly,615 // but that's handled in the module decl code).616 617 if (getLangOpts().CPlusPlusModules && isCurrentModulePurview() &&618 getCurrentModule()->Name == ModuleName) {619 Diag(ImportLoc, diag::err_module_self_import_cxx20)620 << ModuleName << currentModuleIsImplementation();621 return true;622 }623 624 Module *Mod = getModuleLoader().loadModule(625 ImportLoc, Path, Module::AllVisible, /*IsInclusionDirective=*/false);626 if (!Mod)627 return true;628 629 if (!Mod->isInterfaceOrPartition() && !ModuleName.empty() &&630 !getLangOpts().ObjC) {631 Diag(ImportLoc, diag::err_module_import_non_interface_nor_parition)632 << ModuleName;633 return true;634 }635 636 return ActOnModuleImport(StartLoc, ExportLoc, ImportLoc, Mod, Path);637}638 639/// Determine whether \p D is lexically within an export-declaration.640static const ExportDecl *getEnclosingExportDecl(const Decl *D) {641 for (auto *DC = D->getLexicalDeclContext(); DC; DC = DC->getLexicalParent())642 if (auto *ED = dyn_cast<ExportDecl>(DC))643 return ED;644 return nullptr;645}646 647DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,648 SourceLocation ExportLoc,649 SourceLocation ImportLoc, Module *Mod,650 ModuleIdPath Path) {651 if (Mod->isHeaderUnit())652 Diag(ImportLoc, diag::warn_experimental_header_unit);653 654 if (Mod->isNamedModule())655 makeTransitiveImportsVisible(getASTContext(), VisibleModules, Mod,656 getCurrentModule(), ImportLoc);657 else658 VisibleModules.setVisible(Mod, ImportLoc);659 660 assert((!Mod->isModulePartitionImplementation() || getCurrentModule()) &&661 "We can only import a partition unit in a named module.");662 if (Mod->isModulePartitionImplementation() &&663 getCurrentModule()->isModuleInterfaceUnit())664 Diag(ImportLoc,665 diag::warn_import_implementation_partition_unit_in_interface_unit)666 << Mod->Name;667 668 checkModuleImportContext(*this, Mod, ImportLoc, CurContext);669 670 // FIXME: we should support importing a submodule within a different submodule671 // of the same top-level module. Until we do, make it an error rather than672 // silently ignoring the import.673 // FIXME: Should we warn on a redundant import of the current module?674 if (Mod->isForBuilding(getLangOpts())) {675 Diag(ImportLoc, getLangOpts().isCompilingModule()676 ? diag::err_module_self_import677 : diag::err_module_import_in_implementation)678 << Mod->getFullModuleName() << getLangOpts().CurrentModule;679 }680 681 SmallVector<SourceLocation, 2> IdentifierLocs;682 683 if (Path.empty()) {684 // If this was a header import, pad out with dummy locations.685 // FIXME: Pass in and use the location of the header-name token in this686 // case.687 for (Module *ModCheck = Mod; ModCheck; ModCheck = ModCheck->Parent)688 IdentifierLocs.push_back(SourceLocation());689 } else if (getLangOpts().CPlusPlusModules && !Mod->Parent) {690 // A single identifier for the whole name.691 IdentifierLocs.push_back(Path[0].getLoc());692 } else {693 Module *ModCheck = Mod;694 for (unsigned I = 0, N = Path.size(); I != N; ++I) {695 // If we've run out of module parents, just drop the remaining696 // identifiers. We need the length to be consistent.697 if (!ModCheck)698 break;699 ModCheck = ModCheck->Parent;700 701 IdentifierLocs.push_back(Path[I].getLoc());702 }703 }704 705 ImportDecl *Import = ImportDecl::Create(Context, CurContext, StartLoc,706 Mod, IdentifierLocs);707 CurContext->addDecl(Import);708 709 // Sequence initialization of the imported module before that of the current710 // module, if any.711 if (!ModuleScopes.empty())712 Context.addModuleInitializer(ModuleScopes.back().Module, Import);713 714 // A module (partition) implementation unit shall not be exported.715 if (getLangOpts().CPlusPlusModules && ExportLoc.isValid() &&716 Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) {717 Diag(ExportLoc, diag::err_export_partition_impl)718 << SourceRange(ExportLoc, Path.back().getLoc());719 } else if (ExportLoc.isValid() &&720 (ModuleScopes.empty() || currentModuleIsImplementation())) {721 // [module.interface]p1:722 // An export-declaration shall inhabit a namespace scope and appear in the723 // purview of a module interface unit.724 Diag(ExportLoc, diag::err_export_not_in_module_interface);725 } else if (!ModuleScopes.empty()) {726 // Re-export the module if the imported module is exported.727 // Note that we don't need to add re-exported module to Imports field728 // since `Exports` implies the module is imported already.729 if (ExportLoc.isValid() || getEnclosingExportDecl(Import))730 getCurrentModule()->Exports.emplace_back(Mod, false);731 else732 getCurrentModule()->Imports.insert(Mod);733 }734 735 HadImportedNamedModules = true;736 737 return Import;738}739 740void Sema::ActOnAnnotModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {741 checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);742 BuildModuleInclude(DirectiveLoc, Mod);743}744 745void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {746 // Determine whether we're in the #include buffer for a module. The #includes747 // in that buffer do not qualify as module imports; they're just an748 // implementation detail of us building the module.749 //750 // FIXME: Should we even get ActOnAnnotModuleInclude calls for those?751 bool IsInModuleIncludes =752 TUKind == TU_ClangModule &&753 getSourceManager().isWrittenInMainFile(DirectiveLoc);754 755 // If we are really importing a module (not just checking layering) due to an756 // #include in the main file, synthesize an ImportDecl.757 if (getLangOpts().Modules && !IsInModuleIncludes) {758 TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();759 ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,760 DirectiveLoc, Mod,761 DirectiveLoc);762 if (!ModuleScopes.empty())763 Context.addModuleInitializer(ModuleScopes.back().Module, ImportD);764 TU->addDecl(ImportD);765 Consumer.HandleImplicitImportDecl(ImportD);766 }767 768 getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc);769 VisibleModules.setVisible(Mod, DirectiveLoc);770 771 if (getLangOpts().isCompilingModule()) {772 Module *ThisModule = PP.getHeaderSearchInfo().lookupModule(773 getLangOpts().CurrentModule, DirectiveLoc, false, false);774 (void)ThisModule;775 // For named modules, the current module name is not known while parsing the776 // global module fragment and lookupModule may return null.777 assert((getLangOpts().getCompilingModule() ==778 LangOptionsBase::CMK_ModuleInterface ||779 ThisModule) &&780 "was expecting a module if building a Clang module");781 }782}783 784void Sema::ActOnAnnotModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {785 checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true);786 787 ModuleScopes.push_back({});788 ModuleScopes.back().Module = Mod;789 if (getLangOpts().ModulesLocalVisibility)790 ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);791 792 VisibleModules.setVisible(Mod, DirectiveLoc);793 794 // The enclosing context is now part of this module.795 // FIXME: Consider creating a child DeclContext to hold the entities796 // lexically within the module.797 if (getLangOpts().trackLocalOwningModule()) {798 for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {799 cast<Decl>(DC)->setModuleOwnershipKind(800 getLangOpts().ModulesLocalVisibility801 ? Decl::ModuleOwnershipKind::VisibleWhenImported802 : Decl::ModuleOwnershipKind::Visible);803 cast<Decl>(DC)->setLocalOwningModule(Mod);804 }805 }806}807 808void Sema::ActOnAnnotModuleEnd(SourceLocation EomLoc, Module *Mod) {809 if (getLangOpts().ModulesLocalVisibility) {810 VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules);811 // Leaving a module hides namespace names, so our visible namespace cache812 // is now out of date.813 VisibleNamespaceCache.clear();814 }815 816 assert(!ModuleScopes.empty() && ModuleScopes.back().Module == Mod &&817 "left the wrong module scope");818 ModuleScopes.pop_back();819 820 // We got to the end of processing a local module. Create an821 // ImportDecl as we would for an imported module.822 FileID File = getSourceManager().getFileID(EomLoc);823 SourceLocation DirectiveLoc;824 if (EomLoc == getSourceManager().getLocForEndOfFile(File)) {825 // We reached the end of a #included module header. Use the #include loc.826 assert(File != getSourceManager().getMainFileID() &&827 "end of submodule in main source file");828 DirectiveLoc = getSourceManager().getIncludeLoc(File);829 } else {830 // We reached an EOM pragma. Use the pragma location.831 DirectiveLoc = EomLoc;832 }833 BuildModuleInclude(DirectiveLoc, Mod);834 835 // Any further declarations are in whatever module we returned to.836 if (getLangOpts().trackLocalOwningModule()) {837 // The parser guarantees that this is the same context that we entered838 // the module within.839 for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {840 cast<Decl>(DC)->setLocalOwningModule(getCurrentModule());841 if (!getCurrentModule())842 cast<Decl>(DC)->setModuleOwnershipKind(843 Decl::ModuleOwnershipKind::Unowned);844 }845 }846}847 848void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,849 Module *Mod) {850 // Bail if we're not allowed to implicitly import a module here.851 if (isSFINAEContext() || !getLangOpts().ModulesErrorRecovery ||852 VisibleModules.isVisible(Mod))853 return;854 855 // Create the implicit import declaration.856 TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();857 ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,858 Loc, Mod, Loc);859 TU->addDecl(ImportD);860 Consumer.HandleImplicitImportDecl(ImportD);861 862 // Make the module visible.863 getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc);864 VisibleModules.setVisible(Mod, Loc);865}866 867Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,868 SourceLocation LBraceLoc) {869 ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc);870 871 // Set this temporarily so we know the export-declaration was braced.872 D->setRBraceLoc(LBraceLoc);873 874 CurContext->addDecl(D);875 PushDeclContext(S, D);876 877 // C++2a [module.interface]p1:878 // An export-declaration shall appear only [...] in the purview of a module879 // interface unit. An export-declaration shall not appear directly or880 // indirectly within [...] a private-module-fragment.881 if (!getLangOpts().HLSL) {882 if (!isCurrentModulePurview()) {883 Diag(ExportLoc, diag::err_export_not_in_module_interface) << 0;884 D->setInvalidDecl();885 return D;886 } else if (currentModuleIsImplementation()) {887 Diag(ExportLoc, diag::err_export_not_in_module_interface) << 1;888 Diag(ModuleScopes.back().BeginLoc,889 diag::note_not_module_interface_add_export)890 << FixItHint::CreateInsertion(ModuleScopes.back().BeginLoc, "export ");891 D->setInvalidDecl();892 return D;893 } else if (ModuleScopes.back().Module->Kind ==894 Module::PrivateModuleFragment) {895 Diag(ExportLoc, diag::err_export_in_private_module_fragment);896 Diag(ModuleScopes.back().BeginLoc, diag::note_private_module_fragment);897 D->setInvalidDecl();898 return D;899 }900 }901 902 for (const DeclContext *DC = CurContext; DC; DC = DC->getLexicalParent()) {903 if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) {904 // An export-declaration shall not appear directly or indirectly within905 // an unnamed namespace [...]906 if (ND->isAnonymousNamespace()) {907 Diag(ExportLoc, diag::err_export_within_anonymous_namespace);908 Diag(ND->getLocation(), diag::note_anonymous_namespace);909 // Don't diagnose internal-linkage declarations in this region.910 D->setInvalidDecl();911 return D;912 }913 914 // A declaration is exported if it is [...] a namespace-definition915 // that contains an exported declaration.916 //917 // Defer exporting the namespace until after we leave it, in order to918 // avoid marking all subsequent declarations in the namespace as exported.919 if (!getLangOpts().HLSL && !DeferredExportedNamespaces.insert(ND).second)920 break;921 }922 }923 924 // [...] its declaration or declaration-seq shall not contain an925 // export-declaration.926 if (auto *ED = getEnclosingExportDecl(D)) {927 Diag(ExportLoc, diag::err_export_within_export);928 if (ED->hasBraces())929 Diag(ED->getLocation(), diag::note_export);930 D->setInvalidDecl();931 return D;932 }933 934 if (!getLangOpts().HLSL)935 D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::VisibleWhenImported);936 937 return D;938}939 940static bool checkExportedDecl(Sema &, Decl *, SourceLocation);941 942/// Check that it's valid to export all the declarations in \p DC.943static bool checkExportedDeclContext(Sema &S, DeclContext *DC,944 SourceLocation BlockStart) {945 bool AllUnnamed = true;946 for (auto *D : DC->decls())947 AllUnnamed &= checkExportedDecl(S, D, BlockStart);948 return AllUnnamed;949}950 951/// Check that it's valid to export \p D.952static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) {953 954 // HLSL: export declaration is valid only on functions955 if (S.getLangOpts().HLSL) {956 // Export-within-export was already diagnosed in ActOnStartExportDecl957 if (!isa<FunctionDecl, ExportDecl>(D)) {958 S.Diag(D->getBeginLoc(), diag::err_hlsl_export_not_on_function);959 D->setInvalidDecl();960 return false;961 }962 }963 964 // C++20 [module.interface]p3:965 // [...] it shall not declare a name with internal linkage.966 bool HasName = false;967 if (auto *ND = dyn_cast<NamedDecl>(D)) {968 // Don't diagnose anonymous union objects; we'll diagnose their members969 // instead.970 HasName = (bool)ND->getDeclName();971 if (HasName && ND->getFormalLinkage() == Linkage::Internal) {972 S.Diag(ND->getLocation(), diag::err_export_internal) << ND;973 if (BlockStart.isValid())974 S.Diag(BlockStart, diag::note_export);975 return false;976 }977 }978 979 // C++2a [module.interface]p5:980 // all entities to which all of the using-declarators ultimately refer981 // shall have been introduced with a name having external linkage982 if (auto *USD = dyn_cast<UsingShadowDecl>(D)) {983 NamedDecl *Target = USD->getUnderlyingDecl();984 Linkage Lk = Target->getFormalLinkage();985 if (Lk == Linkage::Internal || Lk == Linkage::Module) {986 S.Diag(USD->getLocation(), diag::err_export_using_internal)987 << (Lk == Linkage::Internal ? 0 : 1) << Target;988 S.Diag(Target->getLocation(), diag::note_using_decl_target);989 if (BlockStart.isValid())990 S.Diag(BlockStart, diag::note_export);991 return false;992 }993 }994 995 // Recurse into namespace-scope DeclContexts. (Only namespace-scope996 // declarations are exported).997 if (auto *DC = dyn_cast<DeclContext>(D)) {998 if (!isa<NamespaceDecl>(D))999 return true;1000 1001 if (auto *ND = dyn_cast<NamedDecl>(D)) {1002 if (!ND->getDeclName()) {1003 S.Diag(ND->getLocation(), diag::err_export_anon_ns_internal);1004 if (BlockStart.isValid())1005 S.Diag(BlockStart, diag::note_export);1006 return false;1007 } else if (!DC->decls().empty() &&1008 DC->getRedeclContext()->isFileContext()) {1009 return checkExportedDeclContext(S, DC, BlockStart);1010 }1011 }1012 }1013 return true;1014}1015 1016Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) {1017 auto *ED = cast<ExportDecl>(D);1018 if (RBraceLoc.isValid())1019 ED->setRBraceLoc(RBraceLoc);1020 1021 PopDeclContext();1022 1023 if (!D->isInvalidDecl()) {1024 SourceLocation BlockStart =1025 ED->hasBraces() ? ED->getBeginLoc() : SourceLocation();1026 for (auto *Child : ED->decls()) {1027 checkExportedDecl(*this, Child, BlockStart);1028 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {1029 // [dcl.inline]/71030 // If an inline function or variable that is attached to a named module1031 // is declared in a definition domain, it shall be defined in that1032 // domain.1033 // So, if the current declaration does not have a definition, we must1034 // check at the end of the TU (or when the PMF starts) to see that we1035 // have a definition at that point.1036 if (FD->isInlineSpecified() && !FD->isDefined())1037 PendingInlineFuncDecls.insert(FD);1038 }1039 }1040 }1041 1042 // Anything exported from a module should never be considered unused.1043 for (auto *Exported : ED->decls())1044 Exported->markUsed(getASTContext());1045 1046 return D;1047}1048 1049Module *Sema::PushGlobalModuleFragment(SourceLocation BeginLoc) {1050 // We shouldn't create new global module fragment if there is already1051 // one.1052 if (!TheGlobalModuleFragment) {1053 ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();1054 TheGlobalModuleFragment = Map.createGlobalModuleFragmentForModuleUnit(1055 BeginLoc, getCurrentModule());1056 }1057 1058 assert(TheGlobalModuleFragment && "module creation should not fail");1059 1060 // Enter the scope of the global module.1061 ModuleScopes.push_back({BeginLoc, TheGlobalModuleFragment,1062 /*OuterVisibleModules=*/{}});1063 VisibleModules.setVisible(TheGlobalModuleFragment, BeginLoc);1064 1065 return TheGlobalModuleFragment;1066}1067 1068void Sema::PopGlobalModuleFragment() {1069 assert(!ModuleScopes.empty() &&1070 getCurrentModule()->isExplicitGlobalModule() &&1071 "left the wrong module scope, which is not global module fragment");1072 ModuleScopes.pop_back();1073}1074 1075Module *Sema::PushImplicitGlobalModuleFragment(SourceLocation BeginLoc) {1076 if (!TheImplicitGlobalModuleFragment) {1077 ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();1078 TheImplicitGlobalModuleFragment =1079 Map.createImplicitGlobalModuleFragmentForModuleUnit(BeginLoc,1080 getCurrentModule());1081 }1082 assert(TheImplicitGlobalModuleFragment && "module creation should not fail");1083 1084 // Enter the scope of the global module.1085 ModuleScopes.push_back({BeginLoc, TheImplicitGlobalModuleFragment,1086 /*OuterVisibleModules=*/{}});1087 VisibleModules.setVisible(TheImplicitGlobalModuleFragment, BeginLoc);1088 return TheImplicitGlobalModuleFragment;1089}1090 1091void Sema::PopImplicitGlobalModuleFragment() {1092 assert(!ModuleScopes.empty() &&1093 getCurrentModule()->isImplicitGlobalModule() &&1094 "left the wrong module scope, which is not global module fragment");1095 ModuleScopes.pop_back();1096}1097 1098bool Sema::isCurrentModulePurview() const {1099 if (!getCurrentModule())1100 return false;1101 1102 /// Does this Module scope describe part of the purview of a standard named1103 /// C++ module?1104 switch (getCurrentModule()->Kind) {1105 case Module::ModuleInterfaceUnit:1106 case Module::ModuleImplementationUnit:1107 case Module::ModulePartitionInterface:1108 case Module::ModulePartitionImplementation:1109 case Module::PrivateModuleFragment:1110 case Module::ImplicitGlobalModuleFragment:1111 return true;1112 default:1113 return false;1114 }1115}1116 1117//===----------------------------------------------------------------------===//1118// Checking Exposure in modules //1119//===----------------------------------------------------------------------===//1120 1121namespace {1122class ExposureChecker {1123public:1124 ExposureChecker(Sema &S) : SemaRef(S) {}1125 1126 bool checkExposure(const VarDecl *D, bool Diag);1127 bool checkExposure(const CXXRecordDecl *D, bool Diag);1128 bool checkExposure(const Stmt *S, bool Diag);1129 bool checkExposure(const FunctionDecl *D, bool Diag);1130 bool checkExposure(const NamedDecl *D, bool Diag);1131 void checkExposureInContext(const DeclContext *DC);1132 bool isExposureCandidate(const NamedDecl *D);1133 1134 bool isTULocal(QualType Ty);1135 bool isTULocal(const NamedDecl *ND);1136 bool isTULocal(const Expr *E);1137 1138 Sema &SemaRef;1139 1140private:1141 llvm::DenseSet<const NamedDecl *> ExposureSet;1142 llvm::DenseSet<const NamedDecl *> KnownNonExposureSet;1143};1144 1145bool ExposureChecker::isTULocal(QualType Ty) {1146 // [basic.link]p15:1147 // An entity is TU-local if it is1148 // - a type, type alias, namespace, namespace alias, function, variable, or1149 // template that1150 // -- has internal linkage, or1151 return Ty->getLinkage() == Linkage::Internal;1152 1153 // TODO:1154 // [basic.link]p15.2:1155 // a type with no name that is defined outside a class-specifier, function1156 // body, or initializer or is introduced by a defining-type-specifier that1157 // is used to declare only TU-local entities,1158}1159 1160bool ExposureChecker::isTULocal(const NamedDecl *D) {1161 if (!D)1162 return false;1163 1164 // [basic.link]p15:1165 // An entity is TU-local if it is1166 // - a type, type alias, namespace, namespace alias, function, variable, or1167 // template that1168 // -- has internal linkage, or1169 if (D->getLinkageInternal() == Linkage::Internal)1170 return true;1171 1172 if (D->isInAnonymousNamespace())1173 return true;1174 1175 // [basic.link]p15.1.2:1176 // does not have a name with linkage and is declared, or introduced by a1177 // lambda-expression, within the definition of a TU-local entity,1178 if (D->getLinkageInternal() == Linkage::None)1179 if (auto *ND = dyn_cast<NamedDecl>(D->getDeclContext());1180 ND && isTULocal(ND))1181 return true;1182 1183 // [basic.link]p15.3, p15.4:1184 // - a specialization of a TU-local template,1185 // - a specialization of a template with any TU-local template argument, or1186 ArrayRef<TemplateArgument> TemplateArgs;1187 NamedDecl *PrimaryTemplate = nullptr;1188 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {1189 TemplateArgs = CTSD->getTemplateArgs().asArray();1190 PrimaryTemplate = CTSD->getSpecializedTemplate();1191 if (isTULocal(PrimaryTemplate))1192 return true;1193 } else if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) {1194 TemplateArgs = VTSD->getTemplateArgs().asArray();1195 PrimaryTemplate = VTSD->getSpecializedTemplate();1196 if (isTULocal(PrimaryTemplate))1197 return true;1198 } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {1199 if (auto *TAList = FD->getTemplateSpecializationArgs())1200 TemplateArgs = TAList->asArray();1201 1202 PrimaryTemplate = FD->getPrimaryTemplate();1203 if (isTULocal(PrimaryTemplate))1204 return true;1205 }1206 1207 if (!PrimaryTemplate)1208 // Following off, we only check for specializations.1209 return false;1210 1211 if (KnownNonExposureSet.count(D))1212 return false;1213 1214 for (auto &TA : TemplateArgs) {1215 switch (TA.getKind()) {1216 case TemplateArgument::Type:1217 if (isTULocal(TA.getAsType()))1218 return true;1219 break;1220 case TemplateArgument::Declaration:1221 if (isTULocal(TA.getAsDecl()))1222 return true;1223 break;1224 default:1225 break;1226 }1227 }1228 1229 // [basic.link]p15.51230 // - a specialization of a template whose (possibly instantiated) declaration1231 // is an exposure.1232 if (ExposureSet.count(PrimaryTemplate) ||1233 checkExposure(PrimaryTemplate, /*Diag=*/false))1234 return true;1235 1236 // Avoid calling checkExposure again since it is expensive.1237 KnownNonExposureSet.insert(D);1238 return false;1239}1240 1241bool ExposureChecker::isTULocal(const Expr *E) {1242 if (!E)1243 return false;1244 1245 // [basic.link]p16:1246 // A value or object is TU-local if either1247 // - it is of TU-local type,1248 if (isTULocal(E->getType()))1249 return true;1250 1251 E = E->IgnoreParenImpCasts();1252 // [basic.link]p16.2:1253 // - it is, or is a pointer to, a TU-local function or the object associated1254 // with a TU-local variable,1255 // - it is an object of class or array type and any of its subobjects or any1256 // of the objects or functions to which its non-static data members of1257 // reference type refer is TU-local and is usable in constant expressions, or1258 // FIXME: But how can we know the value of pointers or arrays at compile time?1259 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {1260 if (auto *FD = dyn_cast_or_null<FunctionDecl>(DRE->getFoundDecl()))1261 return isTULocal(FD);1262 else if (auto *VD = dyn_cast_or_null<VarDecl>(DRE->getFoundDecl()))1263 return isTULocal(VD);1264 else if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(DRE->getFoundDecl()))1265 return isTULocal(RD);1266 }1267 1268 // TODO:1269 // [basic.link]p16.4:1270 // it is a reflection value that represents...1271 1272 return false;1273}1274 1275bool ExposureChecker::isExposureCandidate(const NamedDecl *D) {1276 if (!D)1277 return false;1278 1279 // [basic.link]p17:1280 // If a (possibly instantiated) declaration of, or a deduction guide for,1281 // a non-TU-local entity in a module interface unit1282 // (outside the private-module-fragment, if any) or1283 // module partition is an exposure, the program is ill-formed.1284 Module *M = D->getOwningModule();1285 if (!M)1286 return false;1287 // If M is implicit global module, the declaration must be in the purview of1288 // a module unit.1289 if (M->isImplicitGlobalModule()) {1290 M = M->Parent;1291 assert(M && "Implicit global module must have a parent");1292 }1293 1294 if (!M->isInterfaceOrPartition())1295 return false;1296 1297 if (D->isImplicit())1298 return false;1299 1300 // [basic.link]p14:1301 // A declaration is an exposure if it either names a TU-local entity1302 // (defined below), ignoring:1303 // ...1304 // - friend declarations in a class definition1305 if (D->getFriendObjectKind() &&1306 isa<CXXRecordDecl>(D->getLexicalDeclContext()))1307 return false;1308 1309 return true;1310}1311 1312bool ExposureChecker::checkExposure(const NamedDecl *D, bool Diag) {1313 if (!isExposureCandidate(D))1314 return false;1315 1316 if (auto *FD = dyn_cast<FunctionDecl>(D))1317 return checkExposure(FD, Diag);1318 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))1319 return checkExposure(FTD->getTemplatedDecl(), Diag);1320 1321 if (auto *VD = dyn_cast<VarDecl>(D))1322 return checkExposure(VD, Diag);1323 if (auto *VTD = dyn_cast<VarTemplateDecl>(D))1324 return checkExposure(VTD->getTemplatedDecl(), Diag);1325 1326 if (auto *RD = dyn_cast<CXXRecordDecl>(D))1327 return checkExposure(RD, Diag);1328 1329 if (auto *CTD = dyn_cast<ClassTemplateDecl>(D))1330 return checkExposure(CTD->getTemplatedDecl(), Diag);1331 1332 return false;1333}1334 1335bool ExposureChecker::checkExposure(const FunctionDecl *FD, bool Diag) {1336 bool IsExposure = false;1337 if (isTULocal(FD->getReturnType())) {1338 IsExposure = true;1339 if (Diag)1340 SemaRef.Diag(FD->getReturnTypeSourceRange().getBegin(),1341 diag::warn_exposure)1342 << FD->getReturnType();1343 }1344 1345 for (ParmVarDecl *Parms : FD->parameters())1346 if (isTULocal(Parms->getType())) {1347 IsExposure = true;1348 if (Diag)1349 SemaRef.Diag(Parms->getLocation(), diag::warn_exposure)1350 << Parms->getType();1351 }1352 1353 bool IsImplicitInstantiation =1354 FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;1355 1356 // [basic.link]p14:1357 // A declaration is an exposure if it either names a TU-local entity1358 // (defined below), ignoring:1359 // - the function-body for a non-inline function or function template1360 // (but not the deduced return1361 // type for a (possibly instantiated) definition of a function with a1362 // declared return type that uses a placeholder type1363 // ([dcl.spec.auto])),1364 Diag &=1365 (FD->isInlined() || IsImplicitInstantiation) && !FD->isDependentContext();1366 1367 IsExposure |= checkExposure(FD->getBody(), Diag);1368 if (IsExposure)1369 ExposureSet.insert(FD);1370 1371 return IsExposure;1372}1373 1374bool ExposureChecker::checkExposure(const VarDecl *VD, bool Diag) {1375 bool IsExposure = false;1376 // [basic.link]p14:1377 // A declaration is an exposure if it either names a TU-local entity (defined1378 // below), ignoring:1379 // ...1380 // or defines a constexpr variable initialized to a TU-local value (defined1381 // below).1382 if (VD->isConstexpr() && isTULocal(VD->getInit())) {1383 IsExposure = true;1384 if (Diag)1385 SemaRef.Diag(VD->getInit()->getExprLoc(), diag::warn_exposure)1386 << VD->getInit();1387 }1388 1389 if (isTULocal(VD->getType())) {1390 IsExposure = true;1391 if (Diag)1392 SemaRef.Diag(VD->getLocation(), diag::warn_exposure) << VD->getType();1393 }1394 1395 // [basic.link]p14:1396 // ..., ignoring:1397 // - the initializer for a variable or variable template (but not the1398 // variable's type),1399 //1400 // Note: although the spec says to ignore the initializer for all variable,1401 // for the code we generated now for inline variables, it is dangerous if the1402 // initializer of an inline variable is TULocal.1403 Diag &= !VD->getDeclContext()->isDependentContext() && VD->isInline();1404 IsExposure |= checkExposure(VD->getInit(), Diag);1405 if (IsExposure)1406 ExposureSet.insert(VD);1407 1408 return IsExposure;1409}1410 1411bool ExposureChecker::checkExposure(const CXXRecordDecl *RD, bool Diag) {1412 if (!RD->hasDefinition())1413 return false;1414 1415 bool IsExposure = false;1416 for (CXXMethodDecl *Method : RD->methods())1417 IsExposure |= checkExposure(Method, Diag);1418 1419 for (FieldDecl *FD : RD->fields()) {1420 if (isTULocal(FD->getType())) {1421 IsExposure = true;1422 if (Diag)1423 SemaRef.Diag(FD->getLocation(), diag::warn_exposure) << FD->getType();1424 }1425 }1426 1427 for (const CXXBaseSpecifier &Base : RD->bases()) {1428 if (isTULocal(Base.getType())) {1429 IsExposure = true;1430 if (Diag)1431 SemaRef.Diag(Base.getBaseTypeLoc(), diag::warn_exposure)1432 << Base.getType();1433 }1434 }1435 1436 if (IsExposure)1437 ExposureSet.insert(RD);1438 1439 return IsExposure;1440}1441 1442class ReferenceTULocalChecker : public DynamicRecursiveASTVisitor {1443public:1444 using CallbackTy = std::function<void(DeclRefExpr *, ValueDecl *)>;1445 1446 ReferenceTULocalChecker(ExposureChecker &C, CallbackTy &&Callback)1447 : Checker(C), Callback(std::move(Callback)) {}1448 1449 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {1450 ValueDecl *Referenced = DRE->getDecl();1451 if (!Referenced)1452 return true;1453 1454 if (!Checker.isTULocal(Referenced))1455 // We don't care if the referenced declaration is not TU-local.1456 return true;1457 1458 Qualifiers Qual = DRE->getType().getQualifiers();1459 // [basic.link]p14:1460 // A declaration is an exposure if it either names a TU-local entity1461 // (defined below), ignoring:1462 // ...1463 // - any reference to a non-volatile const object ...1464 if (Qual.hasConst() && !Qual.hasVolatile())1465 return true;1466 1467 // [basic.link]p14:1468 // ..., ignoring:1469 // ...1470 // (p14.4) - ... or reference with internal or no linkage initialized with1471 // a constant expression that is not an odr-use1472 ASTContext &Context = Referenced->getASTContext();1473 Linkage L = Referenced->getLinkageInternal();1474 if (DRE->isNonOdrUse() && (L == Linkage::Internal || L == Linkage::None))1475 if (auto *VD = dyn_cast<VarDecl>(Referenced);1476 VD && VD->getInit() && !VD->getInit()->isValueDependent() &&1477 VD->getInit()->isConstantInitializer(Context, /*IsForRef=*/false))1478 return true;1479 1480 Callback(DRE, Referenced);1481 return true;1482 }1483 1484 ExposureChecker &Checker;1485 CallbackTy Callback;1486};1487 1488bool ExposureChecker::checkExposure(const Stmt *S, bool Diag) {1489 if (!S)1490 return false;1491 1492 bool HasReferencedTULocals = false;1493 ReferenceTULocalChecker Checker(1494 *this, [this, &HasReferencedTULocals, Diag](DeclRefExpr *DRE,1495 ValueDecl *Referenced) {1496 if (Diag) {1497 SemaRef.Diag(DRE->getExprLoc(), diag::warn_exposure) << Referenced;1498 }1499 HasReferencedTULocals = true;1500 });1501 Checker.TraverseStmt(const_cast<Stmt *>(S));1502 return HasReferencedTULocals;1503}1504 1505void ExposureChecker::checkExposureInContext(const DeclContext *DC) {1506 for (auto *TopD : DC->noload_decls()) {1507 if (auto *Export = dyn_cast<ExportDecl>(TopD)) {1508 checkExposureInContext(Export);1509 continue;1510 }1511 1512 if (auto *LinkageSpec = dyn_cast<LinkageSpecDecl>(TopD)) {1513 checkExposureInContext(LinkageSpec);1514 continue;1515 }1516 1517 auto *TopND = dyn_cast<NamedDecl>(TopD);1518 if (!TopND)1519 continue;1520 1521 if (auto *Namespace = dyn_cast<NamespaceDecl>(TopND)) {1522 checkExposureInContext(Namespace);1523 continue;1524 }1525 1526 // [basic.link]p17:1527 // If a (possibly instantiated) declaration of, or a deduction guide for,1528 // a non-TU-local entity in a module interface unit1529 // (outside the private-module-fragment, if any) or1530 // module partition is an exposure, the program is ill-formed.1531 if (!TopND->isFromASTFile() && isExposureCandidate(TopND) &&1532 !isTULocal(TopND))1533 checkExposure(TopND, /*Diag=*/true);1534 }1535}1536 1537} // namespace1538 1539void Sema::checkExposure(const TranslationUnitDecl *TU) {1540 if (!TU)1541 return;1542 1543 ExposureChecker Checker(*this);1544 1545 Module *M = TU->getOwningModule();1546 if (M && M->isInterfaceOrPartition())1547 Checker.checkExposureInContext(TU);1548 1549 // [basic.link]p18:1550 // If a declaration that appears in one translation unit names a TU-local1551 // entity declared in another translation unit that is not a header unit,1552 // the program is ill-formed.1553 for (auto FDAndInstantiationLocPair : PendingCheckReferenceForTULocal) {1554 FunctionDecl *FD = FDAndInstantiationLocPair.first;1555 SourceLocation PointOfInstantiation = FDAndInstantiationLocPair.second;1556 1557 if (!FD->hasBody())1558 continue;1559 1560 ReferenceTULocalChecker(Checker, [&, this](DeclRefExpr *DRE,1561 ValueDecl *Referenced) {1562 // A "defect" in current implementation. Now an implicit instantiation of1563 // a template, the instantiation is considered to be in the same module1564 // unit as the template instead of the module unit where the instantiation1565 // happens.1566 //1567 // See test/Modules/Exposre-2.cppm for example.1568 if (!Referenced->isFromASTFile())1569 return;1570 1571 if (!Referenced->isInAnotherModuleUnit())1572 return;1573 1574 // This is not standard conforming. But given there are too many static1575 // (inline) functions in headers in existing code, it is more user1576 // friendly to ignore them temporarily now. maybe we can have another flag1577 // for this.1578 if (Referenced->getOwningModule()->isExplicitGlobalModule() &&1579 isa<FunctionDecl>(Referenced))1580 return;1581 1582 Diag(PointOfInstantiation,1583 diag::warn_reference_tu_local_entity_in_other_tu)1584 << FD << Referenced1585 << Referenced->getOwningModule()->getTopLevelModuleName();1586 }).TraverseStmt(FD->getBody());1587 }1588}1589 1590void Sema::checkReferenceToTULocalFromOtherTU(1591 FunctionDecl *FD, SourceLocation PointOfInstantiation) {1592 // Checking if a declaration have any reference to TU-local entities in other1593 // TU is expensive. Try to avoid it as much as possible.1594 if (!FD || !HadImportedNamedModules)1595 return;1596 1597 PendingCheckReferenceForTULocal.push_back(1598 std::make_pair(FD, PointOfInstantiation));1599}1600