17330f729Sjoerg //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file defines the ModuleMap implementation, which describes the layout
107330f729Sjoerg // of a module as it relates to headers.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg
147330f729Sjoerg #include "clang/Lex/ModuleMap.h"
157330f729Sjoerg #include "clang/Basic/CharInfo.h"
167330f729Sjoerg #include "clang/Basic/Diagnostic.h"
177330f729Sjoerg #include "clang/Basic/FileManager.h"
187330f729Sjoerg #include "clang/Basic/LLVM.h"
197330f729Sjoerg #include "clang/Basic/LangOptions.h"
207330f729Sjoerg #include "clang/Basic/Module.h"
217330f729Sjoerg #include "clang/Basic/SourceLocation.h"
227330f729Sjoerg #include "clang/Basic/SourceManager.h"
237330f729Sjoerg #include "clang/Basic/TargetInfo.h"
247330f729Sjoerg #include "clang/Lex/HeaderSearch.h"
257330f729Sjoerg #include "clang/Lex/HeaderSearchOptions.h"
267330f729Sjoerg #include "clang/Lex/LexDiagnostic.h"
277330f729Sjoerg #include "clang/Lex/Lexer.h"
287330f729Sjoerg #include "clang/Lex/LiteralSupport.h"
297330f729Sjoerg #include "clang/Lex/Token.h"
307330f729Sjoerg #include "llvm/ADT/DenseMap.h"
317330f729Sjoerg #include "llvm/ADT/None.h"
327330f729Sjoerg #include "llvm/ADT/STLExtras.h"
337330f729Sjoerg #include "llvm/ADT/SmallPtrSet.h"
347330f729Sjoerg #include "llvm/ADT/SmallString.h"
357330f729Sjoerg #include "llvm/ADT/SmallVector.h"
367330f729Sjoerg #include "llvm/ADT/StringMap.h"
377330f729Sjoerg #include "llvm/ADT/StringRef.h"
387330f729Sjoerg #include "llvm/ADT/StringSwitch.h"
397330f729Sjoerg #include "llvm/Support/Allocator.h"
407330f729Sjoerg #include "llvm/Support/Compiler.h"
417330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
427330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
437330f729Sjoerg #include "llvm/Support/Path.h"
447330f729Sjoerg #include "llvm/Support/VirtualFileSystem.h"
457330f729Sjoerg #include "llvm/Support/raw_ostream.h"
467330f729Sjoerg #include <algorithm>
477330f729Sjoerg #include <cassert>
487330f729Sjoerg #include <cstdint>
497330f729Sjoerg #include <cstring>
507330f729Sjoerg #include <string>
517330f729Sjoerg #include <system_error>
527330f729Sjoerg #include <utility>
537330f729Sjoerg
547330f729Sjoerg using namespace clang;
557330f729Sjoerg
anchor()567330f729Sjoerg void ModuleMapCallbacks::anchor() {}
577330f729Sjoerg
resolveLinkAsDependencies(Module * Mod)587330f729Sjoerg void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
597330f729Sjoerg auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
607330f729Sjoerg if (PendingLinkAs != PendingLinkAsModule.end()) {
617330f729Sjoerg for (auto &Name : PendingLinkAs->second) {
627330f729Sjoerg auto *M = findModule(Name.getKey());
637330f729Sjoerg if (M)
647330f729Sjoerg M->UseExportAsModuleLinkName = true;
657330f729Sjoerg }
667330f729Sjoerg }
677330f729Sjoerg }
687330f729Sjoerg
addLinkAsDependency(Module * Mod)697330f729Sjoerg void ModuleMap::addLinkAsDependency(Module *Mod) {
707330f729Sjoerg if (findModule(Mod->ExportAsModule))
717330f729Sjoerg Mod->UseExportAsModuleLinkName = true;
727330f729Sjoerg else
737330f729Sjoerg PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
747330f729Sjoerg }
757330f729Sjoerg
headerRoleToKind(ModuleHeaderRole Role)767330f729Sjoerg Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
777330f729Sjoerg switch ((int)Role) {
787330f729Sjoerg default: llvm_unreachable("unknown header role");
797330f729Sjoerg case NormalHeader:
807330f729Sjoerg return Module::HK_Normal;
817330f729Sjoerg case PrivateHeader:
827330f729Sjoerg return Module::HK_Private;
837330f729Sjoerg case TextualHeader:
847330f729Sjoerg return Module::HK_Textual;
857330f729Sjoerg case PrivateHeader | TextualHeader:
867330f729Sjoerg return Module::HK_PrivateTextual;
877330f729Sjoerg }
887330f729Sjoerg }
897330f729Sjoerg
907330f729Sjoerg ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)917330f729Sjoerg ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
927330f729Sjoerg switch ((int)Kind) {
937330f729Sjoerg case Module::HK_Normal:
947330f729Sjoerg return NormalHeader;
957330f729Sjoerg case Module::HK_Private:
967330f729Sjoerg return PrivateHeader;
977330f729Sjoerg case Module::HK_Textual:
987330f729Sjoerg return TextualHeader;
997330f729Sjoerg case Module::HK_PrivateTextual:
1007330f729Sjoerg return ModuleHeaderRole(PrivateHeader | TextualHeader);
1017330f729Sjoerg case Module::HK_Excluded:
1027330f729Sjoerg llvm_unreachable("unexpected header kind");
1037330f729Sjoerg }
1047330f729Sjoerg llvm_unreachable("unknown header kind");
1057330f729Sjoerg }
1067330f729Sjoerg
1077330f729Sjoerg Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const1087330f729Sjoerg ModuleMap::resolveExport(Module *Mod,
1097330f729Sjoerg const Module::UnresolvedExportDecl &Unresolved,
1107330f729Sjoerg bool Complain) const {
1117330f729Sjoerg // We may have just a wildcard.
1127330f729Sjoerg if (Unresolved.Id.empty()) {
1137330f729Sjoerg assert(Unresolved.Wildcard && "Invalid unresolved export");
1147330f729Sjoerg return Module::ExportDecl(nullptr, true);
1157330f729Sjoerg }
1167330f729Sjoerg
1177330f729Sjoerg // Resolve the module-id.
1187330f729Sjoerg Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
1197330f729Sjoerg if (!Context)
1207330f729Sjoerg return {};
1217330f729Sjoerg
1227330f729Sjoerg return Module::ExportDecl(Context, Unresolved.Wildcard);
1237330f729Sjoerg }
1247330f729Sjoerg
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const1257330f729Sjoerg Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
1267330f729Sjoerg bool Complain) const {
1277330f729Sjoerg // Find the starting module.
1287330f729Sjoerg Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1297330f729Sjoerg if (!Context) {
1307330f729Sjoerg if (Complain)
1317330f729Sjoerg Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
1327330f729Sjoerg << Id[0].first << Mod->getFullModuleName();
1337330f729Sjoerg
1347330f729Sjoerg return nullptr;
1357330f729Sjoerg }
1367330f729Sjoerg
1377330f729Sjoerg // Dig into the module path.
1387330f729Sjoerg for (unsigned I = 1, N = Id.size(); I != N; ++I) {
1397330f729Sjoerg Module *Sub = lookupModuleQualified(Id[I].first, Context);
1407330f729Sjoerg if (!Sub) {
1417330f729Sjoerg if (Complain)
1427330f729Sjoerg Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1437330f729Sjoerg << Id[I].first << Context->getFullModuleName()
1447330f729Sjoerg << SourceRange(Id[0].second, Id[I-1].second);
1457330f729Sjoerg
1467330f729Sjoerg return nullptr;
1477330f729Sjoerg }
1487330f729Sjoerg
1497330f729Sjoerg Context = Sub;
1507330f729Sjoerg }
1517330f729Sjoerg
1527330f729Sjoerg return Context;
1537330f729Sjoerg }
1547330f729Sjoerg
1557330f729Sjoerg /// Append to \p Paths the set of paths needed to get to the
1567330f729Sjoerg /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)1577330f729Sjoerg static void appendSubframeworkPaths(Module *Mod,
1587330f729Sjoerg SmallVectorImpl<char> &Path) {
1597330f729Sjoerg // Collect the framework names from the given module to the top-level module.
1607330f729Sjoerg SmallVector<StringRef, 2> Paths;
1617330f729Sjoerg for (; Mod; Mod = Mod->Parent) {
1627330f729Sjoerg if (Mod->IsFramework)
1637330f729Sjoerg Paths.push_back(Mod->Name);
1647330f729Sjoerg }
1657330f729Sjoerg
1667330f729Sjoerg if (Paths.empty())
1677330f729Sjoerg return;
1687330f729Sjoerg
1697330f729Sjoerg // Add Frameworks/Name.framework for each subframework.
1707330f729Sjoerg for (unsigned I = Paths.size() - 1; I != 0; --I)
1717330f729Sjoerg llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1727330f729Sjoerg }
1737330f729Sjoerg
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)174*e038c9c4Sjoerg Optional<FileEntryRef> ModuleMap::findHeader(
1757330f729Sjoerg Module *M, const Module::UnresolvedHeaderDirective &Header,
1767330f729Sjoerg SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1777330f729Sjoerg // Search for the header file within the module's home directory.
1787330f729Sjoerg auto *Directory = M->Directory;
1797330f729Sjoerg SmallString<128> FullPathName(Directory->getName());
1807330f729Sjoerg
181*e038c9c4Sjoerg auto GetFile = [&](StringRef Filename) -> Optional<FileEntryRef> {
182*e038c9c4Sjoerg auto File =
183*e038c9c4Sjoerg expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
184*e038c9c4Sjoerg if (!File || (Header.Size && File->getSize() != *Header.Size) ||
185*e038c9c4Sjoerg (Header.ModTime && File->getModificationTime() != *Header.ModTime))
186*e038c9c4Sjoerg return None;
1877330f729Sjoerg return *File;
1887330f729Sjoerg };
1897330f729Sjoerg
190*e038c9c4Sjoerg auto GetFrameworkFile = [&]() -> Optional<FileEntryRef> {
1917330f729Sjoerg unsigned FullPathLength = FullPathName.size();
1927330f729Sjoerg appendSubframeworkPaths(M, RelativePathName);
1937330f729Sjoerg unsigned RelativePathLength = RelativePathName.size();
1947330f729Sjoerg
1957330f729Sjoerg // Check whether this file is in the public headers.
1967330f729Sjoerg llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1977330f729Sjoerg llvm::sys::path::append(FullPathName, RelativePathName);
198*e038c9c4Sjoerg if (auto File = GetFile(FullPathName))
1997330f729Sjoerg return File;
2007330f729Sjoerg
2017330f729Sjoerg // Check whether this file is in the private headers.
2027330f729Sjoerg // Ideally, private modules in the form 'FrameworkName.Private' should
2037330f729Sjoerg // be defined as 'module FrameworkName.Private', and not as
2047330f729Sjoerg // 'framework module FrameworkName.Private', since a 'Private.Framework'
2057330f729Sjoerg // does not usually exist. However, since both are currently widely used
2067330f729Sjoerg // for private modules, make sure we find the right path in both cases.
2077330f729Sjoerg if (M->IsFramework && M->Name == "Private")
2087330f729Sjoerg RelativePathName.clear();
2097330f729Sjoerg else
2107330f729Sjoerg RelativePathName.resize(RelativePathLength);
2117330f729Sjoerg FullPathName.resize(FullPathLength);
2127330f729Sjoerg llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2137330f729Sjoerg Header.FileName);
2147330f729Sjoerg llvm::sys::path::append(FullPathName, RelativePathName);
2157330f729Sjoerg return GetFile(FullPathName);
2167330f729Sjoerg };
2177330f729Sjoerg
2187330f729Sjoerg if (llvm::sys::path::is_absolute(Header.FileName)) {
2197330f729Sjoerg RelativePathName.clear();
2207330f729Sjoerg RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2217330f729Sjoerg return GetFile(Header.FileName);
2227330f729Sjoerg }
2237330f729Sjoerg
2247330f729Sjoerg if (M->isPartOfFramework())
2257330f729Sjoerg return GetFrameworkFile();
2267330f729Sjoerg
2277330f729Sjoerg // Lookup for normal headers.
2287330f729Sjoerg llvm::sys::path::append(RelativePathName, Header.FileName);
2297330f729Sjoerg llvm::sys::path::append(FullPathName, RelativePathName);
230*e038c9c4Sjoerg auto NormalHdrFile = GetFile(FullPathName);
2317330f729Sjoerg
232*e038c9c4Sjoerg if (!NormalHdrFile && Directory->getName().endswith(".framework")) {
2337330f729Sjoerg // The lack of 'framework' keyword in a module declaration it's a simple
2347330f729Sjoerg // mistake we can diagnose when the header exists within the proper
2357330f729Sjoerg // framework style path.
2367330f729Sjoerg FullPathName.assign(Directory->getName());
2377330f729Sjoerg RelativePathName.clear();
2387330f729Sjoerg if (GetFrameworkFile()) {
2397330f729Sjoerg Diags.Report(Header.FileNameLoc,
2407330f729Sjoerg diag::warn_mmap_incomplete_framework_module_declaration)
2417330f729Sjoerg << Header.FileName << M->getFullModuleName();
2427330f729Sjoerg NeedsFramework = true;
2437330f729Sjoerg }
244*e038c9c4Sjoerg return None;
2457330f729Sjoerg }
2467330f729Sjoerg
2477330f729Sjoerg return NormalHdrFile;
2487330f729Sjoerg }
2497330f729Sjoerg
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)2507330f729Sjoerg void ModuleMap::resolveHeader(Module *Mod,
2517330f729Sjoerg const Module::UnresolvedHeaderDirective &Header,
2527330f729Sjoerg bool &NeedsFramework) {
2537330f729Sjoerg SmallString<128> RelativePathName;
254*e038c9c4Sjoerg if (Optional<FileEntryRef> File =
2557330f729Sjoerg findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
2567330f729Sjoerg if (Header.IsUmbrella) {
257*e038c9c4Sjoerg const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
2587330f729Sjoerg if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
2597330f729Sjoerg Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2607330f729Sjoerg << UmbrellaMod->getFullModuleName();
2617330f729Sjoerg else
2627330f729Sjoerg // Record this umbrella header.
263*e038c9c4Sjoerg setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
2647330f729Sjoerg } else {
265*e038c9c4Sjoerg Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
266*e038c9c4Sjoerg *File};
2677330f729Sjoerg if (Header.Kind == Module::HK_Excluded)
2687330f729Sjoerg excludeHeader(Mod, H);
2697330f729Sjoerg else
2707330f729Sjoerg addHeader(Mod, H, headerKindToRole(Header.Kind));
2717330f729Sjoerg }
2727330f729Sjoerg } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
2737330f729Sjoerg // There's a builtin header but no corresponding on-disk header. Assume
2747330f729Sjoerg // this was supposed to modularize the builtin header alone.
2757330f729Sjoerg } else if (Header.Kind == Module::HK_Excluded) {
2767330f729Sjoerg // Ignore missing excluded header files. They're optional anyway.
2777330f729Sjoerg } else {
2787330f729Sjoerg // If we find a module that has a missing header, we mark this module as
2797330f729Sjoerg // unavailable and store the header directive for displaying diagnostics.
2807330f729Sjoerg Mod->MissingHeaders.push_back(Header);
2817330f729Sjoerg // A missing header with stat information doesn't make the module
2827330f729Sjoerg // unavailable; this keeps our behavior consistent as headers are lazily
2837330f729Sjoerg // resolved. (Such a module still can't be built though, except from
2847330f729Sjoerg // preprocessed source.)
2857330f729Sjoerg if (!Header.Size && !Header.ModTime)
286*e038c9c4Sjoerg Mod->markUnavailable(/*Unimportable=*/false);
2877330f729Sjoerg }
2887330f729Sjoerg }
2897330f729Sjoerg
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)2907330f729Sjoerg bool ModuleMap::resolveAsBuiltinHeader(
2917330f729Sjoerg Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
2927330f729Sjoerg if (Header.Kind == Module::HK_Excluded ||
2937330f729Sjoerg llvm::sys::path::is_absolute(Header.FileName) ||
2947330f729Sjoerg Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
2957330f729Sjoerg !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
2967330f729Sjoerg !isBuiltinHeader(Header.FileName))
2977330f729Sjoerg return false;
2987330f729Sjoerg
2997330f729Sjoerg // This is a system module with a top-level header. This header
3007330f729Sjoerg // may have a counterpart (or replacement) in the set of headers
3017330f729Sjoerg // supplied by Clang. Find that builtin header.
3027330f729Sjoerg SmallString<128> Path;
3037330f729Sjoerg llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
3047330f729Sjoerg auto File = SourceMgr.getFileManager().getFile(Path);
3057330f729Sjoerg if (!File)
3067330f729Sjoerg return false;
3077330f729Sjoerg
3087330f729Sjoerg auto Role = headerKindToRole(Header.Kind);
309*e038c9c4Sjoerg Module::Header H = {Header.FileName, std::string(Path.str()), *File};
3107330f729Sjoerg addHeader(Mod, H, Role);
3117330f729Sjoerg return true;
3127330f729Sjoerg }
3137330f729Sjoerg
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)3147330f729Sjoerg ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
3157330f729Sjoerg const LangOptions &LangOpts, const TargetInfo *Target,
3167330f729Sjoerg HeaderSearch &HeaderInfo)
3177330f729Sjoerg : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
3187330f729Sjoerg HeaderInfo(HeaderInfo) {
3197330f729Sjoerg MMapLangOpts.LineComment = true;
3207330f729Sjoerg }
3217330f729Sjoerg
~ModuleMap()3227330f729Sjoerg ModuleMap::~ModuleMap() {
3237330f729Sjoerg for (auto &M : Modules)
3247330f729Sjoerg delete M.getValue();
3257330f729Sjoerg for (auto *M : ShadowModules)
3267330f729Sjoerg delete M;
3277330f729Sjoerg }
3287330f729Sjoerg
setTarget(const TargetInfo & Target)3297330f729Sjoerg void ModuleMap::setTarget(const TargetInfo &Target) {
3307330f729Sjoerg assert((!this->Target || this->Target == &Target) &&
3317330f729Sjoerg "Improper target override");
3327330f729Sjoerg this->Target = &Target;
3337330f729Sjoerg }
3347330f729Sjoerg
3357330f729Sjoerg /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)3367330f729Sjoerg static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
3377330f729Sjoerg SmallVectorImpl<char> &Buffer) {
3387330f729Sjoerg if (Name.empty())
3397330f729Sjoerg return Name;
3407330f729Sjoerg
3417330f729Sjoerg if (!isValidIdentifier(Name)) {
3427330f729Sjoerg // If we don't already have something with the form of an identifier,
3437330f729Sjoerg // create a buffer with the sanitized name.
3447330f729Sjoerg Buffer.clear();
3457330f729Sjoerg if (isDigit(Name[0]))
3467330f729Sjoerg Buffer.push_back('_');
3477330f729Sjoerg Buffer.reserve(Buffer.size() + Name.size());
3487330f729Sjoerg for (unsigned I = 0, N = Name.size(); I != N; ++I) {
3497330f729Sjoerg if (isIdentifierBody(Name[I]))
3507330f729Sjoerg Buffer.push_back(Name[I]);
3517330f729Sjoerg else
3527330f729Sjoerg Buffer.push_back('_');
3537330f729Sjoerg }
3547330f729Sjoerg
3557330f729Sjoerg Name = StringRef(Buffer.data(), Buffer.size());
3567330f729Sjoerg }
3577330f729Sjoerg
3587330f729Sjoerg while (llvm::StringSwitch<bool>(Name)
3597330f729Sjoerg #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
3607330f729Sjoerg #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
3617330f729Sjoerg #include "clang/Basic/TokenKinds.def"
3627330f729Sjoerg .Default(false)) {
3637330f729Sjoerg if (Name.data() != Buffer.data())
3647330f729Sjoerg Buffer.append(Name.begin(), Name.end());
3657330f729Sjoerg Buffer.push_back('_');
3667330f729Sjoerg Name = StringRef(Buffer.data(), Buffer.size());
3677330f729Sjoerg }
3687330f729Sjoerg
3697330f729Sjoerg return Name;
3707330f729Sjoerg }
3717330f729Sjoerg
3727330f729Sjoerg /// Determine whether the given file name is the name of a builtin
3737330f729Sjoerg /// header, supplied by Clang to replace, override, or augment existing system
3747330f729Sjoerg /// headers.
isBuiltinHeader(StringRef FileName)3757330f729Sjoerg bool ModuleMap::isBuiltinHeader(StringRef FileName) {
3767330f729Sjoerg return llvm::StringSwitch<bool>(FileName)
3777330f729Sjoerg .Case("float.h", true)
3787330f729Sjoerg .Case("iso646.h", true)
3797330f729Sjoerg .Case("limits.h", true)
3807330f729Sjoerg .Case("stdalign.h", true)
3817330f729Sjoerg .Case("stdarg.h", true)
3827330f729Sjoerg .Case("stdatomic.h", true)
3837330f729Sjoerg .Case("stdbool.h", true)
3847330f729Sjoerg .Case("stddef.h", true)
3857330f729Sjoerg .Case("stdint.h", true)
3867330f729Sjoerg .Case("tgmath.h", true)
3877330f729Sjoerg .Case("unwind.h", true)
3887330f729Sjoerg .Default(false);
3897330f729Sjoerg }
3907330f729Sjoerg
isBuiltinHeader(const FileEntry * File)391*e038c9c4Sjoerg bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
392*e038c9c4Sjoerg return File->getDir() == BuiltinIncludeDir &&
393*e038c9c4Sjoerg ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
394*e038c9c4Sjoerg }
395*e038c9c4Sjoerg
3967330f729Sjoerg ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)3977330f729Sjoerg ModuleMap::findKnownHeader(const FileEntry *File) {
3987330f729Sjoerg resolveHeaderDirectives(File);
3997330f729Sjoerg HeadersMap::iterator Known = Headers.find(File);
4007330f729Sjoerg if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
401*e038c9c4Sjoerg Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
4027330f729Sjoerg HeaderInfo.loadTopLevelSystemModules();
4037330f729Sjoerg return Headers.find(File);
4047330f729Sjoerg }
4057330f729Sjoerg return Known;
4067330f729Sjoerg }
4077330f729Sjoerg
4087330f729Sjoerg ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)4097330f729Sjoerg ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4107330f729Sjoerg SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
4117330f729Sjoerg if (UmbrellaDirs.empty())
4127330f729Sjoerg return {};
4137330f729Sjoerg
4147330f729Sjoerg const DirectoryEntry *Dir = File->getDir();
4157330f729Sjoerg assert(Dir && "file in no directory");
4167330f729Sjoerg
4177330f729Sjoerg // Note: as an egregious but useful hack we use the real path here, because
4187330f729Sjoerg // frameworks moving from top-level frameworks to embedded frameworks tend
4197330f729Sjoerg // to be symlinked from the top-level location to the embedded location,
4207330f729Sjoerg // and we need to resolve lookups as if we had found the embedded location.
4217330f729Sjoerg StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4227330f729Sjoerg
4237330f729Sjoerg // Keep walking up the directory hierarchy, looking for a directory with
4247330f729Sjoerg // an umbrella header.
4257330f729Sjoerg do {
4267330f729Sjoerg auto KnownDir = UmbrellaDirs.find(Dir);
4277330f729Sjoerg if (KnownDir != UmbrellaDirs.end())
4287330f729Sjoerg return KnownHeader(KnownDir->second, NormalHeader);
4297330f729Sjoerg
4307330f729Sjoerg IntermediateDirs.push_back(Dir);
4317330f729Sjoerg
4327330f729Sjoerg // Retrieve our parent path.
4337330f729Sjoerg DirName = llvm::sys::path::parent_path(DirName);
4347330f729Sjoerg if (DirName.empty())
4357330f729Sjoerg break;
4367330f729Sjoerg
4377330f729Sjoerg // Resolve the parent path to a directory entry.
4387330f729Sjoerg if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
4397330f729Sjoerg Dir = *DirEntry;
4407330f729Sjoerg else
4417330f729Sjoerg Dir = nullptr;
4427330f729Sjoerg } while (Dir);
4437330f729Sjoerg return {};
4447330f729Sjoerg }
4457330f729Sjoerg
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)4467330f729Sjoerg static bool violatesPrivateInclude(Module *RequestingModule,
4477330f729Sjoerg const FileEntry *IncFileEnt,
4487330f729Sjoerg ModuleMap::KnownHeader Header) {
4497330f729Sjoerg #ifndef NDEBUG
4507330f729Sjoerg if (Header.getRole() & ModuleMap::PrivateHeader) {
4517330f729Sjoerg // Check for consistency between the module header role
4527330f729Sjoerg // as obtained from the lookup and as obtained from the module.
4537330f729Sjoerg // This check is not cheap, so enable it only for debugging.
4547330f729Sjoerg bool IsPrivate = false;
4557330f729Sjoerg SmallVectorImpl<Module::Header> *HeaderList[] = {
4567330f729Sjoerg &Header.getModule()->Headers[Module::HK_Private],
4577330f729Sjoerg &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4587330f729Sjoerg for (auto *Hs : HeaderList)
4597330f729Sjoerg IsPrivate |=
4607330f729Sjoerg std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4617330f729Sjoerg return H.Entry == IncFileEnt;
4627330f729Sjoerg }) != Hs->end();
4637330f729Sjoerg assert(IsPrivate && "inconsistent headers and roles");
4647330f729Sjoerg }
4657330f729Sjoerg #endif
4667330f729Sjoerg return !Header.isAccessibleFrom(RequestingModule);
4677330f729Sjoerg }
4687330f729Sjoerg
getTopLevelOrNull(Module * M)4697330f729Sjoerg static Module *getTopLevelOrNull(Module *M) {
4707330f729Sjoerg return M ? M->getTopLevelModule() : nullptr;
4717330f729Sjoerg }
4727330f729Sjoerg
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,const FileEntry * File)4737330f729Sjoerg void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4747330f729Sjoerg bool RequestingModuleIsModuleInterface,
4757330f729Sjoerg SourceLocation FilenameLoc,
4767330f729Sjoerg StringRef Filename,
4777330f729Sjoerg const FileEntry *File) {
4787330f729Sjoerg // No errors for indirect modules. This may be a bit of a problem for modules
4797330f729Sjoerg // with no source files.
4807330f729Sjoerg if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
4817330f729Sjoerg return;
4827330f729Sjoerg
4837330f729Sjoerg if (RequestingModule) {
4847330f729Sjoerg resolveUses(RequestingModule, /*Complain=*/false);
4857330f729Sjoerg resolveHeaderDirectives(RequestingModule);
4867330f729Sjoerg }
4877330f729Sjoerg
4887330f729Sjoerg bool Excluded = false;
4897330f729Sjoerg Module *Private = nullptr;
4907330f729Sjoerg Module *NotUsed = nullptr;
4917330f729Sjoerg
4927330f729Sjoerg HeadersMap::iterator Known = findKnownHeader(File);
4937330f729Sjoerg if (Known != Headers.end()) {
4947330f729Sjoerg for (const KnownHeader &Header : Known->second) {
4957330f729Sjoerg // Remember private headers for later printing of a diagnostic.
4967330f729Sjoerg if (violatesPrivateInclude(RequestingModule, File, Header)) {
4977330f729Sjoerg Private = Header.getModule();
4987330f729Sjoerg continue;
4997330f729Sjoerg }
5007330f729Sjoerg
5017330f729Sjoerg // If uses need to be specified explicitly, we are only allowed to return
5027330f729Sjoerg // modules that are explicitly used by the requesting module.
5037330f729Sjoerg if (RequestingModule && LangOpts.ModulesDeclUse &&
5047330f729Sjoerg !RequestingModule->directlyUses(Header.getModule())) {
5057330f729Sjoerg NotUsed = Header.getModule();
5067330f729Sjoerg continue;
5077330f729Sjoerg }
5087330f729Sjoerg
5097330f729Sjoerg // We have found a module that we can happily use.
5107330f729Sjoerg return;
5117330f729Sjoerg }
5127330f729Sjoerg
5137330f729Sjoerg Excluded = true;
5147330f729Sjoerg }
5157330f729Sjoerg
5167330f729Sjoerg // We have found a header, but it is private.
5177330f729Sjoerg if (Private) {
5187330f729Sjoerg Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
5197330f729Sjoerg << Filename;
5207330f729Sjoerg return;
5217330f729Sjoerg }
5227330f729Sjoerg
5237330f729Sjoerg // We have found a module, but we don't use it.
5247330f729Sjoerg if (NotUsed) {
5257330f729Sjoerg Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5267330f729Sjoerg << RequestingModule->getTopLevelModule()->Name << Filename;
5277330f729Sjoerg return;
5287330f729Sjoerg }
5297330f729Sjoerg
5307330f729Sjoerg if (Excluded || isHeaderInUmbrellaDirs(File))
5317330f729Sjoerg return;
5327330f729Sjoerg
5337330f729Sjoerg // At this point, only non-modular includes remain.
5347330f729Sjoerg
5357330f729Sjoerg if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
5367330f729Sjoerg Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5377330f729Sjoerg << RequestingModule->getTopLevelModule()->Name << Filename;
5387330f729Sjoerg } else if (RequestingModule && RequestingModuleIsModuleInterface &&
5397330f729Sjoerg LangOpts.isCompilingModule()) {
5407330f729Sjoerg // Do not diagnose when we are not compiling a module.
5417330f729Sjoerg diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
5427330f729Sjoerg diag::warn_non_modular_include_in_framework_module :
5437330f729Sjoerg diag::warn_non_modular_include_in_module;
5447330f729Sjoerg Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
5457330f729Sjoerg << File->getName();
5467330f729Sjoerg }
5477330f729Sjoerg }
5487330f729Sjoerg
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)5497330f729Sjoerg static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
5507330f729Sjoerg const ModuleMap::KnownHeader &Old) {
5517330f729Sjoerg // Prefer available modules.
552*e038c9c4Sjoerg // FIXME: Considering whether the module is available rather than merely
553*e038c9c4Sjoerg // importable is non-hermetic and can result in surprising behavior for
554*e038c9c4Sjoerg // prebuilt modules. Consider only checking for importability here.
5557330f729Sjoerg if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5567330f729Sjoerg return true;
5577330f729Sjoerg
5587330f729Sjoerg // Prefer a public header over a private header.
5597330f729Sjoerg if ((New.getRole() & ModuleMap::PrivateHeader) !=
5607330f729Sjoerg (Old.getRole() & ModuleMap::PrivateHeader))
5617330f729Sjoerg return !(New.getRole() & ModuleMap::PrivateHeader);
5627330f729Sjoerg
5637330f729Sjoerg // Prefer a non-textual header over a textual header.
5647330f729Sjoerg if ((New.getRole() & ModuleMap::TextualHeader) !=
5657330f729Sjoerg (Old.getRole() & ModuleMap::TextualHeader))
5667330f729Sjoerg return !(New.getRole() & ModuleMap::TextualHeader);
5677330f729Sjoerg
5687330f729Sjoerg // Don't have a reason to choose between these. Just keep the first one.
5697330f729Sjoerg return false;
5707330f729Sjoerg }
5717330f729Sjoerg
findModuleForHeader(const FileEntry * File,bool AllowTextual)5727330f729Sjoerg ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
5737330f729Sjoerg bool AllowTextual) {
5747330f729Sjoerg auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
5757330f729Sjoerg if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
5767330f729Sjoerg return {};
5777330f729Sjoerg return R;
5787330f729Sjoerg };
5797330f729Sjoerg
5807330f729Sjoerg HeadersMap::iterator Known = findKnownHeader(File);
5817330f729Sjoerg if (Known != Headers.end()) {
5827330f729Sjoerg ModuleMap::KnownHeader Result;
5837330f729Sjoerg // Iterate over all modules that 'File' is part of to find the best fit.
5847330f729Sjoerg for (KnownHeader &H : Known->second) {
5857330f729Sjoerg // Prefer a header from the source module over all others.
5867330f729Sjoerg if (H.getModule()->getTopLevelModule() == SourceModule)
5877330f729Sjoerg return MakeResult(H);
5887330f729Sjoerg if (!Result || isBetterKnownHeader(H, Result))
5897330f729Sjoerg Result = H;
5907330f729Sjoerg }
5917330f729Sjoerg return MakeResult(Result);
5927330f729Sjoerg }
5937330f729Sjoerg
5947330f729Sjoerg return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
5957330f729Sjoerg }
5967330f729Sjoerg
5977330f729Sjoerg ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry * File)5987330f729Sjoerg ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
5997330f729Sjoerg assert(!Headers.count(File) && "already have a module for this header");
6007330f729Sjoerg
6017330f729Sjoerg SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6027330f729Sjoerg KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6037330f729Sjoerg if (H) {
6047330f729Sjoerg Module *Result = H.getModule();
6057330f729Sjoerg
6067330f729Sjoerg // Search up the module stack until we find a module with an umbrella
6077330f729Sjoerg // directory.
6087330f729Sjoerg Module *UmbrellaModule = Result;
6097330f729Sjoerg while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
6107330f729Sjoerg UmbrellaModule = UmbrellaModule->Parent;
6117330f729Sjoerg
6127330f729Sjoerg if (UmbrellaModule->InferSubmodules) {
6137330f729Sjoerg const FileEntry *UmbrellaModuleMap =
6147330f729Sjoerg getModuleMapFileForUniquing(UmbrellaModule);
6157330f729Sjoerg
6167330f729Sjoerg // Infer submodules for each of the directories we found between
6177330f729Sjoerg // the directory of the umbrella header and the directory where
6187330f729Sjoerg // the actual header is located.
6197330f729Sjoerg bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6207330f729Sjoerg
6217330f729Sjoerg for (unsigned I = SkippedDirs.size(); I != 0; --I) {
6227330f729Sjoerg // Find or create the module that corresponds to this directory name.
6237330f729Sjoerg SmallString<32> NameBuf;
6247330f729Sjoerg StringRef Name = sanitizeFilenameAsIdentifier(
6257330f729Sjoerg llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6267330f729Sjoerg Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6277330f729Sjoerg Explicit).first;
6287330f729Sjoerg InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6297330f729Sjoerg Result->IsInferred = true;
6307330f729Sjoerg
6317330f729Sjoerg // Associate the module and the directory.
6327330f729Sjoerg UmbrellaDirs[SkippedDirs[I-1]] = Result;
6337330f729Sjoerg
6347330f729Sjoerg // If inferred submodules export everything they import, add a
6357330f729Sjoerg // wildcard to the set of exports.
6367330f729Sjoerg if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6377330f729Sjoerg Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6387330f729Sjoerg }
6397330f729Sjoerg
6407330f729Sjoerg // Infer a submodule with the same name as this header file.
6417330f729Sjoerg SmallString<32> NameBuf;
6427330f729Sjoerg StringRef Name = sanitizeFilenameAsIdentifier(
6437330f729Sjoerg llvm::sys::path::stem(File->getName()), NameBuf);
6447330f729Sjoerg Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6457330f729Sjoerg Explicit).first;
6467330f729Sjoerg InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6477330f729Sjoerg Result->IsInferred = true;
6487330f729Sjoerg Result->addTopHeader(File);
6497330f729Sjoerg
6507330f729Sjoerg // If inferred submodules export everything they import, add a
6517330f729Sjoerg // wildcard to the set of exports.
6527330f729Sjoerg if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6537330f729Sjoerg Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6547330f729Sjoerg } else {
6557330f729Sjoerg // Record each of the directories we stepped through as being part of
6567330f729Sjoerg // the module we found, since the umbrella header covers them all.
6577330f729Sjoerg for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
6587330f729Sjoerg UmbrellaDirs[SkippedDirs[I]] = Result;
6597330f729Sjoerg }
6607330f729Sjoerg
6617330f729Sjoerg KnownHeader Header(Result, NormalHeader);
6627330f729Sjoerg Headers[File].push_back(Header);
6637330f729Sjoerg return Header;
6647330f729Sjoerg }
6657330f729Sjoerg
6667330f729Sjoerg return {};
6677330f729Sjoerg }
6687330f729Sjoerg
6697330f729Sjoerg ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File)670*e038c9c4Sjoerg ModuleMap::findAllModulesForHeader(const FileEntry *File) {
671*e038c9c4Sjoerg HeadersMap::iterator Known = findKnownHeader(File);
672*e038c9c4Sjoerg if (Known != Headers.end())
673*e038c9c4Sjoerg return Known->second;
674*e038c9c4Sjoerg
675*e038c9c4Sjoerg if (findOrCreateModuleForHeaderInUmbrellaDir(File))
676*e038c9c4Sjoerg return Headers.find(File)->second;
677*e038c9c4Sjoerg
678*e038c9c4Sjoerg return None;
679*e038c9c4Sjoerg }
680*e038c9c4Sjoerg
681*e038c9c4Sjoerg ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(const FileEntry * File) const682*e038c9c4Sjoerg ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
683*e038c9c4Sjoerg // FIXME: Is this necessary?
6847330f729Sjoerg resolveHeaderDirectives(File);
6857330f729Sjoerg auto It = Headers.find(File);
6867330f729Sjoerg if (It == Headers.end())
6877330f729Sjoerg return None;
6887330f729Sjoerg return It->second;
6897330f729Sjoerg }
6907330f729Sjoerg
isHeaderInUnavailableModule(const FileEntry * Header) const6917330f729Sjoerg bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
6927330f729Sjoerg return isHeaderUnavailableInModule(Header, nullptr);
6937330f729Sjoerg }
6947330f729Sjoerg
6957330f729Sjoerg bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const6967330f729Sjoerg ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
6977330f729Sjoerg const Module *RequestingModule) const {
6987330f729Sjoerg resolveHeaderDirectives(Header);
6997330f729Sjoerg HeadersMap::const_iterator Known = Headers.find(Header);
7007330f729Sjoerg if (Known != Headers.end()) {
7017330f729Sjoerg for (SmallVectorImpl<KnownHeader>::const_iterator
7027330f729Sjoerg I = Known->second.begin(),
7037330f729Sjoerg E = Known->second.end();
7047330f729Sjoerg I != E; ++I) {
7057330f729Sjoerg
7067330f729Sjoerg if (I->isAvailable() &&
7077330f729Sjoerg (!RequestingModule ||
7087330f729Sjoerg I->getModule()->isSubModuleOf(RequestingModule))) {
7097330f729Sjoerg // When no requesting module is available, the caller is looking if a
7107330f729Sjoerg // header is part a module by only looking into the module map. This is
7117330f729Sjoerg // done by warn_uncovered_module_header checks; don't consider textual
7127330f729Sjoerg // headers part of it in this mode, otherwise we get misleading warnings
7137330f729Sjoerg // that a umbrella header is not including a textual header.
7147330f729Sjoerg if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
7157330f729Sjoerg continue;
7167330f729Sjoerg return false;
7177330f729Sjoerg }
7187330f729Sjoerg }
7197330f729Sjoerg return true;
7207330f729Sjoerg }
7217330f729Sjoerg
7227330f729Sjoerg const DirectoryEntry *Dir = Header->getDir();
7237330f729Sjoerg SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7247330f729Sjoerg StringRef DirName = Dir->getName();
7257330f729Sjoerg
7267330f729Sjoerg auto IsUnavailable = [&](const Module *M) {
7277330f729Sjoerg return !M->isAvailable() && (!RequestingModule ||
7287330f729Sjoerg M->isSubModuleOf(RequestingModule));
7297330f729Sjoerg };
7307330f729Sjoerg
7317330f729Sjoerg // Keep walking up the directory hierarchy, looking for a directory with
7327330f729Sjoerg // an umbrella header.
7337330f729Sjoerg do {
7347330f729Sjoerg llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7357330f729Sjoerg = UmbrellaDirs.find(Dir);
7367330f729Sjoerg if (KnownDir != UmbrellaDirs.end()) {
7377330f729Sjoerg Module *Found = KnownDir->second;
7387330f729Sjoerg if (IsUnavailable(Found))
7397330f729Sjoerg return true;
7407330f729Sjoerg
7417330f729Sjoerg // Search up the module stack until we find a module with an umbrella
7427330f729Sjoerg // directory.
7437330f729Sjoerg Module *UmbrellaModule = Found;
7447330f729Sjoerg while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7457330f729Sjoerg UmbrellaModule = UmbrellaModule->Parent;
7467330f729Sjoerg
7477330f729Sjoerg if (UmbrellaModule->InferSubmodules) {
7487330f729Sjoerg for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7497330f729Sjoerg // Find or create the module that corresponds to this directory name.
7507330f729Sjoerg SmallString<32> NameBuf;
7517330f729Sjoerg StringRef Name = sanitizeFilenameAsIdentifier(
7527330f729Sjoerg llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
7537330f729Sjoerg NameBuf);
7547330f729Sjoerg Found = lookupModuleQualified(Name, Found);
7557330f729Sjoerg if (!Found)
7567330f729Sjoerg return false;
7577330f729Sjoerg if (IsUnavailable(Found))
7587330f729Sjoerg return true;
7597330f729Sjoerg }
7607330f729Sjoerg
7617330f729Sjoerg // Infer a submodule with the same name as this header file.
7627330f729Sjoerg SmallString<32> NameBuf;
7637330f729Sjoerg StringRef Name = sanitizeFilenameAsIdentifier(
7647330f729Sjoerg llvm::sys::path::stem(Header->getName()),
7657330f729Sjoerg NameBuf);
7667330f729Sjoerg Found = lookupModuleQualified(Name, Found);
7677330f729Sjoerg if (!Found)
7687330f729Sjoerg return false;
7697330f729Sjoerg }
7707330f729Sjoerg
7717330f729Sjoerg return IsUnavailable(Found);
7727330f729Sjoerg }
7737330f729Sjoerg
7747330f729Sjoerg SkippedDirs.push_back(Dir);
7757330f729Sjoerg
7767330f729Sjoerg // Retrieve our parent path.
7777330f729Sjoerg DirName = llvm::sys::path::parent_path(DirName);
7787330f729Sjoerg if (DirName.empty())
7797330f729Sjoerg break;
7807330f729Sjoerg
7817330f729Sjoerg // Resolve the parent path to a directory entry.
7827330f729Sjoerg if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
7837330f729Sjoerg Dir = *DirEntry;
7847330f729Sjoerg else
7857330f729Sjoerg Dir = nullptr;
7867330f729Sjoerg } while (Dir);
7877330f729Sjoerg
7887330f729Sjoerg return false;
7897330f729Sjoerg }
7907330f729Sjoerg
findModule(StringRef Name) const7917330f729Sjoerg Module *ModuleMap::findModule(StringRef Name) const {
7927330f729Sjoerg llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
7937330f729Sjoerg if (Known != Modules.end())
7947330f729Sjoerg return Known->getValue();
7957330f729Sjoerg
7967330f729Sjoerg return nullptr;
7977330f729Sjoerg }
7987330f729Sjoerg
lookupModuleUnqualified(StringRef Name,Module * Context) const7997330f729Sjoerg Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
8007330f729Sjoerg Module *Context) const {
8017330f729Sjoerg for(; Context; Context = Context->Parent) {
8027330f729Sjoerg if (Module *Sub = lookupModuleQualified(Name, Context))
8037330f729Sjoerg return Sub;
8047330f729Sjoerg }
8057330f729Sjoerg
8067330f729Sjoerg return findModule(Name);
8077330f729Sjoerg }
8087330f729Sjoerg
lookupModuleQualified(StringRef Name,Module * Context) const8097330f729Sjoerg Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8107330f729Sjoerg if (!Context)
8117330f729Sjoerg return findModule(Name);
8127330f729Sjoerg
8137330f729Sjoerg return Context->findSubmodule(Name);
8147330f729Sjoerg }
8157330f729Sjoerg
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)8167330f729Sjoerg std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
8177330f729Sjoerg Module *Parent,
8187330f729Sjoerg bool IsFramework,
8197330f729Sjoerg bool IsExplicit) {
8207330f729Sjoerg // Try to find an existing module with this name.
8217330f729Sjoerg if (Module *Sub = lookupModuleQualified(Name, Parent))
8227330f729Sjoerg return std::make_pair(Sub, false);
8237330f729Sjoerg
8247330f729Sjoerg // Create a new module with this name.
8257330f729Sjoerg Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8267330f729Sjoerg IsExplicit, NumCreatedModules++);
8277330f729Sjoerg if (!Parent) {
8287330f729Sjoerg if (LangOpts.CurrentModule == Name)
8297330f729Sjoerg SourceModule = Result;
8307330f729Sjoerg Modules[Name] = Result;
8317330f729Sjoerg ModuleScopeIDs[Result] = CurrentModuleScopeID;
8327330f729Sjoerg }
8337330f729Sjoerg return std::make_pair(Result, true);
8347330f729Sjoerg }
8357330f729Sjoerg
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc)8367330f729Sjoerg Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
8377330f729Sjoerg PendingSubmodules.emplace_back(
8387330f729Sjoerg new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
8397330f729Sjoerg /*IsExplicit*/ true, NumCreatedModules++));
8407330f729Sjoerg PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
8417330f729Sjoerg return PendingSubmodules.back().get();
8427330f729Sjoerg }
8437330f729Sjoerg
8447330f729Sjoerg Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)8457330f729Sjoerg ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
8467330f729Sjoerg SourceLocation Loc) {
8477330f729Sjoerg auto *Result =
8487330f729Sjoerg new Module("<private>", Loc, Parent, /*IsFramework*/ false,
8497330f729Sjoerg /*IsExplicit*/ true, NumCreatedModules++);
8507330f729Sjoerg Result->Kind = Module::PrivateModuleFragment;
8517330f729Sjoerg return Result;
8527330f729Sjoerg }
8537330f729Sjoerg
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name,Module * GlobalModule)8547330f729Sjoerg Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
8557330f729Sjoerg StringRef Name,
8567330f729Sjoerg Module *GlobalModule) {
8577330f729Sjoerg assert(LangOpts.CurrentModule == Name && "module name mismatch");
8587330f729Sjoerg assert(!Modules[Name] && "redefining existing module");
8597330f729Sjoerg
8607330f729Sjoerg auto *Result =
8617330f729Sjoerg new Module(Name, Loc, nullptr, /*IsFramework*/ false,
8627330f729Sjoerg /*IsExplicit*/ false, NumCreatedModules++);
8637330f729Sjoerg Result->Kind = Module::ModuleInterfaceUnit;
8647330f729Sjoerg Modules[Name] = SourceModule = Result;
8657330f729Sjoerg
8667330f729Sjoerg // Reparent the current global module fragment as a submodule of this module.
8677330f729Sjoerg for (auto &Submodule : PendingSubmodules) {
8687330f729Sjoerg Submodule->setParent(Result);
8697330f729Sjoerg Submodule.release(); // now owned by parent
8707330f729Sjoerg }
8717330f729Sjoerg PendingSubmodules.clear();
8727330f729Sjoerg
8737330f729Sjoerg // Mark the main source file as being within the newly-created module so that
8747330f729Sjoerg // declarations and macros are properly visibility-restricted to it.
8757330f729Sjoerg auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
8767330f729Sjoerg assert(MainFile && "no input file for module interface");
8777330f729Sjoerg Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
8787330f729Sjoerg
8797330f729Sjoerg return Result;
8807330f729Sjoerg }
8817330f729Sjoerg
createHeaderModule(StringRef Name,ArrayRef<Module::Header> Headers)8827330f729Sjoerg Module *ModuleMap::createHeaderModule(StringRef Name,
8837330f729Sjoerg ArrayRef<Module::Header> Headers) {
8847330f729Sjoerg assert(LangOpts.CurrentModule == Name && "module name mismatch");
8857330f729Sjoerg assert(!Modules[Name] && "redefining existing module");
8867330f729Sjoerg
8877330f729Sjoerg auto *Result =
8887330f729Sjoerg new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
8897330f729Sjoerg /*IsExplicit*/ false, NumCreatedModules++);
8907330f729Sjoerg Result->Kind = Module::ModuleInterfaceUnit;
8917330f729Sjoerg Modules[Name] = SourceModule = Result;
8927330f729Sjoerg
8937330f729Sjoerg for (const Module::Header &H : Headers) {
8947330f729Sjoerg auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
8957330f729Sjoerg /*IsFramework*/ false,
8967330f729Sjoerg /*IsExplicit*/ true, NumCreatedModules++);
8977330f729Sjoerg // Header modules are implicitly 'export *'.
8987330f729Sjoerg M->Exports.push_back(Module::ExportDecl(nullptr, true));
8997330f729Sjoerg addHeader(M, H, NormalHeader);
9007330f729Sjoerg }
9017330f729Sjoerg
9027330f729Sjoerg return Result;
9037330f729Sjoerg }
9047330f729Sjoerg
9057330f729Sjoerg /// For a framework module, infer the framework against which we
9067330f729Sjoerg /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)9077330f729Sjoerg static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
9087330f729Sjoerg FileManager &FileMgr) {
9097330f729Sjoerg assert(Mod->IsFramework && "Can only infer linking for framework modules");
9107330f729Sjoerg assert(!Mod->isSubFramework() &&
9117330f729Sjoerg "Can only infer linking for top-level frameworks");
9127330f729Sjoerg
9137330f729Sjoerg SmallString<128> LibName;
9147330f729Sjoerg LibName += FrameworkDir->getName();
9157330f729Sjoerg llvm::sys::path::append(LibName, Mod->Name);
9167330f729Sjoerg
9177330f729Sjoerg // The library name of a framework has more than one possible extension since
9187330f729Sjoerg // the introduction of the text-based dynamic library format. We need to check
9197330f729Sjoerg // for both before we give up.
9207330f729Sjoerg for (const char *extension : {"", ".tbd"}) {
9217330f729Sjoerg llvm::sys::path::replace_extension(LibName, extension);
9227330f729Sjoerg if (FileMgr.getFile(LibName)) {
9237330f729Sjoerg Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
9247330f729Sjoerg /*IsFramework=*/true));
9257330f729Sjoerg return;
9267330f729Sjoerg }
9277330f729Sjoerg }
9287330f729Sjoerg }
9297330f729Sjoerg
inferFrameworkModule(const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)9307330f729Sjoerg Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
9317330f729Sjoerg bool IsSystem, Module *Parent) {
9327330f729Sjoerg Attributes Attrs;
9337330f729Sjoerg Attrs.IsSystem = IsSystem;
9347330f729Sjoerg return inferFrameworkModule(FrameworkDir, Attrs, Parent);
9357330f729Sjoerg }
9367330f729Sjoerg
inferFrameworkModule(const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)9377330f729Sjoerg Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
9387330f729Sjoerg Attributes Attrs, Module *Parent) {
9397330f729Sjoerg // Note: as an egregious but useful hack we use the real path here, because
9407330f729Sjoerg // we might be looking at an embedded framework that symlinks out to a
9417330f729Sjoerg // top-level framework, and we need to infer as if we were naming the
9427330f729Sjoerg // top-level framework.
9437330f729Sjoerg StringRef FrameworkDirName =
9447330f729Sjoerg SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
9457330f729Sjoerg
9467330f729Sjoerg // In case this is a case-insensitive filesystem, use the canonical
9477330f729Sjoerg // directory name as the ModuleName, since modules are case-sensitive.
9487330f729Sjoerg // FIXME: we should be able to give a fix-it hint for the correct spelling.
9497330f729Sjoerg SmallString<32> ModuleNameStorage;
9507330f729Sjoerg StringRef ModuleName = sanitizeFilenameAsIdentifier(
9517330f729Sjoerg llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
9527330f729Sjoerg
9537330f729Sjoerg // Check whether we've already found this module.
9547330f729Sjoerg if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
9557330f729Sjoerg return Mod;
9567330f729Sjoerg
9577330f729Sjoerg FileManager &FileMgr = SourceMgr.getFileManager();
9587330f729Sjoerg
9597330f729Sjoerg // If the framework has a parent path from which we're allowed to infer
9607330f729Sjoerg // a framework module, do so.
9617330f729Sjoerg const FileEntry *ModuleMapFile = nullptr;
9627330f729Sjoerg if (!Parent) {
9637330f729Sjoerg // Determine whether we're allowed to infer a module map.
9647330f729Sjoerg bool canInfer = false;
9657330f729Sjoerg if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9667330f729Sjoerg // Figure out the parent path.
9677330f729Sjoerg StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9687330f729Sjoerg if (auto ParentDir = FileMgr.getDirectory(Parent)) {
9697330f729Sjoerg // Check whether we have already looked into the parent directory
9707330f729Sjoerg // for a module map.
9717330f729Sjoerg llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9727330f729Sjoerg inferred = InferredDirectories.find(*ParentDir);
9737330f729Sjoerg if (inferred == InferredDirectories.end()) {
9747330f729Sjoerg // We haven't looked here before. Load a module map, if there is
9757330f729Sjoerg // one.
9767330f729Sjoerg bool IsFrameworkDir = Parent.endswith(".framework");
9777330f729Sjoerg if (const FileEntry *ModMapFile =
9787330f729Sjoerg HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
9797330f729Sjoerg parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
9807330f729Sjoerg inferred = InferredDirectories.find(*ParentDir);
9817330f729Sjoerg }
9827330f729Sjoerg
9837330f729Sjoerg if (inferred == InferredDirectories.end())
9847330f729Sjoerg inferred = InferredDirectories.insert(
9857330f729Sjoerg std::make_pair(*ParentDir, InferredDirectory())).first;
9867330f729Sjoerg }
9877330f729Sjoerg
9887330f729Sjoerg if (inferred->second.InferModules) {
9897330f729Sjoerg // We're allowed to infer for this directory, but make sure it's okay
9907330f729Sjoerg // to infer this particular module.
9917330f729Sjoerg StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9927330f729Sjoerg canInfer = std::find(inferred->second.ExcludedModules.begin(),
9937330f729Sjoerg inferred->second.ExcludedModules.end(),
9947330f729Sjoerg Name) == inferred->second.ExcludedModules.end();
9957330f729Sjoerg
9967330f729Sjoerg Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
9977330f729Sjoerg Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
9987330f729Sjoerg Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
9997330f729Sjoerg Attrs.NoUndeclaredIncludes |=
10007330f729Sjoerg inferred->second.Attrs.NoUndeclaredIncludes;
10017330f729Sjoerg ModuleMapFile = inferred->second.ModuleMapFile;
10027330f729Sjoerg }
10037330f729Sjoerg }
10047330f729Sjoerg }
10057330f729Sjoerg
10067330f729Sjoerg // If we're not allowed to infer a framework module, don't.
10077330f729Sjoerg if (!canInfer)
10087330f729Sjoerg return nullptr;
10097330f729Sjoerg } else
10107330f729Sjoerg ModuleMapFile = getModuleMapFileForUniquing(Parent);
10117330f729Sjoerg
10127330f729Sjoerg
10137330f729Sjoerg // Look for an umbrella header.
10147330f729Sjoerg SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
10157330f729Sjoerg llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
10167330f729Sjoerg auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
10177330f729Sjoerg
10187330f729Sjoerg // FIXME: If there's no umbrella header, we could probably scan the
10197330f729Sjoerg // framework to load *everything*. But, it's not clear that this is a good
10207330f729Sjoerg // idea.
10217330f729Sjoerg if (!UmbrellaHeader)
10227330f729Sjoerg return nullptr;
10237330f729Sjoerg
10247330f729Sjoerg Module *Result = new Module(ModuleName, SourceLocation(), Parent,
10257330f729Sjoerg /*IsFramework=*/true, /*IsExplicit=*/false,
10267330f729Sjoerg NumCreatedModules++);
10277330f729Sjoerg InferredModuleAllowedBy[Result] = ModuleMapFile;
10287330f729Sjoerg Result->IsInferred = true;
10297330f729Sjoerg if (!Parent) {
10307330f729Sjoerg if (LangOpts.CurrentModule == ModuleName)
10317330f729Sjoerg SourceModule = Result;
10327330f729Sjoerg Modules[ModuleName] = Result;
10337330f729Sjoerg ModuleScopeIDs[Result] = CurrentModuleScopeID;
10347330f729Sjoerg }
10357330f729Sjoerg
10367330f729Sjoerg Result->IsSystem |= Attrs.IsSystem;
10377330f729Sjoerg Result->IsExternC |= Attrs.IsExternC;
10387330f729Sjoerg Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
10397330f729Sjoerg Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10407330f729Sjoerg Result->Directory = FrameworkDir;
10417330f729Sjoerg
1042*e038c9c4Sjoerg // Chop off the first framework bit, as that is implied.
1043*e038c9c4Sjoerg StringRef RelativePath = UmbrellaName.str().substr(
1044*e038c9c4Sjoerg Result->getTopLevelModule()->Directory->getName().size());
1045*e038c9c4Sjoerg RelativePath = llvm::sys::path::relative_path(RelativePath);
1046*e038c9c4Sjoerg
10477330f729Sjoerg // umbrella header "umbrella-header-name"
1048*e038c9c4Sjoerg setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
10497330f729Sjoerg
10507330f729Sjoerg // export *
10517330f729Sjoerg Result->Exports.push_back(Module::ExportDecl(nullptr, true));
10527330f729Sjoerg
10537330f729Sjoerg // module * { export * }
10547330f729Sjoerg Result->InferSubmodules = true;
10557330f729Sjoerg Result->InferExportWildcard = true;
10567330f729Sjoerg
10577330f729Sjoerg // Look for subframeworks.
10587330f729Sjoerg std::error_code EC;
10597330f729Sjoerg SmallString<128> SubframeworksDirName
10607330f729Sjoerg = StringRef(FrameworkDir->getName());
10617330f729Sjoerg llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10627330f729Sjoerg llvm::sys::path::native(SubframeworksDirName);
10637330f729Sjoerg llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
10647330f729Sjoerg for (llvm::vfs::directory_iterator
10657330f729Sjoerg Dir = FS.dir_begin(SubframeworksDirName, EC),
10667330f729Sjoerg DirEnd;
10677330f729Sjoerg Dir != DirEnd && !EC; Dir.increment(EC)) {
10687330f729Sjoerg if (!StringRef(Dir->path()).endswith(".framework"))
10697330f729Sjoerg continue;
10707330f729Sjoerg
10717330f729Sjoerg if (auto SubframeworkDir =
10727330f729Sjoerg FileMgr.getDirectory(Dir->path())) {
10737330f729Sjoerg // Note: as an egregious but useful hack, we use the real path here and
10747330f729Sjoerg // check whether it is actually a subdirectory of the parent directory.
10757330f729Sjoerg // This will not be the case if the 'subframework' is actually a symlink
10767330f729Sjoerg // out to a top-level framework.
10777330f729Sjoerg StringRef SubframeworkDirName =
10787330f729Sjoerg FileMgr.getCanonicalName(*SubframeworkDir);
10797330f729Sjoerg bool FoundParent = false;
10807330f729Sjoerg do {
10817330f729Sjoerg // Get the parent directory name.
10827330f729Sjoerg SubframeworkDirName
10837330f729Sjoerg = llvm::sys::path::parent_path(SubframeworkDirName);
10847330f729Sjoerg if (SubframeworkDirName.empty())
10857330f729Sjoerg break;
10867330f729Sjoerg
10877330f729Sjoerg if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
10887330f729Sjoerg if (*SubDir == FrameworkDir) {
10897330f729Sjoerg FoundParent = true;
10907330f729Sjoerg break;
10917330f729Sjoerg }
10927330f729Sjoerg }
10937330f729Sjoerg } while (true);
10947330f729Sjoerg
10957330f729Sjoerg if (!FoundParent)
10967330f729Sjoerg continue;
10977330f729Sjoerg
10987330f729Sjoerg // FIXME: Do we want to warn about subframeworks without umbrella headers?
10997330f729Sjoerg inferFrameworkModule(*SubframeworkDir, Attrs, Result);
11007330f729Sjoerg }
11017330f729Sjoerg }
11027330f729Sjoerg
11037330f729Sjoerg // If the module is a top-level framework, automatically link against the
11047330f729Sjoerg // framework.
11057330f729Sjoerg if (!Result->isSubFramework()) {
11067330f729Sjoerg inferFrameworkLink(Result, FrameworkDir, FileMgr);
11077330f729Sjoerg }
11087330f729Sjoerg
11097330f729Sjoerg return Result;
11107330f729Sjoerg }
11117330f729Sjoerg
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)11127330f729Sjoerg Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11137330f729Sjoerg Module *ShadowingModule) {
11147330f729Sjoerg
11157330f729Sjoerg // Create a new module with this name.
11167330f729Sjoerg Module *Result =
11177330f729Sjoerg new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11187330f729Sjoerg /*IsExplicit=*/false, NumCreatedModules++);
11197330f729Sjoerg Result->ShadowingModule = ShadowingModule;
1120*e038c9c4Sjoerg Result->markUnavailable(/*Unimportable*/true);
11217330f729Sjoerg ModuleScopeIDs[Result] = CurrentModuleScopeID;
11227330f729Sjoerg ShadowModules.push_back(Result);
11237330f729Sjoerg
11247330f729Sjoerg return Result;
11257330f729Sjoerg }
11267330f729Sjoerg
setUmbrellaHeader(Module * Mod,const FileEntry * UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1127*e038c9c4Sjoerg void ModuleMap::setUmbrellaHeader(
1128*e038c9c4Sjoerg Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten,
1129*e038c9c4Sjoerg const Twine &PathRelativeToRootModuleDirectory) {
11307330f729Sjoerg Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
11317330f729Sjoerg Mod->Umbrella = UmbrellaHeader;
11327330f729Sjoerg Mod->UmbrellaAsWritten = NameAsWritten.str();
1133*e038c9c4Sjoerg Mod->UmbrellaRelativeToRootModuleDirectory =
1134*e038c9c4Sjoerg PathRelativeToRootModuleDirectory.str();
11357330f729Sjoerg UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
11367330f729Sjoerg
11377330f729Sjoerg // Notify callbacks that we just added a new header.
11387330f729Sjoerg for (const auto &Cb : Callbacks)
11397330f729Sjoerg Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
11407330f729Sjoerg }
11417330f729Sjoerg
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)11427330f729Sjoerg void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1143*e038c9c4Sjoerg const Twine &NameAsWritten,
1144*e038c9c4Sjoerg const Twine &PathRelativeToRootModuleDirectory) {
11457330f729Sjoerg Mod->Umbrella = UmbrellaDir;
11467330f729Sjoerg Mod->UmbrellaAsWritten = NameAsWritten.str();
1147*e038c9c4Sjoerg Mod->UmbrellaRelativeToRootModuleDirectory =
1148*e038c9c4Sjoerg PathRelativeToRootModuleDirectory.str();
11497330f729Sjoerg UmbrellaDirs[UmbrellaDir] = Mod;
11507330f729Sjoerg }
11517330f729Sjoerg
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)11527330f729Sjoerg void ModuleMap::addUnresolvedHeader(Module *Mod,
11537330f729Sjoerg Module::UnresolvedHeaderDirective Header,
11547330f729Sjoerg bool &NeedsFramework) {
11557330f729Sjoerg // If there is a builtin counterpart to this file, add it now so it can
11567330f729Sjoerg // wrap the system header.
11577330f729Sjoerg if (resolveAsBuiltinHeader(Mod, Header)) {
11587330f729Sjoerg // If we have both a builtin and system version of the file, the
11597330f729Sjoerg // builtin version may want to inject macros into the system header, so
11607330f729Sjoerg // force the system header to be treated as a textual header in this
11617330f729Sjoerg // case.
11627330f729Sjoerg Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
11637330f729Sjoerg headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
11647330f729Sjoerg Header.HasBuiltinHeader = true;
11657330f729Sjoerg }
11667330f729Sjoerg
11677330f729Sjoerg // If possible, don't stat the header until we need to. This requires the
11687330f729Sjoerg // user to have provided us with some stat information about the file.
11697330f729Sjoerg // FIXME: Add support for lazily stat'ing umbrella headers and excluded
11707330f729Sjoerg // headers.
11717330f729Sjoerg if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
11727330f729Sjoerg Header.Kind != Module::HK_Excluded) {
11737330f729Sjoerg // We expect more variation in mtime than size, so if we're given both,
11747330f729Sjoerg // use the mtime as the key.
11757330f729Sjoerg if (Header.ModTime)
11767330f729Sjoerg LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
11777330f729Sjoerg else
11787330f729Sjoerg LazyHeadersBySize[*Header.Size].push_back(Mod);
11797330f729Sjoerg Mod->UnresolvedHeaders.push_back(Header);
11807330f729Sjoerg return;
11817330f729Sjoerg }
11827330f729Sjoerg
11837330f729Sjoerg // We don't have stat information or can't defer looking this file up.
11847330f729Sjoerg // Perform the lookup now.
11857330f729Sjoerg resolveHeader(Mod, Header, NeedsFramework);
11867330f729Sjoerg }
11877330f729Sjoerg
resolveHeaderDirectives(const FileEntry * File) const11887330f729Sjoerg void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
11897330f729Sjoerg auto BySize = LazyHeadersBySize.find(File->getSize());
11907330f729Sjoerg if (BySize != LazyHeadersBySize.end()) {
11917330f729Sjoerg for (auto *M : BySize->second)
11927330f729Sjoerg resolveHeaderDirectives(M);
11937330f729Sjoerg LazyHeadersBySize.erase(BySize);
11947330f729Sjoerg }
11957330f729Sjoerg
11967330f729Sjoerg auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
11977330f729Sjoerg if (ByModTime != LazyHeadersByModTime.end()) {
11987330f729Sjoerg for (auto *M : ByModTime->second)
11997330f729Sjoerg resolveHeaderDirectives(M);
12007330f729Sjoerg LazyHeadersByModTime.erase(ByModTime);
12017330f729Sjoerg }
12027330f729Sjoerg }
12037330f729Sjoerg
resolveHeaderDirectives(Module * Mod) const12047330f729Sjoerg void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
12057330f729Sjoerg bool NeedsFramework = false;
12067330f729Sjoerg for (auto &Header : Mod->UnresolvedHeaders)
12077330f729Sjoerg // This operation is logically const; we're just changing how we represent
12087330f729Sjoerg // the header information for this file.
12097330f729Sjoerg const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
12107330f729Sjoerg Mod->UnresolvedHeaders.clear();
12117330f729Sjoerg }
12127330f729Sjoerg
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)12137330f729Sjoerg void ModuleMap::addHeader(Module *Mod, Module::Header Header,
12147330f729Sjoerg ModuleHeaderRole Role, bool Imported) {
12157330f729Sjoerg KnownHeader KH(Mod, Role);
12167330f729Sjoerg
12177330f729Sjoerg // Only add each header to the headers list once.
12187330f729Sjoerg // FIXME: Should we diagnose if a header is listed twice in the
12197330f729Sjoerg // same module definition?
12207330f729Sjoerg auto &HeaderList = Headers[Header.Entry];
12217330f729Sjoerg for (auto H : HeaderList)
12227330f729Sjoerg if (H == KH)
12237330f729Sjoerg return;
12247330f729Sjoerg
12257330f729Sjoerg HeaderList.push_back(KH);
12267330f729Sjoerg Mod->Headers[headerRoleToKind(Role)].push_back(Header);
12277330f729Sjoerg
12287330f729Sjoerg bool isCompilingModuleHeader =
12297330f729Sjoerg LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
12307330f729Sjoerg if (!Imported || isCompilingModuleHeader) {
12317330f729Sjoerg // When we import HeaderFileInfo, the external source is expected to
12327330f729Sjoerg // set the isModuleHeader flag itself.
12337330f729Sjoerg HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
12347330f729Sjoerg isCompilingModuleHeader);
12357330f729Sjoerg }
12367330f729Sjoerg
12377330f729Sjoerg // Notify callbacks that we just added a new header.
12387330f729Sjoerg for (const auto &Cb : Callbacks)
12397330f729Sjoerg Cb->moduleMapAddHeader(Header.Entry->getName());
12407330f729Sjoerg }
12417330f729Sjoerg
excludeHeader(Module * Mod,Module::Header Header)12427330f729Sjoerg void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
12437330f729Sjoerg // Add this as a known header so we won't implicitly add it to any
12447330f729Sjoerg // umbrella directory module.
12457330f729Sjoerg // FIXME: Should we only exclude it from umbrella modules within the
12467330f729Sjoerg // specified module?
12477330f729Sjoerg (void) Headers[Header.Entry];
12487330f729Sjoerg
12497330f729Sjoerg Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
12507330f729Sjoerg }
12517330f729Sjoerg
12527330f729Sjoerg const FileEntry *
getContainingModuleMapFile(const Module * Module) const12537330f729Sjoerg ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12547330f729Sjoerg if (Module->DefinitionLoc.isInvalid())
12557330f729Sjoerg return nullptr;
12567330f729Sjoerg
12577330f729Sjoerg return SourceMgr.getFileEntryForID(
12587330f729Sjoerg SourceMgr.getFileID(Module->DefinitionLoc));
12597330f729Sjoerg }
12607330f729Sjoerg
getModuleMapFileForUniquing(const Module * M) const12617330f729Sjoerg const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12627330f729Sjoerg if (M->IsInferred) {
12637330f729Sjoerg assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12647330f729Sjoerg return InferredModuleAllowedBy.find(M)->second;
12657330f729Sjoerg }
12667330f729Sjoerg return getContainingModuleMapFile(M);
12677330f729Sjoerg }
12687330f729Sjoerg
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)12697330f729Sjoerg void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12707330f729Sjoerg assert(M->IsInferred && "module not inferred");
12717330f729Sjoerg InferredModuleAllowedBy[M] = ModMap;
12727330f729Sjoerg }
12737330f729Sjoerg
addAdditionalModuleMapFile(const Module * M,const FileEntry * ModuleMap)1274*e038c9c4Sjoerg void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1275*e038c9c4Sjoerg const FileEntry *ModuleMap) {
1276*e038c9c4Sjoerg AdditionalModMaps[M].insert(ModuleMap);
1277*e038c9c4Sjoerg }
1278*e038c9c4Sjoerg
dump()12797330f729Sjoerg LLVM_DUMP_METHOD void ModuleMap::dump() {
12807330f729Sjoerg llvm::errs() << "Modules:";
12817330f729Sjoerg for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
12827330f729Sjoerg MEnd = Modules.end();
12837330f729Sjoerg M != MEnd; ++M)
12847330f729Sjoerg M->getValue()->print(llvm::errs(), 2);
12857330f729Sjoerg
12867330f729Sjoerg llvm::errs() << "Headers:";
12877330f729Sjoerg for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
12887330f729Sjoerg H != HEnd; ++H) {
12897330f729Sjoerg llvm::errs() << " \"" << H->first->getName() << "\" -> ";
12907330f729Sjoerg for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
12917330f729Sjoerg E = H->second.end();
12927330f729Sjoerg I != E; ++I) {
12937330f729Sjoerg if (I != H->second.begin())
12947330f729Sjoerg llvm::errs() << ",";
12957330f729Sjoerg llvm::errs() << I->getModule()->getFullModuleName();
12967330f729Sjoerg }
12977330f729Sjoerg llvm::errs() << "\n";
12987330f729Sjoerg }
12997330f729Sjoerg }
13007330f729Sjoerg
resolveExports(Module * Mod,bool Complain)13017330f729Sjoerg bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
13027330f729Sjoerg auto Unresolved = std::move(Mod->UnresolvedExports);
13037330f729Sjoerg Mod->UnresolvedExports.clear();
13047330f729Sjoerg for (auto &UE : Unresolved) {
13057330f729Sjoerg Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
13067330f729Sjoerg if (Export.getPointer() || Export.getInt())
13077330f729Sjoerg Mod->Exports.push_back(Export);
13087330f729Sjoerg else
13097330f729Sjoerg Mod->UnresolvedExports.push_back(UE);
13107330f729Sjoerg }
13117330f729Sjoerg return !Mod->UnresolvedExports.empty();
13127330f729Sjoerg }
13137330f729Sjoerg
resolveUses(Module * Mod,bool Complain)13147330f729Sjoerg bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
13157330f729Sjoerg auto Unresolved = std::move(Mod->UnresolvedDirectUses);
13167330f729Sjoerg Mod->UnresolvedDirectUses.clear();
13177330f729Sjoerg for (auto &UDU : Unresolved) {
13187330f729Sjoerg Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
13197330f729Sjoerg if (DirectUse)
13207330f729Sjoerg Mod->DirectUses.push_back(DirectUse);
13217330f729Sjoerg else
13227330f729Sjoerg Mod->UnresolvedDirectUses.push_back(UDU);
13237330f729Sjoerg }
13247330f729Sjoerg return !Mod->UnresolvedDirectUses.empty();
13257330f729Sjoerg }
13267330f729Sjoerg
resolveConflicts(Module * Mod,bool Complain)13277330f729Sjoerg bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
13287330f729Sjoerg auto Unresolved = std::move(Mod->UnresolvedConflicts);
13297330f729Sjoerg Mod->UnresolvedConflicts.clear();
13307330f729Sjoerg for (auto &UC : Unresolved) {
13317330f729Sjoerg if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
13327330f729Sjoerg Module::Conflict Conflict;
13337330f729Sjoerg Conflict.Other = OtherMod;
13347330f729Sjoerg Conflict.Message = UC.Message;
13357330f729Sjoerg Mod->Conflicts.push_back(Conflict);
13367330f729Sjoerg } else
13377330f729Sjoerg Mod->UnresolvedConflicts.push_back(UC);
13387330f729Sjoerg }
13397330f729Sjoerg return !Mod->UnresolvedConflicts.empty();
13407330f729Sjoerg }
13417330f729Sjoerg
13427330f729Sjoerg //----------------------------------------------------------------------------//
13437330f729Sjoerg // Module map file parser
13447330f729Sjoerg //----------------------------------------------------------------------------//
13457330f729Sjoerg
13467330f729Sjoerg namespace clang {
13477330f729Sjoerg
13487330f729Sjoerg /// A token in a module map file.
13497330f729Sjoerg struct MMToken {
13507330f729Sjoerg enum TokenKind {
13517330f729Sjoerg Comma,
13527330f729Sjoerg ConfigMacros,
13537330f729Sjoerg Conflict,
13547330f729Sjoerg EndOfFile,
13557330f729Sjoerg HeaderKeyword,
13567330f729Sjoerg Identifier,
13577330f729Sjoerg Exclaim,
13587330f729Sjoerg ExcludeKeyword,
13597330f729Sjoerg ExplicitKeyword,
13607330f729Sjoerg ExportKeyword,
13617330f729Sjoerg ExportAsKeyword,
13627330f729Sjoerg ExternKeyword,
13637330f729Sjoerg FrameworkKeyword,
13647330f729Sjoerg LinkKeyword,
13657330f729Sjoerg ModuleKeyword,
13667330f729Sjoerg Period,
13677330f729Sjoerg PrivateKeyword,
13687330f729Sjoerg UmbrellaKeyword,
13697330f729Sjoerg UseKeyword,
13707330f729Sjoerg RequiresKeyword,
13717330f729Sjoerg Star,
13727330f729Sjoerg StringLiteral,
13737330f729Sjoerg IntegerLiteral,
13747330f729Sjoerg TextualKeyword,
13757330f729Sjoerg LBrace,
13767330f729Sjoerg RBrace,
13777330f729Sjoerg LSquare,
13787330f729Sjoerg RSquare
13797330f729Sjoerg } Kind;
13807330f729Sjoerg
13817330f729Sjoerg unsigned Location;
13827330f729Sjoerg unsigned StringLength;
13837330f729Sjoerg union {
13847330f729Sjoerg // If Kind != IntegerLiteral.
13857330f729Sjoerg const char *StringData;
13867330f729Sjoerg
13877330f729Sjoerg // If Kind == IntegerLiteral.
13887330f729Sjoerg uint64_t IntegerValue;
13897330f729Sjoerg };
13907330f729Sjoerg
clearclang::MMToken13917330f729Sjoerg void clear() {
13927330f729Sjoerg Kind = EndOfFile;
13937330f729Sjoerg Location = 0;
13947330f729Sjoerg StringLength = 0;
13957330f729Sjoerg StringData = nullptr;
13967330f729Sjoerg }
13977330f729Sjoerg
isclang::MMToken13987330f729Sjoerg bool is(TokenKind K) const { return Kind == K; }
13997330f729Sjoerg
getLocationclang::MMToken14007330f729Sjoerg SourceLocation getLocation() const {
14017330f729Sjoerg return SourceLocation::getFromRawEncoding(Location);
14027330f729Sjoerg }
14037330f729Sjoerg
getIntegerclang::MMToken14047330f729Sjoerg uint64_t getInteger() const {
14057330f729Sjoerg return Kind == IntegerLiteral ? IntegerValue : 0;
14067330f729Sjoerg }
14077330f729Sjoerg
getStringclang::MMToken14087330f729Sjoerg StringRef getString() const {
14097330f729Sjoerg return Kind == IntegerLiteral ? StringRef()
14107330f729Sjoerg : StringRef(StringData, StringLength);
14117330f729Sjoerg }
14127330f729Sjoerg };
14137330f729Sjoerg
14147330f729Sjoerg class ModuleMapParser {
14157330f729Sjoerg Lexer &L;
14167330f729Sjoerg SourceManager &SourceMgr;
14177330f729Sjoerg
14187330f729Sjoerg /// Default target information, used only for string literal
14197330f729Sjoerg /// parsing.
14207330f729Sjoerg const TargetInfo *Target;
14217330f729Sjoerg
14227330f729Sjoerg DiagnosticsEngine &Diags;
14237330f729Sjoerg ModuleMap ⤅
14247330f729Sjoerg
14257330f729Sjoerg /// The current module map file.
14267330f729Sjoerg const FileEntry *ModuleMapFile;
14277330f729Sjoerg
14287330f729Sjoerg /// Source location of most recent parsed module declaration
14297330f729Sjoerg SourceLocation CurrModuleDeclLoc;
14307330f729Sjoerg
14317330f729Sjoerg /// The directory that file names in this module map file should
14327330f729Sjoerg /// be resolved relative to.
14337330f729Sjoerg const DirectoryEntry *Directory;
14347330f729Sjoerg
14357330f729Sjoerg /// Whether this module map is in a system header directory.
14367330f729Sjoerg bool IsSystem;
14377330f729Sjoerg
14387330f729Sjoerg /// Whether an error occurred.
14397330f729Sjoerg bool HadError = false;
14407330f729Sjoerg
14417330f729Sjoerg /// Stores string data for the various string literals referenced
14427330f729Sjoerg /// during parsing.
14437330f729Sjoerg llvm::BumpPtrAllocator StringData;
14447330f729Sjoerg
14457330f729Sjoerg /// The current token.
14467330f729Sjoerg MMToken Tok;
14477330f729Sjoerg
14487330f729Sjoerg /// The active module.
14497330f729Sjoerg Module *ActiveModule = nullptr;
14507330f729Sjoerg
14517330f729Sjoerg /// Whether a module uses the 'requires excluded' hack to mark its
14527330f729Sjoerg /// contents as 'textual'.
14537330f729Sjoerg ///
14547330f729Sjoerg /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14557330f729Sjoerg /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14567330f729Sjoerg /// non-modular headers. For backwards compatibility, we continue to
14577330f729Sjoerg /// support this idiom for just these modules, and map the headers to
14587330f729Sjoerg /// 'textual' to match the original intent.
14597330f729Sjoerg llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14607330f729Sjoerg
14617330f729Sjoerg /// Consume the current token and return its location.
14627330f729Sjoerg SourceLocation consumeToken();
14637330f729Sjoerg
14647330f729Sjoerg /// Skip tokens until we reach the a token with the given kind
14657330f729Sjoerg /// (or the end of the file).
14667330f729Sjoerg void skipUntil(MMToken::TokenKind K);
14677330f729Sjoerg
14687330f729Sjoerg using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
14697330f729Sjoerg
14707330f729Sjoerg bool parseModuleId(ModuleId &Id);
14717330f729Sjoerg void parseModuleDecl();
14727330f729Sjoerg void parseExternModuleDecl();
14737330f729Sjoerg void parseRequiresDecl();
14747330f729Sjoerg void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
14757330f729Sjoerg void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14767330f729Sjoerg void parseExportDecl();
14777330f729Sjoerg void parseExportAsDecl();
14787330f729Sjoerg void parseUseDecl();
14797330f729Sjoerg void parseLinkDecl();
14807330f729Sjoerg void parseConfigMacros();
14817330f729Sjoerg void parseConflict();
14827330f729Sjoerg void parseInferredModuleDecl(bool Framework, bool Explicit);
14837330f729Sjoerg
14847330f729Sjoerg /// Private modules are canonicalized as Foo_Private. Clang provides extra
14857330f729Sjoerg /// module map search logic to find the appropriate private module when PCH
14867330f729Sjoerg /// is used with implicit module maps. Warn when private modules are written
14877330f729Sjoerg /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14887330f729Sjoerg void diagnosePrivateModules(SourceLocation ExplicitLoc,
14897330f729Sjoerg SourceLocation FrameworkLoc);
14907330f729Sjoerg
14917330f729Sjoerg using Attributes = ModuleMap::Attributes;
14927330f729Sjoerg
14937330f729Sjoerg bool parseOptionalAttributes(Attributes &Attrs);
14947330f729Sjoerg
14957330f729Sjoerg public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,bool IsSystem)14967330f729Sjoerg explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14977330f729Sjoerg const TargetInfo *Target, DiagnosticsEngine &Diags,
14987330f729Sjoerg ModuleMap &Map, const FileEntry *ModuleMapFile,
14997330f729Sjoerg const DirectoryEntry *Directory, bool IsSystem)
15007330f729Sjoerg : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
15017330f729Sjoerg ModuleMapFile(ModuleMapFile), Directory(Directory),
15027330f729Sjoerg IsSystem(IsSystem) {
15037330f729Sjoerg Tok.clear();
15047330f729Sjoerg consumeToken();
15057330f729Sjoerg }
15067330f729Sjoerg
15077330f729Sjoerg bool parseModuleMapFile();
15087330f729Sjoerg
terminatedByDirective()15097330f729Sjoerg bool terminatedByDirective() { return false; }
getLocation()15107330f729Sjoerg SourceLocation getLocation() { return Tok.getLocation(); }
15117330f729Sjoerg };
15127330f729Sjoerg
15137330f729Sjoerg } // namespace clang
15147330f729Sjoerg
consumeToken()15157330f729Sjoerg SourceLocation ModuleMapParser::consumeToken() {
15167330f729Sjoerg SourceLocation Result = Tok.getLocation();
15177330f729Sjoerg
15187330f729Sjoerg retry:
15197330f729Sjoerg Tok.clear();
15207330f729Sjoerg Token LToken;
15217330f729Sjoerg L.LexFromRawLexer(LToken);
15227330f729Sjoerg Tok.Location = LToken.getLocation().getRawEncoding();
15237330f729Sjoerg switch (LToken.getKind()) {
15247330f729Sjoerg case tok::raw_identifier: {
15257330f729Sjoerg StringRef RI = LToken.getRawIdentifier();
15267330f729Sjoerg Tok.StringData = RI.data();
15277330f729Sjoerg Tok.StringLength = RI.size();
15287330f729Sjoerg Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
15297330f729Sjoerg .Case("config_macros", MMToken::ConfigMacros)
15307330f729Sjoerg .Case("conflict", MMToken::Conflict)
15317330f729Sjoerg .Case("exclude", MMToken::ExcludeKeyword)
15327330f729Sjoerg .Case("explicit", MMToken::ExplicitKeyword)
15337330f729Sjoerg .Case("export", MMToken::ExportKeyword)
15347330f729Sjoerg .Case("export_as", MMToken::ExportAsKeyword)
15357330f729Sjoerg .Case("extern", MMToken::ExternKeyword)
15367330f729Sjoerg .Case("framework", MMToken::FrameworkKeyword)
15377330f729Sjoerg .Case("header", MMToken::HeaderKeyword)
15387330f729Sjoerg .Case("link", MMToken::LinkKeyword)
15397330f729Sjoerg .Case("module", MMToken::ModuleKeyword)
15407330f729Sjoerg .Case("private", MMToken::PrivateKeyword)
15417330f729Sjoerg .Case("requires", MMToken::RequiresKeyword)
15427330f729Sjoerg .Case("textual", MMToken::TextualKeyword)
15437330f729Sjoerg .Case("umbrella", MMToken::UmbrellaKeyword)
15447330f729Sjoerg .Case("use", MMToken::UseKeyword)
15457330f729Sjoerg .Default(MMToken::Identifier);
15467330f729Sjoerg break;
15477330f729Sjoerg }
15487330f729Sjoerg
15497330f729Sjoerg case tok::comma:
15507330f729Sjoerg Tok.Kind = MMToken::Comma;
15517330f729Sjoerg break;
15527330f729Sjoerg
15537330f729Sjoerg case tok::eof:
15547330f729Sjoerg Tok.Kind = MMToken::EndOfFile;
15557330f729Sjoerg break;
15567330f729Sjoerg
15577330f729Sjoerg case tok::l_brace:
15587330f729Sjoerg Tok.Kind = MMToken::LBrace;
15597330f729Sjoerg break;
15607330f729Sjoerg
15617330f729Sjoerg case tok::l_square:
15627330f729Sjoerg Tok.Kind = MMToken::LSquare;
15637330f729Sjoerg break;
15647330f729Sjoerg
15657330f729Sjoerg case tok::period:
15667330f729Sjoerg Tok.Kind = MMToken::Period;
15677330f729Sjoerg break;
15687330f729Sjoerg
15697330f729Sjoerg case tok::r_brace:
15707330f729Sjoerg Tok.Kind = MMToken::RBrace;
15717330f729Sjoerg break;
15727330f729Sjoerg
15737330f729Sjoerg case tok::r_square:
15747330f729Sjoerg Tok.Kind = MMToken::RSquare;
15757330f729Sjoerg break;
15767330f729Sjoerg
15777330f729Sjoerg case tok::star:
15787330f729Sjoerg Tok.Kind = MMToken::Star;
15797330f729Sjoerg break;
15807330f729Sjoerg
15817330f729Sjoerg case tok::exclaim:
15827330f729Sjoerg Tok.Kind = MMToken::Exclaim;
15837330f729Sjoerg break;
15847330f729Sjoerg
15857330f729Sjoerg case tok::string_literal: {
15867330f729Sjoerg if (LToken.hasUDSuffix()) {
15877330f729Sjoerg Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
15887330f729Sjoerg HadError = true;
15897330f729Sjoerg goto retry;
15907330f729Sjoerg }
15917330f729Sjoerg
15927330f729Sjoerg // Parse the string literal.
15937330f729Sjoerg LangOptions LangOpts;
15947330f729Sjoerg StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
15957330f729Sjoerg if (StringLiteral.hadError)
15967330f729Sjoerg goto retry;
15977330f729Sjoerg
15987330f729Sjoerg // Copy the string literal into our string data allocator.
15997330f729Sjoerg unsigned Length = StringLiteral.GetStringLength();
16007330f729Sjoerg char *Saved = StringData.Allocate<char>(Length + 1);
16017330f729Sjoerg memcpy(Saved, StringLiteral.GetString().data(), Length);
16027330f729Sjoerg Saved[Length] = 0;
16037330f729Sjoerg
16047330f729Sjoerg // Form the token.
16057330f729Sjoerg Tok.Kind = MMToken::StringLiteral;
16067330f729Sjoerg Tok.StringData = Saved;
16077330f729Sjoerg Tok.StringLength = Length;
16087330f729Sjoerg break;
16097330f729Sjoerg }
16107330f729Sjoerg
16117330f729Sjoerg case tok::numeric_constant: {
16127330f729Sjoerg // We don't support any suffixes or other complications.
16137330f729Sjoerg SmallString<32> SpellingBuffer;
16147330f729Sjoerg SpellingBuffer.resize(LToken.getLength() + 1);
16157330f729Sjoerg const char *Start = SpellingBuffer.data();
16167330f729Sjoerg unsigned Length =
16177330f729Sjoerg Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
16187330f729Sjoerg uint64_t Value;
16197330f729Sjoerg if (StringRef(Start, Length).getAsInteger(0, Value)) {
16207330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
16217330f729Sjoerg HadError = true;
16227330f729Sjoerg goto retry;
16237330f729Sjoerg }
16247330f729Sjoerg
16257330f729Sjoerg Tok.Kind = MMToken::IntegerLiteral;
16267330f729Sjoerg Tok.IntegerValue = Value;
16277330f729Sjoerg break;
16287330f729Sjoerg }
16297330f729Sjoerg
16307330f729Sjoerg case tok::comment:
16317330f729Sjoerg goto retry;
16327330f729Sjoerg
16337330f729Sjoerg case tok::hash:
16347330f729Sjoerg // A module map can be terminated prematurely by
16357330f729Sjoerg // #pragma clang module contents
16367330f729Sjoerg // When building the module, we'll treat the rest of the file as the
16377330f729Sjoerg // contents of the module.
16387330f729Sjoerg {
16397330f729Sjoerg auto NextIsIdent = [&](StringRef Str) -> bool {
16407330f729Sjoerg L.LexFromRawLexer(LToken);
16417330f729Sjoerg return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
16427330f729Sjoerg LToken.getRawIdentifier() == Str;
16437330f729Sjoerg };
16447330f729Sjoerg if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16457330f729Sjoerg NextIsIdent("module") && NextIsIdent("contents")) {
16467330f729Sjoerg Tok.Kind = MMToken::EndOfFile;
16477330f729Sjoerg break;
16487330f729Sjoerg }
16497330f729Sjoerg }
16507330f729Sjoerg LLVM_FALLTHROUGH;
16517330f729Sjoerg
16527330f729Sjoerg default:
16537330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
16547330f729Sjoerg HadError = true;
16557330f729Sjoerg goto retry;
16567330f729Sjoerg }
16577330f729Sjoerg
16587330f729Sjoerg return Result;
16597330f729Sjoerg }
16607330f729Sjoerg
skipUntil(MMToken::TokenKind K)16617330f729Sjoerg void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
16627330f729Sjoerg unsigned braceDepth = 0;
16637330f729Sjoerg unsigned squareDepth = 0;
16647330f729Sjoerg do {
16657330f729Sjoerg switch (Tok.Kind) {
16667330f729Sjoerg case MMToken::EndOfFile:
16677330f729Sjoerg return;
16687330f729Sjoerg
16697330f729Sjoerg case MMToken::LBrace:
16707330f729Sjoerg if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
16717330f729Sjoerg return;
16727330f729Sjoerg
16737330f729Sjoerg ++braceDepth;
16747330f729Sjoerg break;
16757330f729Sjoerg
16767330f729Sjoerg case MMToken::LSquare:
16777330f729Sjoerg if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
16787330f729Sjoerg return;
16797330f729Sjoerg
16807330f729Sjoerg ++squareDepth;
16817330f729Sjoerg break;
16827330f729Sjoerg
16837330f729Sjoerg case MMToken::RBrace:
16847330f729Sjoerg if (braceDepth > 0)
16857330f729Sjoerg --braceDepth;
16867330f729Sjoerg else if (Tok.is(K))
16877330f729Sjoerg return;
16887330f729Sjoerg break;
16897330f729Sjoerg
16907330f729Sjoerg case MMToken::RSquare:
16917330f729Sjoerg if (squareDepth > 0)
16927330f729Sjoerg --squareDepth;
16937330f729Sjoerg else if (Tok.is(K))
16947330f729Sjoerg return;
16957330f729Sjoerg break;
16967330f729Sjoerg
16977330f729Sjoerg default:
16987330f729Sjoerg if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
16997330f729Sjoerg return;
17007330f729Sjoerg break;
17017330f729Sjoerg }
17027330f729Sjoerg
17037330f729Sjoerg consumeToken();
17047330f729Sjoerg } while (true);
17057330f729Sjoerg }
17067330f729Sjoerg
17077330f729Sjoerg /// Parse a module-id.
17087330f729Sjoerg ///
17097330f729Sjoerg /// module-id:
17107330f729Sjoerg /// identifier
17117330f729Sjoerg /// identifier '.' module-id
17127330f729Sjoerg ///
17137330f729Sjoerg /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)17147330f729Sjoerg bool ModuleMapParser::parseModuleId(ModuleId &Id) {
17157330f729Sjoerg Id.clear();
17167330f729Sjoerg do {
17177330f729Sjoerg if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1718*e038c9c4Sjoerg Id.push_back(
1719*e038c9c4Sjoerg std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
17207330f729Sjoerg consumeToken();
17217330f729Sjoerg } else {
17227330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
17237330f729Sjoerg return true;
17247330f729Sjoerg }
17257330f729Sjoerg
17267330f729Sjoerg if (!Tok.is(MMToken::Period))
17277330f729Sjoerg break;
17287330f729Sjoerg
17297330f729Sjoerg consumeToken();
17307330f729Sjoerg } while (true);
17317330f729Sjoerg
17327330f729Sjoerg return false;
17337330f729Sjoerg }
17347330f729Sjoerg
17357330f729Sjoerg namespace {
17367330f729Sjoerg
17377330f729Sjoerg /// Enumerates the known attributes.
17387330f729Sjoerg enum AttributeKind {
17397330f729Sjoerg /// An unknown attribute.
17407330f729Sjoerg AT_unknown,
17417330f729Sjoerg
17427330f729Sjoerg /// The 'system' attribute.
17437330f729Sjoerg AT_system,
17447330f729Sjoerg
17457330f729Sjoerg /// The 'extern_c' attribute.
17467330f729Sjoerg AT_extern_c,
17477330f729Sjoerg
17487330f729Sjoerg /// The 'exhaustive' attribute.
17497330f729Sjoerg AT_exhaustive,
17507330f729Sjoerg
17517330f729Sjoerg /// The 'no_undeclared_includes' attribute.
17527330f729Sjoerg AT_no_undeclared_includes
17537330f729Sjoerg };
17547330f729Sjoerg
17557330f729Sjoerg } // namespace
17567330f729Sjoerg
17577330f729Sjoerg /// Private modules are canonicalized as Foo_Private. Clang provides extra
17587330f729Sjoerg /// module map search logic to find the appropriate private module when PCH
17597330f729Sjoerg /// is used with implicit module maps. Warn when private modules are written
17607330f729Sjoerg /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)17617330f729Sjoerg void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17627330f729Sjoerg SourceLocation FrameworkLoc) {
17637330f729Sjoerg auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17647330f729Sjoerg const Module *M, SourceRange ReplLoc) {
17657330f729Sjoerg auto D = Diags.Report(ActiveModule->DefinitionLoc,
17667330f729Sjoerg diag::note_mmap_rename_top_level_private_module);
17677330f729Sjoerg D << BadName << M->Name;
17687330f729Sjoerg D << FixItHint::CreateReplacement(ReplLoc, Canonical);
17697330f729Sjoerg };
17707330f729Sjoerg
17717330f729Sjoerg for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
17727330f729Sjoerg auto const *M = E->getValue();
17737330f729Sjoerg if (M->Directory != ActiveModule->Directory)
17747330f729Sjoerg continue;
17757330f729Sjoerg
17767330f729Sjoerg SmallString<128> FullName(ActiveModule->getFullModuleName());
17777330f729Sjoerg if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
17787330f729Sjoerg continue;
17797330f729Sjoerg SmallString<128> FixedPrivModDecl;
17807330f729Sjoerg SmallString<128> Canonical(M->Name);
17817330f729Sjoerg Canonical.append("_Private");
17827330f729Sjoerg
17837330f729Sjoerg // Foo.Private -> Foo_Private
17847330f729Sjoerg if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
17857330f729Sjoerg M->Name == ActiveModule->Parent->Name) {
17867330f729Sjoerg Diags.Report(ActiveModule->DefinitionLoc,
17877330f729Sjoerg diag::warn_mmap_mismatched_private_submodule)
17887330f729Sjoerg << FullName;
17897330f729Sjoerg
17907330f729Sjoerg SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17917330f729Sjoerg if (FrameworkLoc.isValid())
17927330f729Sjoerg FixItInitBegin = FrameworkLoc;
17937330f729Sjoerg if (ExplicitLoc.isValid())
17947330f729Sjoerg FixItInitBegin = ExplicitLoc;
17957330f729Sjoerg
17967330f729Sjoerg if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17977330f729Sjoerg FixedPrivModDecl.append("framework ");
17987330f729Sjoerg FixedPrivModDecl.append("module ");
17997330f729Sjoerg FixedPrivModDecl.append(Canonical);
18007330f729Sjoerg
18017330f729Sjoerg GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
18027330f729Sjoerg SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
18037330f729Sjoerg continue;
18047330f729Sjoerg }
18057330f729Sjoerg
18067330f729Sjoerg // FooPrivate and whatnots -> Foo_Private
18077330f729Sjoerg if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
18087330f729Sjoerg ActiveModule->Name != Canonical) {
18097330f729Sjoerg Diags.Report(ActiveModule->DefinitionLoc,
18107330f729Sjoerg diag::warn_mmap_mismatched_private_module_name)
18117330f729Sjoerg << ActiveModule->Name;
18127330f729Sjoerg GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
18137330f729Sjoerg SourceRange(ActiveModule->DefinitionLoc));
18147330f729Sjoerg }
18157330f729Sjoerg }
18167330f729Sjoerg }
18177330f729Sjoerg
18187330f729Sjoerg /// Parse a module declaration.
18197330f729Sjoerg ///
18207330f729Sjoerg /// module-declaration:
18217330f729Sjoerg /// 'extern' 'module' module-id string-literal
18227330f729Sjoerg /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
18237330f729Sjoerg /// { module-member* }
18247330f729Sjoerg ///
18257330f729Sjoerg /// module-member:
18267330f729Sjoerg /// requires-declaration
18277330f729Sjoerg /// header-declaration
18287330f729Sjoerg /// submodule-declaration
18297330f729Sjoerg /// export-declaration
18307330f729Sjoerg /// export-as-declaration
18317330f729Sjoerg /// link-declaration
18327330f729Sjoerg ///
18337330f729Sjoerg /// submodule-declaration:
18347330f729Sjoerg /// module-declaration
18357330f729Sjoerg /// inferred-submodule-declaration
parseModuleDecl()18367330f729Sjoerg void ModuleMapParser::parseModuleDecl() {
18377330f729Sjoerg assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
18387330f729Sjoerg Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
18397330f729Sjoerg if (Tok.is(MMToken::ExternKeyword)) {
18407330f729Sjoerg parseExternModuleDecl();
18417330f729Sjoerg return;
18427330f729Sjoerg }
18437330f729Sjoerg
18447330f729Sjoerg // Parse 'explicit' or 'framework' keyword, if present.
18457330f729Sjoerg SourceLocation ExplicitLoc;
18467330f729Sjoerg SourceLocation FrameworkLoc;
18477330f729Sjoerg bool Explicit = false;
18487330f729Sjoerg bool Framework = false;
18497330f729Sjoerg
18507330f729Sjoerg // Parse 'explicit' keyword, if present.
18517330f729Sjoerg if (Tok.is(MMToken::ExplicitKeyword)) {
18527330f729Sjoerg ExplicitLoc = consumeToken();
18537330f729Sjoerg Explicit = true;
18547330f729Sjoerg }
18557330f729Sjoerg
18567330f729Sjoerg // Parse 'framework' keyword, if present.
18577330f729Sjoerg if (Tok.is(MMToken::FrameworkKeyword)) {
18587330f729Sjoerg FrameworkLoc = consumeToken();
18597330f729Sjoerg Framework = true;
18607330f729Sjoerg }
18617330f729Sjoerg
18627330f729Sjoerg // Parse 'module' keyword.
18637330f729Sjoerg if (!Tok.is(MMToken::ModuleKeyword)) {
18647330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
18657330f729Sjoerg consumeToken();
18667330f729Sjoerg HadError = true;
18677330f729Sjoerg return;
18687330f729Sjoerg }
18697330f729Sjoerg CurrModuleDeclLoc = consumeToken(); // 'module' keyword
18707330f729Sjoerg
18717330f729Sjoerg // If we have a wildcard for the module name, this is an inferred submodule.
18727330f729Sjoerg // Parse it.
18737330f729Sjoerg if (Tok.is(MMToken::Star))
18747330f729Sjoerg return parseInferredModuleDecl(Framework, Explicit);
18757330f729Sjoerg
18767330f729Sjoerg // Parse the module name.
18777330f729Sjoerg ModuleId Id;
18787330f729Sjoerg if (parseModuleId(Id)) {
18797330f729Sjoerg HadError = true;
18807330f729Sjoerg return;
18817330f729Sjoerg }
18827330f729Sjoerg
18837330f729Sjoerg if (ActiveModule) {
18847330f729Sjoerg if (Id.size() > 1) {
18857330f729Sjoerg Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
18867330f729Sjoerg << SourceRange(Id.front().second, Id.back().second);
18877330f729Sjoerg
18887330f729Sjoerg HadError = true;
18897330f729Sjoerg return;
18907330f729Sjoerg }
18917330f729Sjoerg } else if (Id.size() == 1 && Explicit) {
18927330f729Sjoerg // Top-level modules can't be explicit.
18937330f729Sjoerg Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
18947330f729Sjoerg Explicit = false;
18957330f729Sjoerg ExplicitLoc = SourceLocation();
18967330f729Sjoerg HadError = true;
18977330f729Sjoerg }
18987330f729Sjoerg
18997330f729Sjoerg Module *PreviousActiveModule = ActiveModule;
19007330f729Sjoerg if (Id.size() > 1) {
19017330f729Sjoerg // This module map defines a submodule. Go find the module of which it
19027330f729Sjoerg // is a submodule.
19037330f729Sjoerg ActiveModule = nullptr;
19047330f729Sjoerg const Module *TopLevelModule = nullptr;
19057330f729Sjoerg for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
19067330f729Sjoerg if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
19077330f729Sjoerg if (I == 0)
19087330f729Sjoerg TopLevelModule = Next;
19097330f729Sjoerg ActiveModule = Next;
19107330f729Sjoerg continue;
19117330f729Sjoerg }
19127330f729Sjoerg
1913*e038c9c4Sjoerg Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
1914*e038c9c4Sjoerg << Id[I].first << (ActiveModule != nullptr)
1915*e038c9c4Sjoerg << (ActiveModule
1916*e038c9c4Sjoerg ? ActiveModule->getTopLevelModule()->getFullModuleName()
1917*e038c9c4Sjoerg : "");
19187330f729Sjoerg HadError = true;
19197330f729Sjoerg }
19207330f729Sjoerg
1921*e038c9c4Sjoerg if (TopLevelModule &&
1922*e038c9c4Sjoerg ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
19237330f729Sjoerg assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
19247330f729Sjoerg "submodule defined in same file as 'module *' that allowed its "
19257330f729Sjoerg "top-level module");
19267330f729Sjoerg Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
19277330f729Sjoerg }
19287330f729Sjoerg }
19297330f729Sjoerg
19307330f729Sjoerg StringRef ModuleName = Id.back().first;
19317330f729Sjoerg SourceLocation ModuleNameLoc = Id.back().second;
19327330f729Sjoerg
19337330f729Sjoerg // Parse the optional attribute list.
19347330f729Sjoerg Attributes Attrs;
19357330f729Sjoerg if (parseOptionalAttributes(Attrs))
19367330f729Sjoerg return;
19377330f729Sjoerg
19387330f729Sjoerg // Parse the opening brace.
19397330f729Sjoerg if (!Tok.is(MMToken::LBrace)) {
19407330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
19417330f729Sjoerg << ModuleName;
19427330f729Sjoerg HadError = true;
19437330f729Sjoerg return;
19447330f729Sjoerg }
19457330f729Sjoerg SourceLocation LBraceLoc = consumeToken();
19467330f729Sjoerg
19477330f729Sjoerg // Determine whether this (sub)module has already been defined.
19487330f729Sjoerg Module *ShadowingModule = nullptr;
19497330f729Sjoerg if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19507330f729Sjoerg // We might see a (re)definition of a module that we already have a
19517330f729Sjoerg // definition for in two cases:
19527330f729Sjoerg // - If we loaded one definition from an AST file and we've just found a
19537330f729Sjoerg // corresponding definition in a module map file, or
19547330f729Sjoerg bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19557330f729Sjoerg // - If we're building a (preprocessed) module and we've just loaded the
19567330f729Sjoerg // module map file from which it was created.
19577330f729Sjoerg bool ParsedAsMainInput =
19587330f729Sjoerg Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19597330f729Sjoerg Map.LangOpts.CurrentModule == ModuleName &&
19607330f729Sjoerg SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19617330f729Sjoerg SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19627330f729Sjoerg if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
19637330f729Sjoerg // Skip the module definition.
19647330f729Sjoerg skipUntil(MMToken::RBrace);
19657330f729Sjoerg if (Tok.is(MMToken::RBrace))
19667330f729Sjoerg consumeToken();
19677330f729Sjoerg else {
19687330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
19697330f729Sjoerg Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
19707330f729Sjoerg HadError = true;
19717330f729Sjoerg }
19727330f729Sjoerg return;
19737330f729Sjoerg }
19747330f729Sjoerg
19757330f729Sjoerg if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19767330f729Sjoerg ShadowingModule = Existing;
19777330f729Sjoerg } else {
19787330f729Sjoerg // This is not a shawdowed module decl, it is an illegal redefinition.
19797330f729Sjoerg Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
19807330f729Sjoerg << ModuleName;
19817330f729Sjoerg Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
19827330f729Sjoerg
19837330f729Sjoerg // Skip the module definition.
19847330f729Sjoerg skipUntil(MMToken::RBrace);
19857330f729Sjoerg if (Tok.is(MMToken::RBrace))
19867330f729Sjoerg consumeToken();
19877330f729Sjoerg
19887330f729Sjoerg HadError = true;
19897330f729Sjoerg return;
19907330f729Sjoerg }
19917330f729Sjoerg }
19927330f729Sjoerg
19937330f729Sjoerg // Start defining this module.
19947330f729Sjoerg if (ShadowingModule) {
19957330f729Sjoerg ActiveModule =
19967330f729Sjoerg Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19977330f729Sjoerg } else {
19987330f729Sjoerg ActiveModule =
19997330f729Sjoerg Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
20007330f729Sjoerg .first;
20017330f729Sjoerg }
20027330f729Sjoerg
20037330f729Sjoerg ActiveModule->DefinitionLoc = ModuleNameLoc;
20047330f729Sjoerg if (Attrs.IsSystem || IsSystem)
20057330f729Sjoerg ActiveModule->IsSystem = true;
20067330f729Sjoerg if (Attrs.IsExternC)
20077330f729Sjoerg ActiveModule->IsExternC = true;
20087330f729Sjoerg if (Attrs.NoUndeclaredIncludes ||
20097330f729Sjoerg (!ActiveModule->Parent && ModuleName == "Darwin"))
20107330f729Sjoerg ActiveModule->NoUndeclaredIncludes = true;
20117330f729Sjoerg ActiveModule->Directory = Directory;
20127330f729Sjoerg
20137330f729Sjoerg StringRef MapFileName(ModuleMapFile->getName());
20147330f729Sjoerg if (MapFileName.endswith("module.private.modulemap") ||
20157330f729Sjoerg MapFileName.endswith("module_private.map")) {
20167330f729Sjoerg ActiveModule->ModuleMapIsPrivate = true;
20177330f729Sjoerg }
20187330f729Sjoerg
20197330f729Sjoerg // Private modules named as FooPrivate, Foo.Private or similar are likely a
20207330f729Sjoerg // user error; provide warnings, notes and fixits to direct users to use
20217330f729Sjoerg // Foo_Private instead.
20227330f729Sjoerg SourceLocation StartLoc =
20237330f729Sjoerg SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
20247330f729Sjoerg if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
20257330f729Sjoerg !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
20267330f729Sjoerg StartLoc) &&
20277330f729Sjoerg !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
20287330f729Sjoerg StartLoc) &&
20297330f729Sjoerg ActiveModule->ModuleMapIsPrivate)
20307330f729Sjoerg diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
20317330f729Sjoerg
20327330f729Sjoerg bool Done = false;
20337330f729Sjoerg do {
20347330f729Sjoerg switch (Tok.Kind) {
20357330f729Sjoerg case MMToken::EndOfFile:
20367330f729Sjoerg case MMToken::RBrace:
20377330f729Sjoerg Done = true;
20387330f729Sjoerg break;
20397330f729Sjoerg
20407330f729Sjoerg case MMToken::ConfigMacros:
20417330f729Sjoerg parseConfigMacros();
20427330f729Sjoerg break;
20437330f729Sjoerg
20447330f729Sjoerg case MMToken::Conflict:
20457330f729Sjoerg parseConflict();
20467330f729Sjoerg break;
20477330f729Sjoerg
20487330f729Sjoerg case MMToken::ExplicitKeyword:
20497330f729Sjoerg case MMToken::ExternKeyword:
20507330f729Sjoerg case MMToken::FrameworkKeyword:
20517330f729Sjoerg case MMToken::ModuleKeyword:
20527330f729Sjoerg parseModuleDecl();
20537330f729Sjoerg break;
20547330f729Sjoerg
20557330f729Sjoerg case MMToken::ExportKeyword:
20567330f729Sjoerg parseExportDecl();
20577330f729Sjoerg break;
20587330f729Sjoerg
20597330f729Sjoerg case MMToken::ExportAsKeyword:
20607330f729Sjoerg parseExportAsDecl();
20617330f729Sjoerg break;
20627330f729Sjoerg
20637330f729Sjoerg case MMToken::UseKeyword:
20647330f729Sjoerg parseUseDecl();
20657330f729Sjoerg break;
20667330f729Sjoerg
20677330f729Sjoerg case MMToken::RequiresKeyword:
20687330f729Sjoerg parseRequiresDecl();
20697330f729Sjoerg break;
20707330f729Sjoerg
20717330f729Sjoerg case MMToken::TextualKeyword:
20727330f729Sjoerg parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
20737330f729Sjoerg break;
20747330f729Sjoerg
20757330f729Sjoerg case MMToken::UmbrellaKeyword: {
20767330f729Sjoerg SourceLocation UmbrellaLoc = consumeToken();
20777330f729Sjoerg if (Tok.is(MMToken::HeaderKeyword))
20787330f729Sjoerg parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
20797330f729Sjoerg else
20807330f729Sjoerg parseUmbrellaDirDecl(UmbrellaLoc);
20817330f729Sjoerg break;
20827330f729Sjoerg }
20837330f729Sjoerg
20847330f729Sjoerg case MMToken::ExcludeKeyword:
20857330f729Sjoerg parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
20867330f729Sjoerg break;
20877330f729Sjoerg
20887330f729Sjoerg case MMToken::PrivateKeyword:
20897330f729Sjoerg parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
20907330f729Sjoerg break;
20917330f729Sjoerg
20927330f729Sjoerg case MMToken::HeaderKeyword:
20937330f729Sjoerg parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
20947330f729Sjoerg break;
20957330f729Sjoerg
20967330f729Sjoerg case MMToken::LinkKeyword:
20977330f729Sjoerg parseLinkDecl();
20987330f729Sjoerg break;
20997330f729Sjoerg
21007330f729Sjoerg default:
21017330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
21027330f729Sjoerg consumeToken();
21037330f729Sjoerg break;
21047330f729Sjoerg }
21057330f729Sjoerg } while (!Done);
21067330f729Sjoerg
21077330f729Sjoerg if (Tok.is(MMToken::RBrace))
21087330f729Sjoerg consumeToken();
21097330f729Sjoerg else {
21107330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
21117330f729Sjoerg Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
21127330f729Sjoerg HadError = true;
21137330f729Sjoerg }
21147330f729Sjoerg
21157330f729Sjoerg // If the active module is a top-level framework, and there are no link
21167330f729Sjoerg // libraries, automatically link against the framework.
21177330f729Sjoerg if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
21187330f729Sjoerg ActiveModule->LinkLibraries.empty()) {
21197330f729Sjoerg inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
21207330f729Sjoerg }
21217330f729Sjoerg
21227330f729Sjoerg // If the module meets all requirements but is still unavailable, mark the
21237330f729Sjoerg // whole tree as unavailable to prevent it from building.
2124*e038c9c4Sjoerg if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
21257330f729Sjoerg ActiveModule->Parent) {
2126*e038c9c4Sjoerg ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
21277330f729Sjoerg ActiveModule->getTopLevelModule()->MissingHeaders.append(
21287330f729Sjoerg ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
21297330f729Sjoerg }
21307330f729Sjoerg
21317330f729Sjoerg // We're done parsing this module. Pop back to the previous module.
21327330f729Sjoerg ActiveModule = PreviousActiveModule;
21337330f729Sjoerg }
21347330f729Sjoerg
21357330f729Sjoerg /// Parse an extern module declaration.
21367330f729Sjoerg ///
21377330f729Sjoerg /// extern module-declaration:
21387330f729Sjoerg /// 'extern' 'module' module-id string-literal
parseExternModuleDecl()21397330f729Sjoerg void ModuleMapParser::parseExternModuleDecl() {
21407330f729Sjoerg assert(Tok.is(MMToken::ExternKeyword));
21417330f729Sjoerg SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
21427330f729Sjoerg
21437330f729Sjoerg // Parse 'module' keyword.
21447330f729Sjoerg if (!Tok.is(MMToken::ModuleKeyword)) {
21457330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
21467330f729Sjoerg consumeToken();
21477330f729Sjoerg HadError = true;
21487330f729Sjoerg return;
21497330f729Sjoerg }
21507330f729Sjoerg consumeToken(); // 'module' keyword
21517330f729Sjoerg
21527330f729Sjoerg // Parse the module name.
21537330f729Sjoerg ModuleId Id;
21547330f729Sjoerg if (parseModuleId(Id)) {
21557330f729Sjoerg HadError = true;
21567330f729Sjoerg return;
21577330f729Sjoerg }
21587330f729Sjoerg
21597330f729Sjoerg // Parse the referenced module map file name.
21607330f729Sjoerg if (!Tok.is(MMToken::StringLiteral)) {
21617330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
21627330f729Sjoerg HadError = true;
21637330f729Sjoerg return;
21647330f729Sjoerg }
2165*e038c9c4Sjoerg std::string FileName = std::string(Tok.getString());
21667330f729Sjoerg consumeToken(); // filename
21677330f729Sjoerg
21687330f729Sjoerg StringRef FileNameRef = FileName;
21697330f729Sjoerg SmallString<128> ModuleMapFileName;
21707330f729Sjoerg if (llvm::sys::path::is_relative(FileNameRef)) {
21717330f729Sjoerg ModuleMapFileName += Directory->getName();
21727330f729Sjoerg llvm::sys::path::append(ModuleMapFileName, FileName);
21737330f729Sjoerg FileNameRef = ModuleMapFileName;
21747330f729Sjoerg }
21757330f729Sjoerg if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
21767330f729Sjoerg Map.parseModuleMapFile(
21777330f729Sjoerg *File, /*IsSystem=*/false,
21787330f729Sjoerg Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21797330f729Sjoerg ? Directory
21807330f729Sjoerg : (*File)->getDir(),
21817330f729Sjoerg FileID(), nullptr, ExternLoc);
21827330f729Sjoerg }
21837330f729Sjoerg
21847330f729Sjoerg /// Whether to add the requirement \p Feature to the module \p M.
21857330f729Sjoerg ///
21867330f729Sjoerg /// This preserves backwards compatibility for two hacks in the Darwin system
21877330f729Sjoerg /// module map files:
21887330f729Sjoerg ///
21897330f729Sjoerg /// 1. The use of 'requires excluded' to make headers non-modular, which
21907330f729Sjoerg /// should really be mapped to 'textual' now that we have this feature. We
21917330f729Sjoerg /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21927330f729Sjoerg /// true. Later, this bit will be used to map all the headers inside this
21937330f729Sjoerg /// module to 'textual'.
21947330f729Sjoerg ///
21957330f729Sjoerg /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21967330f729Sjoerg ///
21977330f729Sjoerg /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
21987330f729Sjoerg /// was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)21997330f729Sjoerg static bool shouldAddRequirement(Module *M, StringRef Feature,
22007330f729Sjoerg bool &IsRequiresExcludedHack) {
22017330f729Sjoerg if (Feature == "excluded" &&
22027330f729Sjoerg (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
22037330f729Sjoerg M->fullModuleNameIs({"Tcl", "Private"}))) {
22047330f729Sjoerg IsRequiresExcludedHack = true;
22057330f729Sjoerg return false;
22067330f729Sjoerg } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
22077330f729Sjoerg return false;
22087330f729Sjoerg }
22097330f729Sjoerg
22107330f729Sjoerg return true;
22117330f729Sjoerg }
22127330f729Sjoerg
22137330f729Sjoerg /// Parse a requires declaration.
22147330f729Sjoerg ///
22157330f729Sjoerg /// requires-declaration:
22167330f729Sjoerg /// 'requires' feature-list
22177330f729Sjoerg ///
22187330f729Sjoerg /// feature-list:
22197330f729Sjoerg /// feature ',' feature-list
22207330f729Sjoerg /// feature
22217330f729Sjoerg ///
22227330f729Sjoerg /// feature:
22237330f729Sjoerg /// '!'[opt] identifier
parseRequiresDecl()22247330f729Sjoerg void ModuleMapParser::parseRequiresDecl() {
22257330f729Sjoerg assert(Tok.is(MMToken::RequiresKeyword));
22267330f729Sjoerg
22277330f729Sjoerg // Parse 'requires' keyword.
22287330f729Sjoerg consumeToken();
22297330f729Sjoerg
22307330f729Sjoerg // Parse the feature-list.
22317330f729Sjoerg do {
22327330f729Sjoerg bool RequiredState = true;
22337330f729Sjoerg if (Tok.is(MMToken::Exclaim)) {
22347330f729Sjoerg RequiredState = false;
22357330f729Sjoerg consumeToken();
22367330f729Sjoerg }
22377330f729Sjoerg
22387330f729Sjoerg if (!Tok.is(MMToken::Identifier)) {
22397330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
22407330f729Sjoerg HadError = true;
22417330f729Sjoerg return;
22427330f729Sjoerg }
22437330f729Sjoerg
22447330f729Sjoerg // Consume the feature name.
2245*e038c9c4Sjoerg std::string Feature = std::string(Tok.getString());
22467330f729Sjoerg consumeToken();
22477330f729Sjoerg
22487330f729Sjoerg bool IsRequiresExcludedHack = false;
22497330f729Sjoerg bool ShouldAddRequirement =
22507330f729Sjoerg shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22517330f729Sjoerg
22527330f729Sjoerg if (IsRequiresExcludedHack)
22537330f729Sjoerg UsesRequiresExcludedHack.insert(ActiveModule);
22547330f729Sjoerg
22557330f729Sjoerg if (ShouldAddRequirement) {
22567330f729Sjoerg // Add this feature.
22577330f729Sjoerg ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22587330f729Sjoerg *Map.Target);
22597330f729Sjoerg }
22607330f729Sjoerg
22617330f729Sjoerg if (!Tok.is(MMToken::Comma))
22627330f729Sjoerg break;
22637330f729Sjoerg
22647330f729Sjoerg // Consume the comma.
22657330f729Sjoerg consumeToken();
22667330f729Sjoerg } while (true);
22677330f729Sjoerg }
22687330f729Sjoerg
22697330f729Sjoerg /// Parse a header declaration.
22707330f729Sjoerg ///
22717330f729Sjoerg /// header-declaration:
22727330f729Sjoerg /// 'textual'[opt] 'header' string-literal
22737330f729Sjoerg /// 'private' 'textual'[opt] 'header' string-literal
22747330f729Sjoerg /// 'exclude' 'header' string-literal
22757330f729Sjoerg /// 'umbrella' 'header' string-literal
22767330f729Sjoerg ///
22777330f729Sjoerg /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)22787330f729Sjoerg void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
22797330f729Sjoerg SourceLocation LeadingLoc) {
22807330f729Sjoerg // We've already consumed the first token.
22817330f729Sjoerg ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
22827330f729Sjoerg if (LeadingToken == MMToken::PrivateKeyword) {
22837330f729Sjoerg Role = ModuleMap::PrivateHeader;
22847330f729Sjoerg // 'private' may optionally be followed by 'textual'.
22857330f729Sjoerg if (Tok.is(MMToken::TextualKeyword)) {
22867330f729Sjoerg LeadingToken = Tok.Kind;
22877330f729Sjoerg consumeToken();
22887330f729Sjoerg }
22897330f729Sjoerg }
22907330f729Sjoerg
22917330f729Sjoerg if (LeadingToken == MMToken::TextualKeyword)
22927330f729Sjoerg Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22937330f729Sjoerg
22947330f729Sjoerg if (UsesRequiresExcludedHack.count(ActiveModule)) {
22957330f729Sjoerg // Mark this header 'textual' (see doc comment for
22967330f729Sjoerg // Module::UsesRequiresExcludedHack).
22977330f729Sjoerg Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22987330f729Sjoerg }
22997330f729Sjoerg
23007330f729Sjoerg if (LeadingToken != MMToken::HeaderKeyword) {
23017330f729Sjoerg if (!Tok.is(MMToken::HeaderKeyword)) {
23027330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
23037330f729Sjoerg << (LeadingToken == MMToken::PrivateKeyword ? "private" :
23047330f729Sjoerg LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
23057330f729Sjoerg LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
23067330f729Sjoerg return;
23077330f729Sjoerg }
23087330f729Sjoerg consumeToken();
23097330f729Sjoerg }
23107330f729Sjoerg
23117330f729Sjoerg // Parse the header name.
23127330f729Sjoerg if (!Tok.is(MMToken::StringLiteral)) {
23137330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
23147330f729Sjoerg << "header";
23157330f729Sjoerg HadError = true;
23167330f729Sjoerg return;
23177330f729Sjoerg }
23187330f729Sjoerg Module::UnresolvedHeaderDirective Header;
2319*e038c9c4Sjoerg Header.FileName = std::string(Tok.getString());
23207330f729Sjoerg Header.FileNameLoc = consumeToken();
23217330f729Sjoerg Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
23227330f729Sjoerg Header.Kind =
23237330f729Sjoerg (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
23247330f729Sjoerg : Map.headerRoleToKind(Role));
23257330f729Sjoerg
23267330f729Sjoerg // Check whether we already have an umbrella.
23277330f729Sjoerg if (Header.IsUmbrella && ActiveModule->Umbrella) {
23287330f729Sjoerg Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
23297330f729Sjoerg << ActiveModule->getFullModuleName();
23307330f729Sjoerg HadError = true;
23317330f729Sjoerg return;
23327330f729Sjoerg }
23337330f729Sjoerg
23347330f729Sjoerg // If we were given stat information, parse it so we can skip looking for
23357330f729Sjoerg // the file.
23367330f729Sjoerg if (Tok.is(MMToken::LBrace)) {
23377330f729Sjoerg SourceLocation LBraceLoc = consumeToken();
23387330f729Sjoerg
23397330f729Sjoerg while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
23407330f729Sjoerg enum Attribute { Size, ModTime, Unknown };
23417330f729Sjoerg StringRef Str = Tok.getString();
23427330f729Sjoerg SourceLocation Loc = consumeToken();
23437330f729Sjoerg switch (llvm::StringSwitch<Attribute>(Str)
23447330f729Sjoerg .Case("size", Size)
23457330f729Sjoerg .Case("mtime", ModTime)
23467330f729Sjoerg .Default(Unknown)) {
23477330f729Sjoerg case Size:
23487330f729Sjoerg if (Header.Size)
23497330f729Sjoerg Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
23507330f729Sjoerg if (!Tok.is(MMToken::IntegerLiteral)) {
23517330f729Sjoerg Diags.Report(Tok.getLocation(),
23527330f729Sjoerg diag::err_mmap_invalid_header_attribute_value) << Str;
23537330f729Sjoerg skipUntil(MMToken::RBrace);
23547330f729Sjoerg break;
23557330f729Sjoerg }
23567330f729Sjoerg Header.Size = Tok.getInteger();
23577330f729Sjoerg consumeToken();
23587330f729Sjoerg break;
23597330f729Sjoerg
23607330f729Sjoerg case ModTime:
23617330f729Sjoerg if (Header.ModTime)
23627330f729Sjoerg Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
23637330f729Sjoerg if (!Tok.is(MMToken::IntegerLiteral)) {
23647330f729Sjoerg Diags.Report(Tok.getLocation(),
23657330f729Sjoerg diag::err_mmap_invalid_header_attribute_value) << Str;
23667330f729Sjoerg skipUntil(MMToken::RBrace);
23677330f729Sjoerg break;
23687330f729Sjoerg }
23697330f729Sjoerg Header.ModTime = Tok.getInteger();
23707330f729Sjoerg consumeToken();
23717330f729Sjoerg break;
23727330f729Sjoerg
23737330f729Sjoerg case Unknown:
23747330f729Sjoerg Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
23757330f729Sjoerg skipUntil(MMToken::RBrace);
23767330f729Sjoerg break;
23777330f729Sjoerg }
23787330f729Sjoerg }
23797330f729Sjoerg
23807330f729Sjoerg if (Tok.is(MMToken::RBrace))
23817330f729Sjoerg consumeToken();
23827330f729Sjoerg else {
23837330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
23847330f729Sjoerg Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
23857330f729Sjoerg HadError = true;
23867330f729Sjoerg }
23877330f729Sjoerg }
23887330f729Sjoerg
23897330f729Sjoerg bool NeedsFramework = false;
23907330f729Sjoerg Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23917330f729Sjoerg
23927330f729Sjoerg if (NeedsFramework && ActiveModule)
23937330f729Sjoerg Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23947330f729Sjoerg << ActiveModule->getFullModuleName()
23957330f729Sjoerg << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
23967330f729Sjoerg }
23977330f729Sjoerg
compareModuleHeaders(const Module::Header * A,const Module::Header * B)23987330f729Sjoerg static int compareModuleHeaders(const Module::Header *A,
23997330f729Sjoerg const Module::Header *B) {
24007330f729Sjoerg return A->NameAsWritten.compare(B->NameAsWritten);
24017330f729Sjoerg }
24027330f729Sjoerg
24037330f729Sjoerg /// Parse an umbrella directory declaration.
24047330f729Sjoerg ///
24057330f729Sjoerg /// umbrella-dir-declaration:
24067330f729Sjoerg /// umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)24077330f729Sjoerg void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
24087330f729Sjoerg // Parse the directory name.
24097330f729Sjoerg if (!Tok.is(MMToken::StringLiteral)) {
24107330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24117330f729Sjoerg << "umbrella";
24127330f729Sjoerg HadError = true;
24137330f729Sjoerg return;
24147330f729Sjoerg }
24157330f729Sjoerg
2416*e038c9c4Sjoerg std::string DirName = std::string(Tok.getString());
2417*e038c9c4Sjoerg std::string DirNameAsWritten = DirName;
24187330f729Sjoerg SourceLocation DirNameLoc = consumeToken();
24197330f729Sjoerg
24207330f729Sjoerg // Check whether we already have an umbrella.
24217330f729Sjoerg if (ActiveModule->Umbrella) {
24227330f729Sjoerg Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
24237330f729Sjoerg << ActiveModule->getFullModuleName();
24247330f729Sjoerg HadError = true;
24257330f729Sjoerg return;
24267330f729Sjoerg }
24277330f729Sjoerg
24287330f729Sjoerg // Look for this file.
24297330f729Sjoerg const DirectoryEntry *Dir = nullptr;
24307330f729Sjoerg if (llvm::sys::path::is_absolute(DirName)) {
24317330f729Sjoerg if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
24327330f729Sjoerg Dir = *D;
24337330f729Sjoerg } else {
24347330f729Sjoerg SmallString<128> PathName;
24357330f729Sjoerg PathName = Directory->getName();
24367330f729Sjoerg llvm::sys::path::append(PathName, DirName);
24377330f729Sjoerg if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
24387330f729Sjoerg Dir = *D;
24397330f729Sjoerg }
24407330f729Sjoerg
24417330f729Sjoerg if (!Dir) {
24427330f729Sjoerg Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
24437330f729Sjoerg << DirName;
24447330f729Sjoerg return;
24457330f729Sjoerg }
24467330f729Sjoerg
24477330f729Sjoerg if (UsesRequiresExcludedHack.count(ActiveModule)) {
24487330f729Sjoerg // Mark this header 'textual' (see doc comment for
24497330f729Sjoerg // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24507330f729Sjoerg // directory is relatively expensive, in practice this only applies to the
24517330f729Sjoerg // uncommonly used Tcl module on Darwin platforms.
24527330f729Sjoerg std::error_code EC;
24537330f729Sjoerg SmallVector<Module::Header, 6> Headers;
24547330f729Sjoerg llvm::vfs::FileSystem &FS =
24557330f729Sjoerg SourceMgr.getFileManager().getVirtualFileSystem();
24567330f729Sjoerg for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24577330f729Sjoerg I != E && !EC; I.increment(EC)) {
24587330f729Sjoerg if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2459*e038c9c4Sjoerg Module::Header Header = {"", std::string(I->path()), *FE};
24607330f729Sjoerg Headers.push_back(std::move(Header));
24617330f729Sjoerg }
24627330f729Sjoerg }
24637330f729Sjoerg
24647330f729Sjoerg // Sort header paths so that the pcm doesn't depend on iteration order.
24657330f729Sjoerg llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
24667330f729Sjoerg
24677330f729Sjoerg for (auto &Header : Headers)
24687330f729Sjoerg Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24697330f729Sjoerg return;
24707330f729Sjoerg }
24717330f729Sjoerg
24727330f729Sjoerg if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
24737330f729Sjoerg Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
24747330f729Sjoerg << OwningModule->getFullModuleName();
24757330f729Sjoerg HadError = true;
24767330f729Sjoerg return;
24777330f729Sjoerg }
24787330f729Sjoerg
24797330f729Sjoerg // Record this umbrella directory.
2480*e038c9c4Sjoerg Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
24817330f729Sjoerg }
24827330f729Sjoerg
24837330f729Sjoerg /// Parse a module export declaration.
24847330f729Sjoerg ///
24857330f729Sjoerg /// export-declaration:
24867330f729Sjoerg /// 'export' wildcard-module-id
24877330f729Sjoerg ///
24887330f729Sjoerg /// wildcard-module-id:
24897330f729Sjoerg /// identifier
24907330f729Sjoerg /// '*'
24917330f729Sjoerg /// identifier '.' wildcard-module-id
parseExportDecl()24927330f729Sjoerg void ModuleMapParser::parseExportDecl() {
24937330f729Sjoerg assert(Tok.is(MMToken::ExportKeyword));
24947330f729Sjoerg SourceLocation ExportLoc = consumeToken();
24957330f729Sjoerg
24967330f729Sjoerg // Parse the module-id with an optional wildcard at the end.
24977330f729Sjoerg ModuleId ParsedModuleId;
24987330f729Sjoerg bool Wildcard = false;
24997330f729Sjoerg do {
25007330f729Sjoerg // FIXME: Support string-literal module names here.
25017330f729Sjoerg if (Tok.is(MMToken::Identifier)) {
2502*e038c9c4Sjoerg ParsedModuleId.push_back(
2503*e038c9c4Sjoerg std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
25047330f729Sjoerg consumeToken();
25057330f729Sjoerg
25067330f729Sjoerg if (Tok.is(MMToken::Period)) {
25077330f729Sjoerg consumeToken();
25087330f729Sjoerg continue;
25097330f729Sjoerg }
25107330f729Sjoerg
25117330f729Sjoerg break;
25127330f729Sjoerg }
25137330f729Sjoerg
25147330f729Sjoerg if(Tok.is(MMToken::Star)) {
25157330f729Sjoerg Wildcard = true;
25167330f729Sjoerg consumeToken();
25177330f729Sjoerg break;
25187330f729Sjoerg }
25197330f729Sjoerg
25207330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25217330f729Sjoerg HadError = true;
25227330f729Sjoerg return;
25237330f729Sjoerg } while (true);
25247330f729Sjoerg
25257330f729Sjoerg Module::UnresolvedExportDecl Unresolved = {
25267330f729Sjoerg ExportLoc, ParsedModuleId, Wildcard
25277330f729Sjoerg };
25287330f729Sjoerg ActiveModule->UnresolvedExports.push_back(Unresolved);
25297330f729Sjoerg }
25307330f729Sjoerg
25317330f729Sjoerg /// Parse a module export_as declaration.
25327330f729Sjoerg ///
25337330f729Sjoerg /// export-as-declaration:
25347330f729Sjoerg /// 'export_as' identifier
parseExportAsDecl()25357330f729Sjoerg void ModuleMapParser::parseExportAsDecl() {
25367330f729Sjoerg assert(Tok.is(MMToken::ExportAsKeyword));
25377330f729Sjoerg consumeToken();
25387330f729Sjoerg
25397330f729Sjoerg if (!Tok.is(MMToken::Identifier)) {
25407330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25417330f729Sjoerg HadError = true;
25427330f729Sjoerg return;
25437330f729Sjoerg }
25447330f729Sjoerg
25457330f729Sjoerg if (ActiveModule->Parent) {
25467330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
25477330f729Sjoerg consumeToken();
25487330f729Sjoerg return;
25497330f729Sjoerg }
25507330f729Sjoerg
25517330f729Sjoerg if (!ActiveModule->ExportAsModule.empty()) {
25527330f729Sjoerg if (ActiveModule->ExportAsModule == Tok.getString()) {
25537330f729Sjoerg Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
25547330f729Sjoerg << ActiveModule->Name << Tok.getString();
25557330f729Sjoerg } else {
25567330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
25577330f729Sjoerg << ActiveModule->Name << ActiveModule->ExportAsModule
25587330f729Sjoerg << Tok.getString();
25597330f729Sjoerg }
25607330f729Sjoerg }
25617330f729Sjoerg
2562*e038c9c4Sjoerg ActiveModule->ExportAsModule = std::string(Tok.getString());
25637330f729Sjoerg Map.addLinkAsDependency(ActiveModule);
25647330f729Sjoerg
25657330f729Sjoerg consumeToken();
25667330f729Sjoerg }
25677330f729Sjoerg
25687330f729Sjoerg /// Parse a module use declaration.
25697330f729Sjoerg ///
25707330f729Sjoerg /// use-declaration:
25717330f729Sjoerg /// 'use' wildcard-module-id
parseUseDecl()25727330f729Sjoerg void ModuleMapParser::parseUseDecl() {
25737330f729Sjoerg assert(Tok.is(MMToken::UseKeyword));
25747330f729Sjoerg auto KWLoc = consumeToken();
25757330f729Sjoerg // Parse the module-id.
25767330f729Sjoerg ModuleId ParsedModuleId;
25777330f729Sjoerg parseModuleId(ParsedModuleId);
25787330f729Sjoerg
25797330f729Sjoerg if (ActiveModule->Parent)
25807330f729Sjoerg Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25817330f729Sjoerg else
25827330f729Sjoerg ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
25837330f729Sjoerg }
25847330f729Sjoerg
25857330f729Sjoerg /// Parse a link declaration.
25867330f729Sjoerg ///
25877330f729Sjoerg /// module-declaration:
25887330f729Sjoerg /// 'link' 'framework'[opt] string-literal
parseLinkDecl()25897330f729Sjoerg void ModuleMapParser::parseLinkDecl() {
25907330f729Sjoerg assert(Tok.is(MMToken::LinkKeyword));
25917330f729Sjoerg SourceLocation LinkLoc = consumeToken();
25927330f729Sjoerg
25937330f729Sjoerg // Parse the optional 'framework' keyword.
25947330f729Sjoerg bool IsFramework = false;
25957330f729Sjoerg if (Tok.is(MMToken::FrameworkKeyword)) {
25967330f729Sjoerg consumeToken();
25977330f729Sjoerg IsFramework = true;
25987330f729Sjoerg }
25997330f729Sjoerg
26007330f729Sjoerg // Parse the library name
26017330f729Sjoerg if (!Tok.is(MMToken::StringLiteral)) {
26027330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
26037330f729Sjoerg << IsFramework << SourceRange(LinkLoc);
26047330f729Sjoerg HadError = true;
26057330f729Sjoerg return;
26067330f729Sjoerg }
26077330f729Sjoerg
2608*e038c9c4Sjoerg std::string LibraryName = std::string(Tok.getString());
26097330f729Sjoerg consumeToken();
26107330f729Sjoerg ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
26117330f729Sjoerg IsFramework));
26127330f729Sjoerg }
26137330f729Sjoerg
26147330f729Sjoerg /// Parse a configuration macro declaration.
26157330f729Sjoerg ///
26167330f729Sjoerg /// module-declaration:
26177330f729Sjoerg /// 'config_macros' attributes[opt] config-macro-list?
26187330f729Sjoerg ///
26197330f729Sjoerg /// config-macro-list:
26207330f729Sjoerg /// identifier (',' identifier)?
parseConfigMacros()26217330f729Sjoerg void ModuleMapParser::parseConfigMacros() {
26227330f729Sjoerg assert(Tok.is(MMToken::ConfigMacros));
26237330f729Sjoerg SourceLocation ConfigMacrosLoc = consumeToken();
26247330f729Sjoerg
26257330f729Sjoerg // Only top-level modules can have configuration macros.
26267330f729Sjoerg if (ActiveModule->Parent) {
26277330f729Sjoerg Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
26287330f729Sjoerg }
26297330f729Sjoerg
26307330f729Sjoerg // Parse the optional attributes.
26317330f729Sjoerg Attributes Attrs;
26327330f729Sjoerg if (parseOptionalAttributes(Attrs))
26337330f729Sjoerg return;
26347330f729Sjoerg
26357330f729Sjoerg if (Attrs.IsExhaustive && !ActiveModule->Parent) {
26367330f729Sjoerg ActiveModule->ConfigMacrosExhaustive = true;
26377330f729Sjoerg }
26387330f729Sjoerg
26397330f729Sjoerg // If we don't have an identifier, we're done.
26407330f729Sjoerg // FIXME: Support macros with the same name as a keyword here.
26417330f729Sjoerg if (!Tok.is(MMToken::Identifier))
26427330f729Sjoerg return;
26437330f729Sjoerg
26447330f729Sjoerg // Consume the first identifier.
26457330f729Sjoerg if (!ActiveModule->Parent) {
26467330f729Sjoerg ActiveModule->ConfigMacros.push_back(Tok.getString().str());
26477330f729Sjoerg }
26487330f729Sjoerg consumeToken();
26497330f729Sjoerg
26507330f729Sjoerg do {
26517330f729Sjoerg // If there's a comma, consume it.
26527330f729Sjoerg if (!Tok.is(MMToken::Comma))
26537330f729Sjoerg break;
26547330f729Sjoerg consumeToken();
26557330f729Sjoerg
26567330f729Sjoerg // We expect to see a macro name here.
26577330f729Sjoerg // FIXME: Support macros with the same name as a keyword here.
26587330f729Sjoerg if (!Tok.is(MMToken::Identifier)) {
26597330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
26607330f729Sjoerg break;
26617330f729Sjoerg }
26627330f729Sjoerg
26637330f729Sjoerg // Consume the macro name.
26647330f729Sjoerg if (!ActiveModule->Parent) {
26657330f729Sjoerg ActiveModule->ConfigMacros.push_back(Tok.getString().str());
26667330f729Sjoerg }
26677330f729Sjoerg consumeToken();
26687330f729Sjoerg } while (true);
26697330f729Sjoerg }
26707330f729Sjoerg
26717330f729Sjoerg /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)26727330f729Sjoerg static std::string formatModuleId(const ModuleId &Id) {
26737330f729Sjoerg std::string result;
26747330f729Sjoerg {
26757330f729Sjoerg llvm::raw_string_ostream OS(result);
26767330f729Sjoerg
26777330f729Sjoerg for (unsigned I = 0, N = Id.size(); I != N; ++I) {
26787330f729Sjoerg if (I)
26797330f729Sjoerg OS << ".";
26807330f729Sjoerg OS << Id[I].first;
26817330f729Sjoerg }
26827330f729Sjoerg }
26837330f729Sjoerg
26847330f729Sjoerg return result;
26857330f729Sjoerg }
26867330f729Sjoerg
26877330f729Sjoerg /// Parse a conflict declaration.
26887330f729Sjoerg ///
26897330f729Sjoerg /// module-declaration:
26907330f729Sjoerg /// 'conflict' module-id ',' string-literal
parseConflict()26917330f729Sjoerg void ModuleMapParser::parseConflict() {
26927330f729Sjoerg assert(Tok.is(MMToken::Conflict));
26937330f729Sjoerg SourceLocation ConflictLoc = consumeToken();
26947330f729Sjoerg Module::UnresolvedConflict Conflict;
26957330f729Sjoerg
26967330f729Sjoerg // Parse the module-id.
26977330f729Sjoerg if (parseModuleId(Conflict.Id))
26987330f729Sjoerg return;
26997330f729Sjoerg
27007330f729Sjoerg // Parse the ','.
27017330f729Sjoerg if (!Tok.is(MMToken::Comma)) {
27027330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
27037330f729Sjoerg << SourceRange(ConflictLoc);
27047330f729Sjoerg return;
27057330f729Sjoerg }
27067330f729Sjoerg consumeToken();
27077330f729Sjoerg
27087330f729Sjoerg // Parse the message.
27097330f729Sjoerg if (!Tok.is(MMToken::StringLiteral)) {
27107330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
27117330f729Sjoerg << formatModuleId(Conflict.Id);
27127330f729Sjoerg return;
27137330f729Sjoerg }
27147330f729Sjoerg Conflict.Message = Tok.getString().str();
27157330f729Sjoerg consumeToken();
27167330f729Sjoerg
27177330f729Sjoerg // Add this unresolved conflict.
27187330f729Sjoerg ActiveModule->UnresolvedConflicts.push_back(Conflict);
27197330f729Sjoerg }
27207330f729Sjoerg
27217330f729Sjoerg /// Parse an inferred module declaration (wildcard modules).
27227330f729Sjoerg ///
27237330f729Sjoerg /// module-declaration:
27247330f729Sjoerg /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
27257330f729Sjoerg /// { inferred-module-member* }
27267330f729Sjoerg ///
27277330f729Sjoerg /// inferred-module-member:
27287330f729Sjoerg /// 'export' '*'
27297330f729Sjoerg /// 'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)27307330f729Sjoerg void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
27317330f729Sjoerg assert(Tok.is(MMToken::Star));
27327330f729Sjoerg SourceLocation StarLoc = consumeToken();
27337330f729Sjoerg bool Failed = false;
27347330f729Sjoerg
27357330f729Sjoerg // Inferred modules must be submodules.
27367330f729Sjoerg if (!ActiveModule && !Framework) {
27377330f729Sjoerg Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
27387330f729Sjoerg Failed = true;
27397330f729Sjoerg }
27407330f729Sjoerg
27417330f729Sjoerg if (ActiveModule) {
27427330f729Sjoerg // Inferred modules must have umbrella directories.
27437330f729Sjoerg if (!Failed && ActiveModule->IsAvailable &&
27447330f729Sjoerg !ActiveModule->getUmbrellaDir()) {
27457330f729Sjoerg Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
27467330f729Sjoerg Failed = true;
27477330f729Sjoerg }
27487330f729Sjoerg
27497330f729Sjoerg // Check for redefinition of an inferred module.
27507330f729Sjoerg if (!Failed && ActiveModule->InferSubmodules) {
27517330f729Sjoerg Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
27527330f729Sjoerg if (ActiveModule->InferredSubmoduleLoc.isValid())
27537330f729Sjoerg Diags.Report(ActiveModule->InferredSubmoduleLoc,
27547330f729Sjoerg diag::note_mmap_prev_definition);
27557330f729Sjoerg Failed = true;
27567330f729Sjoerg }
27577330f729Sjoerg
27587330f729Sjoerg // Check for the 'framework' keyword, which is not permitted here.
27597330f729Sjoerg if (Framework) {
27607330f729Sjoerg Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27617330f729Sjoerg Framework = false;
27627330f729Sjoerg }
27637330f729Sjoerg } else if (Explicit) {
27647330f729Sjoerg Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27657330f729Sjoerg Explicit = false;
27667330f729Sjoerg }
27677330f729Sjoerg
27687330f729Sjoerg // If there were any problems with this inferred submodule, skip its body.
27697330f729Sjoerg if (Failed) {
27707330f729Sjoerg if (Tok.is(MMToken::LBrace)) {
27717330f729Sjoerg consumeToken();
27727330f729Sjoerg skipUntil(MMToken::RBrace);
27737330f729Sjoerg if (Tok.is(MMToken::RBrace))
27747330f729Sjoerg consumeToken();
27757330f729Sjoerg }
27767330f729Sjoerg HadError = true;
27777330f729Sjoerg return;
27787330f729Sjoerg }
27797330f729Sjoerg
27807330f729Sjoerg // Parse optional attributes.
27817330f729Sjoerg Attributes Attrs;
27827330f729Sjoerg if (parseOptionalAttributes(Attrs))
27837330f729Sjoerg return;
27847330f729Sjoerg
27857330f729Sjoerg if (ActiveModule) {
27867330f729Sjoerg // Note that we have an inferred submodule.
27877330f729Sjoerg ActiveModule->InferSubmodules = true;
27887330f729Sjoerg ActiveModule->InferredSubmoduleLoc = StarLoc;
27897330f729Sjoerg ActiveModule->InferExplicitSubmodules = Explicit;
27907330f729Sjoerg } else {
27917330f729Sjoerg // We'll be inferring framework modules for this directory.
27927330f729Sjoerg Map.InferredDirectories[Directory].InferModules = true;
27937330f729Sjoerg Map.InferredDirectories[Directory].Attrs = Attrs;
27947330f729Sjoerg Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
27957330f729Sjoerg // FIXME: Handle the 'framework' keyword.
27967330f729Sjoerg }
27977330f729Sjoerg
27987330f729Sjoerg // Parse the opening brace.
27997330f729Sjoerg if (!Tok.is(MMToken::LBrace)) {
28007330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
28017330f729Sjoerg HadError = true;
28027330f729Sjoerg return;
28037330f729Sjoerg }
28047330f729Sjoerg SourceLocation LBraceLoc = consumeToken();
28057330f729Sjoerg
28067330f729Sjoerg // Parse the body of the inferred submodule.
28077330f729Sjoerg bool Done = false;
28087330f729Sjoerg do {
28097330f729Sjoerg switch (Tok.Kind) {
28107330f729Sjoerg case MMToken::EndOfFile:
28117330f729Sjoerg case MMToken::RBrace:
28127330f729Sjoerg Done = true;
28137330f729Sjoerg break;
28147330f729Sjoerg
28157330f729Sjoerg case MMToken::ExcludeKeyword:
28167330f729Sjoerg if (ActiveModule) {
28177330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28187330f729Sjoerg << (ActiveModule != nullptr);
28197330f729Sjoerg consumeToken();
28207330f729Sjoerg break;
28217330f729Sjoerg }
28227330f729Sjoerg
28237330f729Sjoerg consumeToken();
28247330f729Sjoerg // FIXME: Support string-literal module names here.
28257330f729Sjoerg if (!Tok.is(MMToken::Identifier)) {
28267330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
28277330f729Sjoerg break;
28287330f729Sjoerg }
28297330f729Sjoerg
2830*e038c9c4Sjoerg Map.InferredDirectories[Directory].ExcludedModules.push_back(
2831*e038c9c4Sjoerg std::string(Tok.getString()));
28327330f729Sjoerg consumeToken();
28337330f729Sjoerg break;
28347330f729Sjoerg
28357330f729Sjoerg case MMToken::ExportKeyword:
28367330f729Sjoerg if (!ActiveModule) {
28377330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28387330f729Sjoerg << (ActiveModule != nullptr);
28397330f729Sjoerg consumeToken();
28407330f729Sjoerg break;
28417330f729Sjoerg }
28427330f729Sjoerg
28437330f729Sjoerg consumeToken();
28447330f729Sjoerg if (Tok.is(MMToken::Star))
28457330f729Sjoerg ActiveModule->InferExportWildcard = true;
28467330f729Sjoerg else
28477330f729Sjoerg Diags.Report(Tok.getLocation(),
28487330f729Sjoerg diag::err_mmap_expected_export_wildcard);
28497330f729Sjoerg consumeToken();
28507330f729Sjoerg break;
28517330f729Sjoerg
28527330f729Sjoerg case MMToken::ExplicitKeyword:
28537330f729Sjoerg case MMToken::ModuleKeyword:
28547330f729Sjoerg case MMToken::HeaderKeyword:
28557330f729Sjoerg case MMToken::PrivateKeyword:
28567330f729Sjoerg case MMToken::UmbrellaKeyword:
28577330f729Sjoerg default:
28587330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28597330f729Sjoerg << (ActiveModule != nullptr);
28607330f729Sjoerg consumeToken();
28617330f729Sjoerg break;
28627330f729Sjoerg }
28637330f729Sjoerg } while (!Done);
28647330f729Sjoerg
28657330f729Sjoerg if (Tok.is(MMToken::RBrace))
28667330f729Sjoerg consumeToken();
28677330f729Sjoerg else {
28687330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
28697330f729Sjoerg Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
28707330f729Sjoerg HadError = true;
28717330f729Sjoerg }
28727330f729Sjoerg }
28737330f729Sjoerg
28747330f729Sjoerg /// Parse optional attributes.
28757330f729Sjoerg ///
28767330f729Sjoerg /// attributes:
28777330f729Sjoerg /// attribute attributes
28787330f729Sjoerg /// attribute
28797330f729Sjoerg ///
28807330f729Sjoerg /// attribute:
28817330f729Sjoerg /// [ identifier ]
28827330f729Sjoerg ///
28837330f729Sjoerg /// \param Attrs Will be filled in with the parsed attributes.
28847330f729Sjoerg ///
28857330f729Sjoerg /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)28867330f729Sjoerg bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28877330f729Sjoerg bool HadError = false;
28887330f729Sjoerg
28897330f729Sjoerg while (Tok.is(MMToken::LSquare)) {
28907330f729Sjoerg // Consume the '['.
28917330f729Sjoerg SourceLocation LSquareLoc = consumeToken();
28927330f729Sjoerg
28937330f729Sjoerg // Check whether we have an attribute name here.
28947330f729Sjoerg if (!Tok.is(MMToken::Identifier)) {
28957330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28967330f729Sjoerg skipUntil(MMToken::RSquare);
28977330f729Sjoerg if (Tok.is(MMToken::RSquare))
28987330f729Sjoerg consumeToken();
28997330f729Sjoerg HadError = true;
29007330f729Sjoerg }
29017330f729Sjoerg
29027330f729Sjoerg // Decode the attribute name.
29037330f729Sjoerg AttributeKind Attribute
29047330f729Sjoerg = llvm::StringSwitch<AttributeKind>(Tok.getString())
29057330f729Sjoerg .Case("exhaustive", AT_exhaustive)
29067330f729Sjoerg .Case("extern_c", AT_extern_c)
29077330f729Sjoerg .Case("no_undeclared_includes", AT_no_undeclared_includes)
29087330f729Sjoerg .Case("system", AT_system)
29097330f729Sjoerg .Default(AT_unknown);
29107330f729Sjoerg switch (Attribute) {
29117330f729Sjoerg case AT_unknown:
29127330f729Sjoerg Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
29137330f729Sjoerg << Tok.getString();
29147330f729Sjoerg break;
29157330f729Sjoerg
29167330f729Sjoerg case AT_system:
29177330f729Sjoerg Attrs.IsSystem = true;
29187330f729Sjoerg break;
29197330f729Sjoerg
29207330f729Sjoerg case AT_extern_c:
29217330f729Sjoerg Attrs.IsExternC = true;
29227330f729Sjoerg break;
29237330f729Sjoerg
29247330f729Sjoerg case AT_exhaustive:
29257330f729Sjoerg Attrs.IsExhaustive = true;
29267330f729Sjoerg break;
29277330f729Sjoerg
29287330f729Sjoerg case AT_no_undeclared_includes:
29297330f729Sjoerg Attrs.NoUndeclaredIncludes = true;
29307330f729Sjoerg break;
29317330f729Sjoerg }
29327330f729Sjoerg consumeToken();
29337330f729Sjoerg
29347330f729Sjoerg // Consume the ']'.
29357330f729Sjoerg if (!Tok.is(MMToken::RSquare)) {
29367330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
29377330f729Sjoerg Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
29387330f729Sjoerg skipUntil(MMToken::RSquare);
29397330f729Sjoerg HadError = true;
29407330f729Sjoerg }
29417330f729Sjoerg
29427330f729Sjoerg if (Tok.is(MMToken::RSquare))
29437330f729Sjoerg consumeToken();
29447330f729Sjoerg }
29457330f729Sjoerg
29467330f729Sjoerg return HadError;
29477330f729Sjoerg }
29487330f729Sjoerg
29497330f729Sjoerg /// Parse a module map file.
29507330f729Sjoerg ///
29517330f729Sjoerg /// module-map-file:
29527330f729Sjoerg /// module-declaration*
parseModuleMapFile()29537330f729Sjoerg bool ModuleMapParser::parseModuleMapFile() {
29547330f729Sjoerg do {
29557330f729Sjoerg switch (Tok.Kind) {
29567330f729Sjoerg case MMToken::EndOfFile:
29577330f729Sjoerg return HadError;
29587330f729Sjoerg
29597330f729Sjoerg case MMToken::ExplicitKeyword:
29607330f729Sjoerg case MMToken::ExternKeyword:
29617330f729Sjoerg case MMToken::ModuleKeyword:
29627330f729Sjoerg case MMToken::FrameworkKeyword:
29637330f729Sjoerg parseModuleDecl();
29647330f729Sjoerg break;
29657330f729Sjoerg
29667330f729Sjoerg case MMToken::Comma:
29677330f729Sjoerg case MMToken::ConfigMacros:
29687330f729Sjoerg case MMToken::Conflict:
29697330f729Sjoerg case MMToken::Exclaim:
29707330f729Sjoerg case MMToken::ExcludeKeyword:
29717330f729Sjoerg case MMToken::ExportKeyword:
29727330f729Sjoerg case MMToken::ExportAsKeyword:
29737330f729Sjoerg case MMToken::HeaderKeyword:
29747330f729Sjoerg case MMToken::Identifier:
29757330f729Sjoerg case MMToken::LBrace:
29767330f729Sjoerg case MMToken::LinkKeyword:
29777330f729Sjoerg case MMToken::LSquare:
29787330f729Sjoerg case MMToken::Period:
29797330f729Sjoerg case MMToken::PrivateKeyword:
29807330f729Sjoerg case MMToken::RBrace:
29817330f729Sjoerg case MMToken::RSquare:
29827330f729Sjoerg case MMToken::RequiresKeyword:
29837330f729Sjoerg case MMToken::Star:
29847330f729Sjoerg case MMToken::StringLiteral:
29857330f729Sjoerg case MMToken::IntegerLiteral:
29867330f729Sjoerg case MMToken::TextualKeyword:
29877330f729Sjoerg case MMToken::UmbrellaKeyword:
29887330f729Sjoerg case MMToken::UseKeyword:
29897330f729Sjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
29907330f729Sjoerg HadError = true;
29917330f729Sjoerg consumeToken();
29927330f729Sjoerg break;
29937330f729Sjoerg }
29947330f729Sjoerg } while (true);
29957330f729Sjoerg }
29967330f729Sjoerg
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)29977330f729Sjoerg bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
29987330f729Sjoerg const DirectoryEntry *Dir, FileID ID,
29997330f729Sjoerg unsigned *Offset,
30007330f729Sjoerg SourceLocation ExternModuleLoc) {
30017330f729Sjoerg assert(Target && "Missing target information");
30027330f729Sjoerg llvm::DenseMap<const FileEntry *, bool>::iterator Known
30037330f729Sjoerg = ParsedModuleMap.find(File);
30047330f729Sjoerg if (Known != ParsedModuleMap.end())
30057330f729Sjoerg return Known->second;
30067330f729Sjoerg
30077330f729Sjoerg // If the module map file wasn't already entered, do so now.
30087330f729Sjoerg if (ID.isInvalid()) {
30097330f729Sjoerg auto FileCharacter =
30107330f729Sjoerg IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
30117330f729Sjoerg ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
30127330f729Sjoerg }
30137330f729Sjoerg
30147330f729Sjoerg assert(Target && "Missing target information");
3015*e038c9c4Sjoerg llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
30167330f729Sjoerg if (!Buffer)
30177330f729Sjoerg return ParsedModuleMap[File] = true;
30187330f729Sjoerg assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
30197330f729Sjoerg "invalid buffer offset");
30207330f729Sjoerg
30217330f729Sjoerg // Parse this module map file.
30227330f729Sjoerg Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
30237330f729Sjoerg Buffer->getBufferStart(),
30247330f729Sjoerg Buffer->getBufferStart() + (Offset ? *Offset : 0),
30257330f729Sjoerg Buffer->getBufferEnd());
30267330f729Sjoerg SourceLocation Start = L.getSourceLocation();
30277330f729Sjoerg ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
30287330f729Sjoerg IsSystem);
30297330f729Sjoerg bool Result = Parser.parseModuleMapFile();
30307330f729Sjoerg ParsedModuleMap[File] = Result;
30317330f729Sjoerg
30327330f729Sjoerg if (Offset) {
30337330f729Sjoerg auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
30347330f729Sjoerg assert(Loc.first == ID && "stopped in a different file?");
30357330f729Sjoerg *Offset = Loc.second;
30367330f729Sjoerg }
30377330f729Sjoerg
30387330f729Sjoerg // Notify callbacks that we parsed it.
30397330f729Sjoerg for (const auto &Cb : Callbacks)
30407330f729Sjoerg Cb->moduleMapFileRead(Start, *File, IsSystem);
30417330f729Sjoerg
30427330f729Sjoerg return Result;
30437330f729Sjoerg }
3044