diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Lex/ModuleMap.cpp | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) |
Notes
Diffstat (limited to 'lib/Lex/ModuleMap.cpp')
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 310 |
1 files changed, 208 insertions, 102 deletions
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index b3ac10c5c5ae8..f048a73a8ccc2 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -54,6 +54,24 @@ using namespace clang; +void ModuleMap::resolveLinkAsDependencies(Module *Mod) { + auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name); + if (PendingLinkAs != PendingLinkAsModule.end()) { + for (auto &Name : PendingLinkAs->second) { + auto *M = findModule(Name.getKey()); + if (M) + M->UseExportAsModuleLinkName = true; + } + } +} + +void ModuleMap::addLinkAsDependency(Module *Mod) { + if (findModule(Mod->ExportAsModule)) + Mod->UseExportAsModuleLinkName = true; + else + PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name); +} + Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { switch ((int)Role) { default: llvm_unreachable("unknown header role"); @@ -133,7 +151,7 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, return Context; } -/// \brief Append to \p Paths the set of paths needed to get to the +/// Append to \p Paths the set of paths needed to get to the /// subframework in which the given module lives. static void appendSubframeworkPaths(Module *Mod, SmallVectorImpl<char> &Path) { @@ -152,10 +170,13 @@ static void appendSubframeworkPaths(Module *Mod, llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework"); } -const FileEntry * -ModuleMap::findHeader(Module *M, - const Module::UnresolvedHeaderDirective &Header, - SmallVectorImpl<char> &RelativePathName) { +const FileEntry *ModuleMap::findHeader( + Module *M, const Module::UnresolvedHeaderDirective &Header, + SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) { + // Search for the header file within the module's home directory. + auto *Directory = M->Directory; + SmallString<128> FullPathName(Directory->getName()); + auto GetFile = [&](StringRef Filename) -> const FileEntry * { auto *File = SourceMgr.getFileManager().getFile(Filename); if (!File || @@ -165,18 +186,8 @@ ModuleMap::findHeader(Module *M, return File; }; - if (llvm::sys::path::is_absolute(Header.FileName)) { - RelativePathName.clear(); - RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); - return GetFile(Header.FileName); - } - - // Search for the header file within the module's home directory. - auto *Directory = M->Directory; - SmallString<128> FullPathName(Directory->getName()); - unsigned FullPathLength = FullPathName.size(); - - if (M->isPartOfFramework()) { + auto GetFrameworkFile = [&]() -> const FileEntry * { + unsigned FullPathLength = FullPathName.size(); appendSubframeworkPaths(M, RelativePathName); unsigned RelativePathLength = RelativePathName.size(); @@ -201,18 +212,46 @@ ModuleMap::findHeader(Module *M, Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); return GetFile(FullPathName); + }; + + if (llvm::sys::path::is_absolute(Header.FileName)) { + RelativePathName.clear(); + RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); + return GetFile(Header.FileName); } + if (M->isPartOfFramework()) + return GetFrameworkFile(); + // Lookup for normal headers. llvm::sys::path::append(RelativePathName, Header.FileName); llvm::sys::path::append(FullPathName, RelativePathName); - return GetFile(FullPathName); + auto *NormalHdrFile = GetFile(FullPathName); + + if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) { + // The lack of 'framework' keyword in a module declaration it's a simple + // mistake we can diagnose when the header exists within the proper + // framework style path. + FullPathName.assign(Directory->getName()); + RelativePathName.clear(); + if (GetFrameworkFile()) { + Diags.Report(Header.FileNameLoc, + diag::warn_mmap_incomplete_framework_module_declaration) + << Header.FileName << M->getFullModuleName(); + NeedsFramework = true; + } + return nullptr; + } + + return NormalHdrFile; } void ModuleMap::resolveHeader(Module *Mod, - const Module::UnresolvedHeaderDirective &Header) { + const Module::UnresolvedHeaderDirective &Header, + bool &NeedsFramework) { SmallString<128> RelativePathName; - if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { + if (const FileEntry *File = + findHeader(Mod, Header, RelativePathName, NeedsFramework)) { if (Header.IsUmbrella) { const DirectoryEntry *UmbrellaDir = File->getDir(); if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) @@ -281,6 +320,8 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, ModuleMap::~ModuleMap() { for (auto &M : Modules) delete M.getValue(); + for (auto *M : ShadowModules) + delete M; } void ModuleMap::setTarget(const TargetInfo &Target) { @@ -289,7 +330,7 @@ void ModuleMap::setTarget(const TargetInfo &Target) { this->Target = &Target; } -/// \brief "Sanitize" a filename so that it can be used as an identifier. +/// "Sanitize" a filename so that it can be used as an identifier. static StringRef sanitizeFilenameAsIdentifier(StringRef Name, SmallVectorImpl<char> &Buffer) { if (Name.empty()) @@ -326,7 +367,7 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name, return Name; } -/// \brief Determine whether the given file name is the name of a builtin +/// Determine whether the given file name is the name of a builtin /// header, supplied by Clang to replace, override, or augment existing system /// headers. bool ModuleMap::isBuiltinHeader(StringRef FileName) { @@ -473,7 +514,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, // We have found a module, but we don't use it. if (NotUsed) { Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) - << RequestingModule->getFullModuleName() << Filename; + << RequestingModule->getTopLevelModule()->Name << Filename; return; } @@ -484,7 +525,7 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, if (LangOpts.ModulesStrictDeclUse) { Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) - << RequestingModule->getFullModuleName() << Filename; + << RequestingModule->getTopLevelModule()->Name << Filename; } else if (RequestingModule && RequestingModuleIsModuleInterface && LangOpts.isCompilingModule()) { // Do not diagnose when we are not compiling a module. @@ -751,7 +792,7 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, // Try to find an existing module with this name. if (Module *Sub = lookupModuleQualified(Name, Parent)) return std::make_pair(Sub, false); - + // Create a new module with this name. Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, IsExplicit, NumCreatedModules++); @@ -759,6 +800,7 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, if (LangOpts.CurrentModule == Name) SourceModule = Result; Modules[Name] = Result; + ModuleScopeIDs[Result] = CurrentModuleScopeID; } return std::make_pair(Result, true); } @@ -799,7 +841,7 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, return Result; } -/// \brief For a framework module, infer the framework against which we +/// For a framework module, infer the framework against which we /// should link. static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, FileManager &FileMgr) { @@ -927,6 +969,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, if (LangOpts.CurrentModule == ModuleName) SourceModule = Result; Modules[ModuleName] = Result; + ModuleScopeIDs[Result] = CurrentModuleScopeID; } Result->IsSystem |= Attrs.IsSystem; @@ -999,6 +1042,21 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, return Result; } +Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, + Module *ShadowingModule) { + + // Create a new module with this name. + Module *Result = + new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, + /*IsExplicit=*/false, NumCreatedModules++); + Result->ShadowingModule = ShadowingModule; + Result->IsAvailable = false; + ModuleScopeIDs[Result] = CurrentModuleScopeID; + ShadowModules.push_back(Result); + + return Result; +} + void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, Twine NameAsWritten) { Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); @@ -1019,7 +1077,8 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, } void ModuleMap::addUnresolvedHeader(Module *Mod, - Module::UnresolvedHeaderDirective Header) { + Module::UnresolvedHeaderDirective Header, + bool &NeedsFramework) { // If there is a builtin counterpart to this file, add it now so it can // wrap the system header. if (resolveAsBuiltinHeader(Mod, Header)) { @@ -1050,7 +1109,7 @@ void ModuleMap::addUnresolvedHeader(Module *Mod, // We don't have stat information or can't defer looking this file up. // Perform the lookup now. - resolveHeader(Mod, Header); + resolveHeader(Mod, Header, NeedsFramework); } void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { @@ -1070,10 +1129,11 @@ void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { } void ModuleMap::resolveHeaderDirectives(Module *Mod) const { + bool NeedsFramework = false; for (auto &Header : Mod->UnresolvedHeaders) // This operation is logically const; we're just changing how we represent // the header information for this file. - const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header); + const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework); Mod->UnresolvedHeaders.clear(); } @@ -1207,7 +1267,7 @@ bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { namespace clang { - /// \brief A token in a module map file. + /// A token in a module map file. struct MMToken { enum TokenKind { Comma, @@ -1277,37 +1337,40 @@ namespace clang { Lexer &L; SourceManager &SourceMgr; - /// \brief Default target information, used only for string literal + /// Default target information, used only for string literal /// parsing. const TargetInfo *Target; DiagnosticsEngine &Diags; ModuleMap ⤅ - /// \brief The current module map file. + /// The current module map file. const FileEntry *ModuleMapFile; - - /// \brief The directory that file names in this module map file should + + /// Source location of most recent parsed module declaration + SourceLocation CurrModuleDeclLoc; + + /// The directory that file names in this module map file should /// be resolved relative to. const DirectoryEntry *Directory; - /// \brief Whether this module map is in a system header directory. + /// Whether this module map is in a system header directory. bool IsSystem; - /// \brief Whether an error occurred. + /// Whether an error occurred. bool HadError = false; - /// \brief Stores string data for the various string literals referenced + /// Stores string data for the various string literals referenced /// during parsing. llvm::BumpPtrAllocator StringData; - /// \brief The current token. + /// The current token. MMToken Tok; - /// \brief The active module. + /// The active module. Module *ActiveModule = nullptr; - /// \brief Whether a module uses the 'requires excluded' hack to mark its + /// Whether a module uses the 'requires excluded' hack to mark its /// contents as 'textual'. /// /// On older Darwin SDK versions, 'requires excluded' is used to mark the @@ -1317,10 +1380,10 @@ namespace clang { /// 'textual' to match the original intent. llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; - /// \brief Consume the current token and return its location. + /// Consume the current token and return its location. SourceLocation consumeToken(); - - /// \brief Skip tokens until we reach the a token with the given kind + + /// Skip tokens until we reach the a token with the given kind /// (or the end of the file). void skipUntil(MMToken::TokenKind K); @@ -1340,25 +1403,29 @@ namespace clang { void parseConflict(); void parseInferredModuleDecl(bool Framework, bool Explicit); + /// Private modules are canonicalized as Foo_Private. Clang provides extra + /// module map search logic to find the appropriate private module when PCH + /// is used with implicit module maps. Warn when private modules are written + /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. + void diagnosePrivateModules(SourceLocation ExplicitLoc, + SourceLocation FrameworkLoc); + using Attributes = ModuleMap::Attributes; bool parseOptionalAttributes(Attributes &Attrs); public: - explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, - const TargetInfo *Target, - DiagnosticsEngine &Diags, - ModuleMap &Map, - const FileEntry *ModuleMapFile, - const DirectoryEntry *Directory, - bool IsSystem) + explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, + const TargetInfo *Target, DiagnosticsEngine &Diags, + ModuleMap &Map, const FileEntry *ModuleMapFile, + const DirectoryEntry *Directory, bool IsSystem) : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), ModuleMapFile(ModuleMapFile), Directory(Directory), IsSystem(IsSystem) { Tok.clear(); consumeToken(); } - + bool parseModuleMapFile(); bool terminatedByDirective() { return false; } @@ -1559,7 +1626,7 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) { } while (true); } -/// \brief Parse a module-id. +/// Parse a module-id. /// /// module-id: /// identifier @@ -1588,21 +1655,21 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) { namespace { - /// \brief Enumerates the known attributes. + /// Enumerates the known attributes. enum AttributeKind { - /// \brief An unknown attribute. + /// An unknown attribute. AT_unknown, - /// \brief The 'system' attribute. + /// The 'system' attribute. AT_system, - /// \brief The 'extern_c' attribute. + /// The 'extern_c' attribute. AT_extern_c, - /// \brief The 'exhaustive' attribute. + /// The 'exhaustive' attribute. AT_exhaustive, - /// \brief The 'no_undeclared_includes' attribute. + /// The 'no_undeclared_includes' attribute. AT_no_undeclared_includes }; @@ -1612,16 +1679,14 @@ namespace { /// module map search logic to find the appropriate private module when PCH /// is used with implicit module maps. Warn when private modules are written /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. -static void diagnosePrivateModules(const ModuleMap &Map, - DiagnosticsEngine &Diags, - const Module *ActiveModule) { - +void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, + SourceLocation FrameworkLoc) { auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, - const Module *M) { + const Module *M, SourceRange ReplLoc) { auto D = Diags.Report(ActiveModule->DefinitionLoc, diag::note_mmap_rename_top_level_private_module); D << BadName << M->Name; - D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, Canonical); + D << FixItHint::CreateReplacement(ReplLoc, Canonical); }; for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { @@ -1632,6 +1697,7 @@ static void diagnosePrivateModules(const ModuleMap &Map, SmallString<128> FullName(ActiveModule->getFullModuleName()); if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) continue; + SmallString<128> FixedPrivModDecl; SmallString<128> Canonical(M->Name); Canonical.append("_Private"); @@ -1641,7 +1707,20 @@ static void diagnosePrivateModules(const ModuleMap &Map, Diags.Report(ActiveModule->DefinitionLoc, diag::warn_mmap_mismatched_private_submodule) << FullName; - GenNoteAndFixIt(FullName, Canonical, M); + + SourceLocation FixItInitBegin = CurrModuleDeclLoc; + if (FrameworkLoc.isValid()) + FixItInitBegin = FrameworkLoc; + if (ExplicitLoc.isValid()) + FixItInitBegin = ExplicitLoc; + + if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) + FixedPrivModDecl.append("framework "); + FixedPrivModDecl.append("module "); + FixedPrivModDecl.append(Canonical); + + GenNoteAndFixIt(FullName, FixedPrivModDecl, M, + SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); continue; } @@ -1651,12 +1730,13 @@ static void diagnosePrivateModules(const ModuleMap &Map, Diags.Report(ActiveModule->DefinitionLoc, diag::warn_mmap_mismatched_private_module_name) << ActiveModule->Name; - GenNoteAndFixIt(ActiveModule->Name, Canonical, M); + GenNoteAndFixIt(ActiveModule->Name, Canonical, M, + SourceRange(ActiveModule->DefinitionLoc)); } } } -/// \brief Parse a module declaration. +/// Parse a module declaration. /// /// module-declaration: /// 'extern' 'module' module-id string-literal @@ -1684,6 +1764,7 @@ void ModuleMapParser::parseModuleDecl() { // Parse 'explicit' or 'framework' keyword, if present. SourceLocation ExplicitLoc; + SourceLocation FrameworkLoc; bool Explicit = false; bool Framework = false; @@ -1695,7 +1776,7 @@ void ModuleMapParser::parseModuleDecl() { // Parse 'framework' keyword, if present. if (Tok.is(MMToken::FrameworkKeyword)) { - consumeToken(); + FrameworkLoc = consumeToken(); Framework = true; } @@ -1706,7 +1787,7 @@ void ModuleMapParser::parseModuleDecl() { HadError = true; return; } - consumeToken(); // 'module' keyword + CurrModuleDeclLoc = consumeToken(); // 'module' keyword // If we have a wildcard for the module name, this is an inferred submodule. // Parse it. @@ -1787,6 +1868,7 @@ void ModuleMapParser::parseModuleDecl() { SourceLocation LBraceLoc = consumeToken(); // Determine whether this (sub)module has already been defined. + Module *ShadowingModule = nullptr; if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { // We might see a (re)definition of a module that we already have a // definition for in two cases: @@ -1812,23 +1894,35 @@ void ModuleMapParser::parseModuleDecl() { } return; } - - Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) - << ModuleName; - Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); - - // Skip the module definition. - skipUntil(MMToken::RBrace); - if (Tok.is(MMToken::RBrace)) - consumeToken(); - - HadError = true; - return; + + if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { + ShadowingModule = Existing; + } else { + // This is not a shawdowed module decl, it is an illegal redefinition. + Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) + << ModuleName; + Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); + + // Skip the module definition. + skipUntil(MMToken::RBrace); + if (Tok.is(MMToken::RBrace)) + consumeToken(); + + HadError = true; + return; + } } // Start defining this module. - ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, - Explicit).first; + if (ShadowingModule) { + ActiveModule = + Map.createShadowedModule(ModuleName, Framework, ShadowingModule); + } else { + ActiveModule = + Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) + .first; + } + ActiveModule->DefinitionLoc = ModuleNameLoc; if (Attrs.IsSystem || IsSystem) ActiveModule->IsSystem = true; @@ -1839,21 +1933,24 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule->NoUndeclaredIncludes = true; ActiveModule->Directory = Directory; + StringRef MapFileName(ModuleMapFile->getName()); + if (MapFileName.endswith("module.private.modulemap") || + MapFileName.endswith("module_private.map")) { + ActiveModule->ModuleMapIsPrivate = true; + } // Private modules named as FooPrivate, Foo.Private or similar are likely a // user error; provide warnings, notes and fixits to direct users to use // Foo_Private instead. SourceLocation StartLoc = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); - StringRef MapFileName(ModuleMapFile->getName()); if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, StartLoc) && !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, StartLoc) && - (MapFileName.endswith("module.private.modulemap") || - MapFileName.endswith("module_private.map"))) - diagnosePrivateModules(Map, Diags, ActiveModule); + ActiveModule->ModuleMapIsPrivate) + diagnosePrivateModules(ExplicitLoc, FrameworkLoc); bool Done = false; do { @@ -1958,7 +2055,7 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule = PreviousActiveModule; } -/// \brief Parse an extern module declaration. +/// Parse an extern module declaration. /// /// extern module-declaration: /// 'extern' 'module' module-id string-literal @@ -2036,7 +2133,7 @@ static bool shouldAddRequirement(Module *M, StringRef Feature, return true; } -/// \brief Parse a requires declaration. +/// Parse a requires declaration. /// /// requires-declaration: /// 'requires' feature-list @@ -2092,7 +2189,7 @@ void ModuleMapParser::parseRequiresDecl() { } while (true); } -/// \brief Parse a header declaration. +/// Parse a header declaration. /// /// header-declaration: /// 'textual'[opt] 'header' string-literal @@ -2212,7 +2309,13 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, } } - Map.addUnresolvedHeader(ActiveModule, std::move(Header)); + bool NeedsFramework = false; + Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); + + if (NeedsFramework && ActiveModule) + Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) + << ActiveModule->getFullModuleName() + << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); } static int compareModuleHeaders(const Module::Header *A, @@ -2220,7 +2323,7 @@ static int compareModuleHeaders(const Module::Header *A, return A->NameAsWritten.compare(B->NameAsWritten); } -/// \brief Parse an umbrella directory declaration. +/// Parse an umbrella directory declaration. /// /// umbrella-dir-declaration: /// umbrella string-literal @@ -2298,7 +2401,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { Map.setUmbrellaDir(ActiveModule, Dir, DirName); } -/// \brief Parse a module export declaration. +/// Parse a module export declaration. /// /// export-declaration: /// 'export' wildcard-module-id @@ -2346,7 +2449,7 @@ void ModuleMapParser::parseExportDecl() { ActiveModule->UnresolvedExports.push_back(Unresolved); } -/// \brief Parse a module export_as declaration. +/// Parse a module export_as declaration. /// /// export-as-declaration: /// 'export_as' identifier @@ -2378,10 +2481,12 @@ void ModuleMapParser::parseExportAsDecl() { } ActiveModule->ExportAsModule = Tok.getString(); + Map.addLinkAsDependency(ActiveModule); + consumeToken(); } -/// \brief Parse a module use declaration. +/// Parse a module use declaration. /// /// use-declaration: /// 'use' wildcard-module-id @@ -2398,7 +2503,7 @@ void ModuleMapParser::parseUseDecl() { ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); } -/// \brief Parse a link declaration. +/// Parse a link declaration. /// /// module-declaration: /// 'link' 'framework'[opt] string-literal @@ -2427,7 +2532,7 @@ void ModuleMapParser::parseLinkDecl() { IsFramework)); } -/// \brief Parse a configuration macro declaration. +/// Parse a configuration macro declaration. /// /// module-declaration: /// 'config_macros' attributes[opt] config-macro-list? @@ -2484,7 +2589,7 @@ void ModuleMapParser::parseConfigMacros() { } while (true); } -/// \brief Format a module-id into a string. +/// Format a module-id into a string. static std::string formatModuleId(const ModuleId &Id) { std::string result; { @@ -2500,7 +2605,7 @@ static std::string formatModuleId(const ModuleId &Id) { return result; } -/// \brief Parse a conflict declaration. +/// Parse a conflict declaration. /// /// module-declaration: /// 'conflict' module-id ',' string-literal @@ -2534,7 +2639,7 @@ void ModuleMapParser::parseConflict() { ActiveModule->UnresolvedConflicts.push_back(Conflict); } -/// \brief Parse an inferred module declaration (wildcard modules). +/// Parse an inferred module declaration (wildcard modules). /// /// module-declaration: /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] @@ -2687,7 +2792,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { } } -/// \brief Parse optional attributes. +/// Parse optional attributes. /// /// attributes: /// attribute attributes @@ -2762,7 +2867,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { return HadError; } -/// \brief Parse a module map file. +/// Parse a module map file. /// /// module-map-file: /// module-declaration* @@ -2854,5 +2959,6 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, // Notify callbacks that we parsed it. for (const auto &Cb : Callbacks) Cb->moduleMapFileRead(Start, *File, IsSystem); + return Result; } |