106f32e7eSjoerg //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file defines the ModuleMap implementation, which describes the layout
1006f32e7eSjoerg // of a module as it relates to headers.
1106f32e7eSjoerg //
1206f32e7eSjoerg //===----------------------------------------------------------------------===//
1306f32e7eSjoerg
1406f32e7eSjoerg #include "clang/Lex/ModuleMap.h"
1506f32e7eSjoerg #include "clang/Basic/CharInfo.h"
1606f32e7eSjoerg #include "clang/Basic/Diagnostic.h"
1706f32e7eSjoerg #include "clang/Basic/FileManager.h"
1806f32e7eSjoerg #include "clang/Basic/LLVM.h"
1906f32e7eSjoerg #include "clang/Basic/LangOptions.h"
2006f32e7eSjoerg #include "clang/Basic/Module.h"
2106f32e7eSjoerg #include "clang/Basic/SourceLocation.h"
2206f32e7eSjoerg #include "clang/Basic/SourceManager.h"
2306f32e7eSjoerg #include "clang/Basic/TargetInfo.h"
2406f32e7eSjoerg #include "clang/Lex/HeaderSearch.h"
2506f32e7eSjoerg #include "clang/Lex/HeaderSearchOptions.h"
2606f32e7eSjoerg #include "clang/Lex/LexDiagnostic.h"
2706f32e7eSjoerg #include "clang/Lex/Lexer.h"
2806f32e7eSjoerg #include "clang/Lex/LiteralSupport.h"
2906f32e7eSjoerg #include "clang/Lex/Token.h"
3006f32e7eSjoerg #include "llvm/ADT/DenseMap.h"
3106f32e7eSjoerg #include "llvm/ADT/None.h"
3206f32e7eSjoerg #include "llvm/ADT/STLExtras.h"
3306f32e7eSjoerg #include "llvm/ADT/SmallPtrSet.h"
3406f32e7eSjoerg #include "llvm/ADT/SmallString.h"
3506f32e7eSjoerg #include "llvm/ADT/SmallVector.h"
3606f32e7eSjoerg #include "llvm/ADT/StringMap.h"
3706f32e7eSjoerg #include "llvm/ADT/StringRef.h"
3806f32e7eSjoerg #include "llvm/ADT/StringSwitch.h"
3906f32e7eSjoerg #include "llvm/Support/Allocator.h"
4006f32e7eSjoerg #include "llvm/Support/Compiler.h"
4106f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
4206f32e7eSjoerg #include "llvm/Support/MemoryBuffer.h"
4306f32e7eSjoerg #include "llvm/Support/Path.h"
4406f32e7eSjoerg #include "llvm/Support/VirtualFileSystem.h"
4506f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
4606f32e7eSjoerg #include <algorithm>
4706f32e7eSjoerg #include <cassert>
4806f32e7eSjoerg #include <cstdint>
4906f32e7eSjoerg #include <cstring>
5006f32e7eSjoerg #include <string>
5106f32e7eSjoerg #include <system_error>
5206f32e7eSjoerg #include <utility>
5306f32e7eSjoerg
5406f32e7eSjoerg using namespace clang;
5506f32e7eSjoerg
anchor()5606f32e7eSjoerg void ModuleMapCallbacks::anchor() {}
5706f32e7eSjoerg
resolveLinkAsDependencies(Module * Mod)5806f32e7eSjoerg void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
5906f32e7eSjoerg auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
6006f32e7eSjoerg if (PendingLinkAs != PendingLinkAsModule.end()) {
6106f32e7eSjoerg for (auto &Name : PendingLinkAs->second) {
6206f32e7eSjoerg auto *M = findModule(Name.getKey());
6306f32e7eSjoerg if (M)
6406f32e7eSjoerg M->UseExportAsModuleLinkName = true;
6506f32e7eSjoerg }
6606f32e7eSjoerg }
6706f32e7eSjoerg }
6806f32e7eSjoerg
addLinkAsDependency(Module * Mod)6906f32e7eSjoerg void ModuleMap::addLinkAsDependency(Module *Mod) {
7006f32e7eSjoerg if (findModule(Mod->ExportAsModule))
7106f32e7eSjoerg Mod->UseExportAsModuleLinkName = true;
7206f32e7eSjoerg else
7306f32e7eSjoerg PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
7406f32e7eSjoerg }
7506f32e7eSjoerg
headerRoleToKind(ModuleHeaderRole Role)7606f32e7eSjoerg Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
7706f32e7eSjoerg switch ((int)Role) {
7806f32e7eSjoerg default: llvm_unreachable("unknown header role");
7906f32e7eSjoerg case NormalHeader:
8006f32e7eSjoerg return Module::HK_Normal;
8106f32e7eSjoerg case PrivateHeader:
8206f32e7eSjoerg return Module::HK_Private;
8306f32e7eSjoerg case TextualHeader:
8406f32e7eSjoerg return Module::HK_Textual;
8506f32e7eSjoerg case PrivateHeader | TextualHeader:
8606f32e7eSjoerg return Module::HK_PrivateTextual;
8706f32e7eSjoerg }
8806f32e7eSjoerg }
8906f32e7eSjoerg
9006f32e7eSjoerg ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)9106f32e7eSjoerg ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
9206f32e7eSjoerg switch ((int)Kind) {
9306f32e7eSjoerg case Module::HK_Normal:
9406f32e7eSjoerg return NormalHeader;
9506f32e7eSjoerg case Module::HK_Private:
9606f32e7eSjoerg return PrivateHeader;
9706f32e7eSjoerg case Module::HK_Textual:
9806f32e7eSjoerg return TextualHeader;
9906f32e7eSjoerg case Module::HK_PrivateTextual:
10006f32e7eSjoerg return ModuleHeaderRole(PrivateHeader | TextualHeader);
10106f32e7eSjoerg case Module::HK_Excluded:
10206f32e7eSjoerg llvm_unreachable("unexpected header kind");
10306f32e7eSjoerg }
10406f32e7eSjoerg llvm_unreachable("unknown header kind");
10506f32e7eSjoerg }
10606f32e7eSjoerg
10706f32e7eSjoerg Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const10806f32e7eSjoerg ModuleMap::resolveExport(Module *Mod,
10906f32e7eSjoerg const Module::UnresolvedExportDecl &Unresolved,
11006f32e7eSjoerg bool Complain) const {
11106f32e7eSjoerg // We may have just a wildcard.
11206f32e7eSjoerg if (Unresolved.Id.empty()) {
11306f32e7eSjoerg assert(Unresolved.Wildcard && "Invalid unresolved export");
11406f32e7eSjoerg return Module::ExportDecl(nullptr, true);
11506f32e7eSjoerg }
11606f32e7eSjoerg
11706f32e7eSjoerg // Resolve the module-id.
11806f32e7eSjoerg Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
11906f32e7eSjoerg if (!Context)
12006f32e7eSjoerg return {};
12106f32e7eSjoerg
12206f32e7eSjoerg return Module::ExportDecl(Context, Unresolved.Wildcard);
12306f32e7eSjoerg }
12406f32e7eSjoerg
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const12506f32e7eSjoerg Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
12606f32e7eSjoerg bool Complain) const {
12706f32e7eSjoerg // Find the starting module.
12806f32e7eSjoerg Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
12906f32e7eSjoerg if (!Context) {
13006f32e7eSjoerg if (Complain)
13106f32e7eSjoerg Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
13206f32e7eSjoerg << Id[0].first << Mod->getFullModuleName();
13306f32e7eSjoerg
13406f32e7eSjoerg return nullptr;
13506f32e7eSjoerg }
13606f32e7eSjoerg
13706f32e7eSjoerg // Dig into the module path.
13806f32e7eSjoerg for (unsigned I = 1, N = Id.size(); I != N; ++I) {
13906f32e7eSjoerg Module *Sub = lookupModuleQualified(Id[I].first, Context);
14006f32e7eSjoerg if (!Sub) {
14106f32e7eSjoerg if (Complain)
14206f32e7eSjoerg Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
14306f32e7eSjoerg << Id[I].first << Context->getFullModuleName()
14406f32e7eSjoerg << SourceRange(Id[0].second, Id[I-1].second);
14506f32e7eSjoerg
14606f32e7eSjoerg return nullptr;
14706f32e7eSjoerg }
14806f32e7eSjoerg
14906f32e7eSjoerg Context = Sub;
15006f32e7eSjoerg }
15106f32e7eSjoerg
15206f32e7eSjoerg return Context;
15306f32e7eSjoerg }
15406f32e7eSjoerg
15506f32e7eSjoerg /// Append to \p Paths the set of paths needed to get to the
15606f32e7eSjoerg /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)15706f32e7eSjoerg static void appendSubframeworkPaths(Module *Mod,
15806f32e7eSjoerg SmallVectorImpl<char> &Path) {
15906f32e7eSjoerg // Collect the framework names from the given module to the top-level module.
16006f32e7eSjoerg SmallVector<StringRef, 2> Paths;
16106f32e7eSjoerg for (; Mod; Mod = Mod->Parent) {
16206f32e7eSjoerg if (Mod->IsFramework)
16306f32e7eSjoerg Paths.push_back(Mod->Name);
16406f32e7eSjoerg }
16506f32e7eSjoerg
16606f32e7eSjoerg if (Paths.empty())
16706f32e7eSjoerg return;
16806f32e7eSjoerg
16906f32e7eSjoerg // Add Frameworks/Name.framework for each subframework.
17006f32e7eSjoerg for (unsigned I = Paths.size() - 1; I != 0; --I)
17106f32e7eSjoerg llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
17206f32e7eSjoerg }
17306f32e7eSjoerg
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)174*13fbcb42Sjoerg Optional<FileEntryRef> ModuleMap::findHeader(
17506f32e7eSjoerg Module *M, const Module::UnresolvedHeaderDirective &Header,
17606f32e7eSjoerg SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
17706f32e7eSjoerg // Search for the header file within the module's home directory.
17806f32e7eSjoerg auto *Directory = M->Directory;
17906f32e7eSjoerg SmallString<128> FullPathName(Directory->getName());
18006f32e7eSjoerg
181*13fbcb42Sjoerg auto GetFile = [&](StringRef Filename) -> Optional<FileEntryRef> {
182*13fbcb42Sjoerg auto File =
183*13fbcb42Sjoerg expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
184*13fbcb42Sjoerg if (!File || (Header.Size && File->getSize() != *Header.Size) ||
185*13fbcb42Sjoerg (Header.ModTime && File->getModificationTime() != *Header.ModTime))
186*13fbcb42Sjoerg return None;
18706f32e7eSjoerg return *File;
18806f32e7eSjoerg };
18906f32e7eSjoerg
190*13fbcb42Sjoerg auto GetFrameworkFile = [&]() -> Optional<FileEntryRef> {
19106f32e7eSjoerg unsigned FullPathLength = FullPathName.size();
19206f32e7eSjoerg appendSubframeworkPaths(M, RelativePathName);
19306f32e7eSjoerg unsigned RelativePathLength = RelativePathName.size();
19406f32e7eSjoerg
19506f32e7eSjoerg // Check whether this file is in the public headers.
19606f32e7eSjoerg llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
19706f32e7eSjoerg llvm::sys::path::append(FullPathName, RelativePathName);
198*13fbcb42Sjoerg if (auto File = GetFile(FullPathName))
19906f32e7eSjoerg return File;
20006f32e7eSjoerg
20106f32e7eSjoerg // Check whether this file is in the private headers.
20206f32e7eSjoerg // Ideally, private modules in the form 'FrameworkName.Private' should
20306f32e7eSjoerg // be defined as 'module FrameworkName.Private', and not as
20406f32e7eSjoerg // 'framework module FrameworkName.Private', since a 'Private.Framework'
20506f32e7eSjoerg // does not usually exist. However, since both are currently widely used
20606f32e7eSjoerg // for private modules, make sure we find the right path in both cases.
20706f32e7eSjoerg if (M->IsFramework && M->Name == "Private")
20806f32e7eSjoerg RelativePathName.clear();
20906f32e7eSjoerg else
21006f32e7eSjoerg RelativePathName.resize(RelativePathLength);
21106f32e7eSjoerg FullPathName.resize(FullPathLength);
21206f32e7eSjoerg llvm::sys::path::append(RelativePathName, "PrivateHeaders",
21306f32e7eSjoerg Header.FileName);
21406f32e7eSjoerg llvm::sys::path::append(FullPathName, RelativePathName);
21506f32e7eSjoerg return GetFile(FullPathName);
21606f32e7eSjoerg };
21706f32e7eSjoerg
21806f32e7eSjoerg if (llvm::sys::path::is_absolute(Header.FileName)) {
21906f32e7eSjoerg RelativePathName.clear();
22006f32e7eSjoerg RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
22106f32e7eSjoerg return GetFile(Header.FileName);
22206f32e7eSjoerg }
22306f32e7eSjoerg
22406f32e7eSjoerg if (M->isPartOfFramework())
22506f32e7eSjoerg return GetFrameworkFile();
22606f32e7eSjoerg
22706f32e7eSjoerg // Lookup for normal headers.
22806f32e7eSjoerg llvm::sys::path::append(RelativePathName, Header.FileName);
22906f32e7eSjoerg llvm::sys::path::append(FullPathName, RelativePathName);
230*13fbcb42Sjoerg auto NormalHdrFile = GetFile(FullPathName);
23106f32e7eSjoerg
232*13fbcb42Sjoerg if (!NormalHdrFile && Directory->getName().endswith(".framework")) {
23306f32e7eSjoerg // The lack of 'framework' keyword in a module declaration it's a simple
23406f32e7eSjoerg // mistake we can diagnose when the header exists within the proper
23506f32e7eSjoerg // framework style path.
23606f32e7eSjoerg FullPathName.assign(Directory->getName());
23706f32e7eSjoerg RelativePathName.clear();
23806f32e7eSjoerg if (GetFrameworkFile()) {
23906f32e7eSjoerg Diags.Report(Header.FileNameLoc,
24006f32e7eSjoerg diag::warn_mmap_incomplete_framework_module_declaration)
24106f32e7eSjoerg << Header.FileName << M->getFullModuleName();
24206f32e7eSjoerg NeedsFramework = true;
24306f32e7eSjoerg }
244*13fbcb42Sjoerg return None;
24506f32e7eSjoerg }
24606f32e7eSjoerg
24706f32e7eSjoerg return NormalHdrFile;
24806f32e7eSjoerg }
24906f32e7eSjoerg
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)25006f32e7eSjoerg void ModuleMap::resolveHeader(Module *Mod,
25106f32e7eSjoerg const Module::UnresolvedHeaderDirective &Header,
25206f32e7eSjoerg bool &NeedsFramework) {
25306f32e7eSjoerg SmallString<128> RelativePathName;
254*13fbcb42Sjoerg if (Optional<FileEntryRef> File =
25506f32e7eSjoerg findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
25606f32e7eSjoerg if (Header.IsUmbrella) {
257*13fbcb42Sjoerg const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
25806f32e7eSjoerg if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
25906f32e7eSjoerg Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
26006f32e7eSjoerg << UmbrellaMod->getFullModuleName();
26106f32e7eSjoerg else
26206f32e7eSjoerg // Record this umbrella header.
263*13fbcb42Sjoerg setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
26406f32e7eSjoerg } else {
265*13fbcb42Sjoerg Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
266*13fbcb42Sjoerg *File};
26706f32e7eSjoerg if (Header.Kind == Module::HK_Excluded)
26806f32e7eSjoerg excludeHeader(Mod, H);
26906f32e7eSjoerg else
27006f32e7eSjoerg addHeader(Mod, H, headerKindToRole(Header.Kind));
27106f32e7eSjoerg }
27206f32e7eSjoerg } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
27306f32e7eSjoerg // There's a builtin header but no corresponding on-disk header. Assume
27406f32e7eSjoerg // this was supposed to modularize the builtin header alone.
27506f32e7eSjoerg } else if (Header.Kind == Module::HK_Excluded) {
27606f32e7eSjoerg // Ignore missing excluded header files. They're optional anyway.
27706f32e7eSjoerg } else {
27806f32e7eSjoerg // If we find a module that has a missing header, we mark this module as
27906f32e7eSjoerg // unavailable and store the header directive for displaying diagnostics.
28006f32e7eSjoerg Mod->MissingHeaders.push_back(Header);
28106f32e7eSjoerg // A missing header with stat information doesn't make the module
28206f32e7eSjoerg // unavailable; this keeps our behavior consistent as headers are lazily
28306f32e7eSjoerg // resolved. (Such a module still can't be built though, except from
28406f32e7eSjoerg // preprocessed source.)
28506f32e7eSjoerg if (!Header.Size && !Header.ModTime)
286*13fbcb42Sjoerg Mod->markUnavailable(/*Unimportable=*/false);
28706f32e7eSjoerg }
28806f32e7eSjoerg }
28906f32e7eSjoerg
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)29006f32e7eSjoerg bool ModuleMap::resolveAsBuiltinHeader(
29106f32e7eSjoerg Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
29206f32e7eSjoerg if (Header.Kind == Module::HK_Excluded ||
29306f32e7eSjoerg llvm::sys::path::is_absolute(Header.FileName) ||
29406f32e7eSjoerg Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
29506f32e7eSjoerg !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
29606f32e7eSjoerg !isBuiltinHeader(Header.FileName))
29706f32e7eSjoerg return false;
29806f32e7eSjoerg
29906f32e7eSjoerg // This is a system module with a top-level header. This header
30006f32e7eSjoerg // may have a counterpart (or replacement) in the set of headers
30106f32e7eSjoerg // supplied by Clang. Find that builtin header.
30206f32e7eSjoerg SmallString<128> Path;
30306f32e7eSjoerg llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
30406f32e7eSjoerg auto File = SourceMgr.getFileManager().getFile(Path);
30506f32e7eSjoerg if (!File)
30606f32e7eSjoerg return false;
30706f32e7eSjoerg
30806f32e7eSjoerg auto Role = headerKindToRole(Header.Kind);
309*13fbcb42Sjoerg Module::Header H = {Header.FileName, std::string(Path.str()), *File};
31006f32e7eSjoerg addHeader(Mod, H, Role);
31106f32e7eSjoerg return true;
31206f32e7eSjoerg }
31306f32e7eSjoerg
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)31406f32e7eSjoerg ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
31506f32e7eSjoerg const LangOptions &LangOpts, const TargetInfo *Target,
31606f32e7eSjoerg HeaderSearch &HeaderInfo)
31706f32e7eSjoerg : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
31806f32e7eSjoerg HeaderInfo(HeaderInfo) {
31906f32e7eSjoerg MMapLangOpts.LineComment = true;
32006f32e7eSjoerg }
32106f32e7eSjoerg
~ModuleMap()32206f32e7eSjoerg ModuleMap::~ModuleMap() {
32306f32e7eSjoerg for (auto &M : Modules)
32406f32e7eSjoerg delete M.getValue();
32506f32e7eSjoerg for (auto *M : ShadowModules)
32606f32e7eSjoerg delete M;
32706f32e7eSjoerg }
32806f32e7eSjoerg
setTarget(const TargetInfo & Target)32906f32e7eSjoerg void ModuleMap::setTarget(const TargetInfo &Target) {
33006f32e7eSjoerg assert((!this->Target || this->Target == &Target) &&
33106f32e7eSjoerg "Improper target override");
33206f32e7eSjoerg this->Target = &Target;
33306f32e7eSjoerg }
33406f32e7eSjoerg
33506f32e7eSjoerg /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)33606f32e7eSjoerg static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
33706f32e7eSjoerg SmallVectorImpl<char> &Buffer) {
33806f32e7eSjoerg if (Name.empty())
33906f32e7eSjoerg return Name;
34006f32e7eSjoerg
34106f32e7eSjoerg if (!isValidIdentifier(Name)) {
34206f32e7eSjoerg // If we don't already have something with the form of an identifier,
34306f32e7eSjoerg // create a buffer with the sanitized name.
34406f32e7eSjoerg Buffer.clear();
34506f32e7eSjoerg if (isDigit(Name[0]))
34606f32e7eSjoerg Buffer.push_back('_');
34706f32e7eSjoerg Buffer.reserve(Buffer.size() + Name.size());
34806f32e7eSjoerg for (unsigned I = 0, N = Name.size(); I != N; ++I) {
34906f32e7eSjoerg if (isIdentifierBody(Name[I]))
35006f32e7eSjoerg Buffer.push_back(Name[I]);
35106f32e7eSjoerg else
35206f32e7eSjoerg Buffer.push_back('_');
35306f32e7eSjoerg }
35406f32e7eSjoerg
35506f32e7eSjoerg Name = StringRef(Buffer.data(), Buffer.size());
35606f32e7eSjoerg }
35706f32e7eSjoerg
35806f32e7eSjoerg while (llvm::StringSwitch<bool>(Name)
35906f32e7eSjoerg #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
36006f32e7eSjoerg #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
36106f32e7eSjoerg #include "clang/Basic/TokenKinds.def"
36206f32e7eSjoerg .Default(false)) {
36306f32e7eSjoerg if (Name.data() != Buffer.data())
36406f32e7eSjoerg Buffer.append(Name.begin(), Name.end());
36506f32e7eSjoerg Buffer.push_back('_');
36606f32e7eSjoerg Name = StringRef(Buffer.data(), Buffer.size());
36706f32e7eSjoerg }
36806f32e7eSjoerg
36906f32e7eSjoerg return Name;
37006f32e7eSjoerg }
37106f32e7eSjoerg
37206f32e7eSjoerg /// Determine whether the given file name is the name of a builtin
37306f32e7eSjoerg /// header, supplied by Clang to replace, override, or augment existing system
37406f32e7eSjoerg /// headers.
isBuiltinHeader(StringRef FileName)37506f32e7eSjoerg bool ModuleMap::isBuiltinHeader(StringRef FileName) {
37606f32e7eSjoerg return llvm::StringSwitch<bool>(FileName)
37706f32e7eSjoerg .Case("float.h", true)
37806f32e7eSjoerg .Case("iso646.h", true)
37906f32e7eSjoerg .Case("limits.h", true)
38006f32e7eSjoerg .Case("stdalign.h", true)
38106f32e7eSjoerg .Case("stdarg.h", true)
38206f32e7eSjoerg .Case("stdatomic.h", true)
38306f32e7eSjoerg .Case("stdbool.h", true)
38406f32e7eSjoerg .Case("stddef.h", true)
38506f32e7eSjoerg .Case("stdint.h", true)
38606f32e7eSjoerg .Case("tgmath.h", true)
38706f32e7eSjoerg .Case("unwind.h", true)
38806f32e7eSjoerg .Default(false);
38906f32e7eSjoerg }
39006f32e7eSjoerg
isBuiltinHeader(const FileEntry * File)391*13fbcb42Sjoerg bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
392*13fbcb42Sjoerg return File->getDir() == BuiltinIncludeDir &&
393*13fbcb42Sjoerg ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
394*13fbcb42Sjoerg }
395*13fbcb42Sjoerg
39606f32e7eSjoerg ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)39706f32e7eSjoerg ModuleMap::findKnownHeader(const FileEntry *File) {
39806f32e7eSjoerg resolveHeaderDirectives(File);
39906f32e7eSjoerg HeadersMap::iterator Known = Headers.find(File);
40006f32e7eSjoerg if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
401*13fbcb42Sjoerg Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
40206f32e7eSjoerg HeaderInfo.loadTopLevelSystemModules();
40306f32e7eSjoerg return Headers.find(File);
40406f32e7eSjoerg }
40506f32e7eSjoerg return Known;
40606f32e7eSjoerg }
40706f32e7eSjoerg
40806f32e7eSjoerg ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)40906f32e7eSjoerg ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
41006f32e7eSjoerg SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
41106f32e7eSjoerg if (UmbrellaDirs.empty())
41206f32e7eSjoerg return {};
41306f32e7eSjoerg
41406f32e7eSjoerg const DirectoryEntry *Dir = File->getDir();
41506f32e7eSjoerg assert(Dir && "file in no directory");
41606f32e7eSjoerg
41706f32e7eSjoerg // Note: as an egregious but useful hack we use the real path here, because
41806f32e7eSjoerg // frameworks moving from top-level frameworks to embedded frameworks tend
41906f32e7eSjoerg // to be symlinked from the top-level location to the embedded location,
42006f32e7eSjoerg // and we need to resolve lookups as if we had found the embedded location.
42106f32e7eSjoerg StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
42206f32e7eSjoerg
42306f32e7eSjoerg // Keep walking up the directory hierarchy, looking for a directory with
42406f32e7eSjoerg // an umbrella header.
42506f32e7eSjoerg do {
42606f32e7eSjoerg auto KnownDir = UmbrellaDirs.find(Dir);
42706f32e7eSjoerg if (KnownDir != UmbrellaDirs.end())
42806f32e7eSjoerg return KnownHeader(KnownDir->second, NormalHeader);
42906f32e7eSjoerg
43006f32e7eSjoerg IntermediateDirs.push_back(Dir);
43106f32e7eSjoerg
43206f32e7eSjoerg // Retrieve our parent path.
43306f32e7eSjoerg DirName = llvm::sys::path::parent_path(DirName);
43406f32e7eSjoerg if (DirName.empty())
43506f32e7eSjoerg break;
43606f32e7eSjoerg
43706f32e7eSjoerg // Resolve the parent path to a directory entry.
43806f32e7eSjoerg if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
43906f32e7eSjoerg Dir = *DirEntry;
44006f32e7eSjoerg else
44106f32e7eSjoerg Dir = nullptr;
44206f32e7eSjoerg } while (Dir);
44306f32e7eSjoerg return {};
44406f32e7eSjoerg }
44506f32e7eSjoerg
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)44606f32e7eSjoerg static bool violatesPrivateInclude(Module *RequestingModule,
44706f32e7eSjoerg const FileEntry *IncFileEnt,
44806f32e7eSjoerg ModuleMap::KnownHeader Header) {
44906f32e7eSjoerg #ifndef NDEBUG
45006f32e7eSjoerg if (Header.getRole() & ModuleMap::PrivateHeader) {
45106f32e7eSjoerg // Check for consistency between the module header role
45206f32e7eSjoerg // as obtained from the lookup and as obtained from the module.
45306f32e7eSjoerg // This check is not cheap, so enable it only for debugging.
45406f32e7eSjoerg bool IsPrivate = false;
45506f32e7eSjoerg SmallVectorImpl<Module::Header> *HeaderList[] = {
45606f32e7eSjoerg &Header.getModule()->Headers[Module::HK_Private],
45706f32e7eSjoerg &Header.getModule()->Headers[Module::HK_PrivateTextual]};
45806f32e7eSjoerg for (auto *Hs : HeaderList)
45906f32e7eSjoerg IsPrivate |=
46006f32e7eSjoerg std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
46106f32e7eSjoerg return H.Entry == IncFileEnt;
46206f32e7eSjoerg }) != Hs->end();
46306f32e7eSjoerg assert(IsPrivate && "inconsistent headers and roles");
46406f32e7eSjoerg }
46506f32e7eSjoerg #endif
46606f32e7eSjoerg return !Header.isAccessibleFrom(RequestingModule);
46706f32e7eSjoerg }
46806f32e7eSjoerg
getTopLevelOrNull(Module * M)46906f32e7eSjoerg static Module *getTopLevelOrNull(Module *M) {
47006f32e7eSjoerg return M ? M->getTopLevelModule() : nullptr;
47106f32e7eSjoerg }
47206f32e7eSjoerg
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,const FileEntry * File)47306f32e7eSjoerg void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
47406f32e7eSjoerg bool RequestingModuleIsModuleInterface,
47506f32e7eSjoerg SourceLocation FilenameLoc,
47606f32e7eSjoerg StringRef Filename,
47706f32e7eSjoerg const FileEntry *File) {
47806f32e7eSjoerg // No errors for indirect modules. This may be a bit of a problem for modules
47906f32e7eSjoerg // with no source files.
48006f32e7eSjoerg if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
48106f32e7eSjoerg return;
48206f32e7eSjoerg
48306f32e7eSjoerg if (RequestingModule) {
48406f32e7eSjoerg resolveUses(RequestingModule, /*Complain=*/false);
48506f32e7eSjoerg resolveHeaderDirectives(RequestingModule);
48606f32e7eSjoerg }
48706f32e7eSjoerg
48806f32e7eSjoerg bool Excluded = false;
48906f32e7eSjoerg Module *Private = nullptr;
49006f32e7eSjoerg Module *NotUsed = nullptr;
49106f32e7eSjoerg
49206f32e7eSjoerg HeadersMap::iterator Known = findKnownHeader(File);
49306f32e7eSjoerg if (Known != Headers.end()) {
49406f32e7eSjoerg for (const KnownHeader &Header : Known->second) {
49506f32e7eSjoerg // Remember private headers for later printing of a diagnostic.
49606f32e7eSjoerg if (violatesPrivateInclude(RequestingModule, File, Header)) {
49706f32e7eSjoerg Private = Header.getModule();
49806f32e7eSjoerg continue;
49906f32e7eSjoerg }
50006f32e7eSjoerg
50106f32e7eSjoerg // If uses need to be specified explicitly, we are only allowed to return
50206f32e7eSjoerg // modules that are explicitly used by the requesting module.
50306f32e7eSjoerg if (RequestingModule && LangOpts.ModulesDeclUse &&
50406f32e7eSjoerg !RequestingModule->directlyUses(Header.getModule())) {
50506f32e7eSjoerg NotUsed = Header.getModule();
50606f32e7eSjoerg continue;
50706f32e7eSjoerg }
50806f32e7eSjoerg
50906f32e7eSjoerg // We have found a module that we can happily use.
51006f32e7eSjoerg return;
51106f32e7eSjoerg }
51206f32e7eSjoerg
51306f32e7eSjoerg Excluded = true;
51406f32e7eSjoerg }
51506f32e7eSjoerg
51606f32e7eSjoerg // We have found a header, but it is private.
51706f32e7eSjoerg if (Private) {
51806f32e7eSjoerg Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51906f32e7eSjoerg << Filename;
52006f32e7eSjoerg return;
52106f32e7eSjoerg }
52206f32e7eSjoerg
52306f32e7eSjoerg // We have found a module, but we don't use it.
52406f32e7eSjoerg if (NotUsed) {
52506f32e7eSjoerg Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
52606f32e7eSjoerg << RequestingModule->getTopLevelModule()->Name << Filename;
52706f32e7eSjoerg return;
52806f32e7eSjoerg }
52906f32e7eSjoerg
53006f32e7eSjoerg if (Excluded || isHeaderInUmbrellaDirs(File))
53106f32e7eSjoerg return;
53206f32e7eSjoerg
53306f32e7eSjoerg // At this point, only non-modular includes remain.
53406f32e7eSjoerg
53506f32e7eSjoerg if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
53606f32e7eSjoerg Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
53706f32e7eSjoerg << RequestingModule->getTopLevelModule()->Name << Filename;
53806f32e7eSjoerg } else if (RequestingModule && RequestingModuleIsModuleInterface &&
53906f32e7eSjoerg LangOpts.isCompilingModule()) {
54006f32e7eSjoerg // Do not diagnose when we are not compiling a module.
54106f32e7eSjoerg diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
54206f32e7eSjoerg diag::warn_non_modular_include_in_framework_module :
54306f32e7eSjoerg diag::warn_non_modular_include_in_module;
54406f32e7eSjoerg Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
54506f32e7eSjoerg << File->getName();
54606f32e7eSjoerg }
54706f32e7eSjoerg }
54806f32e7eSjoerg
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)54906f32e7eSjoerg static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
55006f32e7eSjoerg const ModuleMap::KnownHeader &Old) {
55106f32e7eSjoerg // Prefer available modules.
552*13fbcb42Sjoerg // FIXME: Considering whether the module is available rather than merely
553*13fbcb42Sjoerg // importable is non-hermetic and can result in surprising behavior for
554*13fbcb42Sjoerg // prebuilt modules. Consider only checking for importability here.
55506f32e7eSjoerg if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
55606f32e7eSjoerg return true;
55706f32e7eSjoerg
55806f32e7eSjoerg // Prefer a public header over a private header.
55906f32e7eSjoerg if ((New.getRole() & ModuleMap::PrivateHeader) !=
56006f32e7eSjoerg (Old.getRole() & ModuleMap::PrivateHeader))
56106f32e7eSjoerg return !(New.getRole() & ModuleMap::PrivateHeader);
56206f32e7eSjoerg
56306f32e7eSjoerg // Prefer a non-textual header over a textual header.
56406f32e7eSjoerg if ((New.getRole() & ModuleMap::TextualHeader) !=
56506f32e7eSjoerg (Old.getRole() & ModuleMap::TextualHeader))
56606f32e7eSjoerg return !(New.getRole() & ModuleMap::TextualHeader);
56706f32e7eSjoerg
56806f32e7eSjoerg // Don't have a reason to choose between these. Just keep the first one.
56906f32e7eSjoerg return false;
57006f32e7eSjoerg }
57106f32e7eSjoerg
findModuleForHeader(const FileEntry * File,bool AllowTextual)57206f32e7eSjoerg ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
57306f32e7eSjoerg bool AllowTextual) {
57406f32e7eSjoerg auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
57506f32e7eSjoerg if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
57606f32e7eSjoerg return {};
57706f32e7eSjoerg return R;
57806f32e7eSjoerg };
57906f32e7eSjoerg
58006f32e7eSjoerg HeadersMap::iterator Known = findKnownHeader(File);
58106f32e7eSjoerg if (Known != Headers.end()) {
58206f32e7eSjoerg ModuleMap::KnownHeader Result;
58306f32e7eSjoerg // Iterate over all modules that 'File' is part of to find the best fit.
58406f32e7eSjoerg for (KnownHeader &H : Known->second) {
58506f32e7eSjoerg // Prefer a header from the source module over all others.
58606f32e7eSjoerg if (H.getModule()->getTopLevelModule() == SourceModule)
58706f32e7eSjoerg return MakeResult(H);
58806f32e7eSjoerg if (!Result || isBetterKnownHeader(H, Result))
58906f32e7eSjoerg Result = H;
59006f32e7eSjoerg }
59106f32e7eSjoerg return MakeResult(Result);
59206f32e7eSjoerg }
59306f32e7eSjoerg
59406f32e7eSjoerg return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
59506f32e7eSjoerg }
59606f32e7eSjoerg
59706f32e7eSjoerg ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry * File)59806f32e7eSjoerg ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
59906f32e7eSjoerg assert(!Headers.count(File) && "already have a module for this header");
60006f32e7eSjoerg
60106f32e7eSjoerg SmallVector<const DirectoryEntry *, 2> SkippedDirs;
60206f32e7eSjoerg KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
60306f32e7eSjoerg if (H) {
60406f32e7eSjoerg Module *Result = H.getModule();
60506f32e7eSjoerg
60606f32e7eSjoerg // Search up the module stack until we find a module with an umbrella
60706f32e7eSjoerg // directory.
60806f32e7eSjoerg Module *UmbrellaModule = Result;
60906f32e7eSjoerg while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
61006f32e7eSjoerg UmbrellaModule = UmbrellaModule->Parent;
61106f32e7eSjoerg
61206f32e7eSjoerg if (UmbrellaModule->InferSubmodules) {
61306f32e7eSjoerg const FileEntry *UmbrellaModuleMap =
61406f32e7eSjoerg getModuleMapFileForUniquing(UmbrellaModule);
61506f32e7eSjoerg
61606f32e7eSjoerg // Infer submodules for each of the directories we found between
61706f32e7eSjoerg // the directory of the umbrella header and the directory where
61806f32e7eSjoerg // the actual header is located.
61906f32e7eSjoerg bool Explicit = UmbrellaModule->InferExplicitSubmodules;
62006f32e7eSjoerg
62106f32e7eSjoerg for (unsigned I = SkippedDirs.size(); I != 0; --I) {
62206f32e7eSjoerg // Find or create the module that corresponds to this directory name.
62306f32e7eSjoerg SmallString<32> NameBuf;
62406f32e7eSjoerg StringRef Name = sanitizeFilenameAsIdentifier(
62506f32e7eSjoerg llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
62606f32e7eSjoerg Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
62706f32e7eSjoerg Explicit).first;
62806f32e7eSjoerg InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
62906f32e7eSjoerg Result->IsInferred = true;
63006f32e7eSjoerg
63106f32e7eSjoerg // Associate the module and the directory.
63206f32e7eSjoerg UmbrellaDirs[SkippedDirs[I-1]] = Result;
63306f32e7eSjoerg
63406f32e7eSjoerg // If inferred submodules export everything they import, add a
63506f32e7eSjoerg // wildcard to the set of exports.
63606f32e7eSjoerg if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
63706f32e7eSjoerg Result->Exports.push_back(Module::ExportDecl(nullptr, true));
63806f32e7eSjoerg }
63906f32e7eSjoerg
64006f32e7eSjoerg // Infer a submodule with the same name as this header file.
64106f32e7eSjoerg SmallString<32> NameBuf;
64206f32e7eSjoerg StringRef Name = sanitizeFilenameAsIdentifier(
64306f32e7eSjoerg llvm::sys::path::stem(File->getName()), NameBuf);
64406f32e7eSjoerg Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
64506f32e7eSjoerg Explicit).first;
64606f32e7eSjoerg InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
64706f32e7eSjoerg Result->IsInferred = true;
64806f32e7eSjoerg Result->addTopHeader(File);
64906f32e7eSjoerg
65006f32e7eSjoerg // If inferred submodules export everything they import, add a
65106f32e7eSjoerg // wildcard to the set of exports.
65206f32e7eSjoerg if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
65306f32e7eSjoerg Result->Exports.push_back(Module::ExportDecl(nullptr, true));
65406f32e7eSjoerg } else {
65506f32e7eSjoerg // Record each of the directories we stepped through as being part of
65606f32e7eSjoerg // the module we found, since the umbrella header covers them all.
65706f32e7eSjoerg for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
65806f32e7eSjoerg UmbrellaDirs[SkippedDirs[I]] = Result;
65906f32e7eSjoerg }
66006f32e7eSjoerg
66106f32e7eSjoerg KnownHeader Header(Result, NormalHeader);
66206f32e7eSjoerg Headers[File].push_back(Header);
66306f32e7eSjoerg return Header;
66406f32e7eSjoerg }
66506f32e7eSjoerg
66606f32e7eSjoerg return {};
66706f32e7eSjoerg }
66806f32e7eSjoerg
66906f32e7eSjoerg ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File)670*13fbcb42Sjoerg ModuleMap::findAllModulesForHeader(const FileEntry *File) {
671*13fbcb42Sjoerg HeadersMap::iterator Known = findKnownHeader(File);
672*13fbcb42Sjoerg if (Known != Headers.end())
673*13fbcb42Sjoerg return Known->second;
674*13fbcb42Sjoerg
675*13fbcb42Sjoerg if (findOrCreateModuleForHeaderInUmbrellaDir(File))
676*13fbcb42Sjoerg return Headers.find(File)->second;
677*13fbcb42Sjoerg
678*13fbcb42Sjoerg return None;
679*13fbcb42Sjoerg }
680*13fbcb42Sjoerg
681*13fbcb42Sjoerg ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(const FileEntry * File) const682*13fbcb42Sjoerg ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
683*13fbcb42Sjoerg // FIXME: Is this necessary?
68406f32e7eSjoerg resolveHeaderDirectives(File);
68506f32e7eSjoerg auto It = Headers.find(File);
68606f32e7eSjoerg if (It == Headers.end())
68706f32e7eSjoerg return None;
68806f32e7eSjoerg return It->second;
68906f32e7eSjoerg }
69006f32e7eSjoerg
isHeaderInUnavailableModule(const FileEntry * Header) const69106f32e7eSjoerg bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
69206f32e7eSjoerg return isHeaderUnavailableInModule(Header, nullptr);
69306f32e7eSjoerg }
69406f32e7eSjoerg
69506f32e7eSjoerg bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const69606f32e7eSjoerg ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
69706f32e7eSjoerg const Module *RequestingModule) const {
69806f32e7eSjoerg resolveHeaderDirectives(Header);
69906f32e7eSjoerg HeadersMap::const_iterator Known = Headers.find(Header);
70006f32e7eSjoerg if (Known != Headers.end()) {
70106f32e7eSjoerg for (SmallVectorImpl<KnownHeader>::const_iterator
70206f32e7eSjoerg I = Known->second.begin(),
70306f32e7eSjoerg E = Known->second.end();
70406f32e7eSjoerg I != E; ++I) {
70506f32e7eSjoerg
70606f32e7eSjoerg if (I->isAvailable() &&
70706f32e7eSjoerg (!RequestingModule ||
70806f32e7eSjoerg I->getModule()->isSubModuleOf(RequestingModule))) {
70906f32e7eSjoerg // When no requesting module is available, the caller is looking if a
71006f32e7eSjoerg // header is part a module by only looking into the module map. This is
71106f32e7eSjoerg // done by warn_uncovered_module_header checks; don't consider textual
71206f32e7eSjoerg // headers part of it in this mode, otherwise we get misleading warnings
71306f32e7eSjoerg // that a umbrella header is not including a textual header.
71406f32e7eSjoerg if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
71506f32e7eSjoerg continue;
71606f32e7eSjoerg return false;
71706f32e7eSjoerg }
71806f32e7eSjoerg }
71906f32e7eSjoerg return true;
72006f32e7eSjoerg }
72106f32e7eSjoerg
72206f32e7eSjoerg const DirectoryEntry *Dir = Header->getDir();
72306f32e7eSjoerg SmallVector<const DirectoryEntry *, 2> SkippedDirs;
72406f32e7eSjoerg StringRef DirName = Dir->getName();
72506f32e7eSjoerg
72606f32e7eSjoerg auto IsUnavailable = [&](const Module *M) {
72706f32e7eSjoerg return !M->isAvailable() && (!RequestingModule ||
72806f32e7eSjoerg M->isSubModuleOf(RequestingModule));
72906f32e7eSjoerg };
73006f32e7eSjoerg
73106f32e7eSjoerg // Keep walking up the directory hierarchy, looking for a directory with
73206f32e7eSjoerg // an umbrella header.
73306f32e7eSjoerg do {
73406f32e7eSjoerg llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
73506f32e7eSjoerg = UmbrellaDirs.find(Dir);
73606f32e7eSjoerg if (KnownDir != UmbrellaDirs.end()) {
73706f32e7eSjoerg Module *Found = KnownDir->second;
73806f32e7eSjoerg if (IsUnavailable(Found))
73906f32e7eSjoerg return true;
74006f32e7eSjoerg
74106f32e7eSjoerg // Search up the module stack until we find a module with an umbrella
74206f32e7eSjoerg // directory.
74306f32e7eSjoerg Module *UmbrellaModule = Found;
74406f32e7eSjoerg while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
74506f32e7eSjoerg UmbrellaModule = UmbrellaModule->Parent;
74606f32e7eSjoerg
74706f32e7eSjoerg if (UmbrellaModule->InferSubmodules) {
74806f32e7eSjoerg for (unsigned I = SkippedDirs.size(); I != 0; --I) {
74906f32e7eSjoerg // Find or create the module that corresponds to this directory name.
75006f32e7eSjoerg SmallString<32> NameBuf;
75106f32e7eSjoerg StringRef Name = sanitizeFilenameAsIdentifier(
75206f32e7eSjoerg llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
75306f32e7eSjoerg NameBuf);
75406f32e7eSjoerg Found = lookupModuleQualified(Name, Found);
75506f32e7eSjoerg if (!Found)
75606f32e7eSjoerg return false;
75706f32e7eSjoerg if (IsUnavailable(Found))
75806f32e7eSjoerg return true;
75906f32e7eSjoerg }
76006f32e7eSjoerg
76106f32e7eSjoerg // Infer a submodule with the same name as this header file.
76206f32e7eSjoerg SmallString<32> NameBuf;
76306f32e7eSjoerg StringRef Name = sanitizeFilenameAsIdentifier(
76406f32e7eSjoerg llvm::sys::path::stem(Header->getName()),
76506f32e7eSjoerg NameBuf);
76606f32e7eSjoerg Found = lookupModuleQualified(Name, Found);
76706f32e7eSjoerg if (!Found)
76806f32e7eSjoerg return false;
76906f32e7eSjoerg }
77006f32e7eSjoerg
77106f32e7eSjoerg return IsUnavailable(Found);
77206f32e7eSjoerg }
77306f32e7eSjoerg
77406f32e7eSjoerg SkippedDirs.push_back(Dir);
77506f32e7eSjoerg
77606f32e7eSjoerg // Retrieve our parent path.
77706f32e7eSjoerg DirName = llvm::sys::path::parent_path(DirName);
77806f32e7eSjoerg if (DirName.empty())
77906f32e7eSjoerg break;
78006f32e7eSjoerg
78106f32e7eSjoerg // Resolve the parent path to a directory entry.
78206f32e7eSjoerg if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
78306f32e7eSjoerg Dir = *DirEntry;
78406f32e7eSjoerg else
78506f32e7eSjoerg Dir = nullptr;
78606f32e7eSjoerg } while (Dir);
78706f32e7eSjoerg
78806f32e7eSjoerg return false;
78906f32e7eSjoerg }
79006f32e7eSjoerg
findModule(StringRef Name) const79106f32e7eSjoerg Module *ModuleMap::findModule(StringRef Name) const {
79206f32e7eSjoerg llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
79306f32e7eSjoerg if (Known != Modules.end())
79406f32e7eSjoerg return Known->getValue();
79506f32e7eSjoerg
79606f32e7eSjoerg return nullptr;
79706f32e7eSjoerg }
79806f32e7eSjoerg
lookupModuleUnqualified(StringRef Name,Module * Context) const79906f32e7eSjoerg Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
80006f32e7eSjoerg Module *Context) const {
80106f32e7eSjoerg for(; Context; Context = Context->Parent) {
80206f32e7eSjoerg if (Module *Sub = lookupModuleQualified(Name, Context))
80306f32e7eSjoerg return Sub;
80406f32e7eSjoerg }
80506f32e7eSjoerg
80606f32e7eSjoerg return findModule(Name);
80706f32e7eSjoerg }
80806f32e7eSjoerg
lookupModuleQualified(StringRef Name,Module * Context) const80906f32e7eSjoerg Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
81006f32e7eSjoerg if (!Context)
81106f32e7eSjoerg return findModule(Name);
81206f32e7eSjoerg
81306f32e7eSjoerg return Context->findSubmodule(Name);
81406f32e7eSjoerg }
81506f32e7eSjoerg
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)81606f32e7eSjoerg std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
81706f32e7eSjoerg Module *Parent,
81806f32e7eSjoerg bool IsFramework,
81906f32e7eSjoerg bool IsExplicit) {
82006f32e7eSjoerg // Try to find an existing module with this name.
82106f32e7eSjoerg if (Module *Sub = lookupModuleQualified(Name, Parent))
82206f32e7eSjoerg return std::make_pair(Sub, false);
82306f32e7eSjoerg
82406f32e7eSjoerg // Create a new module with this name.
82506f32e7eSjoerg Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
82606f32e7eSjoerg IsExplicit, NumCreatedModules++);
82706f32e7eSjoerg if (!Parent) {
82806f32e7eSjoerg if (LangOpts.CurrentModule == Name)
82906f32e7eSjoerg SourceModule = Result;
83006f32e7eSjoerg Modules[Name] = Result;
83106f32e7eSjoerg ModuleScopeIDs[Result] = CurrentModuleScopeID;
83206f32e7eSjoerg }
83306f32e7eSjoerg return std::make_pair(Result, true);
83406f32e7eSjoerg }
83506f32e7eSjoerg
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc)83606f32e7eSjoerg Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
83706f32e7eSjoerg PendingSubmodules.emplace_back(
83806f32e7eSjoerg new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
83906f32e7eSjoerg /*IsExplicit*/ true, NumCreatedModules++));
84006f32e7eSjoerg PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
84106f32e7eSjoerg return PendingSubmodules.back().get();
84206f32e7eSjoerg }
84306f32e7eSjoerg
84406f32e7eSjoerg Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)84506f32e7eSjoerg ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
84606f32e7eSjoerg SourceLocation Loc) {
84706f32e7eSjoerg auto *Result =
84806f32e7eSjoerg new Module("<private>", Loc, Parent, /*IsFramework*/ false,
84906f32e7eSjoerg /*IsExplicit*/ true, NumCreatedModules++);
85006f32e7eSjoerg Result->Kind = Module::PrivateModuleFragment;
85106f32e7eSjoerg return Result;
85206f32e7eSjoerg }
85306f32e7eSjoerg
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name,Module * GlobalModule)85406f32e7eSjoerg Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
85506f32e7eSjoerg StringRef Name,
85606f32e7eSjoerg Module *GlobalModule) {
85706f32e7eSjoerg assert(LangOpts.CurrentModule == Name && "module name mismatch");
85806f32e7eSjoerg assert(!Modules[Name] && "redefining existing module");
85906f32e7eSjoerg
86006f32e7eSjoerg auto *Result =
86106f32e7eSjoerg new Module(Name, Loc, nullptr, /*IsFramework*/ false,
86206f32e7eSjoerg /*IsExplicit*/ false, NumCreatedModules++);
86306f32e7eSjoerg Result->Kind = Module::ModuleInterfaceUnit;
86406f32e7eSjoerg Modules[Name] = SourceModule = Result;
86506f32e7eSjoerg
86606f32e7eSjoerg // Reparent the current global module fragment as a submodule of this module.
86706f32e7eSjoerg for (auto &Submodule : PendingSubmodules) {
86806f32e7eSjoerg Submodule->setParent(Result);
86906f32e7eSjoerg Submodule.release(); // now owned by parent
87006f32e7eSjoerg }
87106f32e7eSjoerg PendingSubmodules.clear();
87206f32e7eSjoerg
87306f32e7eSjoerg // Mark the main source file as being within the newly-created module so that
87406f32e7eSjoerg // declarations and macros are properly visibility-restricted to it.
87506f32e7eSjoerg auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
87606f32e7eSjoerg assert(MainFile && "no input file for module interface");
87706f32e7eSjoerg Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
87806f32e7eSjoerg
87906f32e7eSjoerg return Result;
88006f32e7eSjoerg }
88106f32e7eSjoerg
createHeaderModule(StringRef Name,ArrayRef<Module::Header> Headers)88206f32e7eSjoerg Module *ModuleMap::createHeaderModule(StringRef Name,
88306f32e7eSjoerg ArrayRef<Module::Header> Headers) {
88406f32e7eSjoerg assert(LangOpts.CurrentModule == Name && "module name mismatch");
88506f32e7eSjoerg assert(!Modules[Name] && "redefining existing module");
88606f32e7eSjoerg
88706f32e7eSjoerg auto *Result =
88806f32e7eSjoerg new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
88906f32e7eSjoerg /*IsExplicit*/ false, NumCreatedModules++);
89006f32e7eSjoerg Result->Kind = Module::ModuleInterfaceUnit;
89106f32e7eSjoerg Modules[Name] = SourceModule = Result;
89206f32e7eSjoerg
89306f32e7eSjoerg for (const Module::Header &H : Headers) {
89406f32e7eSjoerg auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
89506f32e7eSjoerg /*IsFramework*/ false,
89606f32e7eSjoerg /*IsExplicit*/ true, NumCreatedModules++);
89706f32e7eSjoerg // Header modules are implicitly 'export *'.
89806f32e7eSjoerg M->Exports.push_back(Module::ExportDecl(nullptr, true));
89906f32e7eSjoerg addHeader(M, H, NormalHeader);
90006f32e7eSjoerg }
90106f32e7eSjoerg
90206f32e7eSjoerg return Result;
90306f32e7eSjoerg }
90406f32e7eSjoerg
90506f32e7eSjoerg /// For a framework module, infer the framework against which we
90606f32e7eSjoerg /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)90706f32e7eSjoerg static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
90806f32e7eSjoerg FileManager &FileMgr) {
90906f32e7eSjoerg assert(Mod->IsFramework && "Can only infer linking for framework modules");
91006f32e7eSjoerg assert(!Mod->isSubFramework() &&
91106f32e7eSjoerg "Can only infer linking for top-level frameworks");
91206f32e7eSjoerg
91306f32e7eSjoerg SmallString<128> LibName;
91406f32e7eSjoerg LibName += FrameworkDir->getName();
91506f32e7eSjoerg llvm::sys::path::append(LibName, Mod->Name);
91606f32e7eSjoerg
91706f32e7eSjoerg // The library name of a framework has more than one possible extension since
91806f32e7eSjoerg // the introduction of the text-based dynamic library format. We need to check
91906f32e7eSjoerg // for both before we give up.
92006f32e7eSjoerg for (const char *extension : {"", ".tbd"}) {
92106f32e7eSjoerg llvm::sys::path::replace_extension(LibName, extension);
92206f32e7eSjoerg if (FileMgr.getFile(LibName)) {
92306f32e7eSjoerg Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
92406f32e7eSjoerg /*IsFramework=*/true));
92506f32e7eSjoerg return;
92606f32e7eSjoerg }
92706f32e7eSjoerg }
92806f32e7eSjoerg }
92906f32e7eSjoerg
inferFrameworkModule(const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)93006f32e7eSjoerg Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
93106f32e7eSjoerg bool IsSystem, Module *Parent) {
93206f32e7eSjoerg Attributes Attrs;
93306f32e7eSjoerg Attrs.IsSystem = IsSystem;
93406f32e7eSjoerg return inferFrameworkModule(FrameworkDir, Attrs, Parent);
93506f32e7eSjoerg }
93606f32e7eSjoerg
inferFrameworkModule(const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)93706f32e7eSjoerg Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
93806f32e7eSjoerg Attributes Attrs, Module *Parent) {
93906f32e7eSjoerg // Note: as an egregious but useful hack we use the real path here, because
94006f32e7eSjoerg // we might be looking at an embedded framework that symlinks out to a
94106f32e7eSjoerg // top-level framework, and we need to infer as if we were naming the
94206f32e7eSjoerg // top-level framework.
94306f32e7eSjoerg StringRef FrameworkDirName =
94406f32e7eSjoerg SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
94506f32e7eSjoerg
94606f32e7eSjoerg // In case this is a case-insensitive filesystem, use the canonical
94706f32e7eSjoerg // directory name as the ModuleName, since modules are case-sensitive.
94806f32e7eSjoerg // FIXME: we should be able to give a fix-it hint for the correct spelling.
94906f32e7eSjoerg SmallString<32> ModuleNameStorage;
95006f32e7eSjoerg StringRef ModuleName = sanitizeFilenameAsIdentifier(
95106f32e7eSjoerg llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
95206f32e7eSjoerg
95306f32e7eSjoerg // Check whether we've already found this module.
95406f32e7eSjoerg if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
95506f32e7eSjoerg return Mod;
95606f32e7eSjoerg
95706f32e7eSjoerg FileManager &FileMgr = SourceMgr.getFileManager();
95806f32e7eSjoerg
95906f32e7eSjoerg // If the framework has a parent path from which we're allowed to infer
96006f32e7eSjoerg // a framework module, do so.
96106f32e7eSjoerg const FileEntry *ModuleMapFile = nullptr;
96206f32e7eSjoerg if (!Parent) {
96306f32e7eSjoerg // Determine whether we're allowed to infer a module map.
96406f32e7eSjoerg bool canInfer = false;
96506f32e7eSjoerg if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
96606f32e7eSjoerg // Figure out the parent path.
96706f32e7eSjoerg StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
96806f32e7eSjoerg if (auto ParentDir = FileMgr.getDirectory(Parent)) {
96906f32e7eSjoerg // Check whether we have already looked into the parent directory
97006f32e7eSjoerg // for a module map.
97106f32e7eSjoerg llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
97206f32e7eSjoerg inferred = InferredDirectories.find(*ParentDir);
97306f32e7eSjoerg if (inferred == InferredDirectories.end()) {
97406f32e7eSjoerg // We haven't looked here before. Load a module map, if there is
97506f32e7eSjoerg // one.
97606f32e7eSjoerg bool IsFrameworkDir = Parent.endswith(".framework");
97706f32e7eSjoerg if (const FileEntry *ModMapFile =
97806f32e7eSjoerg HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
97906f32e7eSjoerg parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
98006f32e7eSjoerg inferred = InferredDirectories.find(*ParentDir);
98106f32e7eSjoerg }
98206f32e7eSjoerg
98306f32e7eSjoerg if (inferred == InferredDirectories.end())
98406f32e7eSjoerg inferred = InferredDirectories.insert(
98506f32e7eSjoerg std::make_pair(*ParentDir, InferredDirectory())).first;
98606f32e7eSjoerg }
98706f32e7eSjoerg
98806f32e7eSjoerg if (inferred->second.InferModules) {
98906f32e7eSjoerg // We're allowed to infer for this directory, but make sure it's okay
99006f32e7eSjoerg // to infer this particular module.
99106f32e7eSjoerg StringRef Name = llvm::sys::path::stem(FrameworkDirName);
99206f32e7eSjoerg canInfer = std::find(inferred->second.ExcludedModules.begin(),
99306f32e7eSjoerg inferred->second.ExcludedModules.end(),
99406f32e7eSjoerg Name) == inferred->second.ExcludedModules.end();
99506f32e7eSjoerg
99606f32e7eSjoerg Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
99706f32e7eSjoerg Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
99806f32e7eSjoerg Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
99906f32e7eSjoerg Attrs.NoUndeclaredIncludes |=
100006f32e7eSjoerg inferred->second.Attrs.NoUndeclaredIncludes;
100106f32e7eSjoerg ModuleMapFile = inferred->second.ModuleMapFile;
100206f32e7eSjoerg }
100306f32e7eSjoerg }
100406f32e7eSjoerg }
100506f32e7eSjoerg
100606f32e7eSjoerg // If we're not allowed to infer a framework module, don't.
100706f32e7eSjoerg if (!canInfer)
100806f32e7eSjoerg return nullptr;
100906f32e7eSjoerg } else
101006f32e7eSjoerg ModuleMapFile = getModuleMapFileForUniquing(Parent);
101106f32e7eSjoerg
101206f32e7eSjoerg
101306f32e7eSjoerg // Look for an umbrella header.
101406f32e7eSjoerg SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
101506f32e7eSjoerg llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
101606f32e7eSjoerg auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
101706f32e7eSjoerg
101806f32e7eSjoerg // FIXME: If there's no umbrella header, we could probably scan the
101906f32e7eSjoerg // framework to load *everything*. But, it's not clear that this is a good
102006f32e7eSjoerg // idea.
102106f32e7eSjoerg if (!UmbrellaHeader)
102206f32e7eSjoerg return nullptr;
102306f32e7eSjoerg
102406f32e7eSjoerg Module *Result = new Module(ModuleName, SourceLocation(), Parent,
102506f32e7eSjoerg /*IsFramework=*/true, /*IsExplicit=*/false,
102606f32e7eSjoerg NumCreatedModules++);
102706f32e7eSjoerg InferredModuleAllowedBy[Result] = ModuleMapFile;
102806f32e7eSjoerg Result->IsInferred = true;
102906f32e7eSjoerg if (!Parent) {
103006f32e7eSjoerg if (LangOpts.CurrentModule == ModuleName)
103106f32e7eSjoerg SourceModule = Result;
103206f32e7eSjoerg Modules[ModuleName] = Result;
103306f32e7eSjoerg ModuleScopeIDs[Result] = CurrentModuleScopeID;
103406f32e7eSjoerg }
103506f32e7eSjoerg
103606f32e7eSjoerg Result->IsSystem |= Attrs.IsSystem;
103706f32e7eSjoerg Result->IsExternC |= Attrs.IsExternC;
103806f32e7eSjoerg Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
103906f32e7eSjoerg Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
104006f32e7eSjoerg Result->Directory = FrameworkDir;
104106f32e7eSjoerg
1042*13fbcb42Sjoerg // Chop off the first framework bit, as that is implied.
1043*13fbcb42Sjoerg StringRef RelativePath = UmbrellaName.str().substr(
1044*13fbcb42Sjoerg Result->getTopLevelModule()->Directory->getName().size());
1045*13fbcb42Sjoerg RelativePath = llvm::sys::path::relative_path(RelativePath);
1046*13fbcb42Sjoerg
104706f32e7eSjoerg // umbrella header "umbrella-header-name"
1048*13fbcb42Sjoerg setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
104906f32e7eSjoerg
105006f32e7eSjoerg // export *
105106f32e7eSjoerg Result->Exports.push_back(Module::ExportDecl(nullptr, true));
105206f32e7eSjoerg
105306f32e7eSjoerg // module * { export * }
105406f32e7eSjoerg Result->InferSubmodules = true;
105506f32e7eSjoerg Result->InferExportWildcard = true;
105606f32e7eSjoerg
105706f32e7eSjoerg // Look for subframeworks.
105806f32e7eSjoerg std::error_code EC;
105906f32e7eSjoerg SmallString<128> SubframeworksDirName
106006f32e7eSjoerg = StringRef(FrameworkDir->getName());
106106f32e7eSjoerg llvm::sys::path::append(SubframeworksDirName, "Frameworks");
106206f32e7eSjoerg llvm::sys::path::native(SubframeworksDirName);
106306f32e7eSjoerg llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
106406f32e7eSjoerg for (llvm::vfs::directory_iterator
106506f32e7eSjoerg Dir = FS.dir_begin(SubframeworksDirName, EC),
106606f32e7eSjoerg DirEnd;
106706f32e7eSjoerg Dir != DirEnd && !EC; Dir.increment(EC)) {
106806f32e7eSjoerg if (!StringRef(Dir->path()).endswith(".framework"))
106906f32e7eSjoerg continue;
107006f32e7eSjoerg
107106f32e7eSjoerg if (auto SubframeworkDir =
107206f32e7eSjoerg FileMgr.getDirectory(Dir->path())) {
107306f32e7eSjoerg // Note: as an egregious but useful hack, we use the real path here and
107406f32e7eSjoerg // check whether it is actually a subdirectory of the parent directory.
107506f32e7eSjoerg // This will not be the case if the 'subframework' is actually a symlink
107606f32e7eSjoerg // out to a top-level framework.
107706f32e7eSjoerg StringRef SubframeworkDirName =
107806f32e7eSjoerg FileMgr.getCanonicalName(*SubframeworkDir);
107906f32e7eSjoerg bool FoundParent = false;
108006f32e7eSjoerg do {
108106f32e7eSjoerg // Get the parent directory name.
108206f32e7eSjoerg SubframeworkDirName
108306f32e7eSjoerg = llvm::sys::path::parent_path(SubframeworkDirName);
108406f32e7eSjoerg if (SubframeworkDirName.empty())
108506f32e7eSjoerg break;
108606f32e7eSjoerg
108706f32e7eSjoerg if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
108806f32e7eSjoerg if (*SubDir == FrameworkDir) {
108906f32e7eSjoerg FoundParent = true;
109006f32e7eSjoerg break;
109106f32e7eSjoerg }
109206f32e7eSjoerg }
109306f32e7eSjoerg } while (true);
109406f32e7eSjoerg
109506f32e7eSjoerg if (!FoundParent)
109606f32e7eSjoerg continue;
109706f32e7eSjoerg
109806f32e7eSjoerg // FIXME: Do we want to warn about subframeworks without umbrella headers?
109906f32e7eSjoerg inferFrameworkModule(*SubframeworkDir, Attrs, Result);
110006f32e7eSjoerg }
110106f32e7eSjoerg }
110206f32e7eSjoerg
110306f32e7eSjoerg // If the module is a top-level framework, automatically link against the
110406f32e7eSjoerg // framework.
110506f32e7eSjoerg if (!Result->isSubFramework()) {
110606f32e7eSjoerg inferFrameworkLink(Result, FrameworkDir, FileMgr);
110706f32e7eSjoerg }
110806f32e7eSjoerg
110906f32e7eSjoerg return Result;
111006f32e7eSjoerg }
111106f32e7eSjoerg
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)111206f32e7eSjoerg Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
111306f32e7eSjoerg Module *ShadowingModule) {
111406f32e7eSjoerg
111506f32e7eSjoerg // Create a new module with this name.
111606f32e7eSjoerg Module *Result =
111706f32e7eSjoerg new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
111806f32e7eSjoerg /*IsExplicit=*/false, NumCreatedModules++);
111906f32e7eSjoerg Result->ShadowingModule = ShadowingModule;
1120*13fbcb42Sjoerg Result->markUnavailable(/*Unimportable*/true);
112106f32e7eSjoerg ModuleScopeIDs[Result] = CurrentModuleScopeID;
112206f32e7eSjoerg ShadowModules.push_back(Result);
112306f32e7eSjoerg
112406f32e7eSjoerg return Result;
112506f32e7eSjoerg }
112606f32e7eSjoerg
setUmbrellaHeader(Module * Mod,const FileEntry * UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1127*13fbcb42Sjoerg void ModuleMap::setUmbrellaHeader(
1128*13fbcb42Sjoerg Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten,
1129*13fbcb42Sjoerg const Twine &PathRelativeToRootModuleDirectory) {
113006f32e7eSjoerg Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
113106f32e7eSjoerg Mod->Umbrella = UmbrellaHeader;
113206f32e7eSjoerg Mod->UmbrellaAsWritten = NameAsWritten.str();
1133*13fbcb42Sjoerg Mod->UmbrellaRelativeToRootModuleDirectory =
1134*13fbcb42Sjoerg PathRelativeToRootModuleDirectory.str();
113506f32e7eSjoerg UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
113606f32e7eSjoerg
113706f32e7eSjoerg // Notify callbacks that we just added a new header.
113806f32e7eSjoerg for (const auto &Cb : Callbacks)
113906f32e7eSjoerg Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
114006f32e7eSjoerg }
114106f32e7eSjoerg
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)114206f32e7eSjoerg void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1143*13fbcb42Sjoerg const Twine &NameAsWritten,
1144*13fbcb42Sjoerg const Twine &PathRelativeToRootModuleDirectory) {
114506f32e7eSjoerg Mod->Umbrella = UmbrellaDir;
114606f32e7eSjoerg Mod->UmbrellaAsWritten = NameAsWritten.str();
1147*13fbcb42Sjoerg Mod->UmbrellaRelativeToRootModuleDirectory =
1148*13fbcb42Sjoerg PathRelativeToRootModuleDirectory.str();
114906f32e7eSjoerg UmbrellaDirs[UmbrellaDir] = Mod;
115006f32e7eSjoerg }
115106f32e7eSjoerg
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)115206f32e7eSjoerg void ModuleMap::addUnresolvedHeader(Module *Mod,
115306f32e7eSjoerg Module::UnresolvedHeaderDirective Header,
115406f32e7eSjoerg bool &NeedsFramework) {
115506f32e7eSjoerg // If there is a builtin counterpart to this file, add it now so it can
115606f32e7eSjoerg // wrap the system header.
115706f32e7eSjoerg if (resolveAsBuiltinHeader(Mod, Header)) {
115806f32e7eSjoerg // If we have both a builtin and system version of the file, the
115906f32e7eSjoerg // builtin version may want to inject macros into the system header, so
116006f32e7eSjoerg // force the system header to be treated as a textual header in this
116106f32e7eSjoerg // case.
116206f32e7eSjoerg Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
116306f32e7eSjoerg headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
116406f32e7eSjoerg Header.HasBuiltinHeader = true;
116506f32e7eSjoerg }
116606f32e7eSjoerg
116706f32e7eSjoerg // If possible, don't stat the header until we need to. This requires the
116806f32e7eSjoerg // user to have provided us with some stat information about the file.
116906f32e7eSjoerg // FIXME: Add support for lazily stat'ing umbrella headers and excluded
117006f32e7eSjoerg // headers.
117106f32e7eSjoerg if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
117206f32e7eSjoerg Header.Kind != Module::HK_Excluded) {
117306f32e7eSjoerg // We expect more variation in mtime than size, so if we're given both,
117406f32e7eSjoerg // use the mtime as the key.
117506f32e7eSjoerg if (Header.ModTime)
117606f32e7eSjoerg LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
117706f32e7eSjoerg else
117806f32e7eSjoerg LazyHeadersBySize[*Header.Size].push_back(Mod);
117906f32e7eSjoerg Mod->UnresolvedHeaders.push_back(Header);
118006f32e7eSjoerg return;
118106f32e7eSjoerg }
118206f32e7eSjoerg
118306f32e7eSjoerg // We don't have stat information or can't defer looking this file up.
118406f32e7eSjoerg // Perform the lookup now.
118506f32e7eSjoerg resolveHeader(Mod, Header, NeedsFramework);
118606f32e7eSjoerg }
118706f32e7eSjoerg
resolveHeaderDirectives(const FileEntry * File) const118806f32e7eSjoerg void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
118906f32e7eSjoerg auto BySize = LazyHeadersBySize.find(File->getSize());
119006f32e7eSjoerg if (BySize != LazyHeadersBySize.end()) {
119106f32e7eSjoerg for (auto *M : BySize->second)
119206f32e7eSjoerg resolveHeaderDirectives(M);
119306f32e7eSjoerg LazyHeadersBySize.erase(BySize);
119406f32e7eSjoerg }
119506f32e7eSjoerg
119606f32e7eSjoerg auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
119706f32e7eSjoerg if (ByModTime != LazyHeadersByModTime.end()) {
119806f32e7eSjoerg for (auto *M : ByModTime->second)
119906f32e7eSjoerg resolveHeaderDirectives(M);
120006f32e7eSjoerg LazyHeadersByModTime.erase(ByModTime);
120106f32e7eSjoerg }
120206f32e7eSjoerg }
120306f32e7eSjoerg
resolveHeaderDirectives(Module * Mod) const120406f32e7eSjoerg void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
120506f32e7eSjoerg bool NeedsFramework = false;
120606f32e7eSjoerg for (auto &Header : Mod->UnresolvedHeaders)
120706f32e7eSjoerg // This operation is logically const; we're just changing how we represent
120806f32e7eSjoerg // the header information for this file.
120906f32e7eSjoerg const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
121006f32e7eSjoerg Mod->UnresolvedHeaders.clear();
121106f32e7eSjoerg }
121206f32e7eSjoerg
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)121306f32e7eSjoerg void ModuleMap::addHeader(Module *Mod, Module::Header Header,
121406f32e7eSjoerg ModuleHeaderRole Role, bool Imported) {
121506f32e7eSjoerg KnownHeader KH(Mod, Role);
121606f32e7eSjoerg
121706f32e7eSjoerg // Only add each header to the headers list once.
121806f32e7eSjoerg // FIXME: Should we diagnose if a header is listed twice in the
121906f32e7eSjoerg // same module definition?
122006f32e7eSjoerg auto &HeaderList = Headers[Header.Entry];
122106f32e7eSjoerg for (auto H : HeaderList)
122206f32e7eSjoerg if (H == KH)
122306f32e7eSjoerg return;
122406f32e7eSjoerg
122506f32e7eSjoerg HeaderList.push_back(KH);
122606f32e7eSjoerg Mod->Headers[headerRoleToKind(Role)].push_back(Header);
122706f32e7eSjoerg
122806f32e7eSjoerg bool isCompilingModuleHeader =
122906f32e7eSjoerg LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
123006f32e7eSjoerg if (!Imported || isCompilingModuleHeader) {
123106f32e7eSjoerg // When we import HeaderFileInfo, the external source is expected to
123206f32e7eSjoerg // set the isModuleHeader flag itself.
123306f32e7eSjoerg HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
123406f32e7eSjoerg isCompilingModuleHeader);
123506f32e7eSjoerg }
123606f32e7eSjoerg
123706f32e7eSjoerg // Notify callbacks that we just added a new header.
123806f32e7eSjoerg for (const auto &Cb : Callbacks)
123906f32e7eSjoerg Cb->moduleMapAddHeader(Header.Entry->getName());
124006f32e7eSjoerg }
124106f32e7eSjoerg
excludeHeader(Module * Mod,Module::Header Header)124206f32e7eSjoerg void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
124306f32e7eSjoerg // Add this as a known header so we won't implicitly add it to any
124406f32e7eSjoerg // umbrella directory module.
124506f32e7eSjoerg // FIXME: Should we only exclude it from umbrella modules within the
124606f32e7eSjoerg // specified module?
124706f32e7eSjoerg (void) Headers[Header.Entry];
124806f32e7eSjoerg
124906f32e7eSjoerg Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
125006f32e7eSjoerg }
125106f32e7eSjoerg
125206f32e7eSjoerg const FileEntry *
getContainingModuleMapFile(const Module * Module) const125306f32e7eSjoerg ModuleMap::getContainingModuleMapFile(const Module *Module) const {
125406f32e7eSjoerg if (Module->DefinitionLoc.isInvalid())
125506f32e7eSjoerg return nullptr;
125606f32e7eSjoerg
125706f32e7eSjoerg return SourceMgr.getFileEntryForID(
125806f32e7eSjoerg SourceMgr.getFileID(Module->DefinitionLoc));
125906f32e7eSjoerg }
126006f32e7eSjoerg
getModuleMapFileForUniquing(const Module * M) const126106f32e7eSjoerg const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
126206f32e7eSjoerg if (M->IsInferred) {
126306f32e7eSjoerg assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
126406f32e7eSjoerg return InferredModuleAllowedBy.find(M)->second;
126506f32e7eSjoerg }
126606f32e7eSjoerg return getContainingModuleMapFile(M);
126706f32e7eSjoerg }
126806f32e7eSjoerg
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)126906f32e7eSjoerg void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
127006f32e7eSjoerg assert(M->IsInferred && "module not inferred");
127106f32e7eSjoerg InferredModuleAllowedBy[M] = ModMap;
127206f32e7eSjoerg }
127306f32e7eSjoerg
addAdditionalModuleMapFile(const Module * M,const FileEntry * ModuleMap)1274*13fbcb42Sjoerg void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1275*13fbcb42Sjoerg const FileEntry *ModuleMap) {
1276*13fbcb42Sjoerg AdditionalModMaps[M].insert(ModuleMap);
1277*13fbcb42Sjoerg }
1278*13fbcb42Sjoerg
dump()127906f32e7eSjoerg LLVM_DUMP_METHOD void ModuleMap::dump() {
128006f32e7eSjoerg llvm::errs() << "Modules:";
128106f32e7eSjoerg for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
128206f32e7eSjoerg MEnd = Modules.end();
128306f32e7eSjoerg M != MEnd; ++M)
128406f32e7eSjoerg M->getValue()->print(llvm::errs(), 2);
128506f32e7eSjoerg
128606f32e7eSjoerg llvm::errs() << "Headers:";
128706f32e7eSjoerg for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
128806f32e7eSjoerg H != HEnd; ++H) {
128906f32e7eSjoerg llvm::errs() << " \"" << H->first->getName() << "\" -> ";
129006f32e7eSjoerg for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
129106f32e7eSjoerg E = H->second.end();
129206f32e7eSjoerg I != E; ++I) {
129306f32e7eSjoerg if (I != H->second.begin())
129406f32e7eSjoerg llvm::errs() << ",";
129506f32e7eSjoerg llvm::errs() << I->getModule()->getFullModuleName();
129606f32e7eSjoerg }
129706f32e7eSjoerg llvm::errs() << "\n";
129806f32e7eSjoerg }
129906f32e7eSjoerg }
130006f32e7eSjoerg
resolveExports(Module * Mod,bool Complain)130106f32e7eSjoerg bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
130206f32e7eSjoerg auto Unresolved = std::move(Mod->UnresolvedExports);
130306f32e7eSjoerg Mod->UnresolvedExports.clear();
130406f32e7eSjoerg for (auto &UE : Unresolved) {
130506f32e7eSjoerg Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
130606f32e7eSjoerg if (Export.getPointer() || Export.getInt())
130706f32e7eSjoerg Mod->Exports.push_back(Export);
130806f32e7eSjoerg else
130906f32e7eSjoerg Mod->UnresolvedExports.push_back(UE);
131006f32e7eSjoerg }
131106f32e7eSjoerg return !Mod->UnresolvedExports.empty();
131206f32e7eSjoerg }
131306f32e7eSjoerg
resolveUses(Module * Mod,bool Complain)131406f32e7eSjoerg bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
131506f32e7eSjoerg auto Unresolved = std::move(Mod->UnresolvedDirectUses);
131606f32e7eSjoerg Mod->UnresolvedDirectUses.clear();
131706f32e7eSjoerg for (auto &UDU : Unresolved) {
131806f32e7eSjoerg Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
131906f32e7eSjoerg if (DirectUse)
132006f32e7eSjoerg Mod->DirectUses.push_back(DirectUse);
132106f32e7eSjoerg else
132206f32e7eSjoerg Mod->UnresolvedDirectUses.push_back(UDU);
132306f32e7eSjoerg }
132406f32e7eSjoerg return !Mod->UnresolvedDirectUses.empty();
132506f32e7eSjoerg }
132606f32e7eSjoerg
resolveConflicts(Module * Mod,bool Complain)132706f32e7eSjoerg bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
132806f32e7eSjoerg auto Unresolved = std::move(Mod->UnresolvedConflicts);
132906f32e7eSjoerg Mod->UnresolvedConflicts.clear();
133006f32e7eSjoerg for (auto &UC : Unresolved) {
133106f32e7eSjoerg if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
133206f32e7eSjoerg Module::Conflict Conflict;
133306f32e7eSjoerg Conflict.Other = OtherMod;
133406f32e7eSjoerg Conflict.Message = UC.Message;
133506f32e7eSjoerg Mod->Conflicts.push_back(Conflict);
133606f32e7eSjoerg } else
133706f32e7eSjoerg Mod->UnresolvedConflicts.push_back(UC);
133806f32e7eSjoerg }
133906f32e7eSjoerg return !Mod->UnresolvedConflicts.empty();
134006f32e7eSjoerg }
134106f32e7eSjoerg
134206f32e7eSjoerg //----------------------------------------------------------------------------//
134306f32e7eSjoerg // Module map file parser
134406f32e7eSjoerg //----------------------------------------------------------------------------//
134506f32e7eSjoerg
134606f32e7eSjoerg namespace clang {
134706f32e7eSjoerg
134806f32e7eSjoerg /// A token in a module map file.
134906f32e7eSjoerg struct MMToken {
135006f32e7eSjoerg enum TokenKind {
135106f32e7eSjoerg Comma,
135206f32e7eSjoerg ConfigMacros,
135306f32e7eSjoerg Conflict,
135406f32e7eSjoerg EndOfFile,
135506f32e7eSjoerg HeaderKeyword,
135606f32e7eSjoerg Identifier,
135706f32e7eSjoerg Exclaim,
135806f32e7eSjoerg ExcludeKeyword,
135906f32e7eSjoerg ExplicitKeyword,
136006f32e7eSjoerg ExportKeyword,
136106f32e7eSjoerg ExportAsKeyword,
136206f32e7eSjoerg ExternKeyword,
136306f32e7eSjoerg FrameworkKeyword,
136406f32e7eSjoerg LinkKeyword,
136506f32e7eSjoerg ModuleKeyword,
136606f32e7eSjoerg Period,
136706f32e7eSjoerg PrivateKeyword,
136806f32e7eSjoerg UmbrellaKeyword,
136906f32e7eSjoerg UseKeyword,
137006f32e7eSjoerg RequiresKeyword,
137106f32e7eSjoerg Star,
137206f32e7eSjoerg StringLiteral,
137306f32e7eSjoerg IntegerLiteral,
137406f32e7eSjoerg TextualKeyword,
137506f32e7eSjoerg LBrace,
137606f32e7eSjoerg RBrace,
137706f32e7eSjoerg LSquare,
137806f32e7eSjoerg RSquare
137906f32e7eSjoerg } Kind;
138006f32e7eSjoerg
138106f32e7eSjoerg unsigned Location;
138206f32e7eSjoerg unsigned StringLength;
138306f32e7eSjoerg union {
138406f32e7eSjoerg // If Kind != IntegerLiteral.
138506f32e7eSjoerg const char *StringData;
138606f32e7eSjoerg
138706f32e7eSjoerg // If Kind == IntegerLiteral.
138806f32e7eSjoerg uint64_t IntegerValue;
138906f32e7eSjoerg };
139006f32e7eSjoerg
clearclang::MMToken139106f32e7eSjoerg void clear() {
139206f32e7eSjoerg Kind = EndOfFile;
139306f32e7eSjoerg Location = 0;
139406f32e7eSjoerg StringLength = 0;
139506f32e7eSjoerg StringData = nullptr;
139606f32e7eSjoerg }
139706f32e7eSjoerg
isclang::MMToken139806f32e7eSjoerg bool is(TokenKind K) const { return Kind == K; }
139906f32e7eSjoerg
getLocationclang::MMToken140006f32e7eSjoerg SourceLocation getLocation() const {
140106f32e7eSjoerg return SourceLocation::getFromRawEncoding(Location);
140206f32e7eSjoerg }
140306f32e7eSjoerg
getIntegerclang::MMToken140406f32e7eSjoerg uint64_t getInteger() const {
140506f32e7eSjoerg return Kind == IntegerLiteral ? IntegerValue : 0;
140606f32e7eSjoerg }
140706f32e7eSjoerg
getStringclang::MMToken140806f32e7eSjoerg StringRef getString() const {
140906f32e7eSjoerg return Kind == IntegerLiteral ? StringRef()
141006f32e7eSjoerg : StringRef(StringData, StringLength);
141106f32e7eSjoerg }
141206f32e7eSjoerg };
141306f32e7eSjoerg
141406f32e7eSjoerg class ModuleMapParser {
141506f32e7eSjoerg Lexer &L;
141606f32e7eSjoerg SourceManager &SourceMgr;
141706f32e7eSjoerg
141806f32e7eSjoerg /// Default target information, used only for string literal
141906f32e7eSjoerg /// parsing.
142006f32e7eSjoerg const TargetInfo *Target;
142106f32e7eSjoerg
142206f32e7eSjoerg DiagnosticsEngine &Diags;
142306f32e7eSjoerg ModuleMap ⤅
142406f32e7eSjoerg
142506f32e7eSjoerg /// The current module map file.
142606f32e7eSjoerg const FileEntry *ModuleMapFile;
142706f32e7eSjoerg
142806f32e7eSjoerg /// Source location of most recent parsed module declaration
142906f32e7eSjoerg SourceLocation CurrModuleDeclLoc;
143006f32e7eSjoerg
143106f32e7eSjoerg /// The directory that file names in this module map file should
143206f32e7eSjoerg /// be resolved relative to.
143306f32e7eSjoerg const DirectoryEntry *Directory;
143406f32e7eSjoerg
143506f32e7eSjoerg /// Whether this module map is in a system header directory.
143606f32e7eSjoerg bool IsSystem;
143706f32e7eSjoerg
143806f32e7eSjoerg /// Whether an error occurred.
143906f32e7eSjoerg bool HadError = false;
144006f32e7eSjoerg
144106f32e7eSjoerg /// Stores string data for the various string literals referenced
144206f32e7eSjoerg /// during parsing.
144306f32e7eSjoerg llvm::BumpPtrAllocator StringData;
144406f32e7eSjoerg
144506f32e7eSjoerg /// The current token.
144606f32e7eSjoerg MMToken Tok;
144706f32e7eSjoerg
144806f32e7eSjoerg /// The active module.
144906f32e7eSjoerg Module *ActiveModule = nullptr;
145006f32e7eSjoerg
145106f32e7eSjoerg /// Whether a module uses the 'requires excluded' hack to mark its
145206f32e7eSjoerg /// contents as 'textual'.
145306f32e7eSjoerg ///
145406f32e7eSjoerg /// On older Darwin SDK versions, 'requires excluded' is used to mark the
145506f32e7eSjoerg /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
145606f32e7eSjoerg /// non-modular headers. For backwards compatibility, we continue to
145706f32e7eSjoerg /// support this idiom for just these modules, and map the headers to
145806f32e7eSjoerg /// 'textual' to match the original intent.
145906f32e7eSjoerg llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
146006f32e7eSjoerg
146106f32e7eSjoerg /// Consume the current token and return its location.
146206f32e7eSjoerg SourceLocation consumeToken();
146306f32e7eSjoerg
146406f32e7eSjoerg /// Skip tokens until we reach the a token with the given kind
146506f32e7eSjoerg /// (or the end of the file).
146606f32e7eSjoerg void skipUntil(MMToken::TokenKind K);
146706f32e7eSjoerg
146806f32e7eSjoerg using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
146906f32e7eSjoerg
147006f32e7eSjoerg bool parseModuleId(ModuleId &Id);
147106f32e7eSjoerg void parseModuleDecl();
147206f32e7eSjoerg void parseExternModuleDecl();
147306f32e7eSjoerg void parseRequiresDecl();
147406f32e7eSjoerg void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
147506f32e7eSjoerg void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
147606f32e7eSjoerg void parseExportDecl();
147706f32e7eSjoerg void parseExportAsDecl();
147806f32e7eSjoerg void parseUseDecl();
147906f32e7eSjoerg void parseLinkDecl();
148006f32e7eSjoerg void parseConfigMacros();
148106f32e7eSjoerg void parseConflict();
148206f32e7eSjoerg void parseInferredModuleDecl(bool Framework, bool Explicit);
148306f32e7eSjoerg
148406f32e7eSjoerg /// Private modules are canonicalized as Foo_Private. Clang provides extra
148506f32e7eSjoerg /// module map search logic to find the appropriate private module when PCH
148606f32e7eSjoerg /// is used with implicit module maps. Warn when private modules are written
148706f32e7eSjoerg /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
148806f32e7eSjoerg void diagnosePrivateModules(SourceLocation ExplicitLoc,
148906f32e7eSjoerg SourceLocation FrameworkLoc);
149006f32e7eSjoerg
149106f32e7eSjoerg using Attributes = ModuleMap::Attributes;
149206f32e7eSjoerg
149306f32e7eSjoerg bool parseOptionalAttributes(Attributes &Attrs);
149406f32e7eSjoerg
149506f32e7eSjoerg public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,bool IsSystem)149606f32e7eSjoerg explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
149706f32e7eSjoerg const TargetInfo *Target, DiagnosticsEngine &Diags,
149806f32e7eSjoerg ModuleMap &Map, const FileEntry *ModuleMapFile,
149906f32e7eSjoerg const DirectoryEntry *Directory, bool IsSystem)
150006f32e7eSjoerg : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
150106f32e7eSjoerg ModuleMapFile(ModuleMapFile), Directory(Directory),
150206f32e7eSjoerg IsSystem(IsSystem) {
150306f32e7eSjoerg Tok.clear();
150406f32e7eSjoerg consumeToken();
150506f32e7eSjoerg }
150606f32e7eSjoerg
150706f32e7eSjoerg bool parseModuleMapFile();
150806f32e7eSjoerg
terminatedByDirective()150906f32e7eSjoerg bool terminatedByDirective() { return false; }
getLocation()151006f32e7eSjoerg SourceLocation getLocation() { return Tok.getLocation(); }
151106f32e7eSjoerg };
151206f32e7eSjoerg
151306f32e7eSjoerg } // namespace clang
151406f32e7eSjoerg
consumeToken()151506f32e7eSjoerg SourceLocation ModuleMapParser::consumeToken() {
151606f32e7eSjoerg SourceLocation Result = Tok.getLocation();
151706f32e7eSjoerg
151806f32e7eSjoerg retry:
151906f32e7eSjoerg Tok.clear();
152006f32e7eSjoerg Token LToken;
152106f32e7eSjoerg L.LexFromRawLexer(LToken);
152206f32e7eSjoerg Tok.Location = LToken.getLocation().getRawEncoding();
152306f32e7eSjoerg switch (LToken.getKind()) {
152406f32e7eSjoerg case tok::raw_identifier: {
152506f32e7eSjoerg StringRef RI = LToken.getRawIdentifier();
152606f32e7eSjoerg Tok.StringData = RI.data();
152706f32e7eSjoerg Tok.StringLength = RI.size();
152806f32e7eSjoerg Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
152906f32e7eSjoerg .Case("config_macros", MMToken::ConfigMacros)
153006f32e7eSjoerg .Case("conflict", MMToken::Conflict)
153106f32e7eSjoerg .Case("exclude", MMToken::ExcludeKeyword)
153206f32e7eSjoerg .Case("explicit", MMToken::ExplicitKeyword)
153306f32e7eSjoerg .Case("export", MMToken::ExportKeyword)
153406f32e7eSjoerg .Case("export_as", MMToken::ExportAsKeyword)
153506f32e7eSjoerg .Case("extern", MMToken::ExternKeyword)
153606f32e7eSjoerg .Case("framework", MMToken::FrameworkKeyword)
153706f32e7eSjoerg .Case("header", MMToken::HeaderKeyword)
153806f32e7eSjoerg .Case("link", MMToken::LinkKeyword)
153906f32e7eSjoerg .Case("module", MMToken::ModuleKeyword)
154006f32e7eSjoerg .Case("private", MMToken::PrivateKeyword)
154106f32e7eSjoerg .Case("requires", MMToken::RequiresKeyword)
154206f32e7eSjoerg .Case("textual", MMToken::TextualKeyword)
154306f32e7eSjoerg .Case("umbrella", MMToken::UmbrellaKeyword)
154406f32e7eSjoerg .Case("use", MMToken::UseKeyword)
154506f32e7eSjoerg .Default(MMToken::Identifier);
154606f32e7eSjoerg break;
154706f32e7eSjoerg }
154806f32e7eSjoerg
154906f32e7eSjoerg case tok::comma:
155006f32e7eSjoerg Tok.Kind = MMToken::Comma;
155106f32e7eSjoerg break;
155206f32e7eSjoerg
155306f32e7eSjoerg case tok::eof:
155406f32e7eSjoerg Tok.Kind = MMToken::EndOfFile;
155506f32e7eSjoerg break;
155606f32e7eSjoerg
155706f32e7eSjoerg case tok::l_brace:
155806f32e7eSjoerg Tok.Kind = MMToken::LBrace;
155906f32e7eSjoerg break;
156006f32e7eSjoerg
156106f32e7eSjoerg case tok::l_square:
156206f32e7eSjoerg Tok.Kind = MMToken::LSquare;
156306f32e7eSjoerg break;
156406f32e7eSjoerg
156506f32e7eSjoerg case tok::period:
156606f32e7eSjoerg Tok.Kind = MMToken::Period;
156706f32e7eSjoerg break;
156806f32e7eSjoerg
156906f32e7eSjoerg case tok::r_brace:
157006f32e7eSjoerg Tok.Kind = MMToken::RBrace;
157106f32e7eSjoerg break;
157206f32e7eSjoerg
157306f32e7eSjoerg case tok::r_square:
157406f32e7eSjoerg Tok.Kind = MMToken::RSquare;
157506f32e7eSjoerg break;
157606f32e7eSjoerg
157706f32e7eSjoerg case tok::star:
157806f32e7eSjoerg Tok.Kind = MMToken::Star;
157906f32e7eSjoerg break;
158006f32e7eSjoerg
158106f32e7eSjoerg case tok::exclaim:
158206f32e7eSjoerg Tok.Kind = MMToken::Exclaim;
158306f32e7eSjoerg break;
158406f32e7eSjoerg
158506f32e7eSjoerg case tok::string_literal: {
158606f32e7eSjoerg if (LToken.hasUDSuffix()) {
158706f32e7eSjoerg Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
158806f32e7eSjoerg HadError = true;
158906f32e7eSjoerg goto retry;
159006f32e7eSjoerg }
159106f32e7eSjoerg
159206f32e7eSjoerg // Parse the string literal.
159306f32e7eSjoerg LangOptions LangOpts;
159406f32e7eSjoerg StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
159506f32e7eSjoerg if (StringLiteral.hadError)
159606f32e7eSjoerg goto retry;
159706f32e7eSjoerg
159806f32e7eSjoerg // Copy the string literal into our string data allocator.
159906f32e7eSjoerg unsigned Length = StringLiteral.GetStringLength();
160006f32e7eSjoerg char *Saved = StringData.Allocate<char>(Length + 1);
160106f32e7eSjoerg memcpy(Saved, StringLiteral.GetString().data(), Length);
160206f32e7eSjoerg Saved[Length] = 0;
160306f32e7eSjoerg
160406f32e7eSjoerg // Form the token.
160506f32e7eSjoerg Tok.Kind = MMToken::StringLiteral;
160606f32e7eSjoerg Tok.StringData = Saved;
160706f32e7eSjoerg Tok.StringLength = Length;
160806f32e7eSjoerg break;
160906f32e7eSjoerg }
161006f32e7eSjoerg
161106f32e7eSjoerg case tok::numeric_constant: {
161206f32e7eSjoerg // We don't support any suffixes or other complications.
161306f32e7eSjoerg SmallString<32> SpellingBuffer;
161406f32e7eSjoerg SpellingBuffer.resize(LToken.getLength() + 1);
161506f32e7eSjoerg const char *Start = SpellingBuffer.data();
161606f32e7eSjoerg unsigned Length =
161706f32e7eSjoerg Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
161806f32e7eSjoerg uint64_t Value;
161906f32e7eSjoerg if (StringRef(Start, Length).getAsInteger(0, Value)) {
162006f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
162106f32e7eSjoerg HadError = true;
162206f32e7eSjoerg goto retry;
162306f32e7eSjoerg }
162406f32e7eSjoerg
162506f32e7eSjoerg Tok.Kind = MMToken::IntegerLiteral;
162606f32e7eSjoerg Tok.IntegerValue = Value;
162706f32e7eSjoerg break;
162806f32e7eSjoerg }
162906f32e7eSjoerg
163006f32e7eSjoerg case tok::comment:
163106f32e7eSjoerg goto retry;
163206f32e7eSjoerg
163306f32e7eSjoerg case tok::hash:
163406f32e7eSjoerg // A module map can be terminated prematurely by
163506f32e7eSjoerg // #pragma clang module contents
163606f32e7eSjoerg // When building the module, we'll treat the rest of the file as the
163706f32e7eSjoerg // contents of the module.
163806f32e7eSjoerg {
163906f32e7eSjoerg auto NextIsIdent = [&](StringRef Str) -> bool {
164006f32e7eSjoerg L.LexFromRawLexer(LToken);
164106f32e7eSjoerg return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
164206f32e7eSjoerg LToken.getRawIdentifier() == Str;
164306f32e7eSjoerg };
164406f32e7eSjoerg if (NextIsIdent("pragma") && NextIsIdent("clang") &&
164506f32e7eSjoerg NextIsIdent("module") && NextIsIdent("contents")) {
164606f32e7eSjoerg Tok.Kind = MMToken::EndOfFile;
164706f32e7eSjoerg break;
164806f32e7eSjoerg }
164906f32e7eSjoerg }
165006f32e7eSjoerg LLVM_FALLTHROUGH;
165106f32e7eSjoerg
165206f32e7eSjoerg default:
165306f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
165406f32e7eSjoerg HadError = true;
165506f32e7eSjoerg goto retry;
165606f32e7eSjoerg }
165706f32e7eSjoerg
165806f32e7eSjoerg return Result;
165906f32e7eSjoerg }
166006f32e7eSjoerg
skipUntil(MMToken::TokenKind K)166106f32e7eSjoerg void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
166206f32e7eSjoerg unsigned braceDepth = 0;
166306f32e7eSjoerg unsigned squareDepth = 0;
166406f32e7eSjoerg do {
166506f32e7eSjoerg switch (Tok.Kind) {
166606f32e7eSjoerg case MMToken::EndOfFile:
166706f32e7eSjoerg return;
166806f32e7eSjoerg
166906f32e7eSjoerg case MMToken::LBrace:
167006f32e7eSjoerg if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
167106f32e7eSjoerg return;
167206f32e7eSjoerg
167306f32e7eSjoerg ++braceDepth;
167406f32e7eSjoerg break;
167506f32e7eSjoerg
167606f32e7eSjoerg case MMToken::LSquare:
167706f32e7eSjoerg if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
167806f32e7eSjoerg return;
167906f32e7eSjoerg
168006f32e7eSjoerg ++squareDepth;
168106f32e7eSjoerg break;
168206f32e7eSjoerg
168306f32e7eSjoerg case MMToken::RBrace:
168406f32e7eSjoerg if (braceDepth > 0)
168506f32e7eSjoerg --braceDepth;
168606f32e7eSjoerg else if (Tok.is(K))
168706f32e7eSjoerg return;
168806f32e7eSjoerg break;
168906f32e7eSjoerg
169006f32e7eSjoerg case MMToken::RSquare:
169106f32e7eSjoerg if (squareDepth > 0)
169206f32e7eSjoerg --squareDepth;
169306f32e7eSjoerg else if (Tok.is(K))
169406f32e7eSjoerg return;
169506f32e7eSjoerg break;
169606f32e7eSjoerg
169706f32e7eSjoerg default:
169806f32e7eSjoerg if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
169906f32e7eSjoerg return;
170006f32e7eSjoerg break;
170106f32e7eSjoerg }
170206f32e7eSjoerg
170306f32e7eSjoerg consumeToken();
170406f32e7eSjoerg } while (true);
170506f32e7eSjoerg }
170606f32e7eSjoerg
170706f32e7eSjoerg /// Parse a module-id.
170806f32e7eSjoerg ///
170906f32e7eSjoerg /// module-id:
171006f32e7eSjoerg /// identifier
171106f32e7eSjoerg /// identifier '.' module-id
171206f32e7eSjoerg ///
171306f32e7eSjoerg /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)171406f32e7eSjoerg bool ModuleMapParser::parseModuleId(ModuleId &Id) {
171506f32e7eSjoerg Id.clear();
171606f32e7eSjoerg do {
171706f32e7eSjoerg if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1718*13fbcb42Sjoerg Id.push_back(
1719*13fbcb42Sjoerg std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
172006f32e7eSjoerg consumeToken();
172106f32e7eSjoerg } else {
172206f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
172306f32e7eSjoerg return true;
172406f32e7eSjoerg }
172506f32e7eSjoerg
172606f32e7eSjoerg if (!Tok.is(MMToken::Period))
172706f32e7eSjoerg break;
172806f32e7eSjoerg
172906f32e7eSjoerg consumeToken();
173006f32e7eSjoerg } while (true);
173106f32e7eSjoerg
173206f32e7eSjoerg return false;
173306f32e7eSjoerg }
173406f32e7eSjoerg
173506f32e7eSjoerg namespace {
173606f32e7eSjoerg
173706f32e7eSjoerg /// Enumerates the known attributes.
173806f32e7eSjoerg enum AttributeKind {
173906f32e7eSjoerg /// An unknown attribute.
174006f32e7eSjoerg AT_unknown,
174106f32e7eSjoerg
174206f32e7eSjoerg /// The 'system' attribute.
174306f32e7eSjoerg AT_system,
174406f32e7eSjoerg
174506f32e7eSjoerg /// The 'extern_c' attribute.
174606f32e7eSjoerg AT_extern_c,
174706f32e7eSjoerg
174806f32e7eSjoerg /// The 'exhaustive' attribute.
174906f32e7eSjoerg AT_exhaustive,
175006f32e7eSjoerg
175106f32e7eSjoerg /// The 'no_undeclared_includes' attribute.
175206f32e7eSjoerg AT_no_undeclared_includes
175306f32e7eSjoerg };
175406f32e7eSjoerg
175506f32e7eSjoerg } // namespace
175606f32e7eSjoerg
175706f32e7eSjoerg /// Private modules are canonicalized as Foo_Private. Clang provides extra
175806f32e7eSjoerg /// module map search logic to find the appropriate private module when PCH
175906f32e7eSjoerg /// is used with implicit module maps. Warn when private modules are written
176006f32e7eSjoerg /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)176106f32e7eSjoerg void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
176206f32e7eSjoerg SourceLocation FrameworkLoc) {
176306f32e7eSjoerg auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
176406f32e7eSjoerg const Module *M, SourceRange ReplLoc) {
176506f32e7eSjoerg auto D = Diags.Report(ActiveModule->DefinitionLoc,
176606f32e7eSjoerg diag::note_mmap_rename_top_level_private_module);
176706f32e7eSjoerg D << BadName << M->Name;
176806f32e7eSjoerg D << FixItHint::CreateReplacement(ReplLoc, Canonical);
176906f32e7eSjoerg };
177006f32e7eSjoerg
177106f32e7eSjoerg for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
177206f32e7eSjoerg auto const *M = E->getValue();
177306f32e7eSjoerg if (M->Directory != ActiveModule->Directory)
177406f32e7eSjoerg continue;
177506f32e7eSjoerg
177606f32e7eSjoerg SmallString<128> FullName(ActiveModule->getFullModuleName());
177706f32e7eSjoerg if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
177806f32e7eSjoerg continue;
177906f32e7eSjoerg SmallString<128> FixedPrivModDecl;
178006f32e7eSjoerg SmallString<128> Canonical(M->Name);
178106f32e7eSjoerg Canonical.append("_Private");
178206f32e7eSjoerg
178306f32e7eSjoerg // Foo.Private -> Foo_Private
178406f32e7eSjoerg if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
178506f32e7eSjoerg M->Name == ActiveModule->Parent->Name) {
178606f32e7eSjoerg Diags.Report(ActiveModule->DefinitionLoc,
178706f32e7eSjoerg diag::warn_mmap_mismatched_private_submodule)
178806f32e7eSjoerg << FullName;
178906f32e7eSjoerg
179006f32e7eSjoerg SourceLocation FixItInitBegin = CurrModuleDeclLoc;
179106f32e7eSjoerg if (FrameworkLoc.isValid())
179206f32e7eSjoerg FixItInitBegin = FrameworkLoc;
179306f32e7eSjoerg if (ExplicitLoc.isValid())
179406f32e7eSjoerg FixItInitBegin = ExplicitLoc;
179506f32e7eSjoerg
179606f32e7eSjoerg if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
179706f32e7eSjoerg FixedPrivModDecl.append("framework ");
179806f32e7eSjoerg FixedPrivModDecl.append("module ");
179906f32e7eSjoerg FixedPrivModDecl.append(Canonical);
180006f32e7eSjoerg
180106f32e7eSjoerg GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
180206f32e7eSjoerg SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
180306f32e7eSjoerg continue;
180406f32e7eSjoerg }
180506f32e7eSjoerg
180606f32e7eSjoerg // FooPrivate and whatnots -> Foo_Private
180706f32e7eSjoerg if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
180806f32e7eSjoerg ActiveModule->Name != Canonical) {
180906f32e7eSjoerg Diags.Report(ActiveModule->DefinitionLoc,
181006f32e7eSjoerg diag::warn_mmap_mismatched_private_module_name)
181106f32e7eSjoerg << ActiveModule->Name;
181206f32e7eSjoerg GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
181306f32e7eSjoerg SourceRange(ActiveModule->DefinitionLoc));
181406f32e7eSjoerg }
181506f32e7eSjoerg }
181606f32e7eSjoerg }
181706f32e7eSjoerg
181806f32e7eSjoerg /// Parse a module declaration.
181906f32e7eSjoerg ///
182006f32e7eSjoerg /// module-declaration:
182106f32e7eSjoerg /// 'extern' 'module' module-id string-literal
182206f32e7eSjoerg /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
182306f32e7eSjoerg /// { module-member* }
182406f32e7eSjoerg ///
182506f32e7eSjoerg /// module-member:
182606f32e7eSjoerg /// requires-declaration
182706f32e7eSjoerg /// header-declaration
182806f32e7eSjoerg /// submodule-declaration
182906f32e7eSjoerg /// export-declaration
183006f32e7eSjoerg /// export-as-declaration
183106f32e7eSjoerg /// link-declaration
183206f32e7eSjoerg ///
183306f32e7eSjoerg /// submodule-declaration:
183406f32e7eSjoerg /// module-declaration
183506f32e7eSjoerg /// inferred-submodule-declaration
parseModuleDecl()183606f32e7eSjoerg void ModuleMapParser::parseModuleDecl() {
183706f32e7eSjoerg assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
183806f32e7eSjoerg Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
183906f32e7eSjoerg if (Tok.is(MMToken::ExternKeyword)) {
184006f32e7eSjoerg parseExternModuleDecl();
184106f32e7eSjoerg return;
184206f32e7eSjoerg }
184306f32e7eSjoerg
184406f32e7eSjoerg // Parse 'explicit' or 'framework' keyword, if present.
184506f32e7eSjoerg SourceLocation ExplicitLoc;
184606f32e7eSjoerg SourceLocation FrameworkLoc;
184706f32e7eSjoerg bool Explicit = false;
184806f32e7eSjoerg bool Framework = false;
184906f32e7eSjoerg
185006f32e7eSjoerg // Parse 'explicit' keyword, if present.
185106f32e7eSjoerg if (Tok.is(MMToken::ExplicitKeyword)) {
185206f32e7eSjoerg ExplicitLoc = consumeToken();
185306f32e7eSjoerg Explicit = true;
185406f32e7eSjoerg }
185506f32e7eSjoerg
185606f32e7eSjoerg // Parse 'framework' keyword, if present.
185706f32e7eSjoerg if (Tok.is(MMToken::FrameworkKeyword)) {
185806f32e7eSjoerg FrameworkLoc = consumeToken();
185906f32e7eSjoerg Framework = true;
186006f32e7eSjoerg }
186106f32e7eSjoerg
186206f32e7eSjoerg // Parse 'module' keyword.
186306f32e7eSjoerg if (!Tok.is(MMToken::ModuleKeyword)) {
186406f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
186506f32e7eSjoerg consumeToken();
186606f32e7eSjoerg HadError = true;
186706f32e7eSjoerg return;
186806f32e7eSjoerg }
186906f32e7eSjoerg CurrModuleDeclLoc = consumeToken(); // 'module' keyword
187006f32e7eSjoerg
187106f32e7eSjoerg // If we have a wildcard for the module name, this is an inferred submodule.
187206f32e7eSjoerg // Parse it.
187306f32e7eSjoerg if (Tok.is(MMToken::Star))
187406f32e7eSjoerg return parseInferredModuleDecl(Framework, Explicit);
187506f32e7eSjoerg
187606f32e7eSjoerg // Parse the module name.
187706f32e7eSjoerg ModuleId Id;
187806f32e7eSjoerg if (parseModuleId(Id)) {
187906f32e7eSjoerg HadError = true;
188006f32e7eSjoerg return;
188106f32e7eSjoerg }
188206f32e7eSjoerg
188306f32e7eSjoerg if (ActiveModule) {
188406f32e7eSjoerg if (Id.size() > 1) {
188506f32e7eSjoerg Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
188606f32e7eSjoerg << SourceRange(Id.front().second, Id.back().second);
188706f32e7eSjoerg
188806f32e7eSjoerg HadError = true;
188906f32e7eSjoerg return;
189006f32e7eSjoerg }
189106f32e7eSjoerg } else if (Id.size() == 1 && Explicit) {
189206f32e7eSjoerg // Top-level modules can't be explicit.
189306f32e7eSjoerg Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
189406f32e7eSjoerg Explicit = false;
189506f32e7eSjoerg ExplicitLoc = SourceLocation();
189606f32e7eSjoerg HadError = true;
189706f32e7eSjoerg }
189806f32e7eSjoerg
189906f32e7eSjoerg Module *PreviousActiveModule = ActiveModule;
190006f32e7eSjoerg if (Id.size() > 1) {
190106f32e7eSjoerg // This module map defines a submodule. Go find the module of which it
190206f32e7eSjoerg // is a submodule.
190306f32e7eSjoerg ActiveModule = nullptr;
190406f32e7eSjoerg const Module *TopLevelModule = nullptr;
190506f32e7eSjoerg for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
190606f32e7eSjoerg if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
190706f32e7eSjoerg if (I == 0)
190806f32e7eSjoerg TopLevelModule = Next;
190906f32e7eSjoerg ActiveModule = Next;
191006f32e7eSjoerg continue;
191106f32e7eSjoerg }
191206f32e7eSjoerg
1913*13fbcb42Sjoerg Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
1914*13fbcb42Sjoerg << Id[I].first << (ActiveModule != nullptr)
1915*13fbcb42Sjoerg << (ActiveModule
1916*13fbcb42Sjoerg ? ActiveModule->getTopLevelModule()->getFullModuleName()
1917*13fbcb42Sjoerg : "");
191806f32e7eSjoerg HadError = true;
191906f32e7eSjoerg }
192006f32e7eSjoerg
1921*13fbcb42Sjoerg if (TopLevelModule &&
1922*13fbcb42Sjoerg ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
192306f32e7eSjoerg assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
192406f32e7eSjoerg "submodule defined in same file as 'module *' that allowed its "
192506f32e7eSjoerg "top-level module");
192606f32e7eSjoerg Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
192706f32e7eSjoerg }
192806f32e7eSjoerg }
192906f32e7eSjoerg
193006f32e7eSjoerg StringRef ModuleName = Id.back().first;
193106f32e7eSjoerg SourceLocation ModuleNameLoc = Id.back().second;
193206f32e7eSjoerg
193306f32e7eSjoerg // Parse the optional attribute list.
193406f32e7eSjoerg Attributes Attrs;
193506f32e7eSjoerg if (parseOptionalAttributes(Attrs))
193606f32e7eSjoerg return;
193706f32e7eSjoerg
193806f32e7eSjoerg // Parse the opening brace.
193906f32e7eSjoerg if (!Tok.is(MMToken::LBrace)) {
194006f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
194106f32e7eSjoerg << ModuleName;
194206f32e7eSjoerg HadError = true;
194306f32e7eSjoerg return;
194406f32e7eSjoerg }
194506f32e7eSjoerg SourceLocation LBraceLoc = consumeToken();
194606f32e7eSjoerg
194706f32e7eSjoerg // Determine whether this (sub)module has already been defined.
194806f32e7eSjoerg Module *ShadowingModule = nullptr;
194906f32e7eSjoerg if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
195006f32e7eSjoerg // We might see a (re)definition of a module that we already have a
195106f32e7eSjoerg // definition for in two cases:
195206f32e7eSjoerg // - If we loaded one definition from an AST file and we've just found a
195306f32e7eSjoerg // corresponding definition in a module map file, or
195406f32e7eSjoerg bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
195506f32e7eSjoerg // - If we're building a (preprocessed) module and we've just loaded the
195606f32e7eSjoerg // module map file from which it was created.
195706f32e7eSjoerg bool ParsedAsMainInput =
195806f32e7eSjoerg Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
195906f32e7eSjoerg Map.LangOpts.CurrentModule == ModuleName &&
196006f32e7eSjoerg SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
196106f32e7eSjoerg SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
196206f32e7eSjoerg if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
196306f32e7eSjoerg // Skip the module definition.
196406f32e7eSjoerg skipUntil(MMToken::RBrace);
196506f32e7eSjoerg if (Tok.is(MMToken::RBrace))
196606f32e7eSjoerg consumeToken();
196706f32e7eSjoerg else {
196806f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
196906f32e7eSjoerg Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
197006f32e7eSjoerg HadError = true;
197106f32e7eSjoerg }
197206f32e7eSjoerg return;
197306f32e7eSjoerg }
197406f32e7eSjoerg
197506f32e7eSjoerg if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
197606f32e7eSjoerg ShadowingModule = Existing;
197706f32e7eSjoerg } else {
197806f32e7eSjoerg // This is not a shawdowed module decl, it is an illegal redefinition.
197906f32e7eSjoerg Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
198006f32e7eSjoerg << ModuleName;
198106f32e7eSjoerg Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
198206f32e7eSjoerg
198306f32e7eSjoerg // Skip the module definition.
198406f32e7eSjoerg skipUntil(MMToken::RBrace);
198506f32e7eSjoerg if (Tok.is(MMToken::RBrace))
198606f32e7eSjoerg consumeToken();
198706f32e7eSjoerg
198806f32e7eSjoerg HadError = true;
198906f32e7eSjoerg return;
199006f32e7eSjoerg }
199106f32e7eSjoerg }
199206f32e7eSjoerg
199306f32e7eSjoerg // Start defining this module.
199406f32e7eSjoerg if (ShadowingModule) {
199506f32e7eSjoerg ActiveModule =
199606f32e7eSjoerg Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
199706f32e7eSjoerg } else {
199806f32e7eSjoerg ActiveModule =
199906f32e7eSjoerg Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
200006f32e7eSjoerg .first;
200106f32e7eSjoerg }
200206f32e7eSjoerg
200306f32e7eSjoerg ActiveModule->DefinitionLoc = ModuleNameLoc;
200406f32e7eSjoerg if (Attrs.IsSystem || IsSystem)
200506f32e7eSjoerg ActiveModule->IsSystem = true;
200606f32e7eSjoerg if (Attrs.IsExternC)
200706f32e7eSjoerg ActiveModule->IsExternC = true;
200806f32e7eSjoerg if (Attrs.NoUndeclaredIncludes ||
200906f32e7eSjoerg (!ActiveModule->Parent && ModuleName == "Darwin"))
201006f32e7eSjoerg ActiveModule->NoUndeclaredIncludes = true;
201106f32e7eSjoerg ActiveModule->Directory = Directory;
201206f32e7eSjoerg
201306f32e7eSjoerg StringRef MapFileName(ModuleMapFile->getName());
201406f32e7eSjoerg if (MapFileName.endswith("module.private.modulemap") ||
201506f32e7eSjoerg MapFileName.endswith("module_private.map")) {
201606f32e7eSjoerg ActiveModule->ModuleMapIsPrivate = true;
201706f32e7eSjoerg }
201806f32e7eSjoerg
201906f32e7eSjoerg // Private modules named as FooPrivate, Foo.Private or similar are likely a
202006f32e7eSjoerg // user error; provide warnings, notes and fixits to direct users to use
202106f32e7eSjoerg // Foo_Private instead.
202206f32e7eSjoerg SourceLocation StartLoc =
202306f32e7eSjoerg SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
202406f32e7eSjoerg if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
202506f32e7eSjoerg !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
202606f32e7eSjoerg StartLoc) &&
202706f32e7eSjoerg !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
202806f32e7eSjoerg StartLoc) &&
202906f32e7eSjoerg ActiveModule->ModuleMapIsPrivate)
203006f32e7eSjoerg diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
203106f32e7eSjoerg
203206f32e7eSjoerg bool Done = false;
203306f32e7eSjoerg do {
203406f32e7eSjoerg switch (Tok.Kind) {
203506f32e7eSjoerg case MMToken::EndOfFile:
203606f32e7eSjoerg case MMToken::RBrace:
203706f32e7eSjoerg Done = true;
203806f32e7eSjoerg break;
203906f32e7eSjoerg
204006f32e7eSjoerg case MMToken::ConfigMacros:
204106f32e7eSjoerg parseConfigMacros();
204206f32e7eSjoerg break;
204306f32e7eSjoerg
204406f32e7eSjoerg case MMToken::Conflict:
204506f32e7eSjoerg parseConflict();
204606f32e7eSjoerg break;
204706f32e7eSjoerg
204806f32e7eSjoerg case MMToken::ExplicitKeyword:
204906f32e7eSjoerg case MMToken::ExternKeyword:
205006f32e7eSjoerg case MMToken::FrameworkKeyword:
205106f32e7eSjoerg case MMToken::ModuleKeyword:
205206f32e7eSjoerg parseModuleDecl();
205306f32e7eSjoerg break;
205406f32e7eSjoerg
205506f32e7eSjoerg case MMToken::ExportKeyword:
205606f32e7eSjoerg parseExportDecl();
205706f32e7eSjoerg break;
205806f32e7eSjoerg
205906f32e7eSjoerg case MMToken::ExportAsKeyword:
206006f32e7eSjoerg parseExportAsDecl();
206106f32e7eSjoerg break;
206206f32e7eSjoerg
206306f32e7eSjoerg case MMToken::UseKeyword:
206406f32e7eSjoerg parseUseDecl();
206506f32e7eSjoerg break;
206606f32e7eSjoerg
206706f32e7eSjoerg case MMToken::RequiresKeyword:
206806f32e7eSjoerg parseRequiresDecl();
206906f32e7eSjoerg break;
207006f32e7eSjoerg
207106f32e7eSjoerg case MMToken::TextualKeyword:
207206f32e7eSjoerg parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
207306f32e7eSjoerg break;
207406f32e7eSjoerg
207506f32e7eSjoerg case MMToken::UmbrellaKeyword: {
207606f32e7eSjoerg SourceLocation UmbrellaLoc = consumeToken();
207706f32e7eSjoerg if (Tok.is(MMToken::HeaderKeyword))
207806f32e7eSjoerg parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
207906f32e7eSjoerg else
208006f32e7eSjoerg parseUmbrellaDirDecl(UmbrellaLoc);
208106f32e7eSjoerg break;
208206f32e7eSjoerg }
208306f32e7eSjoerg
208406f32e7eSjoerg case MMToken::ExcludeKeyword:
208506f32e7eSjoerg parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
208606f32e7eSjoerg break;
208706f32e7eSjoerg
208806f32e7eSjoerg case MMToken::PrivateKeyword:
208906f32e7eSjoerg parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
209006f32e7eSjoerg break;
209106f32e7eSjoerg
209206f32e7eSjoerg case MMToken::HeaderKeyword:
209306f32e7eSjoerg parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
209406f32e7eSjoerg break;
209506f32e7eSjoerg
209606f32e7eSjoerg case MMToken::LinkKeyword:
209706f32e7eSjoerg parseLinkDecl();
209806f32e7eSjoerg break;
209906f32e7eSjoerg
210006f32e7eSjoerg default:
210106f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
210206f32e7eSjoerg consumeToken();
210306f32e7eSjoerg break;
210406f32e7eSjoerg }
210506f32e7eSjoerg } while (!Done);
210606f32e7eSjoerg
210706f32e7eSjoerg if (Tok.is(MMToken::RBrace))
210806f32e7eSjoerg consumeToken();
210906f32e7eSjoerg else {
211006f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
211106f32e7eSjoerg Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
211206f32e7eSjoerg HadError = true;
211306f32e7eSjoerg }
211406f32e7eSjoerg
211506f32e7eSjoerg // If the active module is a top-level framework, and there are no link
211606f32e7eSjoerg // libraries, automatically link against the framework.
211706f32e7eSjoerg if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
211806f32e7eSjoerg ActiveModule->LinkLibraries.empty()) {
211906f32e7eSjoerg inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
212006f32e7eSjoerg }
212106f32e7eSjoerg
212206f32e7eSjoerg // If the module meets all requirements but is still unavailable, mark the
212306f32e7eSjoerg // whole tree as unavailable to prevent it from building.
2124*13fbcb42Sjoerg if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
212506f32e7eSjoerg ActiveModule->Parent) {
2126*13fbcb42Sjoerg ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
212706f32e7eSjoerg ActiveModule->getTopLevelModule()->MissingHeaders.append(
212806f32e7eSjoerg ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
212906f32e7eSjoerg }
213006f32e7eSjoerg
213106f32e7eSjoerg // We're done parsing this module. Pop back to the previous module.
213206f32e7eSjoerg ActiveModule = PreviousActiveModule;
213306f32e7eSjoerg }
213406f32e7eSjoerg
213506f32e7eSjoerg /// Parse an extern module declaration.
213606f32e7eSjoerg ///
213706f32e7eSjoerg /// extern module-declaration:
213806f32e7eSjoerg /// 'extern' 'module' module-id string-literal
parseExternModuleDecl()213906f32e7eSjoerg void ModuleMapParser::parseExternModuleDecl() {
214006f32e7eSjoerg assert(Tok.is(MMToken::ExternKeyword));
214106f32e7eSjoerg SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
214206f32e7eSjoerg
214306f32e7eSjoerg // Parse 'module' keyword.
214406f32e7eSjoerg if (!Tok.is(MMToken::ModuleKeyword)) {
214506f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
214606f32e7eSjoerg consumeToken();
214706f32e7eSjoerg HadError = true;
214806f32e7eSjoerg return;
214906f32e7eSjoerg }
215006f32e7eSjoerg consumeToken(); // 'module' keyword
215106f32e7eSjoerg
215206f32e7eSjoerg // Parse the module name.
215306f32e7eSjoerg ModuleId Id;
215406f32e7eSjoerg if (parseModuleId(Id)) {
215506f32e7eSjoerg HadError = true;
215606f32e7eSjoerg return;
215706f32e7eSjoerg }
215806f32e7eSjoerg
215906f32e7eSjoerg // Parse the referenced module map file name.
216006f32e7eSjoerg if (!Tok.is(MMToken::StringLiteral)) {
216106f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
216206f32e7eSjoerg HadError = true;
216306f32e7eSjoerg return;
216406f32e7eSjoerg }
2165*13fbcb42Sjoerg std::string FileName = std::string(Tok.getString());
216606f32e7eSjoerg consumeToken(); // filename
216706f32e7eSjoerg
216806f32e7eSjoerg StringRef FileNameRef = FileName;
216906f32e7eSjoerg SmallString<128> ModuleMapFileName;
217006f32e7eSjoerg if (llvm::sys::path::is_relative(FileNameRef)) {
217106f32e7eSjoerg ModuleMapFileName += Directory->getName();
217206f32e7eSjoerg llvm::sys::path::append(ModuleMapFileName, FileName);
217306f32e7eSjoerg FileNameRef = ModuleMapFileName;
217406f32e7eSjoerg }
217506f32e7eSjoerg if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
217606f32e7eSjoerg Map.parseModuleMapFile(
217706f32e7eSjoerg *File, /*IsSystem=*/false,
217806f32e7eSjoerg Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
217906f32e7eSjoerg ? Directory
218006f32e7eSjoerg : (*File)->getDir(),
218106f32e7eSjoerg FileID(), nullptr, ExternLoc);
218206f32e7eSjoerg }
218306f32e7eSjoerg
218406f32e7eSjoerg /// Whether to add the requirement \p Feature to the module \p M.
218506f32e7eSjoerg ///
218606f32e7eSjoerg /// This preserves backwards compatibility for two hacks in the Darwin system
218706f32e7eSjoerg /// module map files:
218806f32e7eSjoerg ///
218906f32e7eSjoerg /// 1. The use of 'requires excluded' to make headers non-modular, which
219006f32e7eSjoerg /// should really be mapped to 'textual' now that we have this feature. We
219106f32e7eSjoerg /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
219206f32e7eSjoerg /// true. Later, this bit will be used to map all the headers inside this
219306f32e7eSjoerg /// module to 'textual'.
219406f32e7eSjoerg ///
219506f32e7eSjoerg /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
219606f32e7eSjoerg ///
219706f32e7eSjoerg /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
219806f32e7eSjoerg /// was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)219906f32e7eSjoerg static bool shouldAddRequirement(Module *M, StringRef Feature,
220006f32e7eSjoerg bool &IsRequiresExcludedHack) {
220106f32e7eSjoerg if (Feature == "excluded" &&
220206f32e7eSjoerg (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
220306f32e7eSjoerg M->fullModuleNameIs({"Tcl", "Private"}))) {
220406f32e7eSjoerg IsRequiresExcludedHack = true;
220506f32e7eSjoerg return false;
220606f32e7eSjoerg } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
220706f32e7eSjoerg return false;
220806f32e7eSjoerg }
220906f32e7eSjoerg
221006f32e7eSjoerg return true;
221106f32e7eSjoerg }
221206f32e7eSjoerg
221306f32e7eSjoerg /// Parse a requires declaration.
221406f32e7eSjoerg ///
221506f32e7eSjoerg /// requires-declaration:
221606f32e7eSjoerg /// 'requires' feature-list
221706f32e7eSjoerg ///
221806f32e7eSjoerg /// feature-list:
221906f32e7eSjoerg /// feature ',' feature-list
222006f32e7eSjoerg /// feature
222106f32e7eSjoerg ///
222206f32e7eSjoerg /// feature:
222306f32e7eSjoerg /// '!'[opt] identifier
parseRequiresDecl()222406f32e7eSjoerg void ModuleMapParser::parseRequiresDecl() {
222506f32e7eSjoerg assert(Tok.is(MMToken::RequiresKeyword));
222606f32e7eSjoerg
222706f32e7eSjoerg // Parse 'requires' keyword.
222806f32e7eSjoerg consumeToken();
222906f32e7eSjoerg
223006f32e7eSjoerg // Parse the feature-list.
223106f32e7eSjoerg do {
223206f32e7eSjoerg bool RequiredState = true;
223306f32e7eSjoerg if (Tok.is(MMToken::Exclaim)) {
223406f32e7eSjoerg RequiredState = false;
223506f32e7eSjoerg consumeToken();
223606f32e7eSjoerg }
223706f32e7eSjoerg
223806f32e7eSjoerg if (!Tok.is(MMToken::Identifier)) {
223906f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
224006f32e7eSjoerg HadError = true;
224106f32e7eSjoerg return;
224206f32e7eSjoerg }
224306f32e7eSjoerg
224406f32e7eSjoerg // Consume the feature name.
2245*13fbcb42Sjoerg std::string Feature = std::string(Tok.getString());
224606f32e7eSjoerg consumeToken();
224706f32e7eSjoerg
224806f32e7eSjoerg bool IsRequiresExcludedHack = false;
224906f32e7eSjoerg bool ShouldAddRequirement =
225006f32e7eSjoerg shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
225106f32e7eSjoerg
225206f32e7eSjoerg if (IsRequiresExcludedHack)
225306f32e7eSjoerg UsesRequiresExcludedHack.insert(ActiveModule);
225406f32e7eSjoerg
225506f32e7eSjoerg if (ShouldAddRequirement) {
225606f32e7eSjoerg // Add this feature.
225706f32e7eSjoerg ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
225806f32e7eSjoerg *Map.Target);
225906f32e7eSjoerg }
226006f32e7eSjoerg
226106f32e7eSjoerg if (!Tok.is(MMToken::Comma))
226206f32e7eSjoerg break;
226306f32e7eSjoerg
226406f32e7eSjoerg // Consume the comma.
226506f32e7eSjoerg consumeToken();
226606f32e7eSjoerg } while (true);
226706f32e7eSjoerg }
226806f32e7eSjoerg
226906f32e7eSjoerg /// Parse a header declaration.
227006f32e7eSjoerg ///
227106f32e7eSjoerg /// header-declaration:
227206f32e7eSjoerg /// 'textual'[opt] 'header' string-literal
227306f32e7eSjoerg /// 'private' 'textual'[opt] 'header' string-literal
227406f32e7eSjoerg /// 'exclude' 'header' string-literal
227506f32e7eSjoerg /// 'umbrella' 'header' string-literal
227606f32e7eSjoerg ///
227706f32e7eSjoerg /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)227806f32e7eSjoerg void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
227906f32e7eSjoerg SourceLocation LeadingLoc) {
228006f32e7eSjoerg // We've already consumed the first token.
228106f32e7eSjoerg ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
228206f32e7eSjoerg if (LeadingToken == MMToken::PrivateKeyword) {
228306f32e7eSjoerg Role = ModuleMap::PrivateHeader;
228406f32e7eSjoerg // 'private' may optionally be followed by 'textual'.
228506f32e7eSjoerg if (Tok.is(MMToken::TextualKeyword)) {
228606f32e7eSjoerg LeadingToken = Tok.Kind;
228706f32e7eSjoerg consumeToken();
228806f32e7eSjoerg }
228906f32e7eSjoerg }
229006f32e7eSjoerg
229106f32e7eSjoerg if (LeadingToken == MMToken::TextualKeyword)
229206f32e7eSjoerg Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
229306f32e7eSjoerg
229406f32e7eSjoerg if (UsesRequiresExcludedHack.count(ActiveModule)) {
229506f32e7eSjoerg // Mark this header 'textual' (see doc comment for
229606f32e7eSjoerg // Module::UsesRequiresExcludedHack).
229706f32e7eSjoerg Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
229806f32e7eSjoerg }
229906f32e7eSjoerg
230006f32e7eSjoerg if (LeadingToken != MMToken::HeaderKeyword) {
230106f32e7eSjoerg if (!Tok.is(MMToken::HeaderKeyword)) {
230206f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
230306f32e7eSjoerg << (LeadingToken == MMToken::PrivateKeyword ? "private" :
230406f32e7eSjoerg LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
230506f32e7eSjoerg LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
230606f32e7eSjoerg return;
230706f32e7eSjoerg }
230806f32e7eSjoerg consumeToken();
230906f32e7eSjoerg }
231006f32e7eSjoerg
231106f32e7eSjoerg // Parse the header name.
231206f32e7eSjoerg if (!Tok.is(MMToken::StringLiteral)) {
231306f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
231406f32e7eSjoerg << "header";
231506f32e7eSjoerg HadError = true;
231606f32e7eSjoerg return;
231706f32e7eSjoerg }
231806f32e7eSjoerg Module::UnresolvedHeaderDirective Header;
2319*13fbcb42Sjoerg Header.FileName = std::string(Tok.getString());
232006f32e7eSjoerg Header.FileNameLoc = consumeToken();
232106f32e7eSjoerg Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
232206f32e7eSjoerg Header.Kind =
232306f32e7eSjoerg (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
232406f32e7eSjoerg : Map.headerRoleToKind(Role));
232506f32e7eSjoerg
232606f32e7eSjoerg // Check whether we already have an umbrella.
232706f32e7eSjoerg if (Header.IsUmbrella && ActiveModule->Umbrella) {
232806f32e7eSjoerg Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
232906f32e7eSjoerg << ActiveModule->getFullModuleName();
233006f32e7eSjoerg HadError = true;
233106f32e7eSjoerg return;
233206f32e7eSjoerg }
233306f32e7eSjoerg
233406f32e7eSjoerg // If we were given stat information, parse it so we can skip looking for
233506f32e7eSjoerg // the file.
233606f32e7eSjoerg if (Tok.is(MMToken::LBrace)) {
233706f32e7eSjoerg SourceLocation LBraceLoc = consumeToken();
233806f32e7eSjoerg
233906f32e7eSjoerg while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
234006f32e7eSjoerg enum Attribute { Size, ModTime, Unknown };
234106f32e7eSjoerg StringRef Str = Tok.getString();
234206f32e7eSjoerg SourceLocation Loc = consumeToken();
234306f32e7eSjoerg switch (llvm::StringSwitch<Attribute>(Str)
234406f32e7eSjoerg .Case("size", Size)
234506f32e7eSjoerg .Case("mtime", ModTime)
234606f32e7eSjoerg .Default(Unknown)) {
234706f32e7eSjoerg case Size:
234806f32e7eSjoerg if (Header.Size)
234906f32e7eSjoerg Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
235006f32e7eSjoerg if (!Tok.is(MMToken::IntegerLiteral)) {
235106f32e7eSjoerg Diags.Report(Tok.getLocation(),
235206f32e7eSjoerg diag::err_mmap_invalid_header_attribute_value) << Str;
235306f32e7eSjoerg skipUntil(MMToken::RBrace);
235406f32e7eSjoerg break;
235506f32e7eSjoerg }
235606f32e7eSjoerg Header.Size = Tok.getInteger();
235706f32e7eSjoerg consumeToken();
235806f32e7eSjoerg break;
235906f32e7eSjoerg
236006f32e7eSjoerg case ModTime:
236106f32e7eSjoerg if (Header.ModTime)
236206f32e7eSjoerg Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
236306f32e7eSjoerg if (!Tok.is(MMToken::IntegerLiteral)) {
236406f32e7eSjoerg Diags.Report(Tok.getLocation(),
236506f32e7eSjoerg diag::err_mmap_invalid_header_attribute_value) << Str;
236606f32e7eSjoerg skipUntil(MMToken::RBrace);
236706f32e7eSjoerg break;
236806f32e7eSjoerg }
236906f32e7eSjoerg Header.ModTime = Tok.getInteger();
237006f32e7eSjoerg consumeToken();
237106f32e7eSjoerg break;
237206f32e7eSjoerg
237306f32e7eSjoerg case Unknown:
237406f32e7eSjoerg Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
237506f32e7eSjoerg skipUntil(MMToken::RBrace);
237606f32e7eSjoerg break;
237706f32e7eSjoerg }
237806f32e7eSjoerg }
237906f32e7eSjoerg
238006f32e7eSjoerg if (Tok.is(MMToken::RBrace))
238106f32e7eSjoerg consumeToken();
238206f32e7eSjoerg else {
238306f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
238406f32e7eSjoerg Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
238506f32e7eSjoerg HadError = true;
238606f32e7eSjoerg }
238706f32e7eSjoerg }
238806f32e7eSjoerg
238906f32e7eSjoerg bool NeedsFramework = false;
239006f32e7eSjoerg Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
239106f32e7eSjoerg
239206f32e7eSjoerg if (NeedsFramework && ActiveModule)
239306f32e7eSjoerg Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
239406f32e7eSjoerg << ActiveModule->getFullModuleName()
239506f32e7eSjoerg << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
239606f32e7eSjoerg }
239706f32e7eSjoerg
compareModuleHeaders(const Module::Header * A,const Module::Header * B)239806f32e7eSjoerg static int compareModuleHeaders(const Module::Header *A,
239906f32e7eSjoerg const Module::Header *B) {
240006f32e7eSjoerg return A->NameAsWritten.compare(B->NameAsWritten);
240106f32e7eSjoerg }
240206f32e7eSjoerg
240306f32e7eSjoerg /// Parse an umbrella directory declaration.
240406f32e7eSjoerg ///
240506f32e7eSjoerg /// umbrella-dir-declaration:
240606f32e7eSjoerg /// umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)240706f32e7eSjoerg void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
240806f32e7eSjoerg // Parse the directory name.
240906f32e7eSjoerg if (!Tok.is(MMToken::StringLiteral)) {
241006f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
241106f32e7eSjoerg << "umbrella";
241206f32e7eSjoerg HadError = true;
241306f32e7eSjoerg return;
241406f32e7eSjoerg }
241506f32e7eSjoerg
2416*13fbcb42Sjoerg std::string DirName = std::string(Tok.getString());
2417*13fbcb42Sjoerg std::string DirNameAsWritten = DirName;
241806f32e7eSjoerg SourceLocation DirNameLoc = consumeToken();
241906f32e7eSjoerg
242006f32e7eSjoerg // Check whether we already have an umbrella.
242106f32e7eSjoerg if (ActiveModule->Umbrella) {
242206f32e7eSjoerg Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
242306f32e7eSjoerg << ActiveModule->getFullModuleName();
242406f32e7eSjoerg HadError = true;
242506f32e7eSjoerg return;
242606f32e7eSjoerg }
242706f32e7eSjoerg
242806f32e7eSjoerg // Look for this file.
242906f32e7eSjoerg const DirectoryEntry *Dir = nullptr;
243006f32e7eSjoerg if (llvm::sys::path::is_absolute(DirName)) {
243106f32e7eSjoerg if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
243206f32e7eSjoerg Dir = *D;
243306f32e7eSjoerg } else {
243406f32e7eSjoerg SmallString<128> PathName;
243506f32e7eSjoerg PathName = Directory->getName();
243606f32e7eSjoerg llvm::sys::path::append(PathName, DirName);
243706f32e7eSjoerg if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
243806f32e7eSjoerg Dir = *D;
243906f32e7eSjoerg }
244006f32e7eSjoerg
244106f32e7eSjoerg if (!Dir) {
244206f32e7eSjoerg Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
244306f32e7eSjoerg << DirName;
244406f32e7eSjoerg return;
244506f32e7eSjoerg }
244606f32e7eSjoerg
244706f32e7eSjoerg if (UsesRequiresExcludedHack.count(ActiveModule)) {
244806f32e7eSjoerg // Mark this header 'textual' (see doc comment for
244906f32e7eSjoerg // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
245006f32e7eSjoerg // directory is relatively expensive, in practice this only applies to the
245106f32e7eSjoerg // uncommonly used Tcl module on Darwin platforms.
245206f32e7eSjoerg std::error_code EC;
245306f32e7eSjoerg SmallVector<Module::Header, 6> Headers;
245406f32e7eSjoerg llvm::vfs::FileSystem &FS =
245506f32e7eSjoerg SourceMgr.getFileManager().getVirtualFileSystem();
245606f32e7eSjoerg for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
245706f32e7eSjoerg I != E && !EC; I.increment(EC)) {
245806f32e7eSjoerg if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2459*13fbcb42Sjoerg Module::Header Header = {"", std::string(I->path()), *FE};
246006f32e7eSjoerg Headers.push_back(std::move(Header));
246106f32e7eSjoerg }
246206f32e7eSjoerg }
246306f32e7eSjoerg
246406f32e7eSjoerg // Sort header paths so that the pcm doesn't depend on iteration order.
246506f32e7eSjoerg llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
246606f32e7eSjoerg
246706f32e7eSjoerg for (auto &Header : Headers)
246806f32e7eSjoerg Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
246906f32e7eSjoerg return;
247006f32e7eSjoerg }
247106f32e7eSjoerg
247206f32e7eSjoerg if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
247306f32e7eSjoerg Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
247406f32e7eSjoerg << OwningModule->getFullModuleName();
247506f32e7eSjoerg HadError = true;
247606f32e7eSjoerg return;
247706f32e7eSjoerg }
247806f32e7eSjoerg
247906f32e7eSjoerg // Record this umbrella directory.
2480*13fbcb42Sjoerg Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
248106f32e7eSjoerg }
248206f32e7eSjoerg
248306f32e7eSjoerg /// Parse a module export declaration.
248406f32e7eSjoerg ///
248506f32e7eSjoerg /// export-declaration:
248606f32e7eSjoerg /// 'export' wildcard-module-id
248706f32e7eSjoerg ///
248806f32e7eSjoerg /// wildcard-module-id:
248906f32e7eSjoerg /// identifier
249006f32e7eSjoerg /// '*'
249106f32e7eSjoerg /// identifier '.' wildcard-module-id
parseExportDecl()249206f32e7eSjoerg void ModuleMapParser::parseExportDecl() {
249306f32e7eSjoerg assert(Tok.is(MMToken::ExportKeyword));
249406f32e7eSjoerg SourceLocation ExportLoc = consumeToken();
249506f32e7eSjoerg
249606f32e7eSjoerg // Parse the module-id with an optional wildcard at the end.
249706f32e7eSjoerg ModuleId ParsedModuleId;
249806f32e7eSjoerg bool Wildcard = false;
249906f32e7eSjoerg do {
250006f32e7eSjoerg // FIXME: Support string-literal module names here.
250106f32e7eSjoerg if (Tok.is(MMToken::Identifier)) {
2502*13fbcb42Sjoerg ParsedModuleId.push_back(
2503*13fbcb42Sjoerg std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
250406f32e7eSjoerg consumeToken();
250506f32e7eSjoerg
250606f32e7eSjoerg if (Tok.is(MMToken::Period)) {
250706f32e7eSjoerg consumeToken();
250806f32e7eSjoerg continue;
250906f32e7eSjoerg }
251006f32e7eSjoerg
251106f32e7eSjoerg break;
251206f32e7eSjoerg }
251306f32e7eSjoerg
251406f32e7eSjoerg if(Tok.is(MMToken::Star)) {
251506f32e7eSjoerg Wildcard = true;
251606f32e7eSjoerg consumeToken();
251706f32e7eSjoerg break;
251806f32e7eSjoerg }
251906f32e7eSjoerg
252006f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
252106f32e7eSjoerg HadError = true;
252206f32e7eSjoerg return;
252306f32e7eSjoerg } while (true);
252406f32e7eSjoerg
252506f32e7eSjoerg Module::UnresolvedExportDecl Unresolved = {
252606f32e7eSjoerg ExportLoc, ParsedModuleId, Wildcard
252706f32e7eSjoerg };
252806f32e7eSjoerg ActiveModule->UnresolvedExports.push_back(Unresolved);
252906f32e7eSjoerg }
253006f32e7eSjoerg
253106f32e7eSjoerg /// Parse a module export_as declaration.
253206f32e7eSjoerg ///
253306f32e7eSjoerg /// export-as-declaration:
253406f32e7eSjoerg /// 'export_as' identifier
parseExportAsDecl()253506f32e7eSjoerg void ModuleMapParser::parseExportAsDecl() {
253606f32e7eSjoerg assert(Tok.is(MMToken::ExportAsKeyword));
253706f32e7eSjoerg consumeToken();
253806f32e7eSjoerg
253906f32e7eSjoerg if (!Tok.is(MMToken::Identifier)) {
254006f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
254106f32e7eSjoerg HadError = true;
254206f32e7eSjoerg return;
254306f32e7eSjoerg }
254406f32e7eSjoerg
254506f32e7eSjoerg if (ActiveModule->Parent) {
254606f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
254706f32e7eSjoerg consumeToken();
254806f32e7eSjoerg return;
254906f32e7eSjoerg }
255006f32e7eSjoerg
255106f32e7eSjoerg if (!ActiveModule->ExportAsModule.empty()) {
255206f32e7eSjoerg if (ActiveModule->ExportAsModule == Tok.getString()) {
255306f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
255406f32e7eSjoerg << ActiveModule->Name << Tok.getString();
255506f32e7eSjoerg } else {
255606f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
255706f32e7eSjoerg << ActiveModule->Name << ActiveModule->ExportAsModule
255806f32e7eSjoerg << Tok.getString();
255906f32e7eSjoerg }
256006f32e7eSjoerg }
256106f32e7eSjoerg
2562*13fbcb42Sjoerg ActiveModule->ExportAsModule = std::string(Tok.getString());
256306f32e7eSjoerg Map.addLinkAsDependency(ActiveModule);
256406f32e7eSjoerg
256506f32e7eSjoerg consumeToken();
256606f32e7eSjoerg }
256706f32e7eSjoerg
256806f32e7eSjoerg /// Parse a module use declaration.
256906f32e7eSjoerg ///
257006f32e7eSjoerg /// use-declaration:
257106f32e7eSjoerg /// 'use' wildcard-module-id
parseUseDecl()257206f32e7eSjoerg void ModuleMapParser::parseUseDecl() {
257306f32e7eSjoerg assert(Tok.is(MMToken::UseKeyword));
257406f32e7eSjoerg auto KWLoc = consumeToken();
257506f32e7eSjoerg // Parse the module-id.
257606f32e7eSjoerg ModuleId ParsedModuleId;
257706f32e7eSjoerg parseModuleId(ParsedModuleId);
257806f32e7eSjoerg
257906f32e7eSjoerg if (ActiveModule->Parent)
258006f32e7eSjoerg Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
258106f32e7eSjoerg else
258206f32e7eSjoerg ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
258306f32e7eSjoerg }
258406f32e7eSjoerg
258506f32e7eSjoerg /// Parse a link declaration.
258606f32e7eSjoerg ///
258706f32e7eSjoerg /// module-declaration:
258806f32e7eSjoerg /// 'link' 'framework'[opt] string-literal
parseLinkDecl()258906f32e7eSjoerg void ModuleMapParser::parseLinkDecl() {
259006f32e7eSjoerg assert(Tok.is(MMToken::LinkKeyword));
259106f32e7eSjoerg SourceLocation LinkLoc = consumeToken();
259206f32e7eSjoerg
259306f32e7eSjoerg // Parse the optional 'framework' keyword.
259406f32e7eSjoerg bool IsFramework = false;
259506f32e7eSjoerg if (Tok.is(MMToken::FrameworkKeyword)) {
259606f32e7eSjoerg consumeToken();
259706f32e7eSjoerg IsFramework = true;
259806f32e7eSjoerg }
259906f32e7eSjoerg
260006f32e7eSjoerg // Parse the library name
260106f32e7eSjoerg if (!Tok.is(MMToken::StringLiteral)) {
260206f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
260306f32e7eSjoerg << IsFramework << SourceRange(LinkLoc);
260406f32e7eSjoerg HadError = true;
260506f32e7eSjoerg return;
260606f32e7eSjoerg }
260706f32e7eSjoerg
2608*13fbcb42Sjoerg std::string LibraryName = std::string(Tok.getString());
260906f32e7eSjoerg consumeToken();
261006f32e7eSjoerg ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
261106f32e7eSjoerg IsFramework));
261206f32e7eSjoerg }
261306f32e7eSjoerg
261406f32e7eSjoerg /// Parse a configuration macro declaration.
261506f32e7eSjoerg ///
261606f32e7eSjoerg /// module-declaration:
261706f32e7eSjoerg /// 'config_macros' attributes[opt] config-macro-list?
261806f32e7eSjoerg ///
261906f32e7eSjoerg /// config-macro-list:
262006f32e7eSjoerg /// identifier (',' identifier)?
parseConfigMacros()262106f32e7eSjoerg void ModuleMapParser::parseConfigMacros() {
262206f32e7eSjoerg assert(Tok.is(MMToken::ConfigMacros));
262306f32e7eSjoerg SourceLocation ConfigMacrosLoc = consumeToken();
262406f32e7eSjoerg
262506f32e7eSjoerg // Only top-level modules can have configuration macros.
262606f32e7eSjoerg if (ActiveModule->Parent) {
262706f32e7eSjoerg Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
262806f32e7eSjoerg }
262906f32e7eSjoerg
263006f32e7eSjoerg // Parse the optional attributes.
263106f32e7eSjoerg Attributes Attrs;
263206f32e7eSjoerg if (parseOptionalAttributes(Attrs))
263306f32e7eSjoerg return;
263406f32e7eSjoerg
263506f32e7eSjoerg if (Attrs.IsExhaustive && !ActiveModule->Parent) {
263606f32e7eSjoerg ActiveModule->ConfigMacrosExhaustive = true;
263706f32e7eSjoerg }
263806f32e7eSjoerg
263906f32e7eSjoerg // If we don't have an identifier, we're done.
264006f32e7eSjoerg // FIXME: Support macros with the same name as a keyword here.
264106f32e7eSjoerg if (!Tok.is(MMToken::Identifier))
264206f32e7eSjoerg return;
264306f32e7eSjoerg
264406f32e7eSjoerg // Consume the first identifier.
264506f32e7eSjoerg if (!ActiveModule->Parent) {
264606f32e7eSjoerg ActiveModule->ConfigMacros.push_back(Tok.getString().str());
264706f32e7eSjoerg }
264806f32e7eSjoerg consumeToken();
264906f32e7eSjoerg
265006f32e7eSjoerg do {
265106f32e7eSjoerg // If there's a comma, consume it.
265206f32e7eSjoerg if (!Tok.is(MMToken::Comma))
265306f32e7eSjoerg break;
265406f32e7eSjoerg consumeToken();
265506f32e7eSjoerg
265606f32e7eSjoerg // We expect to see a macro name here.
265706f32e7eSjoerg // FIXME: Support macros with the same name as a keyword here.
265806f32e7eSjoerg if (!Tok.is(MMToken::Identifier)) {
265906f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
266006f32e7eSjoerg break;
266106f32e7eSjoerg }
266206f32e7eSjoerg
266306f32e7eSjoerg // Consume the macro name.
266406f32e7eSjoerg if (!ActiveModule->Parent) {
266506f32e7eSjoerg ActiveModule->ConfigMacros.push_back(Tok.getString().str());
266606f32e7eSjoerg }
266706f32e7eSjoerg consumeToken();
266806f32e7eSjoerg } while (true);
266906f32e7eSjoerg }
267006f32e7eSjoerg
267106f32e7eSjoerg /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)267206f32e7eSjoerg static std::string formatModuleId(const ModuleId &Id) {
267306f32e7eSjoerg std::string result;
267406f32e7eSjoerg {
267506f32e7eSjoerg llvm::raw_string_ostream OS(result);
267606f32e7eSjoerg
267706f32e7eSjoerg for (unsigned I = 0, N = Id.size(); I != N; ++I) {
267806f32e7eSjoerg if (I)
267906f32e7eSjoerg OS << ".";
268006f32e7eSjoerg OS << Id[I].first;
268106f32e7eSjoerg }
268206f32e7eSjoerg }
268306f32e7eSjoerg
268406f32e7eSjoerg return result;
268506f32e7eSjoerg }
268606f32e7eSjoerg
268706f32e7eSjoerg /// Parse a conflict declaration.
268806f32e7eSjoerg ///
268906f32e7eSjoerg /// module-declaration:
269006f32e7eSjoerg /// 'conflict' module-id ',' string-literal
parseConflict()269106f32e7eSjoerg void ModuleMapParser::parseConflict() {
269206f32e7eSjoerg assert(Tok.is(MMToken::Conflict));
269306f32e7eSjoerg SourceLocation ConflictLoc = consumeToken();
269406f32e7eSjoerg Module::UnresolvedConflict Conflict;
269506f32e7eSjoerg
269606f32e7eSjoerg // Parse the module-id.
269706f32e7eSjoerg if (parseModuleId(Conflict.Id))
269806f32e7eSjoerg return;
269906f32e7eSjoerg
270006f32e7eSjoerg // Parse the ','.
270106f32e7eSjoerg if (!Tok.is(MMToken::Comma)) {
270206f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
270306f32e7eSjoerg << SourceRange(ConflictLoc);
270406f32e7eSjoerg return;
270506f32e7eSjoerg }
270606f32e7eSjoerg consumeToken();
270706f32e7eSjoerg
270806f32e7eSjoerg // Parse the message.
270906f32e7eSjoerg if (!Tok.is(MMToken::StringLiteral)) {
271006f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
271106f32e7eSjoerg << formatModuleId(Conflict.Id);
271206f32e7eSjoerg return;
271306f32e7eSjoerg }
271406f32e7eSjoerg Conflict.Message = Tok.getString().str();
271506f32e7eSjoerg consumeToken();
271606f32e7eSjoerg
271706f32e7eSjoerg // Add this unresolved conflict.
271806f32e7eSjoerg ActiveModule->UnresolvedConflicts.push_back(Conflict);
271906f32e7eSjoerg }
272006f32e7eSjoerg
272106f32e7eSjoerg /// Parse an inferred module declaration (wildcard modules).
272206f32e7eSjoerg ///
272306f32e7eSjoerg /// module-declaration:
272406f32e7eSjoerg /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
272506f32e7eSjoerg /// { inferred-module-member* }
272606f32e7eSjoerg ///
272706f32e7eSjoerg /// inferred-module-member:
272806f32e7eSjoerg /// 'export' '*'
272906f32e7eSjoerg /// 'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)273006f32e7eSjoerg void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
273106f32e7eSjoerg assert(Tok.is(MMToken::Star));
273206f32e7eSjoerg SourceLocation StarLoc = consumeToken();
273306f32e7eSjoerg bool Failed = false;
273406f32e7eSjoerg
273506f32e7eSjoerg // Inferred modules must be submodules.
273606f32e7eSjoerg if (!ActiveModule && !Framework) {
273706f32e7eSjoerg Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
273806f32e7eSjoerg Failed = true;
273906f32e7eSjoerg }
274006f32e7eSjoerg
274106f32e7eSjoerg if (ActiveModule) {
274206f32e7eSjoerg // Inferred modules must have umbrella directories.
274306f32e7eSjoerg if (!Failed && ActiveModule->IsAvailable &&
274406f32e7eSjoerg !ActiveModule->getUmbrellaDir()) {
274506f32e7eSjoerg Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
274606f32e7eSjoerg Failed = true;
274706f32e7eSjoerg }
274806f32e7eSjoerg
274906f32e7eSjoerg // Check for redefinition of an inferred module.
275006f32e7eSjoerg if (!Failed && ActiveModule->InferSubmodules) {
275106f32e7eSjoerg Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
275206f32e7eSjoerg if (ActiveModule->InferredSubmoduleLoc.isValid())
275306f32e7eSjoerg Diags.Report(ActiveModule->InferredSubmoduleLoc,
275406f32e7eSjoerg diag::note_mmap_prev_definition);
275506f32e7eSjoerg Failed = true;
275606f32e7eSjoerg }
275706f32e7eSjoerg
275806f32e7eSjoerg // Check for the 'framework' keyword, which is not permitted here.
275906f32e7eSjoerg if (Framework) {
276006f32e7eSjoerg Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
276106f32e7eSjoerg Framework = false;
276206f32e7eSjoerg }
276306f32e7eSjoerg } else if (Explicit) {
276406f32e7eSjoerg Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
276506f32e7eSjoerg Explicit = false;
276606f32e7eSjoerg }
276706f32e7eSjoerg
276806f32e7eSjoerg // If there were any problems with this inferred submodule, skip its body.
276906f32e7eSjoerg if (Failed) {
277006f32e7eSjoerg if (Tok.is(MMToken::LBrace)) {
277106f32e7eSjoerg consumeToken();
277206f32e7eSjoerg skipUntil(MMToken::RBrace);
277306f32e7eSjoerg if (Tok.is(MMToken::RBrace))
277406f32e7eSjoerg consumeToken();
277506f32e7eSjoerg }
277606f32e7eSjoerg HadError = true;
277706f32e7eSjoerg return;
277806f32e7eSjoerg }
277906f32e7eSjoerg
278006f32e7eSjoerg // Parse optional attributes.
278106f32e7eSjoerg Attributes Attrs;
278206f32e7eSjoerg if (parseOptionalAttributes(Attrs))
278306f32e7eSjoerg return;
278406f32e7eSjoerg
278506f32e7eSjoerg if (ActiveModule) {
278606f32e7eSjoerg // Note that we have an inferred submodule.
278706f32e7eSjoerg ActiveModule->InferSubmodules = true;
278806f32e7eSjoerg ActiveModule->InferredSubmoduleLoc = StarLoc;
278906f32e7eSjoerg ActiveModule->InferExplicitSubmodules = Explicit;
279006f32e7eSjoerg } else {
279106f32e7eSjoerg // We'll be inferring framework modules for this directory.
279206f32e7eSjoerg Map.InferredDirectories[Directory].InferModules = true;
279306f32e7eSjoerg Map.InferredDirectories[Directory].Attrs = Attrs;
279406f32e7eSjoerg Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
279506f32e7eSjoerg // FIXME: Handle the 'framework' keyword.
279606f32e7eSjoerg }
279706f32e7eSjoerg
279806f32e7eSjoerg // Parse the opening brace.
279906f32e7eSjoerg if (!Tok.is(MMToken::LBrace)) {
280006f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
280106f32e7eSjoerg HadError = true;
280206f32e7eSjoerg return;
280306f32e7eSjoerg }
280406f32e7eSjoerg SourceLocation LBraceLoc = consumeToken();
280506f32e7eSjoerg
280606f32e7eSjoerg // Parse the body of the inferred submodule.
280706f32e7eSjoerg bool Done = false;
280806f32e7eSjoerg do {
280906f32e7eSjoerg switch (Tok.Kind) {
281006f32e7eSjoerg case MMToken::EndOfFile:
281106f32e7eSjoerg case MMToken::RBrace:
281206f32e7eSjoerg Done = true;
281306f32e7eSjoerg break;
281406f32e7eSjoerg
281506f32e7eSjoerg case MMToken::ExcludeKeyword:
281606f32e7eSjoerg if (ActiveModule) {
281706f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
281806f32e7eSjoerg << (ActiveModule != nullptr);
281906f32e7eSjoerg consumeToken();
282006f32e7eSjoerg break;
282106f32e7eSjoerg }
282206f32e7eSjoerg
282306f32e7eSjoerg consumeToken();
282406f32e7eSjoerg // FIXME: Support string-literal module names here.
282506f32e7eSjoerg if (!Tok.is(MMToken::Identifier)) {
282606f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
282706f32e7eSjoerg break;
282806f32e7eSjoerg }
282906f32e7eSjoerg
2830*13fbcb42Sjoerg Map.InferredDirectories[Directory].ExcludedModules.push_back(
2831*13fbcb42Sjoerg std::string(Tok.getString()));
283206f32e7eSjoerg consumeToken();
283306f32e7eSjoerg break;
283406f32e7eSjoerg
283506f32e7eSjoerg case MMToken::ExportKeyword:
283606f32e7eSjoerg if (!ActiveModule) {
283706f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
283806f32e7eSjoerg << (ActiveModule != nullptr);
283906f32e7eSjoerg consumeToken();
284006f32e7eSjoerg break;
284106f32e7eSjoerg }
284206f32e7eSjoerg
284306f32e7eSjoerg consumeToken();
284406f32e7eSjoerg if (Tok.is(MMToken::Star))
284506f32e7eSjoerg ActiveModule->InferExportWildcard = true;
284606f32e7eSjoerg else
284706f32e7eSjoerg Diags.Report(Tok.getLocation(),
284806f32e7eSjoerg diag::err_mmap_expected_export_wildcard);
284906f32e7eSjoerg consumeToken();
285006f32e7eSjoerg break;
285106f32e7eSjoerg
285206f32e7eSjoerg case MMToken::ExplicitKeyword:
285306f32e7eSjoerg case MMToken::ModuleKeyword:
285406f32e7eSjoerg case MMToken::HeaderKeyword:
285506f32e7eSjoerg case MMToken::PrivateKeyword:
285606f32e7eSjoerg case MMToken::UmbrellaKeyword:
285706f32e7eSjoerg default:
285806f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
285906f32e7eSjoerg << (ActiveModule != nullptr);
286006f32e7eSjoerg consumeToken();
286106f32e7eSjoerg break;
286206f32e7eSjoerg }
286306f32e7eSjoerg } while (!Done);
286406f32e7eSjoerg
286506f32e7eSjoerg if (Tok.is(MMToken::RBrace))
286606f32e7eSjoerg consumeToken();
286706f32e7eSjoerg else {
286806f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
286906f32e7eSjoerg Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
287006f32e7eSjoerg HadError = true;
287106f32e7eSjoerg }
287206f32e7eSjoerg }
287306f32e7eSjoerg
287406f32e7eSjoerg /// Parse optional attributes.
287506f32e7eSjoerg ///
287606f32e7eSjoerg /// attributes:
287706f32e7eSjoerg /// attribute attributes
287806f32e7eSjoerg /// attribute
287906f32e7eSjoerg ///
288006f32e7eSjoerg /// attribute:
288106f32e7eSjoerg /// [ identifier ]
288206f32e7eSjoerg ///
288306f32e7eSjoerg /// \param Attrs Will be filled in with the parsed attributes.
288406f32e7eSjoerg ///
288506f32e7eSjoerg /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)288606f32e7eSjoerg bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
288706f32e7eSjoerg bool HadError = false;
288806f32e7eSjoerg
288906f32e7eSjoerg while (Tok.is(MMToken::LSquare)) {
289006f32e7eSjoerg // Consume the '['.
289106f32e7eSjoerg SourceLocation LSquareLoc = consumeToken();
289206f32e7eSjoerg
289306f32e7eSjoerg // Check whether we have an attribute name here.
289406f32e7eSjoerg if (!Tok.is(MMToken::Identifier)) {
289506f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
289606f32e7eSjoerg skipUntil(MMToken::RSquare);
289706f32e7eSjoerg if (Tok.is(MMToken::RSquare))
289806f32e7eSjoerg consumeToken();
289906f32e7eSjoerg HadError = true;
290006f32e7eSjoerg }
290106f32e7eSjoerg
290206f32e7eSjoerg // Decode the attribute name.
290306f32e7eSjoerg AttributeKind Attribute
290406f32e7eSjoerg = llvm::StringSwitch<AttributeKind>(Tok.getString())
290506f32e7eSjoerg .Case("exhaustive", AT_exhaustive)
290606f32e7eSjoerg .Case("extern_c", AT_extern_c)
290706f32e7eSjoerg .Case("no_undeclared_includes", AT_no_undeclared_includes)
290806f32e7eSjoerg .Case("system", AT_system)
290906f32e7eSjoerg .Default(AT_unknown);
291006f32e7eSjoerg switch (Attribute) {
291106f32e7eSjoerg case AT_unknown:
291206f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
291306f32e7eSjoerg << Tok.getString();
291406f32e7eSjoerg break;
291506f32e7eSjoerg
291606f32e7eSjoerg case AT_system:
291706f32e7eSjoerg Attrs.IsSystem = true;
291806f32e7eSjoerg break;
291906f32e7eSjoerg
292006f32e7eSjoerg case AT_extern_c:
292106f32e7eSjoerg Attrs.IsExternC = true;
292206f32e7eSjoerg break;
292306f32e7eSjoerg
292406f32e7eSjoerg case AT_exhaustive:
292506f32e7eSjoerg Attrs.IsExhaustive = true;
292606f32e7eSjoerg break;
292706f32e7eSjoerg
292806f32e7eSjoerg case AT_no_undeclared_includes:
292906f32e7eSjoerg Attrs.NoUndeclaredIncludes = true;
293006f32e7eSjoerg break;
293106f32e7eSjoerg }
293206f32e7eSjoerg consumeToken();
293306f32e7eSjoerg
293406f32e7eSjoerg // Consume the ']'.
293506f32e7eSjoerg if (!Tok.is(MMToken::RSquare)) {
293606f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
293706f32e7eSjoerg Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
293806f32e7eSjoerg skipUntil(MMToken::RSquare);
293906f32e7eSjoerg HadError = true;
294006f32e7eSjoerg }
294106f32e7eSjoerg
294206f32e7eSjoerg if (Tok.is(MMToken::RSquare))
294306f32e7eSjoerg consumeToken();
294406f32e7eSjoerg }
294506f32e7eSjoerg
294606f32e7eSjoerg return HadError;
294706f32e7eSjoerg }
294806f32e7eSjoerg
294906f32e7eSjoerg /// Parse a module map file.
295006f32e7eSjoerg ///
295106f32e7eSjoerg /// module-map-file:
295206f32e7eSjoerg /// module-declaration*
parseModuleMapFile()295306f32e7eSjoerg bool ModuleMapParser::parseModuleMapFile() {
295406f32e7eSjoerg do {
295506f32e7eSjoerg switch (Tok.Kind) {
295606f32e7eSjoerg case MMToken::EndOfFile:
295706f32e7eSjoerg return HadError;
295806f32e7eSjoerg
295906f32e7eSjoerg case MMToken::ExplicitKeyword:
296006f32e7eSjoerg case MMToken::ExternKeyword:
296106f32e7eSjoerg case MMToken::ModuleKeyword:
296206f32e7eSjoerg case MMToken::FrameworkKeyword:
296306f32e7eSjoerg parseModuleDecl();
296406f32e7eSjoerg break;
296506f32e7eSjoerg
296606f32e7eSjoerg case MMToken::Comma:
296706f32e7eSjoerg case MMToken::ConfigMacros:
296806f32e7eSjoerg case MMToken::Conflict:
296906f32e7eSjoerg case MMToken::Exclaim:
297006f32e7eSjoerg case MMToken::ExcludeKeyword:
297106f32e7eSjoerg case MMToken::ExportKeyword:
297206f32e7eSjoerg case MMToken::ExportAsKeyword:
297306f32e7eSjoerg case MMToken::HeaderKeyword:
297406f32e7eSjoerg case MMToken::Identifier:
297506f32e7eSjoerg case MMToken::LBrace:
297606f32e7eSjoerg case MMToken::LinkKeyword:
297706f32e7eSjoerg case MMToken::LSquare:
297806f32e7eSjoerg case MMToken::Period:
297906f32e7eSjoerg case MMToken::PrivateKeyword:
298006f32e7eSjoerg case MMToken::RBrace:
298106f32e7eSjoerg case MMToken::RSquare:
298206f32e7eSjoerg case MMToken::RequiresKeyword:
298306f32e7eSjoerg case MMToken::Star:
298406f32e7eSjoerg case MMToken::StringLiteral:
298506f32e7eSjoerg case MMToken::IntegerLiteral:
298606f32e7eSjoerg case MMToken::TextualKeyword:
298706f32e7eSjoerg case MMToken::UmbrellaKeyword:
298806f32e7eSjoerg case MMToken::UseKeyword:
298906f32e7eSjoerg Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
299006f32e7eSjoerg HadError = true;
299106f32e7eSjoerg consumeToken();
299206f32e7eSjoerg break;
299306f32e7eSjoerg }
299406f32e7eSjoerg } while (true);
299506f32e7eSjoerg }
299606f32e7eSjoerg
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)299706f32e7eSjoerg bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
299806f32e7eSjoerg const DirectoryEntry *Dir, FileID ID,
299906f32e7eSjoerg unsigned *Offset,
300006f32e7eSjoerg SourceLocation ExternModuleLoc) {
300106f32e7eSjoerg assert(Target && "Missing target information");
300206f32e7eSjoerg llvm::DenseMap<const FileEntry *, bool>::iterator Known
300306f32e7eSjoerg = ParsedModuleMap.find(File);
300406f32e7eSjoerg if (Known != ParsedModuleMap.end())
300506f32e7eSjoerg return Known->second;
300606f32e7eSjoerg
300706f32e7eSjoerg // If the module map file wasn't already entered, do so now.
300806f32e7eSjoerg if (ID.isInvalid()) {
300906f32e7eSjoerg auto FileCharacter =
301006f32e7eSjoerg IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
301106f32e7eSjoerg ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
301206f32e7eSjoerg }
301306f32e7eSjoerg
301406f32e7eSjoerg assert(Target && "Missing target information");
3015*13fbcb42Sjoerg llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
301606f32e7eSjoerg if (!Buffer)
301706f32e7eSjoerg return ParsedModuleMap[File] = true;
301806f32e7eSjoerg assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
301906f32e7eSjoerg "invalid buffer offset");
302006f32e7eSjoerg
302106f32e7eSjoerg // Parse this module map file.
302206f32e7eSjoerg Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
302306f32e7eSjoerg Buffer->getBufferStart(),
302406f32e7eSjoerg Buffer->getBufferStart() + (Offset ? *Offset : 0),
302506f32e7eSjoerg Buffer->getBufferEnd());
302606f32e7eSjoerg SourceLocation Start = L.getSourceLocation();
302706f32e7eSjoerg ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
302806f32e7eSjoerg IsSystem);
302906f32e7eSjoerg bool Result = Parser.parseModuleMapFile();
303006f32e7eSjoerg ParsedModuleMap[File] = Result;
303106f32e7eSjoerg
303206f32e7eSjoerg if (Offset) {
303306f32e7eSjoerg auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
303406f32e7eSjoerg assert(Loc.first == ID && "stopped in a different file?");
303506f32e7eSjoerg *Offset = Loc.second;
303606f32e7eSjoerg }
303706f32e7eSjoerg
303806f32e7eSjoerg // Notify callbacks that we parsed it.
303906f32e7eSjoerg for (const auto &Cb : Callbacks)
304006f32e7eSjoerg Cb->moduleMapFileRead(Start, *File, IsSystem);
304106f32e7eSjoerg
304206f32e7eSjoerg return Result;
304306f32e7eSjoerg }
3044