diff options
| author | 2019-01-27 16:42:12 +0000 | |
|---|---|---|
| committer | 2019-01-27 16:42:12 +0000 | |
| commit | b773203fb58f3ef282fb69c832d8710cab5bc82d (patch) | |
| tree | e75913f147570fbd75169647b144df85b88a038c /gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp | |
| parent | tweak errno in previous (diff) | |
| download | wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip | |
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp | 486 |
1 files changed, 296 insertions, 190 deletions
diff --git a/gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp b/gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp index b3ac10c5c5a..87749f74734 100644 --- a/gnu/llvm/tools/clang/lib/Lex/ModuleMap.cpp +++ b/gnu/llvm/tools/clang/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"); @@ -85,8 +103,8 @@ ModuleMap::headerKindToRole(Module::HeaderKind Kind) { llvm_unreachable("unknown header kind"); } -Module::ExportDecl -ModuleMap::resolveExport(Module *Mod, +Module::ExportDecl +ModuleMap::resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, bool Complain) const { // We may have just a wildcard. @@ -94,7 +112,7 @@ ModuleMap::resolveExport(Module *Mod, assert(Unresolved.Wildcard && "Invalid unresolved export"); return Module::ExportDecl(nullptr, true); } - + // Resolve the module-id. Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain); if (!Context) @@ -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) { @@ -143,19 +161,22 @@ static void appendSubframeworkPaths(Module *Mod, if (Mod->IsFramework) Paths.push_back(Mod->Name); } - + if (Paths.empty()) return; - + // Add Frameworks/Name.framework for each subframework. for (unsigned I = Paths.size() - 1; I != 0; --I) 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,15 +320,17 @@ 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) { - assert((!this->Target || this->Target == &Target) && + assert((!this->Target || this->Target == &Target) && "Improper target override"); 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,10 +525,10 @@ 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. + // Do not diagnose when we are not compiling a module. diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? diag::warn_non_modular_include_in_framework_module : diag::warn_non_modular_include_in_module; @@ -691,7 +732,7 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, if (IsUnavailable(Found)) return true; } - + // Infer a submodule with the same name as this header file. SmallString<32> NameBuf; StringRef Name = sanitizeFilenameAsIdentifier( @@ -704,18 +745,18 @@ ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, return IsUnavailable(Found); } - + SkippedDirs.push_back(Dir); - + // Retrieve our parent path. DirName = llvm::sys::path::parent_path(DirName); if (DirName.empty()) break; - + // Resolve the parent path to a directory entry. Dir = SourceMgr.getFileManager().getDirectory(DirName); } while (Dir); - + return false; } @@ -733,14 +774,14 @@ Module *ModuleMap::lookupModuleUnqualified(StringRef Name, if (Module *Sub = lookupModuleQualified(Name, Context)) return Sub; } - + return findModule(Name); } Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ if (!Context) return findModule(Name); - + return Context->findSubmodule(Name); } @@ -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) { @@ -850,7 +892,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, // Check whether we've already found this module. if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) return Mod; - + FileManager &FileMgr = SourceMgr.getFileManager(); // If the framework has a parent path from which we're allowed to infer @@ -911,7 +953,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); - + // FIXME: If there's no umbrella header, we could probably scan the // framework to load *everything*. But, it's not clear that this is a good // idea. @@ -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; @@ -940,14 +983,14 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, // The "Headers/" component of the name is implied because this is // a framework module. setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); - + // export * Result->Exports.push_back(Module::ExportDecl(nullptr, true)); // module * { export * } Result->InferSubmodules = true; Result->InferExportWildcard = true; - + // Look for subframeworks. std::error_code EC; SmallString<128> SubframeworksDirName @@ -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(); } @@ -1140,11 +1200,11 @@ void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { LLVM_DUMP_METHOD void ModuleMap::dump() { llvm::errs() << "Modules:"; - for (llvm::StringMap<Module *>::iterator M = Modules.begin(), - MEnd = Modules.end(); + for (llvm::StringMap<Module *>::iterator M = Modules.begin(), + MEnd = Modules.end(); M != MEnd; ++M) M->getValue()->print(llvm::errs(), 2); - + llvm::errs() << "Headers:"; for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); H != HEnd; ++H) { @@ -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, @@ -1239,7 +1299,7 @@ namespace clang { LSquare, RSquare } Kind; - + unsigned Location; unsigned StringLength; union { @@ -1249,16 +1309,16 @@ namespace clang { // If Kind == IntegerLiteral. uint64_t IntegerValue; }; - + void clear() { Kind = EndOfFile; Location = 0; StringLength = 0; StringData = nullptr; } - + bool is(TokenKind K) const { return Kind == K; } - + SourceLocation getLocation() const { return SourceLocation::getFromRawEncoding(Location); } @@ -1266,7 +1326,7 @@ namespace clang { uint64_t getInteger() const { return Kind == IntegerLiteral ? IntegerValue : 0; } - + StringRef getString() const { return Kind == IntegerLiteral ? StringRef() : StringRef(StringData, StringLength); @@ -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; } @@ -1408,7 +1475,7 @@ retry: case tok::eof: Tok.Kind = MMToken::EndOfFile; break; - + case tok::l_brace: Tok.Kind = MMToken::LBrace; break; @@ -1416,27 +1483,27 @@ retry: case tok::l_square: Tok.Kind = MMToken::LSquare; break; - + case tok::period: Tok.Kind = MMToken::Period; break; - + case tok::r_brace: Tok.Kind = MMToken::RBrace; break; - + case tok::r_square: Tok.Kind = MMToken::RSquare; break; - + case tok::star: Tok.Kind = MMToken::Star; break; - + case tok::exclaim: Tok.Kind = MMToken::Exclaim; break; - + case tok::string_literal: { if (LToken.hasUDSuffix()) { Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); @@ -1449,13 +1516,13 @@ retry: StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); if (StringLiteral.hadError) goto retry; - + // Copy the string literal into our string data allocator. unsigned Length = StringLiteral.GetStringLength(); char *Saved = StringData.Allocate<char>(Length + 1); memcpy(Saved, StringLiteral.GetString().data(), Length); Saved[Length] = 0; - + // Form the token. Tok.Kind = MMToken::StringLiteral; Tok.StringData = Saved; @@ -1481,7 +1548,7 @@ retry: Tok.IntegerValue = Value; break; } - + case tok::comment: goto retry; @@ -1509,7 +1576,7 @@ retry: HadError = true; goto retry; } - + return Result; } @@ -1524,14 +1591,14 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) { case MMToken::LBrace: if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) return; - + ++braceDepth; break; case MMToken::LSquare: if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) return; - + ++squareDepth; break; @@ -1554,12 +1621,12 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) { return; break; } - + consumeToken(); } while (true); } -/// \brief Parse a module-id. +/// Parse a module-id. /// /// module-id: /// identifier @@ -1576,33 +1643,33 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); return true; } - + if (!Tok.is(MMToken::Period)) break; - + consumeToken(); } while (true); - + return false; } 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,16 +1730,17 @@ 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 -/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] +/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] /// { module-member* } /// /// module-member: @@ -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,10 +1776,10 @@ void ModuleMapParser::parseModuleDecl() { // Parse 'framework' keyword, if present. if (Tok.is(MMToken::FrameworkKeyword)) { - consumeToken(); + FrameworkLoc = consumeToken(); Framework = true; - } - + } + // Parse 'module' keyword. if (!Tok.is(MMToken::ModuleKeyword)) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); @@ -1706,13 +1787,13 @@ 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. + // Parse it. if (Tok.is(MMToken::Star)) return parseInferredModuleDecl(Framework, Explicit); - + // Parse the module name. ModuleId Id; if (parseModuleId(Id)) { @@ -1724,7 +1805,7 @@ void ModuleMapParser::parseModuleDecl() { if (Id.size() > 1) { Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) << SourceRange(Id.front().second, Id.back().second); - + HadError = true; return; } @@ -1735,8 +1816,8 @@ void ModuleMapParser::parseModuleDecl() { ExplicitLoc = SourceLocation(); HadError = true; } - - Module *PreviousActiveModule = ActiveModule; + + Module *PreviousActiveModule = ActiveModule; if (Id.size() > 1) { // This module map defines a submodule. Go find the module of which it // is a submodule. @@ -1749,7 +1830,7 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule = Next; continue; } - + if (ActiveModule) { Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) << Id[I].first @@ -1768,10 +1849,10 @@ void ModuleMapParser::parseModuleDecl() { Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); } } - + StringRef ModuleName = Id.back().first; SourceLocation ModuleNameLoc = Id.back().second; - + // Parse the optional attribute list. Attributes Attrs; if (parseOptionalAttributes(Attrs)) @@ -1783,10 +1864,11 @@ void ModuleMapParser::parseModuleDecl() { << ModuleName; HadError = true; return; - } + } 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: @@ -1808,27 +1890,39 @@ void ModuleMapParser::parseModuleDecl() { else { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); - HadError = true; + HadError = true; } 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 { @@ -1889,7 +1986,7 @@ void ModuleMapParser::parseModuleDecl() { case MMToken::UseKeyword: parseUseDecl(); break; - + case MMToken::RequiresKeyword: parseRequiresDecl(); break; @@ -1926,7 +2023,7 @@ void ModuleMapParser::parseModuleDecl() { default: Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); consumeToken(); - break; + break; } } while (!Done); @@ -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 @@ -2136,7 +2233,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, // Parse the header name. if (!Tok.is(MMToken::StringLiteral)) { - Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) << "header"; HadError = true; return; @@ -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,14 +2323,14 @@ 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 void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { // Parse the directory name. if (!Tok.is(MMToken::StringLiteral)) { - Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) << "umbrella"; HadError = true; return; @@ -2235,7 +2338,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { std::string DirName = Tok.getString(); SourceLocation DirNameLoc = consumeToken(); - + // Check whether we already have an umbrella. if (ActiveModule->Umbrella) { Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) @@ -2254,7 +2357,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { llvm::sys::path::append(PathName, DirName); Dir = SourceMgr.getFileManager().getDirectory(PathName); } - + if (!Dir) { Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) << DirName; @@ -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 @@ -2310,43 +2413,43 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { void ModuleMapParser::parseExportDecl() { assert(Tok.is(MMToken::ExportKeyword)); SourceLocation ExportLoc = consumeToken(); - + // Parse the module-id with an optional wildcard at the end. ModuleId ParsedModuleId; bool Wildcard = false; do { // FIXME: Support string-literal module names here. if (Tok.is(MMToken::Identifier)) { - ParsedModuleId.push_back(std::make_pair(Tok.getString(), + ParsedModuleId.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); consumeToken(); - + if (Tok.is(MMToken::Period)) { consumeToken(); continue; - } - + } + break; } - + if(Tok.is(MMToken::Star)) { Wildcard = true; consumeToken(); break; } - + Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); HadError = true; return; } while (true); - - Module::UnresolvedExportDecl Unresolved = { - ExportLoc, ParsedModuleId, Wildcard + + Module::UnresolvedExportDecl Unresolved = { + ExportLoc, ParsedModuleId, Wildcard }; ActiveModule->UnresolvedExports.push_back(Unresolved); } -/// \brief Parse a module export_as declaration. +/// Parse a module export_as declaration. /// /// export-as-declaration: /// 'export_as' identifier @@ -2365,7 +2468,7 @@ void ModuleMapParser::parseExportAsDecl() { consumeToken(); return; } - + if (!ActiveModule->ExportAsModule.empty()) { if (ActiveModule->ExportAsModule == Tok.getString()) { Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) @@ -2376,12 +2479,14 @@ void ModuleMapParser::parseExportAsDecl() { << Tok.getString(); } } - + 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] @@ -2561,7 +2666,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); Failed = true; } - + // Check for redefinition of an inferred module. if (!Failed && ActiveModule->InferSubmodules) { Diags.Report(StarLoc, diag::err_mmap_inferred_redef); @@ -2616,7 +2721,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); HadError = true; return; - } + } SourceLocation LBraceLoc = consumeToken(); // Parse the body of the inferred submodule. @@ -2657,10 +2762,10 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { } consumeToken(); - if (Tok.is(MMToken::Star)) + if (Tok.is(MMToken::Star)) ActiveModule->InferExportWildcard = true; else - Diags.Report(Tok.getLocation(), + Diags.Report(Tok.getLocation(), diag::err_mmap_expected_export_wildcard); consumeToken(); break; @@ -2674,10 +2779,10 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) << (ActiveModule != nullptr); consumeToken(); - break; + break; } } while (!Done); - + if (Tok.is(MMToken::RBrace)) consumeToken(); else { @@ -2687,7 +2792,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { } } -/// \brief Parse optional attributes. +/// Parse optional attributes. /// /// attributes: /// attribute attributes @@ -2701,7 +2806,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { /// \returns true if an error occurred, false otherwise. bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { bool HadError = false; - + while (Tok.is(MMToken::LSquare)) { // Consume the '['. SourceLocation LSquareLoc = consumeToken(); @@ -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* @@ -2771,7 +2876,7 @@ bool ModuleMapParser::parseModuleMapFile() { switch (Tok.Kind) { case MMToken::EndOfFile: return HadError; - + case MMToken::ExplicitKeyword: case MMToken::ExternKeyword: case MMToken::ModuleKeyword: @@ -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; } |
