xref: /openbsd-src/gnu/llvm/clang/lib/Lex/ModuleMap.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file defines the ModuleMap implementation, which describes the layout
10e5dd7070Spatrick // of a module as it relates to headers.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #include "clang/Lex/ModuleMap.h"
15e5dd7070Spatrick #include "clang/Basic/CharInfo.h"
16e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
17e5dd7070Spatrick #include "clang/Basic/FileManager.h"
18e5dd7070Spatrick #include "clang/Basic/LLVM.h"
19e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
20e5dd7070Spatrick #include "clang/Basic/Module.h"
21e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
22e5dd7070Spatrick #include "clang/Basic/SourceManager.h"
23e5dd7070Spatrick #include "clang/Basic/TargetInfo.h"
24e5dd7070Spatrick #include "clang/Lex/HeaderSearch.h"
25e5dd7070Spatrick #include "clang/Lex/HeaderSearchOptions.h"
26e5dd7070Spatrick #include "clang/Lex/LexDiagnostic.h"
27e5dd7070Spatrick #include "clang/Lex/Lexer.h"
28e5dd7070Spatrick #include "clang/Lex/LiteralSupport.h"
29e5dd7070Spatrick #include "clang/Lex/Token.h"
30e5dd7070Spatrick #include "llvm/ADT/DenseMap.h"
31e5dd7070Spatrick #include "llvm/ADT/STLExtras.h"
32e5dd7070Spatrick #include "llvm/ADT/SmallPtrSet.h"
33e5dd7070Spatrick #include "llvm/ADT/SmallString.h"
34e5dd7070Spatrick #include "llvm/ADT/SmallVector.h"
35e5dd7070Spatrick #include "llvm/ADT/StringMap.h"
36e5dd7070Spatrick #include "llvm/ADT/StringRef.h"
37e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
38e5dd7070Spatrick #include "llvm/Support/Allocator.h"
39e5dd7070Spatrick #include "llvm/Support/Compiler.h"
40e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
41e5dd7070Spatrick #include "llvm/Support/MemoryBuffer.h"
42e5dd7070Spatrick #include "llvm/Support/Path.h"
43e5dd7070Spatrick #include "llvm/Support/VirtualFileSystem.h"
44e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
45e5dd7070Spatrick #include <algorithm>
46e5dd7070Spatrick #include <cassert>
47e5dd7070Spatrick #include <cstdint>
48e5dd7070Spatrick #include <cstring>
49*12c85518Srobert #include <optional>
50e5dd7070Spatrick #include <string>
51e5dd7070Spatrick #include <system_error>
52e5dd7070Spatrick #include <utility>
53e5dd7070Spatrick 
54e5dd7070Spatrick using namespace clang;
55e5dd7070Spatrick 
anchor()56e5dd7070Spatrick void ModuleMapCallbacks::anchor() {}
57e5dd7070Spatrick 
resolveLinkAsDependencies(Module * Mod)58e5dd7070Spatrick void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
59e5dd7070Spatrick   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
60e5dd7070Spatrick   if (PendingLinkAs != PendingLinkAsModule.end()) {
61e5dd7070Spatrick     for (auto &Name : PendingLinkAs->second) {
62e5dd7070Spatrick       auto *M = findModule(Name.getKey());
63e5dd7070Spatrick       if (M)
64e5dd7070Spatrick         M->UseExportAsModuleLinkName = true;
65e5dd7070Spatrick     }
66e5dd7070Spatrick   }
67e5dd7070Spatrick }
68e5dd7070Spatrick 
addLinkAsDependency(Module * Mod)69e5dd7070Spatrick void ModuleMap::addLinkAsDependency(Module *Mod) {
70e5dd7070Spatrick   if (findModule(Mod->ExportAsModule))
71e5dd7070Spatrick     Mod->UseExportAsModuleLinkName = true;
72e5dd7070Spatrick   else
73e5dd7070Spatrick     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
74e5dd7070Spatrick }
75e5dd7070Spatrick 
headerRoleToKind(ModuleHeaderRole Role)76e5dd7070Spatrick Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
77e5dd7070Spatrick   switch ((int)Role) {
78e5dd7070Spatrick   case NormalHeader:
79e5dd7070Spatrick     return Module::HK_Normal;
80e5dd7070Spatrick   case PrivateHeader:
81e5dd7070Spatrick     return Module::HK_Private;
82e5dd7070Spatrick   case TextualHeader:
83e5dd7070Spatrick     return Module::HK_Textual;
84e5dd7070Spatrick   case PrivateHeader | TextualHeader:
85e5dd7070Spatrick     return Module::HK_PrivateTextual;
86*12c85518Srobert   case ExcludedHeader:
87*12c85518Srobert     return Module::HK_Excluded;
88e5dd7070Spatrick   }
89*12c85518Srobert   llvm_unreachable("unknown header role");
90e5dd7070Spatrick }
91e5dd7070Spatrick 
92e5dd7070Spatrick ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)93e5dd7070Spatrick ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
94e5dd7070Spatrick   switch ((int)Kind) {
95e5dd7070Spatrick   case Module::HK_Normal:
96e5dd7070Spatrick     return NormalHeader;
97e5dd7070Spatrick   case Module::HK_Private:
98e5dd7070Spatrick     return PrivateHeader;
99e5dd7070Spatrick   case Module::HK_Textual:
100e5dd7070Spatrick     return TextualHeader;
101e5dd7070Spatrick   case Module::HK_PrivateTextual:
102e5dd7070Spatrick     return ModuleHeaderRole(PrivateHeader | TextualHeader);
103e5dd7070Spatrick   case Module::HK_Excluded:
104*12c85518Srobert     return ExcludedHeader;
105e5dd7070Spatrick   }
106e5dd7070Spatrick   llvm_unreachable("unknown header kind");
107e5dd7070Spatrick }
108e5dd7070Spatrick 
isModular(ModuleHeaderRole Role)109*12c85518Srobert bool ModuleMap::isModular(ModuleHeaderRole Role) {
110*12c85518Srobert   return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));
111*12c85518Srobert }
112*12c85518Srobert 
113e5dd7070Spatrick Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const114e5dd7070Spatrick ModuleMap::resolveExport(Module *Mod,
115e5dd7070Spatrick                          const Module::UnresolvedExportDecl &Unresolved,
116e5dd7070Spatrick                          bool Complain) const {
117e5dd7070Spatrick   // We may have just a wildcard.
118e5dd7070Spatrick   if (Unresolved.Id.empty()) {
119e5dd7070Spatrick     assert(Unresolved.Wildcard && "Invalid unresolved export");
120e5dd7070Spatrick     return Module::ExportDecl(nullptr, true);
121e5dd7070Spatrick   }
122e5dd7070Spatrick 
123e5dd7070Spatrick   // Resolve the module-id.
124e5dd7070Spatrick   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
125e5dd7070Spatrick   if (!Context)
126e5dd7070Spatrick     return {};
127e5dd7070Spatrick 
128e5dd7070Spatrick   return Module::ExportDecl(Context, Unresolved.Wildcard);
129e5dd7070Spatrick }
130e5dd7070Spatrick 
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const131e5dd7070Spatrick Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
132e5dd7070Spatrick                                    bool Complain) const {
133e5dd7070Spatrick   // Find the starting module.
134e5dd7070Spatrick   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
135e5dd7070Spatrick   if (!Context) {
136e5dd7070Spatrick     if (Complain)
137e5dd7070Spatrick       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
138e5dd7070Spatrick       << Id[0].first << Mod->getFullModuleName();
139e5dd7070Spatrick 
140e5dd7070Spatrick     return nullptr;
141e5dd7070Spatrick   }
142e5dd7070Spatrick 
143e5dd7070Spatrick   // Dig into the module path.
144e5dd7070Spatrick   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
145e5dd7070Spatrick     Module *Sub = lookupModuleQualified(Id[I].first, Context);
146e5dd7070Spatrick     if (!Sub) {
147e5dd7070Spatrick       if (Complain)
148e5dd7070Spatrick         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
149e5dd7070Spatrick         << Id[I].first << Context->getFullModuleName()
150e5dd7070Spatrick         << SourceRange(Id[0].second, Id[I-1].second);
151e5dd7070Spatrick 
152e5dd7070Spatrick       return nullptr;
153e5dd7070Spatrick     }
154e5dd7070Spatrick 
155e5dd7070Spatrick     Context = Sub;
156e5dd7070Spatrick   }
157e5dd7070Spatrick 
158e5dd7070Spatrick   return Context;
159e5dd7070Spatrick }
160e5dd7070Spatrick 
161e5dd7070Spatrick /// Append to \p Paths the set of paths needed to get to the
162e5dd7070Spatrick /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)163e5dd7070Spatrick static void appendSubframeworkPaths(Module *Mod,
164e5dd7070Spatrick                                     SmallVectorImpl<char> &Path) {
165e5dd7070Spatrick   // Collect the framework names from the given module to the top-level module.
166e5dd7070Spatrick   SmallVector<StringRef, 2> Paths;
167e5dd7070Spatrick   for (; Mod; Mod = Mod->Parent) {
168e5dd7070Spatrick     if (Mod->IsFramework)
169e5dd7070Spatrick       Paths.push_back(Mod->Name);
170e5dd7070Spatrick   }
171e5dd7070Spatrick 
172e5dd7070Spatrick   if (Paths.empty())
173e5dd7070Spatrick     return;
174e5dd7070Spatrick 
175e5dd7070Spatrick   // Add Frameworks/Name.framework for each subframework.
176*12c85518Srobert   for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
177*12c85518Srobert     llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");
178e5dd7070Spatrick }
179e5dd7070Spatrick 
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)180*12c85518Srobert OptionalFileEntryRef ModuleMap::findHeader(
181e5dd7070Spatrick     Module *M, const Module::UnresolvedHeaderDirective &Header,
182e5dd7070Spatrick     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
183e5dd7070Spatrick   // Search for the header file within the module's home directory.
184e5dd7070Spatrick   auto *Directory = M->Directory;
185e5dd7070Spatrick   SmallString<128> FullPathName(Directory->getName());
186e5dd7070Spatrick 
187*12c85518Srobert   auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef {
188a9ac8606Spatrick     auto File =
189a9ac8606Spatrick         expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
190a9ac8606Spatrick     if (!File || (Header.Size && File->getSize() != *Header.Size) ||
191a9ac8606Spatrick         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
192*12c85518Srobert       return std::nullopt;
193e5dd7070Spatrick     return *File;
194e5dd7070Spatrick   };
195e5dd7070Spatrick 
196*12c85518Srobert   auto GetFrameworkFile = [&]() -> OptionalFileEntryRef {
197e5dd7070Spatrick     unsigned FullPathLength = FullPathName.size();
198e5dd7070Spatrick     appendSubframeworkPaths(M, RelativePathName);
199e5dd7070Spatrick     unsigned RelativePathLength = RelativePathName.size();
200e5dd7070Spatrick 
201e5dd7070Spatrick     // Check whether this file is in the public headers.
202e5dd7070Spatrick     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
203e5dd7070Spatrick     llvm::sys::path::append(FullPathName, RelativePathName);
204a9ac8606Spatrick     if (auto File = GetFile(FullPathName))
205e5dd7070Spatrick       return File;
206e5dd7070Spatrick 
207e5dd7070Spatrick     // Check whether this file is in the private headers.
208e5dd7070Spatrick     // Ideally, private modules in the form 'FrameworkName.Private' should
209e5dd7070Spatrick     // be defined as 'module FrameworkName.Private', and not as
210e5dd7070Spatrick     // 'framework module FrameworkName.Private', since a 'Private.Framework'
211e5dd7070Spatrick     // does not usually exist. However, since both are currently widely used
212e5dd7070Spatrick     // for private modules, make sure we find the right path in both cases.
213e5dd7070Spatrick     if (M->IsFramework && M->Name == "Private")
214e5dd7070Spatrick       RelativePathName.clear();
215e5dd7070Spatrick     else
216e5dd7070Spatrick       RelativePathName.resize(RelativePathLength);
217e5dd7070Spatrick     FullPathName.resize(FullPathLength);
218e5dd7070Spatrick     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
219e5dd7070Spatrick                             Header.FileName);
220e5dd7070Spatrick     llvm::sys::path::append(FullPathName, RelativePathName);
221e5dd7070Spatrick     return GetFile(FullPathName);
222e5dd7070Spatrick   };
223e5dd7070Spatrick 
224e5dd7070Spatrick   if (llvm::sys::path::is_absolute(Header.FileName)) {
225e5dd7070Spatrick     RelativePathName.clear();
226e5dd7070Spatrick     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
227e5dd7070Spatrick     return GetFile(Header.FileName);
228e5dd7070Spatrick   }
229e5dd7070Spatrick 
230e5dd7070Spatrick   if (M->isPartOfFramework())
231e5dd7070Spatrick     return GetFrameworkFile();
232e5dd7070Spatrick 
233e5dd7070Spatrick   // Lookup for normal headers.
234e5dd7070Spatrick   llvm::sys::path::append(RelativePathName, Header.FileName);
235e5dd7070Spatrick   llvm::sys::path::append(FullPathName, RelativePathName);
236a9ac8606Spatrick   auto NormalHdrFile = GetFile(FullPathName);
237e5dd7070Spatrick 
238e5dd7070Spatrick   if (!NormalHdrFile && Directory->getName().endswith(".framework")) {
239e5dd7070Spatrick     // The lack of 'framework' keyword in a module declaration it's a simple
240e5dd7070Spatrick     // mistake we can diagnose when the header exists within the proper
241e5dd7070Spatrick     // framework style path.
242e5dd7070Spatrick     FullPathName.assign(Directory->getName());
243e5dd7070Spatrick     RelativePathName.clear();
244e5dd7070Spatrick     if (GetFrameworkFile()) {
245e5dd7070Spatrick       Diags.Report(Header.FileNameLoc,
246e5dd7070Spatrick                    diag::warn_mmap_incomplete_framework_module_declaration)
247e5dd7070Spatrick           << Header.FileName << M->getFullModuleName();
248e5dd7070Spatrick       NeedsFramework = true;
249e5dd7070Spatrick     }
250*12c85518Srobert     return std::nullopt;
251e5dd7070Spatrick   }
252e5dd7070Spatrick 
253e5dd7070Spatrick   return NormalHdrFile;
254e5dd7070Spatrick }
255e5dd7070Spatrick 
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)256e5dd7070Spatrick void ModuleMap::resolveHeader(Module *Mod,
257e5dd7070Spatrick                               const Module::UnresolvedHeaderDirective &Header,
258e5dd7070Spatrick                               bool &NeedsFramework) {
259e5dd7070Spatrick   SmallString<128> RelativePathName;
260*12c85518Srobert   if (OptionalFileEntryRef File =
261e5dd7070Spatrick           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
262e5dd7070Spatrick     if (Header.IsUmbrella) {
263a9ac8606Spatrick       const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
264e5dd7070Spatrick       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
265e5dd7070Spatrick         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
266e5dd7070Spatrick           << UmbrellaMod->getFullModuleName();
267e5dd7070Spatrick       else
268e5dd7070Spatrick         // Record this umbrella header.
269a9ac8606Spatrick         setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
270e5dd7070Spatrick     } else {
271a9ac8606Spatrick       Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
272a9ac8606Spatrick                           *File};
273e5dd7070Spatrick       addHeader(Mod, H, headerKindToRole(Header.Kind));
274e5dd7070Spatrick     }
275e5dd7070Spatrick   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
276e5dd7070Spatrick     // There's a builtin header but no corresponding on-disk header. Assume
277e5dd7070Spatrick     // this was supposed to modularize the builtin header alone.
278e5dd7070Spatrick   } else if (Header.Kind == Module::HK_Excluded) {
279e5dd7070Spatrick     // Ignore missing excluded header files. They're optional anyway.
280e5dd7070Spatrick   } else {
281e5dd7070Spatrick     // If we find a module that has a missing header, we mark this module as
282e5dd7070Spatrick     // unavailable and store the header directive for displaying diagnostics.
283e5dd7070Spatrick     Mod->MissingHeaders.push_back(Header);
284e5dd7070Spatrick     // A missing header with stat information doesn't make the module
285e5dd7070Spatrick     // unavailable; this keeps our behavior consistent as headers are lazily
286e5dd7070Spatrick     // resolved. (Such a module still can't be built though, except from
287e5dd7070Spatrick     // preprocessed source.)
288e5dd7070Spatrick     if (!Header.Size && !Header.ModTime)
289ec727ea7Spatrick       Mod->markUnavailable(/*Unimportable=*/false);
290e5dd7070Spatrick   }
291e5dd7070Spatrick }
292e5dd7070Spatrick 
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)293e5dd7070Spatrick bool ModuleMap::resolveAsBuiltinHeader(
294e5dd7070Spatrick     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
295e5dd7070Spatrick   if (Header.Kind == Module::HK_Excluded ||
296e5dd7070Spatrick       llvm::sys::path::is_absolute(Header.FileName) ||
297e5dd7070Spatrick       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
298e5dd7070Spatrick       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
299e5dd7070Spatrick       !isBuiltinHeader(Header.FileName))
300e5dd7070Spatrick     return false;
301e5dd7070Spatrick 
302e5dd7070Spatrick   // This is a system module with a top-level header. This header
303e5dd7070Spatrick   // may have a counterpart (or replacement) in the set of headers
304e5dd7070Spatrick   // supplied by Clang. Find that builtin header.
305e5dd7070Spatrick   SmallString<128> Path;
306e5dd7070Spatrick   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
307*12c85518Srobert   auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
308e5dd7070Spatrick   if (!File)
309e5dd7070Spatrick     return false;
310e5dd7070Spatrick 
311e5dd7070Spatrick   auto Role = headerKindToRole(Header.Kind);
312a9ac8606Spatrick   Module::Header H = {Header.FileName, std::string(Path.str()), *File};
313e5dd7070Spatrick   addHeader(Mod, H, Role);
314e5dd7070Spatrick   return true;
315e5dd7070Spatrick }
316e5dd7070Spatrick 
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)317e5dd7070Spatrick ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
318e5dd7070Spatrick                      const LangOptions &LangOpts, const TargetInfo *Target,
319e5dd7070Spatrick                      HeaderSearch &HeaderInfo)
320e5dd7070Spatrick     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
321e5dd7070Spatrick       HeaderInfo(HeaderInfo) {
322e5dd7070Spatrick   MMapLangOpts.LineComment = true;
323e5dd7070Spatrick }
324e5dd7070Spatrick 
~ModuleMap()325e5dd7070Spatrick ModuleMap::~ModuleMap() {
326e5dd7070Spatrick   for (auto &M : Modules)
327e5dd7070Spatrick     delete M.getValue();
328e5dd7070Spatrick   for (auto *M : ShadowModules)
329e5dd7070Spatrick     delete M;
330e5dd7070Spatrick }
331e5dd7070Spatrick 
setTarget(const TargetInfo & Target)332e5dd7070Spatrick void ModuleMap::setTarget(const TargetInfo &Target) {
333e5dd7070Spatrick   assert((!this->Target || this->Target == &Target) &&
334e5dd7070Spatrick          "Improper target override");
335e5dd7070Spatrick   this->Target = &Target;
336e5dd7070Spatrick }
337e5dd7070Spatrick 
338e5dd7070Spatrick /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)339e5dd7070Spatrick static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
340e5dd7070Spatrick                                               SmallVectorImpl<char> &Buffer) {
341e5dd7070Spatrick   if (Name.empty())
342e5dd7070Spatrick     return Name;
343e5dd7070Spatrick 
344*12c85518Srobert   if (!isValidAsciiIdentifier(Name)) {
345e5dd7070Spatrick     // If we don't already have something with the form of an identifier,
346e5dd7070Spatrick     // create a buffer with the sanitized name.
347e5dd7070Spatrick     Buffer.clear();
348e5dd7070Spatrick     if (isDigit(Name[0]))
349e5dd7070Spatrick       Buffer.push_back('_');
350e5dd7070Spatrick     Buffer.reserve(Buffer.size() + Name.size());
351e5dd7070Spatrick     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
352*12c85518Srobert       if (isAsciiIdentifierContinue(Name[I]))
353e5dd7070Spatrick         Buffer.push_back(Name[I]);
354e5dd7070Spatrick       else
355e5dd7070Spatrick         Buffer.push_back('_');
356e5dd7070Spatrick     }
357e5dd7070Spatrick 
358e5dd7070Spatrick     Name = StringRef(Buffer.data(), Buffer.size());
359e5dd7070Spatrick   }
360e5dd7070Spatrick 
361e5dd7070Spatrick   while (llvm::StringSwitch<bool>(Name)
362e5dd7070Spatrick #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
363e5dd7070Spatrick #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
364e5dd7070Spatrick #include "clang/Basic/TokenKinds.def"
365e5dd7070Spatrick            .Default(false)) {
366e5dd7070Spatrick     if (Name.data() != Buffer.data())
367e5dd7070Spatrick       Buffer.append(Name.begin(), Name.end());
368e5dd7070Spatrick     Buffer.push_back('_');
369e5dd7070Spatrick     Name = StringRef(Buffer.data(), Buffer.size());
370e5dd7070Spatrick   }
371e5dd7070Spatrick 
372e5dd7070Spatrick   return Name;
373e5dd7070Spatrick }
374e5dd7070Spatrick 
375e5dd7070Spatrick /// Determine whether the given file name is the name of a builtin
376e5dd7070Spatrick /// header, supplied by Clang to replace, override, or augment existing system
377e5dd7070Spatrick /// headers.
isBuiltinHeader(StringRef FileName)378e5dd7070Spatrick bool ModuleMap::isBuiltinHeader(StringRef FileName) {
379e5dd7070Spatrick   return llvm::StringSwitch<bool>(FileName)
380e5dd7070Spatrick            .Case("float.h", true)
381e5dd7070Spatrick            .Case("iso646.h", true)
382e5dd7070Spatrick            .Case("limits.h", true)
383e5dd7070Spatrick            .Case("stdalign.h", true)
384e5dd7070Spatrick            .Case("stdarg.h", true)
385e5dd7070Spatrick            .Case("stdatomic.h", true)
386e5dd7070Spatrick            .Case("stdbool.h", true)
387e5dd7070Spatrick            .Case("stddef.h", true)
388e5dd7070Spatrick            .Case("stdint.h", true)
389e5dd7070Spatrick            .Case("tgmath.h", true)
390e5dd7070Spatrick            .Case("unwind.h", true)
391e5dd7070Spatrick            .Default(false);
392e5dd7070Spatrick }
393e5dd7070Spatrick 
isBuiltinHeader(const FileEntry * File)394ec727ea7Spatrick bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
395ec727ea7Spatrick   return File->getDir() == BuiltinIncludeDir &&
396ec727ea7Spatrick          ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
397ec727ea7Spatrick }
398ec727ea7Spatrick 
399e5dd7070Spatrick ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)400e5dd7070Spatrick ModuleMap::findKnownHeader(const FileEntry *File) {
401e5dd7070Spatrick   resolveHeaderDirectives(File);
402e5dd7070Spatrick   HeadersMap::iterator Known = Headers.find(File);
403e5dd7070Spatrick   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
404ec727ea7Spatrick       Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
405e5dd7070Spatrick     HeaderInfo.loadTopLevelSystemModules();
406e5dd7070Spatrick     return Headers.find(File);
407e5dd7070Spatrick   }
408e5dd7070Spatrick   return Known;
409e5dd7070Spatrick }
410e5dd7070Spatrick 
411e5dd7070Spatrick ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)412e5dd7070Spatrick ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
413e5dd7070Spatrick                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
414e5dd7070Spatrick   if (UmbrellaDirs.empty())
415e5dd7070Spatrick     return {};
416e5dd7070Spatrick 
417e5dd7070Spatrick   const DirectoryEntry *Dir = File->getDir();
418e5dd7070Spatrick   assert(Dir && "file in no directory");
419e5dd7070Spatrick 
420e5dd7070Spatrick   // Note: as an egregious but useful hack we use the real path here, because
421e5dd7070Spatrick   // frameworks moving from top-level frameworks to embedded frameworks tend
422e5dd7070Spatrick   // to be symlinked from the top-level location to the embedded location,
423e5dd7070Spatrick   // and we need to resolve lookups as if we had found the embedded location.
424e5dd7070Spatrick   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
425e5dd7070Spatrick 
426e5dd7070Spatrick   // Keep walking up the directory hierarchy, looking for a directory with
427e5dd7070Spatrick   // an umbrella header.
428e5dd7070Spatrick   do {
429e5dd7070Spatrick     auto KnownDir = UmbrellaDirs.find(Dir);
430e5dd7070Spatrick     if (KnownDir != UmbrellaDirs.end())
431e5dd7070Spatrick       return KnownHeader(KnownDir->second, NormalHeader);
432e5dd7070Spatrick 
433e5dd7070Spatrick     IntermediateDirs.push_back(Dir);
434e5dd7070Spatrick 
435e5dd7070Spatrick     // Retrieve our parent path.
436e5dd7070Spatrick     DirName = llvm::sys::path::parent_path(DirName);
437e5dd7070Spatrick     if (DirName.empty())
438e5dd7070Spatrick       break;
439e5dd7070Spatrick 
440e5dd7070Spatrick     // Resolve the parent path to a directory entry.
441e5dd7070Spatrick     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
442e5dd7070Spatrick       Dir = *DirEntry;
443e5dd7070Spatrick     else
444e5dd7070Spatrick       Dir = nullptr;
445e5dd7070Spatrick   } while (Dir);
446e5dd7070Spatrick   return {};
447e5dd7070Spatrick }
448e5dd7070Spatrick 
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)449e5dd7070Spatrick static bool violatesPrivateInclude(Module *RequestingModule,
450e5dd7070Spatrick                                    const FileEntry *IncFileEnt,
451e5dd7070Spatrick                                    ModuleMap::KnownHeader Header) {
452e5dd7070Spatrick #ifndef NDEBUG
453e5dd7070Spatrick   if (Header.getRole() & ModuleMap::PrivateHeader) {
454e5dd7070Spatrick     // Check for consistency between the module header role
455e5dd7070Spatrick     // as obtained from the lookup and as obtained from the module.
456e5dd7070Spatrick     // This check is not cheap, so enable it only for debugging.
457e5dd7070Spatrick     bool IsPrivate = false;
458e5dd7070Spatrick     SmallVectorImpl<Module::Header> *HeaderList[] = {
459e5dd7070Spatrick         &Header.getModule()->Headers[Module::HK_Private],
460e5dd7070Spatrick         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
461e5dd7070Spatrick     for (auto *Hs : HeaderList)
462*12c85518Srobert       IsPrivate |= llvm::any_of(
463*12c85518Srobert           *Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
464e5dd7070Spatrick     assert(IsPrivate && "inconsistent headers and roles");
465e5dd7070Spatrick   }
466e5dd7070Spatrick #endif
467e5dd7070Spatrick   return !Header.isAccessibleFrom(RequestingModule);
468e5dd7070Spatrick }
469e5dd7070Spatrick 
getTopLevelOrNull(Module * M)470e5dd7070Spatrick static Module *getTopLevelOrNull(Module *M) {
471e5dd7070Spatrick   return M ? M->getTopLevelModule() : nullptr;
472e5dd7070Spatrick }
473e5dd7070Spatrick 
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,FileEntryRef File)474e5dd7070Spatrick void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
475e5dd7070Spatrick                                         bool RequestingModuleIsModuleInterface,
476e5dd7070Spatrick                                         SourceLocation FilenameLoc,
477*12c85518Srobert                                         StringRef Filename, FileEntryRef File) {
478e5dd7070Spatrick   // No errors for indirect modules. This may be a bit of a problem for modules
479e5dd7070Spatrick   // with no source files.
480e5dd7070Spatrick   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
481e5dd7070Spatrick     return;
482e5dd7070Spatrick 
483e5dd7070Spatrick   if (RequestingModule) {
484e5dd7070Spatrick     resolveUses(RequestingModule, /*Complain=*/false);
485*12c85518Srobert     resolveHeaderDirectives(RequestingModule, /*File=*/std::nullopt);
486e5dd7070Spatrick   }
487e5dd7070Spatrick 
488e5dd7070Spatrick   bool Excluded = false;
489e5dd7070Spatrick   Module *Private = nullptr;
490e5dd7070Spatrick   Module *NotUsed = nullptr;
491e5dd7070Spatrick 
492e5dd7070Spatrick   HeadersMap::iterator Known = findKnownHeader(File);
493e5dd7070Spatrick   if (Known != Headers.end()) {
494e5dd7070Spatrick     for (const KnownHeader &Header : Known->second) {
495*12c85518Srobert       // Excluded headers don't really belong to a module.
496*12c85518Srobert       if (Header.getRole() == ModuleMap::ExcludedHeader) {
497*12c85518Srobert         Excluded = true;
498*12c85518Srobert         continue;
499*12c85518Srobert       }
500*12c85518Srobert 
501e5dd7070Spatrick       // Remember private headers for later printing of a diagnostic.
502e5dd7070Spatrick       if (violatesPrivateInclude(RequestingModule, File, Header)) {
503e5dd7070Spatrick         Private = Header.getModule();
504e5dd7070Spatrick         continue;
505e5dd7070Spatrick       }
506e5dd7070Spatrick 
507e5dd7070Spatrick       // If uses need to be specified explicitly, we are only allowed to return
508e5dd7070Spatrick       // modules that are explicitly used by the requesting module.
509e5dd7070Spatrick       if (RequestingModule && LangOpts.ModulesDeclUse &&
510e5dd7070Spatrick           !RequestingModule->directlyUses(Header.getModule())) {
511e5dd7070Spatrick         NotUsed = Header.getModule();
512e5dd7070Spatrick         continue;
513e5dd7070Spatrick       }
514e5dd7070Spatrick 
515e5dd7070Spatrick       // We have found a module that we can happily use.
516e5dd7070Spatrick       return;
517e5dd7070Spatrick     }
518e5dd7070Spatrick 
519e5dd7070Spatrick     Excluded = true;
520e5dd7070Spatrick   }
521e5dd7070Spatrick 
522e5dd7070Spatrick   // We have found a header, but it is private.
523e5dd7070Spatrick   if (Private) {
524e5dd7070Spatrick     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
525e5dd7070Spatrick         << Filename;
526e5dd7070Spatrick     return;
527e5dd7070Spatrick   }
528e5dd7070Spatrick 
529e5dd7070Spatrick   // We have found a module, but we don't use it.
530e5dd7070Spatrick   if (NotUsed) {
531e5dd7070Spatrick     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
532e5dd7070Spatrick         << RequestingModule->getTopLevelModule()->Name << Filename;
533e5dd7070Spatrick     return;
534e5dd7070Spatrick   }
535e5dd7070Spatrick 
536e5dd7070Spatrick   if (Excluded || isHeaderInUmbrellaDirs(File))
537e5dd7070Spatrick     return;
538e5dd7070Spatrick 
539e5dd7070Spatrick   // At this point, only non-modular includes remain.
540e5dd7070Spatrick 
541e5dd7070Spatrick   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
542e5dd7070Spatrick     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
543e5dd7070Spatrick         << RequestingModule->getTopLevelModule()->Name << Filename;
544e5dd7070Spatrick   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
545e5dd7070Spatrick              LangOpts.isCompilingModule()) {
546e5dd7070Spatrick     // Do not diagnose when we are not compiling a module.
547e5dd7070Spatrick     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
548e5dd7070Spatrick         diag::warn_non_modular_include_in_framework_module :
549e5dd7070Spatrick         diag::warn_non_modular_include_in_module;
550e5dd7070Spatrick     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
551*12c85518Srobert         << File.getName();
552e5dd7070Spatrick   }
553e5dd7070Spatrick }
554e5dd7070Spatrick 
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)555e5dd7070Spatrick static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
556e5dd7070Spatrick                                 const ModuleMap::KnownHeader &Old) {
557e5dd7070Spatrick   // Prefer available modules.
558ec727ea7Spatrick   // FIXME: Considering whether the module is available rather than merely
559ec727ea7Spatrick   // importable is non-hermetic and can result in surprising behavior for
560ec727ea7Spatrick   // prebuilt modules. Consider only checking for importability here.
561e5dd7070Spatrick   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
562e5dd7070Spatrick     return true;
563e5dd7070Spatrick 
564e5dd7070Spatrick   // Prefer a public header over a private header.
565e5dd7070Spatrick   if ((New.getRole() & ModuleMap::PrivateHeader) !=
566e5dd7070Spatrick       (Old.getRole() & ModuleMap::PrivateHeader))
567e5dd7070Spatrick     return !(New.getRole() & ModuleMap::PrivateHeader);
568e5dd7070Spatrick 
569e5dd7070Spatrick   // Prefer a non-textual header over a textual header.
570e5dd7070Spatrick   if ((New.getRole() & ModuleMap::TextualHeader) !=
571e5dd7070Spatrick       (Old.getRole() & ModuleMap::TextualHeader))
572e5dd7070Spatrick     return !(New.getRole() & ModuleMap::TextualHeader);
573e5dd7070Spatrick 
574*12c85518Srobert   // Prefer a non-excluded header over an excluded header.
575*12c85518Srobert   if ((New.getRole() == ModuleMap::ExcludedHeader) !=
576*12c85518Srobert       (Old.getRole() == ModuleMap::ExcludedHeader))
577*12c85518Srobert     return New.getRole() != ModuleMap::ExcludedHeader;
578*12c85518Srobert 
579e5dd7070Spatrick   // Don't have a reason to choose between these. Just keep the first one.
580e5dd7070Spatrick   return false;
581e5dd7070Spatrick }
582e5dd7070Spatrick 
findModuleForHeader(const FileEntry * File,bool AllowTextual,bool AllowExcluded)583e5dd7070Spatrick ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
584*12c85518Srobert                                                       bool AllowTextual,
585*12c85518Srobert                                                       bool AllowExcluded) {
586e5dd7070Spatrick   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
587e5dd7070Spatrick     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
588e5dd7070Spatrick       return {};
589e5dd7070Spatrick     return R;
590e5dd7070Spatrick   };
591e5dd7070Spatrick 
592e5dd7070Spatrick   HeadersMap::iterator Known = findKnownHeader(File);
593e5dd7070Spatrick   if (Known != Headers.end()) {
594e5dd7070Spatrick     ModuleMap::KnownHeader Result;
595e5dd7070Spatrick     // Iterate over all modules that 'File' is part of to find the best fit.
596e5dd7070Spatrick     for (KnownHeader &H : Known->second) {
597*12c85518Srobert       // Cannot use a module if the header is excluded in it.
598*12c85518Srobert       if (!AllowExcluded && H.getRole() == ModuleMap::ExcludedHeader)
599*12c85518Srobert         continue;
600e5dd7070Spatrick       // Prefer a header from the source module over all others.
601e5dd7070Spatrick       if (H.getModule()->getTopLevelModule() == SourceModule)
602e5dd7070Spatrick         return MakeResult(H);
603e5dd7070Spatrick       if (!Result || isBetterKnownHeader(H, Result))
604e5dd7070Spatrick         Result = H;
605e5dd7070Spatrick     }
606e5dd7070Spatrick     return MakeResult(Result);
607e5dd7070Spatrick   }
608e5dd7070Spatrick 
609e5dd7070Spatrick   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
610e5dd7070Spatrick }
611e5dd7070Spatrick 
612e5dd7070Spatrick ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry * File)613e5dd7070Spatrick ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
614e5dd7070Spatrick   assert(!Headers.count(File) && "already have a module for this header");
615e5dd7070Spatrick 
616e5dd7070Spatrick   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
617e5dd7070Spatrick   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
618e5dd7070Spatrick   if (H) {
619e5dd7070Spatrick     Module *Result = H.getModule();
620e5dd7070Spatrick 
621e5dd7070Spatrick     // Search up the module stack until we find a module with an umbrella
622e5dd7070Spatrick     // directory.
623e5dd7070Spatrick     Module *UmbrellaModule = Result;
624e5dd7070Spatrick     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
625e5dd7070Spatrick       UmbrellaModule = UmbrellaModule->Parent;
626e5dd7070Spatrick 
627e5dd7070Spatrick     if (UmbrellaModule->InferSubmodules) {
628*12c85518Srobert       OptionalFileEntryRefDegradesToFileEntryPtr UmbrellaModuleMap =
629e5dd7070Spatrick           getModuleMapFileForUniquing(UmbrellaModule);
630e5dd7070Spatrick 
631e5dd7070Spatrick       // Infer submodules for each of the directories we found between
632e5dd7070Spatrick       // the directory of the umbrella header and the directory where
633e5dd7070Spatrick       // the actual header is located.
634e5dd7070Spatrick       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
635e5dd7070Spatrick 
636*12c85518Srobert       for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) {
637e5dd7070Spatrick         // Find or create the module that corresponds to this directory name.
638e5dd7070Spatrick         SmallString<32> NameBuf;
639e5dd7070Spatrick         StringRef Name = sanitizeFilenameAsIdentifier(
640*12c85518Srobert             llvm::sys::path::stem(SkippedDir->getName()), NameBuf);
641e5dd7070Spatrick         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
642e5dd7070Spatrick                                     Explicit).first;
643e5dd7070Spatrick         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
644e5dd7070Spatrick         Result->IsInferred = true;
645e5dd7070Spatrick 
646e5dd7070Spatrick         // Associate the module and the directory.
647*12c85518Srobert         UmbrellaDirs[SkippedDir] = Result;
648e5dd7070Spatrick 
649e5dd7070Spatrick         // If inferred submodules export everything they import, add a
650e5dd7070Spatrick         // wildcard to the set of exports.
651e5dd7070Spatrick         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
652e5dd7070Spatrick           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
653e5dd7070Spatrick       }
654e5dd7070Spatrick 
655e5dd7070Spatrick       // Infer a submodule with the same name as this header file.
656e5dd7070Spatrick       SmallString<32> NameBuf;
657e5dd7070Spatrick       StringRef Name = sanitizeFilenameAsIdentifier(
658e5dd7070Spatrick                          llvm::sys::path::stem(File->getName()), NameBuf);
659e5dd7070Spatrick       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
660e5dd7070Spatrick                                   Explicit).first;
661e5dd7070Spatrick       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
662e5dd7070Spatrick       Result->IsInferred = true;
663e5dd7070Spatrick       Result->addTopHeader(File);
664e5dd7070Spatrick 
665e5dd7070Spatrick       // If inferred submodules export everything they import, add a
666e5dd7070Spatrick       // wildcard to the set of exports.
667e5dd7070Spatrick       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
668e5dd7070Spatrick         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
669e5dd7070Spatrick     } else {
670e5dd7070Spatrick       // Record each of the directories we stepped through as being part of
671e5dd7070Spatrick       // the module we found, since the umbrella header covers them all.
672e5dd7070Spatrick       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
673e5dd7070Spatrick         UmbrellaDirs[SkippedDirs[I]] = Result;
674e5dd7070Spatrick     }
675e5dd7070Spatrick 
676e5dd7070Spatrick     KnownHeader Header(Result, NormalHeader);
677e5dd7070Spatrick     Headers[File].push_back(Header);
678e5dd7070Spatrick     return Header;
679e5dd7070Spatrick   }
680e5dd7070Spatrick 
681e5dd7070Spatrick   return {};
682e5dd7070Spatrick }
683e5dd7070Spatrick 
684e5dd7070Spatrick ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File)685ec727ea7Spatrick ModuleMap::findAllModulesForHeader(const FileEntry *File) {
686ec727ea7Spatrick   HeadersMap::iterator Known = findKnownHeader(File);
687ec727ea7Spatrick   if (Known != Headers.end())
688ec727ea7Spatrick     return Known->second;
689ec727ea7Spatrick 
690ec727ea7Spatrick   if (findOrCreateModuleForHeaderInUmbrellaDir(File))
691ec727ea7Spatrick     return Headers.find(File)->second;
692ec727ea7Spatrick 
693*12c85518Srobert   return std::nullopt;
694ec727ea7Spatrick }
695ec727ea7Spatrick 
696ec727ea7Spatrick ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(const FileEntry * File) const697ec727ea7Spatrick ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
698ec727ea7Spatrick   // FIXME: Is this necessary?
699e5dd7070Spatrick   resolveHeaderDirectives(File);
700e5dd7070Spatrick   auto It = Headers.find(File);
701e5dd7070Spatrick   if (It == Headers.end())
702*12c85518Srobert     return std::nullopt;
703e5dd7070Spatrick   return It->second;
704e5dd7070Spatrick }
705e5dd7070Spatrick 
isHeaderInUnavailableModule(const FileEntry * Header) const706e5dd7070Spatrick bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
707e5dd7070Spatrick   return isHeaderUnavailableInModule(Header, nullptr);
708e5dd7070Spatrick }
709e5dd7070Spatrick 
710e5dd7070Spatrick bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const711e5dd7070Spatrick ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
712e5dd7070Spatrick                                        const Module *RequestingModule) const {
713e5dd7070Spatrick   resolveHeaderDirectives(Header);
714e5dd7070Spatrick   HeadersMap::const_iterator Known = Headers.find(Header);
715e5dd7070Spatrick   if (Known != Headers.end()) {
716e5dd7070Spatrick     for (SmallVectorImpl<KnownHeader>::const_iterator
717e5dd7070Spatrick              I = Known->second.begin(),
718e5dd7070Spatrick              E = Known->second.end();
719e5dd7070Spatrick          I != E; ++I) {
720e5dd7070Spatrick 
721*12c85518Srobert       if (I->getRole() == ModuleMap::ExcludedHeader)
722*12c85518Srobert         continue;
723*12c85518Srobert 
724e5dd7070Spatrick       if (I->isAvailable() &&
725e5dd7070Spatrick           (!RequestingModule ||
726e5dd7070Spatrick            I->getModule()->isSubModuleOf(RequestingModule))) {
727e5dd7070Spatrick         // When no requesting module is available, the caller is looking if a
728e5dd7070Spatrick         // header is part a module by only looking into the module map. This is
729e5dd7070Spatrick         // done by warn_uncovered_module_header checks; don't consider textual
730e5dd7070Spatrick         // headers part of it in this mode, otherwise we get misleading warnings
731e5dd7070Spatrick         // that a umbrella header is not including a textual header.
732e5dd7070Spatrick         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
733e5dd7070Spatrick           continue;
734e5dd7070Spatrick         return false;
735e5dd7070Spatrick       }
736e5dd7070Spatrick     }
737e5dd7070Spatrick     return true;
738e5dd7070Spatrick   }
739e5dd7070Spatrick 
740e5dd7070Spatrick   const DirectoryEntry *Dir = Header->getDir();
741e5dd7070Spatrick   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
742e5dd7070Spatrick   StringRef DirName = Dir->getName();
743e5dd7070Spatrick 
744e5dd7070Spatrick   auto IsUnavailable = [&](const Module *M) {
745e5dd7070Spatrick     return !M->isAvailable() && (!RequestingModule ||
746e5dd7070Spatrick                                  M->isSubModuleOf(RequestingModule));
747e5dd7070Spatrick   };
748e5dd7070Spatrick 
749e5dd7070Spatrick   // Keep walking up the directory hierarchy, looking for a directory with
750e5dd7070Spatrick   // an umbrella header.
751e5dd7070Spatrick   do {
752e5dd7070Spatrick     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
753e5dd7070Spatrick       = UmbrellaDirs.find(Dir);
754e5dd7070Spatrick     if (KnownDir != UmbrellaDirs.end()) {
755e5dd7070Spatrick       Module *Found = KnownDir->second;
756e5dd7070Spatrick       if (IsUnavailable(Found))
757e5dd7070Spatrick         return true;
758e5dd7070Spatrick 
759e5dd7070Spatrick       // Search up the module stack until we find a module with an umbrella
760e5dd7070Spatrick       // directory.
761e5dd7070Spatrick       Module *UmbrellaModule = Found;
762e5dd7070Spatrick       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
763e5dd7070Spatrick         UmbrellaModule = UmbrellaModule->Parent;
764e5dd7070Spatrick 
765e5dd7070Spatrick       if (UmbrellaModule->InferSubmodules) {
766*12c85518Srobert         for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) {
767e5dd7070Spatrick           // Find or create the module that corresponds to this directory name.
768e5dd7070Spatrick           SmallString<32> NameBuf;
769e5dd7070Spatrick           StringRef Name = sanitizeFilenameAsIdentifier(
770*12c85518Srobert               llvm::sys::path::stem(SkippedDir->getName()), NameBuf);
771e5dd7070Spatrick           Found = lookupModuleQualified(Name, Found);
772e5dd7070Spatrick           if (!Found)
773e5dd7070Spatrick             return false;
774e5dd7070Spatrick           if (IsUnavailable(Found))
775e5dd7070Spatrick             return true;
776e5dd7070Spatrick         }
777e5dd7070Spatrick 
778e5dd7070Spatrick         // Infer a submodule with the same name as this header file.
779e5dd7070Spatrick         SmallString<32> NameBuf;
780e5dd7070Spatrick         StringRef Name = sanitizeFilenameAsIdentifier(
781e5dd7070Spatrick                            llvm::sys::path::stem(Header->getName()),
782e5dd7070Spatrick                            NameBuf);
783e5dd7070Spatrick         Found = lookupModuleQualified(Name, Found);
784e5dd7070Spatrick         if (!Found)
785e5dd7070Spatrick           return false;
786e5dd7070Spatrick       }
787e5dd7070Spatrick 
788e5dd7070Spatrick       return IsUnavailable(Found);
789e5dd7070Spatrick     }
790e5dd7070Spatrick 
791e5dd7070Spatrick     SkippedDirs.push_back(Dir);
792e5dd7070Spatrick 
793e5dd7070Spatrick     // Retrieve our parent path.
794e5dd7070Spatrick     DirName = llvm::sys::path::parent_path(DirName);
795e5dd7070Spatrick     if (DirName.empty())
796e5dd7070Spatrick       break;
797e5dd7070Spatrick 
798e5dd7070Spatrick     // Resolve the parent path to a directory entry.
799e5dd7070Spatrick     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
800e5dd7070Spatrick       Dir = *DirEntry;
801e5dd7070Spatrick     else
802e5dd7070Spatrick       Dir = nullptr;
803e5dd7070Spatrick   } while (Dir);
804e5dd7070Spatrick 
805e5dd7070Spatrick   return false;
806e5dd7070Spatrick }
807e5dd7070Spatrick 
findModule(StringRef Name) const808e5dd7070Spatrick Module *ModuleMap::findModule(StringRef Name) const {
809e5dd7070Spatrick   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
810e5dd7070Spatrick   if (Known != Modules.end())
811e5dd7070Spatrick     return Known->getValue();
812e5dd7070Spatrick 
813e5dd7070Spatrick   return nullptr;
814e5dd7070Spatrick }
815e5dd7070Spatrick 
lookupModuleUnqualified(StringRef Name,Module * Context) const816e5dd7070Spatrick Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
817e5dd7070Spatrick                                            Module *Context) const {
818e5dd7070Spatrick   for(; Context; Context = Context->Parent) {
819e5dd7070Spatrick     if (Module *Sub = lookupModuleQualified(Name, Context))
820e5dd7070Spatrick       return Sub;
821e5dd7070Spatrick   }
822e5dd7070Spatrick 
823e5dd7070Spatrick   return findModule(Name);
824e5dd7070Spatrick }
825e5dd7070Spatrick 
lookupModuleQualified(StringRef Name,Module * Context) const826e5dd7070Spatrick Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
827e5dd7070Spatrick   if (!Context)
828e5dd7070Spatrick     return findModule(Name);
829e5dd7070Spatrick 
830e5dd7070Spatrick   return Context->findSubmodule(Name);
831e5dd7070Spatrick }
832e5dd7070Spatrick 
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)833e5dd7070Spatrick std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
834e5dd7070Spatrick                                                         Module *Parent,
835e5dd7070Spatrick                                                         bool IsFramework,
836e5dd7070Spatrick                                                         bool IsExplicit) {
837e5dd7070Spatrick   // Try to find an existing module with this name.
838e5dd7070Spatrick   if (Module *Sub = lookupModuleQualified(Name, Parent))
839e5dd7070Spatrick     return std::make_pair(Sub, false);
840e5dd7070Spatrick 
841e5dd7070Spatrick   // Create a new module with this name.
842e5dd7070Spatrick   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
843e5dd7070Spatrick                               IsExplicit, NumCreatedModules++);
844e5dd7070Spatrick   if (!Parent) {
845e5dd7070Spatrick     if (LangOpts.CurrentModule == Name)
846e5dd7070Spatrick       SourceModule = Result;
847e5dd7070Spatrick     Modules[Name] = Result;
848e5dd7070Spatrick     ModuleScopeIDs[Result] = CurrentModuleScopeID;
849e5dd7070Spatrick   }
850e5dd7070Spatrick   return std::make_pair(Result, true);
851e5dd7070Spatrick }
852e5dd7070Spatrick 
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)853*12c85518Srobert Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
854*12c85518Srobert                                                            Module *Parent) {
855*12c85518Srobert   auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
856*12c85518Srobert                             /*IsExplicit*/ true, NumCreatedModules++);
857*12c85518Srobert   Result->Kind = Module::GlobalModuleFragment;
858*12c85518Srobert   // If the created module isn't owned by a parent, send it to PendingSubmodules
859*12c85518Srobert   // to wait for its parent.
860*12c85518Srobert   if (!Result->Parent)
861*12c85518Srobert     PendingSubmodules.emplace_back(Result);
862*12c85518Srobert   return Result;
863e5dd7070Spatrick }
864e5dd7070Spatrick 
865e5dd7070Spatrick Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)866e5dd7070Spatrick ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
867e5dd7070Spatrick                                                        SourceLocation Loc) {
868e5dd7070Spatrick   auto *Result =
869e5dd7070Spatrick       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
870e5dd7070Spatrick                  /*IsExplicit*/ true, NumCreatedModules++);
871e5dd7070Spatrick   Result->Kind = Module::PrivateModuleFragment;
872e5dd7070Spatrick   return Result;
873e5dd7070Spatrick }
874e5dd7070Spatrick 
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name)875e5dd7070Spatrick Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
876*12c85518Srobert                                                 StringRef Name) {
877e5dd7070Spatrick   assert(LangOpts.CurrentModule == Name && "module name mismatch");
878e5dd7070Spatrick   assert(!Modules[Name] && "redefining existing module");
879e5dd7070Spatrick 
880e5dd7070Spatrick   auto *Result =
881e5dd7070Spatrick       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
882e5dd7070Spatrick                  /*IsExplicit*/ false, NumCreatedModules++);
883e5dd7070Spatrick   Result->Kind = Module::ModuleInterfaceUnit;
884e5dd7070Spatrick   Modules[Name] = SourceModule = Result;
885e5dd7070Spatrick 
886e5dd7070Spatrick   // Reparent the current global module fragment as a submodule of this module.
887e5dd7070Spatrick   for (auto &Submodule : PendingSubmodules) {
888e5dd7070Spatrick     Submodule->setParent(Result);
889e5dd7070Spatrick     Submodule.release(); // now owned by parent
890e5dd7070Spatrick   }
891e5dd7070Spatrick   PendingSubmodules.clear();
892e5dd7070Spatrick 
893e5dd7070Spatrick   // Mark the main source file as being within the newly-created module so that
894e5dd7070Spatrick   // declarations and macros are properly visibility-restricted to it.
895e5dd7070Spatrick   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
896e5dd7070Spatrick   assert(MainFile && "no input file for module interface");
897e5dd7070Spatrick   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
898e5dd7070Spatrick 
899e5dd7070Spatrick   return Result;
900e5dd7070Spatrick }
901e5dd7070Spatrick 
createHeaderUnit(SourceLocation Loc,StringRef Name,Module::Header H)902*12c85518Srobert Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
903*12c85518Srobert                                     Module::Header H) {
904e5dd7070Spatrick   assert(LangOpts.CurrentModule == Name && "module name mismatch");
905e5dd7070Spatrick   assert(!Modules[Name] && "redefining existing module");
906e5dd7070Spatrick 
907*12c85518Srobert   auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
908e5dd7070Spatrick                             /*IsExplicit*/ false, NumCreatedModules++);
909*12c85518Srobert   Result->Kind = Module::ModuleHeaderUnit;
910e5dd7070Spatrick   Modules[Name] = SourceModule = Result;
911*12c85518Srobert   addHeader(Result, H, NormalHeader);
912e5dd7070Spatrick   return Result;
913e5dd7070Spatrick }
914e5dd7070Spatrick 
915e5dd7070Spatrick /// For a framework module, infer the framework against which we
916e5dd7070Spatrick /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)917e5dd7070Spatrick static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
918e5dd7070Spatrick                                FileManager &FileMgr) {
919e5dd7070Spatrick   assert(Mod->IsFramework && "Can only infer linking for framework modules");
920e5dd7070Spatrick   assert(!Mod->isSubFramework() &&
921e5dd7070Spatrick          "Can only infer linking for top-level frameworks");
922e5dd7070Spatrick 
923e5dd7070Spatrick   SmallString<128> LibName;
924e5dd7070Spatrick   LibName += FrameworkDir->getName();
925e5dd7070Spatrick   llvm::sys::path::append(LibName, Mod->Name);
926e5dd7070Spatrick 
927e5dd7070Spatrick   // The library name of a framework has more than one possible extension since
928e5dd7070Spatrick   // the introduction of the text-based dynamic library format. We need to check
929e5dd7070Spatrick   // for both before we give up.
930e5dd7070Spatrick   for (const char *extension : {"", ".tbd"}) {
931e5dd7070Spatrick     llvm::sys::path::replace_extension(LibName, extension);
932e5dd7070Spatrick     if (FileMgr.getFile(LibName)) {
933e5dd7070Spatrick       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
934e5dd7070Spatrick                                                        /*IsFramework=*/true));
935e5dd7070Spatrick       return;
936e5dd7070Spatrick     }
937e5dd7070Spatrick   }
938e5dd7070Spatrick }
939e5dd7070Spatrick 
inferFrameworkModule(const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)940e5dd7070Spatrick Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
941e5dd7070Spatrick                                         bool IsSystem, Module *Parent) {
942e5dd7070Spatrick   Attributes Attrs;
943e5dd7070Spatrick   Attrs.IsSystem = IsSystem;
944e5dd7070Spatrick   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
945e5dd7070Spatrick }
946e5dd7070Spatrick 
inferFrameworkModule(const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)947e5dd7070Spatrick Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
948e5dd7070Spatrick                                         Attributes Attrs, Module *Parent) {
949e5dd7070Spatrick   // Note: as an egregious but useful hack we use the real path here, because
950e5dd7070Spatrick   // we might be looking at an embedded framework that symlinks out to a
951e5dd7070Spatrick   // top-level framework, and we need to infer as if we were naming the
952e5dd7070Spatrick   // top-level framework.
953e5dd7070Spatrick   StringRef FrameworkDirName =
954e5dd7070Spatrick       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
955e5dd7070Spatrick 
956e5dd7070Spatrick   // In case this is a case-insensitive filesystem, use the canonical
957e5dd7070Spatrick   // directory name as the ModuleName, since modules are case-sensitive.
958e5dd7070Spatrick   // FIXME: we should be able to give a fix-it hint for the correct spelling.
959e5dd7070Spatrick   SmallString<32> ModuleNameStorage;
960e5dd7070Spatrick   StringRef ModuleName = sanitizeFilenameAsIdentifier(
961e5dd7070Spatrick       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
962e5dd7070Spatrick 
963e5dd7070Spatrick   // Check whether we've already found this module.
964e5dd7070Spatrick   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
965e5dd7070Spatrick     return Mod;
966e5dd7070Spatrick 
967e5dd7070Spatrick   FileManager &FileMgr = SourceMgr.getFileManager();
968e5dd7070Spatrick 
969e5dd7070Spatrick   // If the framework has a parent path from which we're allowed to infer
970e5dd7070Spatrick   // a framework module, do so.
971e5dd7070Spatrick   const FileEntry *ModuleMapFile = nullptr;
972e5dd7070Spatrick   if (!Parent) {
973e5dd7070Spatrick     // Determine whether we're allowed to infer a module map.
974e5dd7070Spatrick     bool canInfer = false;
975e5dd7070Spatrick     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
976e5dd7070Spatrick       // Figure out the parent path.
977e5dd7070Spatrick       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
978e5dd7070Spatrick       if (auto ParentDir = FileMgr.getDirectory(Parent)) {
979e5dd7070Spatrick         // Check whether we have already looked into the parent directory
980e5dd7070Spatrick         // for a module map.
981e5dd7070Spatrick         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
982e5dd7070Spatrick           inferred = InferredDirectories.find(*ParentDir);
983e5dd7070Spatrick         if (inferred == InferredDirectories.end()) {
984e5dd7070Spatrick           // We haven't looked here before. Load a module map, if there is
985e5dd7070Spatrick           // one.
986e5dd7070Spatrick           bool IsFrameworkDir = Parent.endswith(".framework");
987e5dd7070Spatrick           if (const FileEntry *ModMapFile =
988e5dd7070Spatrick                 HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
989e5dd7070Spatrick             parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
990e5dd7070Spatrick             inferred = InferredDirectories.find(*ParentDir);
991e5dd7070Spatrick           }
992e5dd7070Spatrick 
993e5dd7070Spatrick           if (inferred == InferredDirectories.end())
994e5dd7070Spatrick             inferred = InferredDirectories.insert(
995e5dd7070Spatrick                          std::make_pair(*ParentDir, InferredDirectory())).first;
996e5dd7070Spatrick         }
997e5dd7070Spatrick 
998e5dd7070Spatrick         if (inferred->second.InferModules) {
999e5dd7070Spatrick           // We're allowed to infer for this directory, but make sure it's okay
1000e5dd7070Spatrick           // to infer this particular module.
1001e5dd7070Spatrick           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1002*12c85518Srobert           canInfer =
1003*12c85518Srobert               !llvm::is_contained(inferred->second.ExcludedModules, Name);
1004e5dd7070Spatrick 
1005e5dd7070Spatrick           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
1006e5dd7070Spatrick           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
1007e5dd7070Spatrick           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1008e5dd7070Spatrick           Attrs.NoUndeclaredIncludes |=
1009e5dd7070Spatrick               inferred->second.Attrs.NoUndeclaredIncludes;
1010e5dd7070Spatrick           ModuleMapFile = inferred->second.ModuleMapFile;
1011e5dd7070Spatrick         }
1012e5dd7070Spatrick       }
1013e5dd7070Spatrick     }
1014e5dd7070Spatrick 
1015e5dd7070Spatrick     // If we're not allowed to infer a framework module, don't.
1016e5dd7070Spatrick     if (!canInfer)
1017e5dd7070Spatrick       return nullptr;
1018*12c85518Srobert   } else {
1019*12c85518Srobert     OptionalFileEntryRefDegradesToFileEntryPtr ModuleMapRef =
1020*12c85518Srobert         getModuleMapFileForUniquing(Parent);
1021*12c85518Srobert     ModuleMapFile = ModuleMapRef;
1022*12c85518Srobert   }
1023e5dd7070Spatrick 
1024e5dd7070Spatrick   // Look for an umbrella header.
1025e5dd7070Spatrick   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
1026e5dd7070Spatrick   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
1027*12c85518Srobert   auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);
1028e5dd7070Spatrick 
1029e5dd7070Spatrick   // FIXME: If there's no umbrella header, we could probably scan the
1030e5dd7070Spatrick   // framework to load *everything*. But, it's not clear that this is a good
1031e5dd7070Spatrick   // idea.
1032e5dd7070Spatrick   if (!UmbrellaHeader)
1033e5dd7070Spatrick     return nullptr;
1034e5dd7070Spatrick 
1035e5dd7070Spatrick   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1036e5dd7070Spatrick                               /*IsFramework=*/true, /*IsExplicit=*/false,
1037e5dd7070Spatrick                               NumCreatedModules++);
1038e5dd7070Spatrick   InferredModuleAllowedBy[Result] = ModuleMapFile;
1039e5dd7070Spatrick   Result->IsInferred = true;
1040e5dd7070Spatrick   if (!Parent) {
1041e5dd7070Spatrick     if (LangOpts.CurrentModule == ModuleName)
1042e5dd7070Spatrick       SourceModule = Result;
1043e5dd7070Spatrick     Modules[ModuleName] = Result;
1044e5dd7070Spatrick     ModuleScopeIDs[Result] = CurrentModuleScopeID;
1045e5dd7070Spatrick   }
1046e5dd7070Spatrick 
1047e5dd7070Spatrick   Result->IsSystem |= Attrs.IsSystem;
1048e5dd7070Spatrick   Result->IsExternC |= Attrs.IsExternC;
1049e5dd7070Spatrick   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1050e5dd7070Spatrick   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
1051e5dd7070Spatrick   Result->Directory = FrameworkDir;
1052e5dd7070Spatrick 
1053a9ac8606Spatrick   // Chop off the first framework bit, as that is implied.
1054a9ac8606Spatrick   StringRef RelativePath = UmbrellaName.str().substr(
1055a9ac8606Spatrick       Result->getTopLevelModule()->Directory->getName().size());
1056a9ac8606Spatrick   RelativePath = llvm::sys::path::relative_path(RelativePath);
1057a9ac8606Spatrick 
1058e5dd7070Spatrick   // umbrella header "umbrella-header-name"
1059a9ac8606Spatrick   setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
1060e5dd7070Spatrick 
1061e5dd7070Spatrick   // export *
1062e5dd7070Spatrick   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1063e5dd7070Spatrick 
1064e5dd7070Spatrick   // module * { export * }
1065e5dd7070Spatrick   Result->InferSubmodules = true;
1066e5dd7070Spatrick   Result->InferExportWildcard = true;
1067e5dd7070Spatrick 
1068e5dd7070Spatrick   // Look for subframeworks.
1069e5dd7070Spatrick   std::error_code EC;
1070e5dd7070Spatrick   SmallString<128> SubframeworksDirName
1071e5dd7070Spatrick     = StringRef(FrameworkDir->getName());
1072e5dd7070Spatrick   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
1073e5dd7070Spatrick   llvm::sys::path::native(SubframeworksDirName);
1074e5dd7070Spatrick   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1075e5dd7070Spatrick   for (llvm::vfs::directory_iterator
1076e5dd7070Spatrick            Dir = FS.dir_begin(SubframeworksDirName, EC),
1077e5dd7070Spatrick            DirEnd;
1078e5dd7070Spatrick        Dir != DirEnd && !EC; Dir.increment(EC)) {
1079e5dd7070Spatrick     if (!StringRef(Dir->path()).endswith(".framework"))
1080e5dd7070Spatrick       continue;
1081e5dd7070Spatrick 
1082e5dd7070Spatrick     if (auto SubframeworkDir =
1083e5dd7070Spatrick             FileMgr.getDirectory(Dir->path())) {
1084e5dd7070Spatrick       // Note: as an egregious but useful hack, we use the real path here and
1085e5dd7070Spatrick       // check whether it is actually a subdirectory of the parent directory.
1086e5dd7070Spatrick       // This will not be the case if the 'subframework' is actually a symlink
1087e5dd7070Spatrick       // out to a top-level framework.
1088e5dd7070Spatrick       StringRef SubframeworkDirName =
1089e5dd7070Spatrick           FileMgr.getCanonicalName(*SubframeworkDir);
1090e5dd7070Spatrick       bool FoundParent = false;
1091e5dd7070Spatrick       do {
1092e5dd7070Spatrick         // Get the parent directory name.
1093e5dd7070Spatrick         SubframeworkDirName
1094e5dd7070Spatrick           = llvm::sys::path::parent_path(SubframeworkDirName);
1095e5dd7070Spatrick         if (SubframeworkDirName.empty())
1096e5dd7070Spatrick           break;
1097e5dd7070Spatrick 
1098e5dd7070Spatrick         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
1099e5dd7070Spatrick           if (*SubDir == FrameworkDir) {
1100e5dd7070Spatrick             FoundParent = true;
1101e5dd7070Spatrick             break;
1102e5dd7070Spatrick           }
1103e5dd7070Spatrick         }
1104e5dd7070Spatrick       } while (true);
1105e5dd7070Spatrick 
1106e5dd7070Spatrick       if (!FoundParent)
1107e5dd7070Spatrick         continue;
1108e5dd7070Spatrick 
1109e5dd7070Spatrick       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1110e5dd7070Spatrick       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1111e5dd7070Spatrick     }
1112e5dd7070Spatrick   }
1113e5dd7070Spatrick 
1114e5dd7070Spatrick   // If the module is a top-level framework, automatically link against the
1115e5dd7070Spatrick   // framework.
1116e5dd7070Spatrick   if (!Result->isSubFramework()) {
1117e5dd7070Spatrick     inferFrameworkLink(Result, FrameworkDir, FileMgr);
1118e5dd7070Spatrick   }
1119e5dd7070Spatrick 
1120e5dd7070Spatrick   return Result;
1121e5dd7070Spatrick }
1122e5dd7070Spatrick 
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)1123e5dd7070Spatrick Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
1124e5dd7070Spatrick                                         Module *ShadowingModule) {
1125e5dd7070Spatrick 
1126e5dd7070Spatrick   // Create a new module with this name.
1127e5dd7070Spatrick   Module *Result =
1128e5dd7070Spatrick       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
1129e5dd7070Spatrick                  /*IsExplicit=*/false, NumCreatedModules++);
1130e5dd7070Spatrick   Result->ShadowingModule = ShadowingModule;
1131ec727ea7Spatrick   Result->markUnavailable(/*Unimportable*/true);
1132e5dd7070Spatrick   ModuleScopeIDs[Result] = CurrentModuleScopeID;
1133e5dd7070Spatrick   ShadowModules.push_back(Result);
1134e5dd7070Spatrick 
1135e5dd7070Spatrick   return Result;
1136e5dd7070Spatrick }
1137e5dd7070Spatrick 
setUmbrellaHeader(Module * Mod,FileEntryRef UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1138a9ac8606Spatrick void ModuleMap::setUmbrellaHeader(
1139*12c85518Srobert     Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
1140a9ac8606Spatrick     const Twine &PathRelativeToRootModuleDirectory) {
1141e5dd7070Spatrick   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
1142*12c85518Srobert   Mod->Umbrella = &UmbrellaHeader.getMapEntry();
1143e5dd7070Spatrick   Mod->UmbrellaAsWritten = NameAsWritten.str();
1144a9ac8606Spatrick   Mod->UmbrellaRelativeToRootModuleDirectory =
1145a9ac8606Spatrick       PathRelativeToRootModuleDirectory.str();
1146*12c85518Srobert   UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
1147e5dd7070Spatrick 
1148e5dd7070Spatrick   // Notify callbacks that we just added a new header.
1149e5dd7070Spatrick   for (const auto &Cb : Callbacks)
1150e5dd7070Spatrick     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1151e5dd7070Spatrick }
1152e5dd7070Spatrick 
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1153e5dd7070Spatrick void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1154a9ac8606Spatrick                                const Twine &NameAsWritten,
1155a9ac8606Spatrick                                const Twine &PathRelativeToRootModuleDirectory) {
1156e5dd7070Spatrick   Mod->Umbrella = UmbrellaDir;
1157e5dd7070Spatrick   Mod->UmbrellaAsWritten = NameAsWritten.str();
1158a9ac8606Spatrick   Mod->UmbrellaRelativeToRootModuleDirectory =
1159a9ac8606Spatrick       PathRelativeToRootModuleDirectory.str();
1160e5dd7070Spatrick   UmbrellaDirs[UmbrellaDir] = Mod;
1161e5dd7070Spatrick }
1162e5dd7070Spatrick 
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)1163e5dd7070Spatrick void ModuleMap::addUnresolvedHeader(Module *Mod,
1164e5dd7070Spatrick                                     Module::UnresolvedHeaderDirective Header,
1165e5dd7070Spatrick                                     bool &NeedsFramework) {
1166e5dd7070Spatrick   // If there is a builtin counterpart to this file, add it now so it can
1167e5dd7070Spatrick   // wrap the system header.
1168e5dd7070Spatrick   if (resolveAsBuiltinHeader(Mod, Header)) {
1169e5dd7070Spatrick     // If we have both a builtin and system version of the file, the
1170e5dd7070Spatrick     // builtin version may want to inject macros into the system header, so
1171e5dd7070Spatrick     // force the system header to be treated as a textual header in this
1172e5dd7070Spatrick     // case.
1173e5dd7070Spatrick     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1174e5dd7070Spatrick         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1175e5dd7070Spatrick     Header.HasBuiltinHeader = true;
1176e5dd7070Spatrick   }
1177e5dd7070Spatrick 
1178e5dd7070Spatrick   // If possible, don't stat the header until we need to. This requires the
1179e5dd7070Spatrick   // user to have provided us with some stat information about the file.
1180e5dd7070Spatrick   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1181e5dd7070Spatrick   // headers.
1182e5dd7070Spatrick   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1183e5dd7070Spatrick       Header.Kind != Module::HK_Excluded) {
1184e5dd7070Spatrick     // We expect more variation in mtime than size, so if we're given both,
1185e5dd7070Spatrick     // use the mtime as the key.
1186e5dd7070Spatrick     if (Header.ModTime)
1187e5dd7070Spatrick       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1188e5dd7070Spatrick     else
1189e5dd7070Spatrick       LazyHeadersBySize[*Header.Size].push_back(Mod);
1190e5dd7070Spatrick     Mod->UnresolvedHeaders.push_back(Header);
1191e5dd7070Spatrick     return;
1192e5dd7070Spatrick   }
1193e5dd7070Spatrick 
1194e5dd7070Spatrick   // We don't have stat information or can't defer looking this file up.
1195e5dd7070Spatrick   // Perform the lookup now.
1196e5dd7070Spatrick   resolveHeader(Mod, Header, NeedsFramework);
1197e5dd7070Spatrick }
1198e5dd7070Spatrick 
resolveHeaderDirectives(const FileEntry * File) const1199e5dd7070Spatrick void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1200e5dd7070Spatrick   auto BySize = LazyHeadersBySize.find(File->getSize());
1201e5dd7070Spatrick   if (BySize != LazyHeadersBySize.end()) {
1202e5dd7070Spatrick     for (auto *M : BySize->second)
1203*12c85518Srobert       resolveHeaderDirectives(M, File);
1204e5dd7070Spatrick     LazyHeadersBySize.erase(BySize);
1205e5dd7070Spatrick   }
1206e5dd7070Spatrick 
1207e5dd7070Spatrick   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1208e5dd7070Spatrick   if (ByModTime != LazyHeadersByModTime.end()) {
1209e5dd7070Spatrick     for (auto *M : ByModTime->second)
1210*12c85518Srobert       resolveHeaderDirectives(M, File);
1211e5dd7070Spatrick     LazyHeadersByModTime.erase(ByModTime);
1212e5dd7070Spatrick   }
1213e5dd7070Spatrick }
1214e5dd7070Spatrick 
resolveHeaderDirectives(Module * Mod,std::optional<const FileEntry * > File) const1215*12c85518Srobert void ModuleMap::resolveHeaderDirectives(
1216*12c85518Srobert     Module *Mod, std::optional<const FileEntry *> File) const {
1217e5dd7070Spatrick   bool NeedsFramework = false;
1218*12c85518Srobert   SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1219*12c85518Srobert   const auto Size = File ? (*File)->getSize() : 0;
1220*12c85518Srobert   const auto ModTime = File ? (*File)->getModificationTime() : 0;
1221*12c85518Srobert 
1222*12c85518Srobert   for (auto &Header : Mod->UnresolvedHeaders) {
1223*12c85518Srobert     if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
1224*12c85518Srobert                  (Header.Size && Header.Size != Size)))
1225*12c85518Srobert       NewHeaders.push_back(Header);
1226*12c85518Srobert     else
1227e5dd7070Spatrick       // This operation is logically const; we're just changing how we represent
1228e5dd7070Spatrick       // the header information for this file.
1229e5dd7070Spatrick       const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
1230*12c85518Srobert   }
1231*12c85518Srobert   Mod->UnresolvedHeaders.swap(NewHeaders);
1232e5dd7070Spatrick }
1233e5dd7070Spatrick 
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)1234e5dd7070Spatrick void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1235e5dd7070Spatrick                           ModuleHeaderRole Role, bool Imported) {
1236e5dd7070Spatrick   KnownHeader KH(Mod, Role);
1237e5dd7070Spatrick 
1238e5dd7070Spatrick   // Only add each header to the headers list once.
1239e5dd7070Spatrick   // FIXME: Should we diagnose if a header is listed twice in the
1240e5dd7070Spatrick   // same module definition?
1241e5dd7070Spatrick   auto &HeaderList = Headers[Header.Entry];
1242*12c85518Srobert   if (llvm::is_contained(HeaderList, KH))
1243e5dd7070Spatrick     return;
1244e5dd7070Spatrick 
1245e5dd7070Spatrick   HeaderList.push_back(KH);
1246e5dd7070Spatrick   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1247e5dd7070Spatrick 
1248e5dd7070Spatrick   bool isCompilingModuleHeader =
1249e5dd7070Spatrick       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1250e5dd7070Spatrick   if (!Imported || isCompilingModuleHeader) {
1251e5dd7070Spatrick     // When we import HeaderFileInfo, the external source is expected to
1252e5dd7070Spatrick     // set the isModuleHeader flag itself.
1253e5dd7070Spatrick     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1254e5dd7070Spatrick                                     isCompilingModuleHeader);
1255e5dd7070Spatrick   }
1256e5dd7070Spatrick 
1257e5dd7070Spatrick   // Notify callbacks that we just added a new header.
1258e5dd7070Spatrick   for (const auto &Cb : Callbacks)
1259e5dd7070Spatrick     Cb->moduleMapAddHeader(Header.Entry->getName());
1260e5dd7070Spatrick }
1261e5dd7070Spatrick 
1262*12c85518Srobert OptionalFileEntryRef
getContainingModuleMapFile(const Module * Module) const1263e5dd7070Spatrick ModuleMap::getContainingModuleMapFile(const Module *Module) const {
1264e5dd7070Spatrick   if (Module->DefinitionLoc.isInvalid())
1265*12c85518Srobert     return std::nullopt;
1266e5dd7070Spatrick 
1267*12c85518Srobert   return SourceMgr.getFileEntryRefForID(
1268e5dd7070Spatrick       SourceMgr.getFileID(Module->DefinitionLoc));
1269e5dd7070Spatrick }
1270e5dd7070Spatrick 
1271*12c85518Srobert OptionalFileEntryRef
getModuleMapFileForUniquing(const Module * M) const1272*12c85518Srobert ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
1273e5dd7070Spatrick   if (M->IsInferred) {
1274e5dd7070Spatrick     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
1275*12c85518Srobert     // FIXME: Update InferredModuleAllowedBy to use FileEntryRef.
1276*12c85518Srobert     return InferredModuleAllowedBy.find(M)->second->getLastRef();
1277e5dd7070Spatrick   }
1278e5dd7070Spatrick   return getContainingModuleMapFile(M);
1279e5dd7070Spatrick }
1280e5dd7070Spatrick 
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)1281e5dd7070Spatrick void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
1282e5dd7070Spatrick   assert(M->IsInferred && "module not inferred");
1283e5dd7070Spatrick   InferredModuleAllowedBy[M] = ModMap;
1284e5dd7070Spatrick }
1285e5dd7070Spatrick 
1286*12c85518Srobert std::error_code
canonicalizeModuleMapPath(SmallVectorImpl<char> & Path)1287*12c85518Srobert ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
1288*12c85518Srobert   StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1289*12c85518Srobert 
1290*12c85518Srobert   // Do not canonicalize within the framework; the module map parser expects
1291*12c85518Srobert   // Modules/ not Versions/A/Modules.
1292*12c85518Srobert   if (llvm::sys::path::filename(Dir) == "Modules") {
1293*12c85518Srobert     StringRef Parent = llvm::sys::path::parent_path(Dir);
1294*12c85518Srobert     if (Parent.endswith(".framework"))
1295*12c85518Srobert       Dir = Parent;
1296*12c85518Srobert   }
1297*12c85518Srobert 
1298*12c85518Srobert   FileManager &FM = SourceMgr.getFileManager();
1299*12c85518Srobert   auto DirEntry = FM.getDirectory(Dir.empty() ? "." : Dir);
1300*12c85518Srobert   if (!DirEntry)
1301*12c85518Srobert     return DirEntry.getError();
1302*12c85518Srobert 
1303*12c85518Srobert   // Canonicalize the directory.
1304*12c85518Srobert   StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);
1305*12c85518Srobert   if (CanonicalDir != Dir) {
1306*12c85518Srobert     auto CanonicalDirEntry = FM.getDirectory(CanonicalDir);
1307*12c85518Srobert     // Only use the canonicalized path if it resolves to the same entry as the
1308*12c85518Srobert     // original. This is not true if there's a VFS overlay on top of a FS where
1309*12c85518Srobert     // the directory is a symlink. The overlay would not remap the target path
1310*12c85518Srobert     // of the symlink to the same directory entry in that case.
1311*12c85518Srobert     if (CanonicalDirEntry && *CanonicalDirEntry == *DirEntry) {
1312*12c85518Srobert       bool Done = llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1313*12c85518Srobert       (void)Done;
1314*12c85518Srobert       assert(Done && "Path should always start with Dir");
1315*12c85518Srobert     }
1316*12c85518Srobert   }
1317*12c85518Srobert 
1318*12c85518Srobert   // In theory, the filename component should also be canonicalized if it
1319*12c85518Srobert   // on a case-insensitive filesystem. However, the extra canonicalization is
1320*12c85518Srobert   // expensive and if clang looked up the filename it will always be lowercase.
1321*12c85518Srobert 
1322*12c85518Srobert   // Remove ., remove redundant separators, and switch to native separators.
1323*12c85518Srobert   // This is needed for separators between CanonicalDir and the filename.
1324*12c85518Srobert   llvm::sys::path::remove_dots(Path);
1325*12c85518Srobert 
1326*12c85518Srobert   return std::error_code();
1327*12c85518Srobert }
1328*12c85518Srobert 
addAdditionalModuleMapFile(const Module * M,const FileEntry * ModuleMap)1329ec727ea7Spatrick void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1330ec727ea7Spatrick                                            const FileEntry *ModuleMap) {
1331ec727ea7Spatrick   AdditionalModMaps[M].insert(ModuleMap);
1332ec727ea7Spatrick }
1333ec727ea7Spatrick 
dump()1334e5dd7070Spatrick LLVM_DUMP_METHOD void ModuleMap::dump() {
1335e5dd7070Spatrick   llvm::errs() << "Modules:";
1336e5dd7070Spatrick   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1337e5dd7070Spatrick                                         MEnd = Modules.end();
1338e5dd7070Spatrick        M != MEnd; ++M)
1339e5dd7070Spatrick     M->getValue()->print(llvm::errs(), 2);
1340e5dd7070Spatrick 
1341e5dd7070Spatrick   llvm::errs() << "Headers:";
1342e5dd7070Spatrick   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1343e5dd7070Spatrick        H != HEnd; ++H) {
1344e5dd7070Spatrick     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
1345e5dd7070Spatrick     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
1346e5dd7070Spatrick                                                       E = H->second.end();
1347e5dd7070Spatrick          I != E; ++I) {
1348e5dd7070Spatrick       if (I != H->second.begin())
1349e5dd7070Spatrick         llvm::errs() << ",";
1350e5dd7070Spatrick       llvm::errs() << I->getModule()->getFullModuleName();
1351e5dd7070Spatrick     }
1352e5dd7070Spatrick     llvm::errs() << "\n";
1353e5dd7070Spatrick   }
1354e5dd7070Spatrick }
1355e5dd7070Spatrick 
resolveExports(Module * Mod,bool Complain)1356e5dd7070Spatrick bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
1357e5dd7070Spatrick   auto Unresolved = std::move(Mod->UnresolvedExports);
1358e5dd7070Spatrick   Mod->UnresolvedExports.clear();
1359e5dd7070Spatrick   for (auto &UE : Unresolved) {
1360e5dd7070Spatrick     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1361e5dd7070Spatrick     if (Export.getPointer() || Export.getInt())
1362e5dd7070Spatrick       Mod->Exports.push_back(Export);
1363e5dd7070Spatrick     else
1364e5dd7070Spatrick       Mod->UnresolvedExports.push_back(UE);
1365e5dd7070Spatrick   }
1366e5dd7070Spatrick   return !Mod->UnresolvedExports.empty();
1367e5dd7070Spatrick }
1368e5dd7070Spatrick 
resolveUses(Module * Mod,bool Complain)1369e5dd7070Spatrick bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
1370e5dd7070Spatrick   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
1371e5dd7070Spatrick   Mod->UnresolvedDirectUses.clear();
1372e5dd7070Spatrick   for (auto &UDU : Unresolved) {
1373e5dd7070Spatrick     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1374e5dd7070Spatrick     if (DirectUse)
1375e5dd7070Spatrick       Mod->DirectUses.push_back(DirectUse);
1376e5dd7070Spatrick     else
1377e5dd7070Spatrick       Mod->UnresolvedDirectUses.push_back(UDU);
1378e5dd7070Spatrick   }
1379e5dd7070Spatrick   return !Mod->UnresolvedDirectUses.empty();
1380e5dd7070Spatrick }
1381e5dd7070Spatrick 
resolveConflicts(Module * Mod,bool Complain)1382e5dd7070Spatrick bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
1383e5dd7070Spatrick   auto Unresolved = std::move(Mod->UnresolvedConflicts);
1384e5dd7070Spatrick   Mod->UnresolvedConflicts.clear();
1385e5dd7070Spatrick   for (auto &UC : Unresolved) {
1386e5dd7070Spatrick     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1387e5dd7070Spatrick       Module::Conflict Conflict;
1388e5dd7070Spatrick       Conflict.Other = OtherMod;
1389e5dd7070Spatrick       Conflict.Message = UC.Message;
1390e5dd7070Spatrick       Mod->Conflicts.push_back(Conflict);
1391e5dd7070Spatrick     } else
1392e5dd7070Spatrick       Mod->UnresolvedConflicts.push_back(UC);
1393e5dd7070Spatrick   }
1394e5dd7070Spatrick   return !Mod->UnresolvedConflicts.empty();
1395e5dd7070Spatrick }
1396e5dd7070Spatrick 
1397e5dd7070Spatrick //----------------------------------------------------------------------------//
1398e5dd7070Spatrick // Module map file parser
1399e5dd7070Spatrick //----------------------------------------------------------------------------//
1400e5dd7070Spatrick 
1401e5dd7070Spatrick namespace clang {
1402e5dd7070Spatrick 
1403e5dd7070Spatrick   /// A token in a module map file.
1404e5dd7070Spatrick   struct MMToken {
1405e5dd7070Spatrick     enum TokenKind {
1406e5dd7070Spatrick       Comma,
1407e5dd7070Spatrick       ConfigMacros,
1408e5dd7070Spatrick       Conflict,
1409e5dd7070Spatrick       EndOfFile,
1410e5dd7070Spatrick       HeaderKeyword,
1411e5dd7070Spatrick       Identifier,
1412e5dd7070Spatrick       Exclaim,
1413e5dd7070Spatrick       ExcludeKeyword,
1414e5dd7070Spatrick       ExplicitKeyword,
1415e5dd7070Spatrick       ExportKeyword,
1416e5dd7070Spatrick       ExportAsKeyword,
1417e5dd7070Spatrick       ExternKeyword,
1418e5dd7070Spatrick       FrameworkKeyword,
1419e5dd7070Spatrick       LinkKeyword,
1420e5dd7070Spatrick       ModuleKeyword,
1421e5dd7070Spatrick       Period,
1422e5dd7070Spatrick       PrivateKeyword,
1423e5dd7070Spatrick       UmbrellaKeyword,
1424e5dd7070Spatrick       UseKeyword,
1425e5dd7070Spatrick       RequiresKeyword,
1426e5dd7070Spatrick       Star,
1427e5dd7070Spatrick       StringLiteral,
1428e5dd7070Spatrick       IntegerLiteral,
1429e5dd7070Spatrick       TextualKeyword,
1430e5dd7070Spatrick       LBrace,
1431e5dd7070Spatrick       RBrace,
1432e5dd7070Spatrick       LSquare,
1433e5dd7070Spatrick       RSquare
1434e5dd7070Spatrick     } Kind;
1435e5dd7070Spatrick 
1436a9ac8606Spatrick     SourceLocation::UIntTy Location;
1437e5dd7070Spatrick     unsigned StringLength;
1438e5dd7070Spatrick     union {
1439e5dd7070Spatrick       // If Kind != IntegerLiteral.
1440e5dd7070Spatrick       const char *StringData;
1441e5dd7070Spatrick 
1442e5dd7070Spatrick       // If Kind == IntegerLiteral.
1443e5dd7070Spatrick       uint64_t IntegerValue;
1444e5dd7070Spatrick     };
1445e5dd7070Spatrick 
clearclang::MMToken1446e5dd7070Spatrick     void clear() {
1447e5dd7070Spatrick       Kind = EndOfFile;
1448e5dd7070Spatrick       Location = 0;
1449e5dd7070Spatrick       StringLength = 0;
1450e5dd7070Spatrick       StringData = nullptr;
1451e5dd7070Spatrick     }
1452e5dd7070Spatrick 
isclang::MMToken1453e5dd7070Spatrick     bool is(TokenKind K) const { return Kind == K; }
1454e5dd7070Spatrick 
getLocationclang::MMToken1455e5dd7070Spatrick     SourceLocation getLocation() const {
1456e5dd7070Spatrick       return SourceLocation::getFromRawEncoding(Location);
1457e5dd7070Spatrick     }
1458e5dd7070Spatrick 
getIntegerclang::MMToken1459e5dd7070Spatrick     uint64_t getInteger() const {
1460e5dd7070Spatrick       return Kind == IntegerLiteral ? IntegerValue : 0;
1461e5dd7070Spatrick     }
1462e5dd7070Spatrick 
getStringclang::MMToken1463e5dd7070Spatrick     StringRef getString() const {
1464e5dd7070Spatrick       return Kind == IntegerLiteral ? StringRef()
1465e5dd7070Spatrick                                     : StringRef(StringData, StringLength);
1466e5dd7070Spatrick     }
1467e5dd7070Spatrick   };
1468e5dd7070Spatrick 
1469e5dd7070Spatrick   class ModuleMapParser {
1470e5dd7070Spatrick     Lexer &L;
1471e5dd7070Spatrick     SourceManager &SourceMgr;
1472e5dd7070Spatrick 
1473e5dd7070Spatrick     /// Default target information, used only for string literal
1474e5dd7070Spatrick     /// parsing.
1475e5dd7070Spatrick     const TargetInfo *Target;
1476e5dd7070Spatrick 
1477e5dd7070Spatrick     DiagnosticsEngine &Diags;
1478e5dd7070Spatrick     ModuleMap &Map;
1479e5dd7070Spatrick 
1480e5dd7070Spatrick     /// The current module map file.
1481e5dd7070Spatrick     const FileEntry *ModuleMapFile;
1482e5dd7070Spatrick 
1483e5dd7070Spatrick     /// Source location of most recent parsed module declaration
1484e5dd7070Spatrick     SourceLocation CurrModuleDeclLoc;
1485e5dd7070Spatrick 
1486e5dd7070Spatrick     /// The directory that file names in this module map file should
1487e5dd7070Spatrick     /// be resolved relative to.
1488e5dd7070Spatrick     const DirectoryEntry *Directory;
1489e5dd7070Spatrick 
1490e5dd7070Spatrick     /// Whether this module map is in a system header directory.
1491e5dd7070Spatrick     bool IsSystem;
1492e5dd7070Spatrick 
1493e5dd7070Spatrick     /// Whether an error occurred.
1494e5dd7070Spatrick     bool HadError = false;
1495e5dd7070Spatrick 
1496e5dd7070Spatrick     /// Stores string data for the various string literals referenced
1497e5dd7070Spatrick     /// during parsing.
1498e5dd7070Spatrick     llvm::BumpPtrAllocator StringData;
1499e5dd7070Spatrick 
1500e5dd7070Spatrick     /// The current token.
1501e5dd7070Spatrick     MMToken Tok;
1502e5dd7070Spatrick 
1503e5dd7070Spatrick     /// The active module.
1504e5dd7070Spatrick     Module *ActiveModule = nullptr;
1505e5dd7070Spatrick 
1506e5dd7070Spatrick     /// Whether a module uses the 'requires excluded' hack to mark its
1507e5dd7070Spatrick     /// contents as 'textual'.
1508e5dd7070Spatrick     ///
1509e5dd7070Spatrick     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
1510e5dd7070Spatrick     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
1511e5dd7070Spatrick     /// non-modular headers.  For backwards compatibility, we continue to
1512e5dd7070Spatrick     /// support this idiom for just these modules, and map the headers to
1513e5dd7070Spatrick     /// 'textual' to match the original intent.
1514e5dd7070Spatrick     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
1515e5dd7070Spatrick 
1516e5dd7070Spatrick     /// Consume the current token and return its location.
1517e5dd7070Spatrick     SourceLocation consumeToken();
1518e5dd7070Spatrick 
1519e5dd7070Spatrick     /// Skip tokens until we reach the a token with the given kind
1520e5dd7070Spatrick     /// (or the end of the file).
1521e5dd7070Spatrick     void skipUntil(MMToken::TokenKind K);
1522e5dd7070Spatrick 
1523e5dd7070Spatrick     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1524e5dd7070Spatrick 
1525e5dd7070Spatrick     bool parseModuleId(ModuleId &Id);
1526e5dd7070Spatrick     void parseModuleDecl();
1527e5dd7070Spatrick     void parseExternModuleDecl();
1528e5dd7070Spatrick     void parseRequiresDecl();
1529e5dd7070Spatrick     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1530e5dd7070Spatrick     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
1531e5dd7070Spatrick     void parseExportDecl();
1532e5dd7070Spatrick     void parseExportAsDecl();
1533e5dd7070Spatrick     void parseUseDecl();
1534e5dd7070Spatrick     void parseLinkDecl();
1535e5dd7070Spatrick     void parseConfigMacros();
1536e5dd7070Spatrick     void parseConflict();
1537e5dd7070Spatrick     void parseInferredModuleDecl(bool Framework, bool Explicit);
1538e5dd7070Spatrick 
1539e5dd7070Spatrick     /// Private modules are canonicalized as Foo_Private. Clang provides extra
1540e5dd7070Spatrick     /// module map search logic to find the appropriate private module when PCH
1541e5dd7070Spatrick     /// is used with implicit module maps. Warn when private modules are written
1542e5dd7070Spatrick     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
1543e5dd7070Spatrick     void diagnosePrivateModules(SourceLocation ExplicitLoc,
1544e5dd7070Spatrick                                 SourceLocation FrameworkLoc);
1545e5dd7070Spatrick 
1546e5dd7070Spatrick     using Attributes = ModuleMap::Attributes;
1547e5dd7070Spatrick 
1548e5dd7070Spatrick     bool parseOptionalAttributes(Attributes &Attrs);
1549e5dd7070Spatrick 
1550e5dd7070Spatrick   public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,bool IsSystem)1551e5dd7070Spatrick     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
1552e5dd7070Spatrick                              const TargetInfo *Target, DiagnosticsEngine &Diags,
1553e5dd7070Spatrick                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1554e5dd7070Spatrick                              const DirectoryEntry *Directory, bool IsSystem)
1555e5dd7070Spatrick         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1556e5dd7070Spatrick           ModuleMapFile(ModuleMapFile), Directory(Directory),
1557e5dd7070Spatrick           IsSystem(IsSystem) {
1558e5dd7070Spatrick       Tok.clear();
1559e5dd7070Spatrick       consumeToken();
1560e5dd7070Spatrick     }
1561e5dd7070Spatrick 
1562e5dd7070Spatrick     bool parseModuleMapFile();
1563e5dd7070Spatrick 
terminatedByDirective()1564e5dd7070Spatrick     bool terminatedByDirective() { return false; }
getLocation()1565e5dd7070Spatrick     SourceLocation getLocation() { return Tok.getLocation(); }
1566e5dd7070Spatrick   };
1567e5dd7070Spatrick 
1568e5dd7070Spatrick } // namespace clang
1569e5dd7070Spatrick 
consumeToken()1570e5dd7070Spatrick SourceLocation ModuleMapParser::consumeToken() {
1571e5dd7070Spatrick   SourceLocation Result = Tok.getLocation();
1572e5dd7070Spatrick 
1573e5dd7070Spatrick retry:
1574e5dd7070Spatrick   Tok.clear();
1575e5dd7070Spatrick   Token LToken;
1576e5dd7070Spatrick   L.LexFromRawLexer(LToken);
1577e5dd7070Spatrick   Tok.Location = LToken.getLocation().getRawEncoding();
1578e5dd7070Spatrick   switch (LToken.getKind()) {
1579e5dd7070Spatrick   case tok::raw_identifier: {
1580e5dd7070Spatrick     StringRef RI = LToken.getRawIdentifier();
1581e5dd7070Spatrick     Tok.StringData = RI.data();
1582e5dd7070Spatrick     Tok.StringLength = RI.size();
1583e5dd7070Spatrick     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
1584e5dd7070Spatrick                  .Case("config_macros", MMToken::ConfigMacros)
1585e5dd7070Spatrick                  .Case("conflict", MMToken::Conflict)
1586e5dd7070Spatrick                  .Case("exclude", MMToken::ExcludeKeyword)
1587e5dd7070Spatrick                  .Case("explicit", MMToken::ExplicitKeyword)
1588e5dd7070Spatrick                  .Case("export", MMToken::ExportKeyword)
1589e5dd7070Spatrick                  .Case("export_as", MMToken::ExportAsKeyword)
1590e5dd7070Spatrick                  .Case("extern", MMToken::ExternKeyword)
1591e5dd7070Spatrick                  .Case("framework", MMToken::FrameworkKeyword)
1592e5dd7070Spatrick                  .Case("header", MMToken::HeaderKeyword)
1593e5dd7070Spatrick                  .Case("link", MMToken::LinkKeyword)
1594e5dd7070Spatrick                  .Case("module", MMToken::ModuleKeyword)
1595e5dd7070Spatrick                  .Case("private", MMToken::PrivateKeyword)
1596e5dd7070Spatrick                  .Case("requires", MMToken::RequiresKeyword)
1597e5dd7070Spatrick                  .Case("textual", MMToken::TextualKeyword)
1598e5dd7070Spatrick                  .Case("umbrella", MMToken::UmbrellaKeyword)
1599e5dd7070Spatrick                  .Case("use", MMToken::UseKeyword)
1600e5dd7070Spatrick                  .Default(MMToken::Identifier);
1601e5dd7070Spatrick     break;
1602e5dd7070Spatrick   }
1603e5dd7070Spatrick 
1604e5dd7070Spatrick   case tok::comma:
1605e5dd7070Spatrick     Tok.Kind = MMToken::Comma;
1606e5dd7070Spatrick     break;
1607e5dd7070Spatrick 
1608e5dd7070Spatrick   case tok::eof:
1609e5dd7070Spatrick     Tok.Kind = MMToken::EndOfFile;
1610e5dd7070Spatrick     break;
1611e5dd7070Spatrick 
1612e5dd7070Spatrick   case tok::l_brace:
1613e5dd7070Spatrick     Tok.Kind = MMToken::LBrace;
1614e5dd7070Spatrick     break;
1615e5dd7070Spatrick 
1616e5dd7070Spatrick   case tok::l_square:
1617e5dd7070Spatrick     Tok.Kind = MMToken::LSquare;
1618e5dd7070Spatrick     break;
1619e5dd7070Spatrick 
1620e5dd7070Spatrick   case tok::period:
1621e5dd7070Spatrick     Tok.Kind = MMToken::Period;
1622e5dd7070Spatrick     break;
1623e5dd7070Spatrick 
1624e5dd7070Spatrick   case tok::r_brace:
1625e5dd7070Spatrick     Tok.Kind = MMToken::RBrace;
1626e5dd7070Spatrick     break;
1627e5dd7070Spatrick 
1628e5dd7070Spatrick   case tok::r_square:
1629e5dd7070Spatrick     Tok.Kind = MMToken::RSquare;
1630e5dd7070Spatrick     break;
1631e5dd7070Spatrick 
1632e5dd7070Spatrick   case tok::star:
1633e5dd7070Spatrick     Tok.Kind = MMToken::Star;
1634e5dd7070Spatrick     break;
1635e5dd7070Spatrick 
1636e5dd7070Spatrick   case tok::exclaim:
1637e5dd7070Spatrick     Tok.Kind = MMToken::Exclaim;
1638e5dd7070Spatrick     break;
1639e5dd7070Spatrick 
1640e5dd7070Spatrick   case tok::string_literal: {
1641e5dd7070Spatrick     if (LToken.hasUDSuffix()) {
1642e5dd7070Spatrick       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1643e5dd7070Spatrick       HadError = true;
1644e5dd7070Spatrick       goto retry;
1645e5dd7070Spatrick     }
1646e5dd7070Spatrick 
1647e5dd7070Spatrick     // Parse the string literal.
1648e5dd7070Spatrick     LangOptions LangOpts;
1649e5dd7070Spatrick     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1650e5dd7070Spatrick     if (StringLiteral.hadError)
1651e5dd7070Spatrick       goto retry;
1652e5dd7070Spatrick 
1653e5dd7070Spatrick     // Copy the string literal into our string data allocator.
1654e5dd7070Spatrick     unsigned Length = StringLiteral.GetStringLength();
1655e5dd7070Spatrick     char *Saved = StringData.Allocate<char>(Length + 1);
1656e5dd7070Spatrick     memcpy(Saved, StringLiteral.GetString().data(), Length);
1657e5dd7070Spatrick     Saved[Length] = 0;
1658e5dd7070Spatrick 
1659e5dd7070Spatrick     // Form the token.
1660e5dd7070Spatrick     Tok.Kind = MMToken::StringLiteral;
1661e5dd7070Spatrick     Tok.StringData = Saved;
1662e5dd7070Spatrick     Tok.StringLength = Length;
1663e5dd7070Spatrick     break;
1664e5dd7070Spatrick   }
1665e5dd7070Spatrick 
1666e5dd7070Spatrick   case tok::numeric_constant: {
1667e5dd7070Spatrick     // We don't support any suffixes or other complications.
1668e5dd7070Spatrick     SmallString<32> SpellingBuffer;
1669e5dd7070Spatrick     SpellingBuffer.resize(LToken.getLength() + 1);
1670e5dd7070Spatrick     const char *Start = SpellingBuffer.data();
1671e5dd7070Spatrick     unsigned Length =
1672*12c85518Srobert         Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
1673e5dd7070Spatrick     uint64_t Value;
1674e5dd7070Spatrick     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1675e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1676e5dd7070Spatrick       HadError = true;
1677e5dd7070Spatrick       goto retry;
1678e5dd7070Spatrick     }
1679e5dd7070Spatrick 
1680e5dd7070Spatrick     Tok.Kind = MMToken::IntegerLiteral;
1681e5dd7070Spatrick     Tok.IntegerValue = Value;
1682e5dd7070Spatrick     break;
1683e5dd7070Spatrick   }
1684e5dd7070Spatrick 
1685e5dd7070Spatrick   case tok::comment:
1686e5dd7070Spatrick     goto retry;
1687e5dd7070Spatrick 
1688e5dd7070Spatrick   case tok::hash:
1689e5dd7070Spatrick     // A module map can be terminated prematurely by
1690e5dd7070Spatrick     //   #pragma clang module contents
1691e5dd7070Spatrick     // When building the module, we'll treat the rest of the file as the
1692e5dd7070Spatrick     // contents of the module.
1693e5dd7070Spatrick     {
1694e5dd7070Spatrick       auto NextIsIdent = [&](StringRef Str) -> bool {
1695e5dd7070Spatrick         L.LexFromRawLexer(LToken);
1696e5dd7070Spatrick         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
1697e5dd7070Spatrick                LToken.getRawIdentifier() == Str;
1698e5dd7070Spatrick       };
1699e5dd7070Spatrick       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
1700e5dd7070Spatrick           NextIsIdent("module") && NextIsIdent("contents")) {
1701e5dd7070Spatrick         Tok.Kind = MMToken::EndOfFile;
1702e5dd7070Spatrick         break;
1703e5dd7070Spatrick       }
1704e5dd7070Spatrick     }
1705*12c85518Srobert     [[fallthrough]];
1706e5dd7070Spatrick 
1707e5dd7070Spatrick   default:
1708e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1709e5dd7070Spatrick     HadError = true;
1710e5dd7070Spatrick     goto retry;
1711e5dd7070Spatrick   }
1712e5dd7070Spatrick 
1713e5dd7070Spatrick   return Result;
1714e5dd7070Spatrick }
1715e5dd7070Spatrick 
skipUntil(MMToken::TokenKind K)1716e5dd7070Spatrick void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1717e5dd7070Spatrick   unsigned braceDepth = 0;
1718e5dd7070Spatrick   unsigned squareDepth = 0;
1719e5dd7070Spatrick   do {
1720e5dd7070Spatrick     switch (Tok.Kind) {
1721e5dd7070Spatrick     case MMToken::EndOfFile:
1722e5dd7070Spatrick       return;
1723e5dd7070Spatrick 
1724e5dd7070Spatrick     case MMToken::LBrace:
1725e5dd7070Spatrick       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1726e5dd7070Spatrick         return;
1727e5dd7070Spatrick 
1728e5dd7070Spatrick       ++braceDepth;
1729e5dd7070Spatrick       break;
1730e5dd7070Spatrick 
1731e5dd7070Spatrick     case MMToken::LSquare:
1732e5dd7070Spatrick       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1733e5dd7070Spatrick         return;
1734e5dd7070Spatrick 
1735e5dd7070Spatrick       ++squareDepth;
1736e5dd7070Spatrick       break;
1737e5dd7070Spatrick 
1738e5dd7070Spatrick     case MMToken::RBrace:
1739e5dd7070Spatrick       if (braceDepth > 0)
1740e5dd7070Spatrick         --braceDepth;
1741e5dd7070Spatrick       else if (Tok.is(K))
1742e5dd7070Spatrick         return;
1743e5dd7070Spatrick       break;
1744e5dd7070Spatrick 
1745e5dd7070Spatrick     case MMToken::RSquare:
1746e5dd7070Spatrick       if (squareDepth > 0)
1747e5dd7070Spatrick         --squareDepth;
1748e5dd7070Spatrick       else if (Tok.is(K))
1749e5dd7070Spatrick         return;
1750e5dd7070Spatrick       break;
1751e5dd7070Spatrick 
1752e5dd7070Spatrick     default:
1753e5dd7070Spatrick       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1754e5dd7070Spatrick         return;
1755e5dd7070Spatrick       break;
1756e5dd7070Spatrick     }
1757e5dd7070Spatrick 
1758e5dd7070Spatrick    consumeToken();
1759e5dd7070Spatrick   } while (true);
1760e5dd7070Spatrick }
1761e5dd7070Spatrick 
1762e5dd7070Spatrick /// Parse a module-id.
1763e5dd7070Spatrick ///
1764e5dd7070Spatrick ///   module-id:
1765e5dd7070Spatrick ///     identifier
1766e5dd7070Spatrick ///     identifier '.' module-id
1767e5dd7070Spatrick ///
1768e5dd7070Spatrick /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)1769e5dd7070Spatrick bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1770e5dd7070Spatrick   Id.clear();
1771e5dd7070Spatrick   do {
1772e5dd7070Spatrick     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1773ec727ea7Spatrick       Id.push_back(
1774ec727ea7Spatrick           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1775e5dd7070Spatrick       consumeToken();
1776e5dd7070Spatrick     } else {
1777e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1778e5dd7070Spatrick       return true;
1779e5dd7070Spatrick     }
1780e5dd7070Spatrick 
1781e5dd7070Spatrick     if (!Tok.is(MMToken::Period))
1782e5dd7070Spatrick       break;
1783e5dd7070Spatrick 
1784e5dd7070Spatrick     consumeToken();
1785e5dd7070Spatrick   } while (true);
1786e5dd7070Spatrick 
1787e5dd7070Spatrick   return false;
1788e5dd7070Spatrick }
1789e5dd7070Spatrick 
1790e5dd7070Spatrick namespace {
1791e5dd7070Spatrick 
1792e5dd7070Spatrick   /// Enumerates the known attributes.
1793e5dd7070Spatrick   enum AttributeKind {
1794e5dd7070Spatrick     /// An unknown attribute.
1795e5dd7070Spatrick     AT_unknown,
1796e5dd7070Spatrick 
1797e5dd7070Spatrick     /// The 'system' attribute.
1798e5dd7070Spatrick     AT_system,
1799e5dd7070Spatrick 
1800e5dd7070Spatrick     /// The 'extern_c' attribute.
1801e5dd7070Spatrick     AT_extern_c,
1802e5dd7070Spatrick 
1803e5dd7070Spatrick     /// The 'exhaustive' attribute.
1804e5dd7070Spatrick     AT_exhaustive,
1805e5dd7070Spatrick 
1806e5dd7070Spatrick     /// The 'no_undeclared_includes' attribute.
1807e5dd7070Spatrick     AT_no_undeclared_includes
1808e5dd7070Spatrick   };
1809e5dd7070Spatrick 
1810e5dd7070Spatrick } // namespace
1811e5dd7070Spatrick 
1812e5dd7070Spatrick /// Private modules are canonicalized as Foo_Private. Clang provides extra
1813e5dd7070Spatrick /// module map search logic to find the appropriate private module when PCH
1814e5dd7070Spatrick /// is used with implicit module maps. Warn when private modules are written
1815e5dd7070Spatrick /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)1816e5dd7070Spatrick void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
1817e5dd7070Spatrick                                              SourceLocation FrameworkLoc) {
1818e5dd7070Spatrick   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1819e5dd7070Spatrick                              const Module *M, SourceRange ReplLoc) {
1820e5dd7070Spatrick     auto D = Diags.Report(ActiveModule->DefinitionLoc,
1821e5dd7070Spatrick                           diag::note_mmap_rename_top_level_private_module);
1822e5dd7070Spatrick     D << BadName << M->Name;
1823e5dd7070Spatrick     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
1824e5dd7070Spatrick   };
1825e5dd7070Spatrick 
1826e5dd7070Spatrick   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
1827e5dd7070Spatrick     auto const *M = E->getValue();
1828e5dd7070Spatrick     if (M->Directory != ActiveModule->Directory)
1829e5dd7070Spatrick       continue;
1830e5dd7070Spatrick 
1831e5dd7070Spatrick     SmallString<128> FullName(ActiveModule->getFullModuleName());
1832e5dd7070Spatrick     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
1833e5dd7070Spatrick       continue;
1834e5dd7070Spatrick     SmallString<128> FixedPrivModDecl;
1835e5dd7070Spatrick     SmallString<128> Canonical(M->Name);
1836e5dd7070Spatrick     Canonical.append("_Private");
1837e5dd7070Spatrick 
1838e5dd7070Spatrick     // Foo.Private -> Foo_Private
1839e5dd7070Spatrick     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
1840e5dd7070Spatrick         M->Name == ActiveModule->Parent->Name) {
1841e5dd7070Spatrick       Diags.Report(ActiveModule->DefinitionLoc,
1842e5dd7070Spatrick                    diag::warn_mmap_mismatched_private_submodule)
1843e5dd7070Spatrick           << FullName;
1844e5dd7070Spatrick 
1845e5dd7070Spatrick       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
1846e5dd7070Spatrick       if (FrameworkLoc.isValid())
1847e5dd7070Spatrick         FixItInitBegin = FrameworkLoc;
1848e5dd7070Spatrick       if (ExplicitLoc.isValid())
1849e5dd7070Spatrick         FixItInitBegin = ExplicitLoc;
1850e5dd7070Spatrick 
1851e5dd7070Spatrick       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
1852e5dd7070Spatrick         FixedPrivModDecl.append("framework ");
1853e5dd7070Spatrick       FixedPrivModDecl.append("module ");
1854e5dd7070Spatrick       FixedPrivModDecl.append(Canonical);
1855e5dd7070Spatrick 
1856e5dd7070Spatrick       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
1857e5dd7070Spatrick                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
1858e5dd7070Spatrick       continue;
1859e5dd7070Spatrick     }
1860e5dd7070Spatrick 
1861e5dd7070Spatrick     // FooPrivate and whatnots -> Foo_Private
1862e5dd7070Spatrick     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
1863e5dd7070Spatrick         ActiveModule->Name != Canonical) {
1864e5dd7070Spatrick       Diags.Report(ActiveModule->DefinitionLoc,
1865e5dd7070Spatrick                    diag::warn_mmap_mismatched_private_module_name)
1866e5dd7070Spatrick           << ActiveModule->Name;
1867e5dd7070Spatrick       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1868e5dd7070Spatrick                       SourceRange(ActiveModule->DefinitionLoc));
1869e5dd7070Spatrick     }
1870e5dd7070Spatrick   }
1871e5dd7070Spatrick }
1872e5dd7070Spatrick 
1873e5dd7070Spatrick /// Parse a module declaration.
1874e5dd7070Spatrick ///
1875e5dd7070Spatrick ///   module-declaration:
1876e5dd7070Spatrick ///     'extern' 'module' module-id string-literal
1877e5dd7070Spatrick ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1878e5dd7070Spatrick ///       { module-member* }
1879e5dd7070Spatrick ///
1880e5dd7070Spatrick ///   module-member:
1881e5dd7070Spatrick ///     requires-declaration
1882e5dd7070Spatrick ///     header-declaration
1883e5dd7070Spatrick ///     submodule-declaration
1884e5dd7070Spatrick ///     export-declaration
1885e5dd7070Spatrick ///     export-as-declaration
1886e5dd7070Spatrick ///     link-declaration
1887e5dd7070Spatrick ///
1888e5dd7070Spatrick ///   submodule-declaration:
1889e5dd7070Spatrick ///     module-declaration
1890e5dd7070Spatrick ///     inferred-submodule-declaration
parseModuleDecl()1891e5dd7070Spatrick void ModuleMapParser::parseModuleDecl() {
1892e5dd7070Spatrick   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
1893e5dd7070Spatrick          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
1894e5dd7070Spatrick   if (Tok.is(MMToken::ExternKeyword)) {
1895e5dd7070Spatrick     parseExternModuleDecl();
1896e5dd7070Spatrick     return;
1897e5dd7070Spatrick   }
1898e5dd7070Spatrick 
1899e5dd7070Spatrick   // Parse 'explicit' or 'framework' keyword, if present.
1900e5dd7070Spatrick   SourceLocation ExplicitLoc;
1901e5dd7070Spatrick   SourceLocation FrameworkLoc;
1902e5dd7070Spatrick   bool Explicit = false;
1903e5dd7070Spatrick   bool Framework = false;
1904e5dd7070Spatrick 
1905e5dd7070Spatrick   // Parse 'explicit' keyword, if present.
1906e5dd7070Spatrick   if (Tok.is(MMToken::ExplicitKeyword)) {
1907e5dd7070Spatrick     ExplicitLoc = consumeToken();
1908e5dd7070Spatrick     Explicit = true;
1909e5dd7070Spatrick   }
1910e5dd7070Spatrick 
1911e5dd7070Spatrick   // Parse 'framework' keyword, if present.
1912e5dd7070Spatrick   if (Tok.is(MMToken::FrameworkKeyword)) {
1913e5dd7070Spatrick     FrameworkLoc = consumeToken();
1914e5dd7070Spatrick     Framework = true;
1915e5dd7070Spatrick   }
1916e5dd7070Spatrick 
1917e5dd7070Spatrick   // Parse 'module' keyword.
1918e5dd7070Spatrick   if (!Tok.is(MMToken::ModuleKeyword)) {
1919e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1920e5dd7070Spatrick     consumeToken();
1921e5dd7070Spatrick     HadError = true;
1922e5dd7070Spatrick     return;
1923e5dd7070Spatrick   }
1924e5dd7070Spatrick   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1925e5dd7070Spatrick 
1926e5dd7070Spatrick   // If we have a wildcard for the module name, this is an inferred submodule.
1927e5dd7070Spatrick   // Parse it.
1928e5dd7070Spatrick   if (Tok.is(MMToken::Star))
1929e5dd7070Spatrick     return parseInferredModuleDecl(Framework, Explicit);
1930e5dd7070Spatrick 
1931e5dd7070Spatrick   // Parse the module name.
1932e5dd7070Spatrick   ModuleId Id;
1933e5dd7070Spatrick   if (parseModuleId(Id)) {
1934e5dd7070Spatrick     HadError = true;
1935e5dd7070Spatrick     return;
1936e5dd7070Spatrick   }
1937e5dd7070Spatrick 
1938e5dd7070Spatrick   if (ActiveModule) {
1939e5dd7070Spatrick     if (Id.size() > 1) {
1940e5dd7070Spatrick       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1941e5dd7070Spatrick         << SourceRange(Id.front().second, Id.back().second);
1942e5dd7070Spatrick 
1943e5dd7070Spatrick       HadError = true;
1944e5dd7070Spatrick       return;
1945e5dd7070Spatrick     }
1946e5dd7070Spatrick   } else if (Id.size() == 1 && Explicit) {
1947e5dd7070Spatrick     // Top-level modules can't be explicit.
1948e5dd7070Spatrick     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1949e5dd7070Spatrick     Explicit = false;
1950e5dd7070Spatrick     ExplicitLoc = SourceLocation();
1951e5dd7070Spatrick     HadError = true;
1952e5dd7070Spatrick   }
1953e5dd7070Spatrick 
1954e5dd7070Spatrick   Module *PreviousActiveModule = ActiveModule;
1955e5dd7070Spatrick   if (Id.size() > 1) {
1956e5dd7070Spatrick     // This module map defines a submodule. Go find the module of which it
1957e5dd7070Spatrick     // is a submodule.
1958e5dd7070Spatrick     ActiveModule = nullptr;
1959e5dd7070Spatrick     const Module *TopLevelModule = nullptr;
1960e5dd7070Spatrick     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1961e5dd7070Spatrick       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1962e5dd7070Spatrick         if (I == 0)
1963e5dd7070Spatrick           TopLevelModule = Next;
1964e5dd7070Spatrick         ActiveModule = Next;
1965e5dd7070Spatrick         continue;
1966e5dd7070Spatrick       }
1967e5dd7070Spatrick 
1968a9ac8606Spatrick       Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
1969a9ac8606Spatrick           << Id[I].first << (ActiveModule != nullptr)
1970a9ac8606Spatrick           << (ActiveModule
1971a9ac8606Spatrick                   ? ActiveModule->getTopLevelModule()->getFullModuleName()
1972a9ac8606Spatrick                   : "");
1973e5dd7070Spatrick       HadError = true;
1974e5dd7070Spatrick     }
1975e5dd7070Spatrick 
1976a9ac8606Spatrick     if (TopLevelModule &&
1977a9ac8606Spatrick         ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
1978e5dd7070Spatrick       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
1979e5dd7070Spatrick              "submodule defined in same file as 'module *' that allowed its "
1980e5dd7070Spatrick              "top-level module");
1981e5dd7070Spatrick       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
1982e5dd7070Spatrick     }
1983e5dd7070Spatrick   }
1984e5dd7070Spatrick 
1985e5dd7070Spatrick   StringRef ModuleName = Id.back().first;
1986e5dd7070Spatrick   SourceLocation ModuleNameLoc = Id.back().second;
1987e5dd7070Spatrick 
1988e5dd7070Spatrick   // Parse the optional attribute list.
1989e5dd7070Spatrick   Attributes Attrs;
1990e5dd7070Spatrick   if (parseOptionalAttributes(Attrs))
1991e5dd7070Spatrick     return;
1992e5dd7070Spatrick 
1993e5dd7070Spatrick   // Parse the opening brace.
1994e5dd7070Spatrick   if (!Tok.is(MMToken::LBrace)) {
1995e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1996e5dd7070Spatrick       << ModuleName;
1997e5dd7070Spatrick     HadError = true;
1998e5dd7070Spatrick     return;
1999e5dd7070Spatrick   }
2000e5dd7070Spatrick   SourceLocation LBraceLoc = consumeToken();
2001e5dd7070Spatrick 
2002e5dd7070Spatrick   // Determine whether this (sub)module has already been defined.
2003e5dd7070Spatrick   Module *ShadowingModule = nullptr;
2004e5dd7070Spatrick   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
2005e5dd7070Spatrick     // We might see a (re)definition of a module that we already have a
2006e5dd7070Spatrick     // definition for in two cases:
2007e5dd7070Spatrick     //  - If we loaded one definition from an AST file and we've just found a
2008e5dd7070Spatrick     //    corresponding definition in a module map file, or
2009e5dd7070Spatrick     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
2010e5dd7070Spatrick     //  - If we're building a (preprocessed) module and we've just loaded the
2011e5dd7070Spatrick     //    module map file from which it was created.
2012e5dd7070Spatrick     bool ParsedAsMainInput =
2013e5dd7070Spatrick         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
2014e5dd7070Spatrick         Map.LangOpts.CurrentModule == ModuleName &&
2015e5dd7070Spatrick         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
2016e5dd7070Spatrick             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
2017e5dd7070Spatrick     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
2018e5dd7070Spatrick       // Skip the module definition.
2019e5dd7070Spatrick       skipUntil(MMToken::RBrace);
2020e5dd7070Spatrick       if (Tok.is(MMToken::RBrace))
2021e5dd7070Spatrick         consumeToken();
2022e5dd7070Spatrick       else {
2023e5dd7070Spatrick         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2024e5dd7070Spatrick         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2025e5dd7070Spatrick         HadError = true;
2026e5dd7070Spatrick       }
2027e5dd7070Spatrick       return;
2028e5dd7070Spatrick     }
2029e5dd7070Spatrick 
2030e5dd7070Spatrick     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
2031e5dd7070Spatrick       ShadowingModule = Existing;
2032e5dd7070Spatrick     } else {
2033e5dd7070Spatrick       // This is not a shawdowed module decl, it is an illegal redefinition.
2034e5dd7070Spatrick       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
2035e5dd7070Spatrick           << ModuleName;
2036e5dd7070Spatrick       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
2037e5dd7070Spatrick 
2038e5dd7070Spatrick       // Skip the module definition.
2039e5dd7070Spatrick       skipUntil(MMToken::RBrace);
2040e5dd7070Spatrick       if (Tok.is(MMToken::RBrace))
2041e5dd7070Spatrick         consumeToken();
2042e5dd7070Spatrick 
2043e5dd7070Spatrick       HadError = true;
2044e5dd7070Spatrick       return;
2045e5dd7070Spatrick     }
2046e5dd7070Spatrick   }
2047e5dd7070Spatrick 
2048e5dd7070Spatrick   // Start defining this module.
2049e5dd7070Spatrick   if (ShadowingModule) {
2050e5dd7070Spatrick     ActiveModule =
2051e5dd7070Spatrick         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
2052e5dd7070Spatrick   } else {
2053e5dd7070Spatrick     ActiveModule =
2054e5dd7070Spatrick         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
2055e5dd7070Spatrick             .first;
2056e5dd7070Spatrick   }
2057e5dd7070Spatrick 
2058e5dd7070Spatrick   ActiveModule->DefinitionLoc = ModuleNameLoc;
2059e5dd7070Spatrick   if (Attrs.IsSystem || IsSystem)
2060e5dd7070Spatrick     ActiveModule->IsSystem = true;
2061e5dd7070Spatrick   if (Attrs.IsExternC)
2062e5dd7070Spatrick     ActiveModule->IsExternC = true;
2063*12c85518Srobert   if (Attrs.NoUndeclaredIncludes)
2064e5dd7070Spatrick     ActiveModule->NoUndeclaredIncludes = true;
2065e5dd7070Spatrick   ActiveModule->Directory = Directory;
2066e5dd7070Spatrick 
2067e5dd7070Spatrick   StringRef MapFileName(ModuleMapFile->getName());
2068e5dd7070Spatrick   if (MapFileName.endswith("module.private.modulemap") ||
2069e5dd7070Spatrick       MapFileName.endswith("module_private.map")) {
2070e5dd7070Spatrick     ActiveModule->ModuleMapIsPrivate = true;
2071e5dd7070Spatrick   }
2072e5dd7070Spatrick 
2073e5dd7070Spatrick   // Private modules named as FooPrivate, Foo.Private or similar are likely a
2074e5dd7070Spatrick   // user error; provide warnings, notes and fixits to direct users to use
2075e5dd7070Spatrick   // Foo_Private instead.
2076e5dd7070Spatrick   SourceLocation StartLoc =
2077e5dd7070Spatrick       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
2078e5dd7070Spatrick   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
2079e5dd7070Spatrick       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
2080e5dd7070Spatrick                        StartLoc) &&
2081e5dd7070Spatrick       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
2082e5dd7070Spatrick                        StartLoc) &&
2083e5dd7070Spatrick       ActiveModule->ModuleMapIsPrivate)
2084e5dd7070Spatrick     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
2085e5dd7070Spatrick 
2086e5dd7070Spatrick   bool Done = false;
2087e5dd7070Spatrick   do {
2088e5dd7070Spatrick     switch (Tok.Kind) {
2089e5dd7070Spatrick     case MMToken::EndOfFile:
2090e5dd7070Spatrick     case MMToken::RBrace:
2091e5dd7070Spatrick       Done = true;
2092e5dd7070Spatrick       break;
2093e5dd7070Spatrick 
2094e5dd7070Spatrick     case MMToken::ConfigMacros:
2095e5dd7070Spatrick       parseConfigMacros();
2096e5dd7070Spatrick       break;
2097e5dd7070Spatrick 
2098e5dd7070Spatrick     case MMToken::Conflict:
2099e5dd7070Spatrick       parseConflict();
2100e5dd7070Spatrick       break;
2101e5dd7070Spatrick 
2102e5dd7070Spatrick     case MMToken::ExplicitKeyword:
2103e5dd7070Spatrick     case MMToken::ExternKeyword:
2104e5dd7070Spatrick     case MMToken::FrameworkKeyword:
2105e5dd7070Spatrick     case MMToken::ModuleKeyword:
2106e5dd7070Spatrick       parseModuleDecl();
2107e5dd7070Spatrick       break;
2108e5dd7070Spatrick 
2109e5dd7070Spatrick     case MMToken::ExportKeyword:
2110e5dd7070Spatrick       parseExportDecl();
2111e5dd7070Spatrick       break;
2112e5dd7070Spatrick 
2113e5dd7070Spatrick     case MMToken::ExportAsKeyword:
2114e5dd7070Spatrick       parseExportAsDecl();
2115e5dd7070Spatrick       break;
2116e5dd7070Spatrick 
2117e5dd7070Spatrick     case MMToken::UseKeyword:
2118e5dd7070Spatrick       parseUseDecl();
2119e5dd7070Spatrick       break;
2120e5dd7070Spatrick 
2121e5dd7070Spatrick     case MMToken::RequiresKeyword:
2122e5dd7070Spatrick       parseRequiresDecl();
2123e5dd7070Spatrick       break;
2124e5dd7070Spatrick 
2125e5dd7070Spatrick     case MMToken::TextualKeyword:
2126e5dd7070Spatrick       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2127e5dd7070Spatrick       break;
2128e5dd7070Spatrick 
2129e5dd7070Spatrick     case MMToken::UmbrellaKeyword: {
2130e5dd7070Spatrick       SourceLocation UmbrellaLoc = consumeToken();
2131e5dd7070Spatrick       if (Tok.is(MMToken::HeaderKeyword))
2132e5dd7070Spatrick         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2133e5dd7070Spatrick       else
2134e5dd7070Spatrick         parseUmbrellaDirDecl(UmbrellaLoc);
2135e5dd7070Spatrick       break;
2136e5dd7070Spatrick     }
2137e5dd7070Spatrick 
2138e5dd7070Spatrick     case MMToken::ExcludeKeyword:
2139e5dd7070Spatrick       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
2140e5dd7070Spatrick       break;
2141e5dd7070Spatrick 
2142e5dd7070Spatrick     case MMToken::PrivateKeyword:
2143e5dd7070Spatrick       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2144e5dd7070Spatrick       break;
2145e5dd7070Spatrick 
2146e5dd7070Spatrick     case MMToken::HeaderKeyword:
2147e5dd7070Spatrick       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2148e5dd7070Spatrick       break;
2149e5dd7070Spatrick 
2150e5dd7070Spatrick     case MMToken::LinkKeyword:
2151e5dd7070Spatrick       parseLinkDecl();
2152e5dd7070Spatrick       break;
2153e5dd7070Spatrick 
2154e5dd7070Spatrick     default:
2155e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2156e5dd7070Spatrick       consumeToken();
2157e5dd7070Spatrick       break;
2158e5dd7070Spatrick     }
2159e5dd7070Spatrick   } while (!Done);
2160e5dd7070Spatrick 
2161e5dd7070Spatrick   if (Tok.is(MMToken::RBrace))
2162e5dd7070Spatrick     consumeToken();
2163e5dd7070Spatrick   else {
2164e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2165e5dd7070Spatrick     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2166e5dd7070Spatrick     HadError = true;
2167e5dd7070Spatrick   }
2168e5dd7070Spatrick 
2169e5dd7070Spatrick   // If the active module is a top-level framework, and there are no link
2170e5dd7070Spatrick   // libraries, automatically link against the framework.
2171e5dd7070Spatrick   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2172e5dd7070Spatrick       ActiveModule->LinkLibraries.empty()) {
2173e5dd7070Spatrick     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
2174e5dd7070Spatrick   }
2175e5dd7070Spatrick 
2176e5dd7070Spatrick   // If the module meets all requirements but is still unavailable, mark the
2177e5dd7070Spatrick   // whole tree as unavailable to prevent it from building.
2178ec727ea7Spatrick   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2179e5dd7070Spatrick       ActiveModule->Parent) {
2180ec727ea7Spatrick     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
2181e5dd7070Spatrick     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2182e5dd7070Spatrick       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2183e5dd7070Spatrick   }
2184e5dd7070Spatrick 
2185e5dd7070Spatrick   // We're done parsing this module. Pop back to the previous module.
2186e5dd7070Spatrick   ActiveModule = PreviousActiveModule;
2187e5dd7070Spatrick }
2188e5dd7070Spatrick 
2189e5dd7070Spatrick /// Parse an extern module declaration.
2190e5dd7070Spatrick ///
2191e5dd7070Spatrick ///   extern module-declaration:
2192e5dd7070Spatrick ///     'extern' 'module' module-id string-literal
parseExternModuleDecl()2193e5dd7070Spatrick void ModuleMapParser::parseExternModuleDecl() {
2194e5dd7070Spatrick   assert(Tok.is(MMToken::ExternKeyword));
2195e5dd7070Spatrick   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
2196e5dd7070Spatrick 
2197e5dd7070Spatrick   // Parse 'module' keyword.
2198e5dd7070Spatrick   if (!Tok.is(MMToken::ModuleKeyword)) {
2199e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2200e5dd7070Spatrick     consumeToken();
2201e5dd7070Spatrick     HadError = true;
2202e5dd7070Spatrick     return;
2203e5dd7070Spatrick   }
2204e5dd7070Spatrick   consumeToken(); // 'module' keyword
2205e5dd7070Spatrick 
2206e5dd7070Spatrick   // Parse the module name.
2207e5dd7070Spatrick   ModuleId Id;
2208e5dd7070Spatrick   if (parseModuleId(Id)) {
2209e5dd7070Spatrick     HadError = true;
2210e5dd7070Spatrick     return;
2211e5dd7070Spatrick   }
2212e5dd7070Spatrick 
2213e5dd7070Spatrick   // Parse the referenced module map file name.
2214e5dd7070Spatrick   if (!Tok.is(MMToken::StringLiteral)) {
2215e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
2216e5dd7070Spatrick     HadError = true;
2217e5dd7070Spatrick     return;
2218e5dd7070Spatrick   }
2219ec727ea7Spatrick   std::string FileName = std::string(Tok.getString());
2220e5dd7070Spatrick   consumeToken(); // filename
2221e5dd7070Spatrick 
2222e5dd7070Spatrick   StringRef FileNameRef = FileName;
2223e5dd7070Spatrick   SmallString<128> ModuleMapFileName;
2224e5dd7070Spatrick   if (llvm::sys::path::is_relative(FileNameRef)) {
2225e5dd7070Spatrick     ModuleMapFileName += Directory->getName();
2226e5dd7070Spatrick     llvm::sys::path::append(ModuleMapFileName, FileName);
2227e5dd7070Spatrick     FileNameRef = ModuleMapFileName;
2228e5dd7070Spatrick   }
2229e5dd7070Spatrick   if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
2230e5dd7070Spatrick     Map.parseModuleMapFile(
2231*12c85518Srobert         *File, IsSystem,
2232e5dd7070Spatrick         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
2233e5dd7070Spatrick             ? Directory
2234e5dd7070Spatrick             : (*File)->getDir(),
2235e5dd7070Spatrick         FileID(), nullptr, ExternLoc);
2236e5dd7070Spatrick }
2237e5dd7070Spatrick 
2238e5dd7070Spatrick /// Whether to add the requirement \p Feature to the module \p M.
2239e5dd7070Spatrick ///
2240e5dd7070Spatrick /// This preserves backwards compatibility for two hacks in the Darwin system
2241e5dd7070Spatrick /// module map files:
2242e5dd7070Spatrick ///
2243e5dd7070Spatrick /// 1. The use of 'requires excluded' to make headers non-modular, which
2244e5dd7070Spatrick ///    should really be mapped to 'textual' now that we have this feature.  We
2245e5dd7070Spatrick ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
2246e5dd7070Spatrick ///    true.  Later, this bit will be used to map all the headers inside this
2247e5dd7070Spatrick ///    module to 'textual'.
2248e5dd7070Spatrick ///
2249e5dd7070Spatrick ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
2250e5dd7070Spatrick ///
2251e5dd7070Spatrick /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
2252e5dd7070Spatrick ///    was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)2253e5dd7070Spatrick static bool shouldAddRequirement(Module *M, StringRef Feature,
2254e5dd7070Spatrick                                  bool &IsRequiresExcludedHack) {
2255e5dd7070Spatrick   if (Feature == "excluded" &&
2256e5dd7070Spatrick       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
2257e5dd7070Spatrick        M->fullModuleNameIs({"Tcl", "Private"}))) {
2258e5dd7070Spatrick     IsRequiresExcludedHack = true;
2259e5dd7070Spatrick     return false;
2260e5dd7070Spatrick   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
2261e5dd7070Spatrick     return false;
2262e5dd7070Spatrick   }
2263e5dd7070Spatrick 
2264e5dd7070Spatrick   return true;
2265e5dd7070Spatrick }
2266e5dd7070Spatrick 
2267e5dd7070Spatrick /// Parse a requires declaration.
2268e5dd7070Spatrick ///
2269e5dd7070Spatrick ///   requires-declaration:
2270e5dd7070Spatrick ///     'requires' feature-list
2271e5dd7070Spatrick ///
2272e5dd7070Spatrick ///   feature-list:
2273e5dd7070Spatrick ///     feature ',' feature-list
2274e5dd7070Spatrick ///     feature
2275e5dd7070Spatrick ///
2276e5dd7070Spatrick ///   feature:
2277e5dd7070Spatrick ///     '!'[opt] identifier
parseRequiresDecl()2278e5dd7070Spatrick void ModuleMapParser::parseRequiresDecl() {
2279e5dd7070Spatrick   assert(Tok.is(MMToken::RequiresKeyword));
2280e5dd7070Spatrick 
2281e5dd7070Spatrick   // Parse 'requires' keyword.
2282e5dd7070Spatrick   consumeToken();
2283e5dd7070Spatrick 
2284e5dd7070Spatrick   // Parse the feature-list.
2285e5dd7070Spatrick   do {
2286e5dd7070Spatrick     bool RequiredState = true;
2287e5dd7070Spatrick     if (Tok.is(MMToken::Exclaim)) {
2288e5dd7070Spatrick       RequiredState = false;
2289e5dd7070Spatrick       consumeToken();
2290e5dd7070Spatrick     }
2291e5dd7070Spatrick 
2292e5dd7070Spatrick     if (!Tok.is(MMToken::Identifier)) {
2293e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
2294e5dd7070Spatrick       HadError = true;
2295e5dd7070Spatrick       return;
2296e5dd7070Spatrick     }
2297e5dd7070Spatrick 
2298e5dd7070Spatrick     // Consume the feature name.
2299ec727ea7Spatrick     std::string Feature = std::string(Tok.getString());
2300e5dd7070Spatrick     consumeToken();
2301e5dd7070Spatrick 
2302e5dd7070Spatrick     bool IsRequiresExcludedHack = false;
2303e5dd7070Spatrick     bool ShouldAddRequirement =
2304e5dd7070Spatrick         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
2305e5dd7070Spatrick 
2306e5dd7070Spatrick     if (IsRequiresExcludedHack)
2307e5dd7070Spatrick       UsesRequiresExcludedHack.insert(ActiveModule);
2308e5dd7070Spatrick 
2309e5dd7070Spatrick     if (ShouldAddRequirement) {
2310e5dd7070Spatrick       // Add this feature.
2311e5dd7070Spatrick       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
2312e5dd7070Spatrick                                    *Map.Target);
2313e5dd7070Spatrick     }
2314e5dd7070Spatrick 
2315e5dd7070Spatrick     if (!Tok.is(MMToken::Comma))
2316e5dd7070Spatrick       break;
2317e5dd7070Spatrick 
2318e5dd7070Spatrick     // Consume the comma.
2319e5dd7070Spatrick     consumeToken();
2320e5dd7070Spatrick   } while (true);
2321e5dd7070Spatrick }
2322e5dd7070Spatrick 
2323e5dd7070Spatrick /// Parse a header declaration.
2324e5dd7070Spatrick ///
2325e5dd7070Spatrick ///   header-declaration:
2326e5dd7070Spatrick ///     'textual'[opt] 'header' string-literal
2327e5dd7070Spatrick ///     'private' 'textual'[opt] 'header' string-literal
2328e5dd7070Spatrick ///     'exclude' 'header' string-literal
2329e5dd7070Spatrick ///     'umbrella' 'header' string-literal
2330e5dd7070Spatrick ///
2331e5dd7070Spatrick /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)2332e5dd7070Spatrick void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2333e5dd7070Spatrick                                       SourceLocation LeadingLoc) {
2334e5dd7070Spatrick   // We've already consumed the first token.
2335e5dd7070Spatrick   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2336*12c85518Srobert 
2337e5dd7070Spatrick   if (LeadingToken == MMToken::PrivateKeyword) {
2338e5dd7070Spatrick     Role = ModuleMap::PrivateHeader;
2339e5dd7070Spatrick     // 'private' may optionally be followed by 'textual'.
2340e5dd7070Spatrick     if (Tok.is(MMToken::TextualKeyword)) {
2341e5dd7070Spatrick       LeadingToken = Tok.Kind;
2342e5dd7070Spatrick       consumeToken();
2343e5dd7070Spatrick     }
2344*12c85518Srobert   } else if (LeadingToken == MMToken::ExcludeKeyword) {
2345*12c85518Srobert     Role = ModuleMap::ExcludedHeader;
2346e5dd7070Spatrick   }
2347e5dd7070Spatrick 
2348e5dd7070Spatrick   if (LeadingToken == MMToken::TextualKeyword)
2349e5dd7070Spatrick     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2350e5dd7070Spatrick 
2351e5dd7070Spatrick   if (UsesRequiresExcludedHack.count(ActiveModule)) {
2352e5dd7070Spatrick     // Mark this header 'textual' (see doc comment for
2353e5dd7070Spatrick     // Module::UsesRequiresExcludedHack).
2354e5dd7070Spatrick     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2355e5dd7070Spatrick   }
2356e5dd7070Spatrick 
2357e5dd7070Spatrick   if (LeadingToken != MMToken::HeaderKeyword) {
2358e5dd7070Spatrick     if (!Tok.is(MMToken::HeaderKeyword)) {
2359e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2360e5dd7070Spatrick           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2361e5dd7070Spatrick               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2362e5dd7070Spatrick               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2363e5dd7070Spatrick       return;
2364e5dd7070Spatrick     }
2365e5dd7070Spatrick     consumeToken();
2366e5dd7070Spatrick   }
2367e5dd7070Spatrick 
2368e5dd7070Spatrick   // Parse the header name.
2369e5dd7070Spatrick   if (!Tok.is(MMToken::StringLiteral)) {
2370e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2371e5dd7070Spatrick       << "header";
2372e5dd7070Spatrick     HadError = true;
2373e5dd7070Spatrick     return;
2374e5dd7070Spatrick   }
2375e5dd7070Spatrick   Module::UnresolvedHeaderDirective Header;
2376ec727ea7Spatrick   Header.FileName = std::string(Tok.getString());
2377e5dd7070Spatrick   Header.FileNameLoc = consumeToken();
2378e5dd7070Spatrick   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2379*12c85518Srobert   Header.Kind = Map.headerRoleToKind(Role);
2380e5dd7070Spatrick 
2381e5dd7070Spatrick   // Check whether we already have an umbrella.
2382e5dd7070Spatrick   if (Header.IsUmbrella && ActiveModule->Umbrella) {
2383e5dd7070Spatrick     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2384e5dd7070Spatrick       << ActiveModule->getFullModuleName();
2385e5dd7070Spatrick     HadError = true;
2386e5dd7070Spatrick     return;
2387e5dd7070Spatrick   }
2388e5dd7070Spatrick 
2389e5dd7070Spatrick   // If we were given stat information, parse it so we can skip looking for
2390e5dd7070Spatrick   // the file.
2391e5dd7070Spatrick   if (Tok.is(MMToken::LBrace)) {
2392e5dd7070Spatrick     SourceLocation LBraceLoc = consumeToken();
2393e5dd7070Spatrick 
2394e5dd7070Spatrick     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2395e5dd7070Spatrick       enum Attribute { Size, ModTime, Unknown };
2396e5dd7070Spatrick       StringRef Str = Tok.getString();
2397e5dd7070Spatrick       SourceLocation Loc = consumeToken();
2398e5dd7070Spatrick       switch (llvm::StringSwitch<Attribute>(Str)
2399e5dd7070Spatrick                   .Case("size", Size)
2400e5dd7070Spatrick                   .Case("mtime", ModTime)
2401e5dd7070Spatrick                   .Default(Unknown)) {
2402e5dd7070Spatrick       case Size:
2403e5dd7070Spatrick         if (Header.Size)
2404e5dd7070Spatrick           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2405e5dd7070Spatrick         if (!Tok.is(MMToken::IntegerLiteral)) {
2406e5dd7070Spatrick           Diags.Report(Tok.getLocation(),
2407e5dd7070Spatrick                        diag::err_mmap_invalid_header_attribute_value) << Str;
2408e5dd7070Spatrick           skipUntil(MMToken::RBrace);
2409e5dd7070Spatrick           break;
2410e5dd7070Spatrick         }
2411e5dd7070Spatrick         Header.Size = Tok.getInteger();
2412e5dd7070Spatrick         consumeToken();
2413e5dd7070Spatrick         break;
2414e5dd7070Spatrick 
2415e5dd7070Spatrick       case ModTime:
2416e5dd7070Spatrick         if (Header.ModTime)
2417e5dd7070Spatrick           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2418e5dd7070Spatrick         if (!Tok.is(MMToken::IntegerLiteral)) {
2419e5dd7070Spatrick           Diags.Report(Tok.getLocation(),
2420e5dd7070Spatrick                        diag::err_mmap_invalid_header_attribute_value) << Str;
2421e5dd7070Spatrick           skipUntil(MMToken::RBrace);
2422e5dd7070Spatrick           break;
2423e5dd7070Spatrick         }
2424e5dd7070Spatrick         Header.ModTime = Tok.getInteger();
2425e5dd7070Spatrick         consumeToken();
2426e5dd7070Spatrick         break;
2427e5dd7070Spatrick 
2428e5dd7070Spatrick       case Unknown:
2429e5dd7070Spatrick         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2430e5dd7070Spatrick         skipUntil(MMToken::RBrace);
2431e5dd7070Spatrick         break;
2432e5dd7070Spatrick       }
2433e5dd7070Spatrick     }
2434e5dd7070Spatrick 
2435e5dd7070Spatrick     if (Tok.is(MMToken::RBrace))
2436e5dd7070Spatrick       consumeToken();
2437e5dd7070Spatrick     else {
2438e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2439e5dd7070Spatrick       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2440e5dd7070Spatrick       HadError = true;
2441e5dd7070Spatrick     }
2442e5dd7070Spatrick   }
2443e5dd7070Spatrick 
2444e5dd7070Spatrick   bool NeedsFramework = false;
2445e5dd7070Spatrick   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
2446e5dd7070Spatrick 
2447e5dd7070Spatrick   if (NeedsFramework && ActiveModule)
2448e5dd7070Spatrick     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
2449e5dd7070Spatrick       << ActiveModule->getFullModuleName()
2450e5dd7070Spatrick       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2451e5dd7070Spatrick }
2452e5dd7070Spatrick 
compareModuleHeaders(const Module::Header * A,const Module::Header * B)2453e5dd7070Spatrick static int compareModuleHeaders(const Module::Header *A,
2454e5dd7070Spatrick                                 const Module::Header *B) {
2455e5dd7070Spatrick   return A->NameAsWritten.compare(B->NameAsWritten);
2456e5dd7070Spatrick }
2457e5dd7070Spatrick 
2458e5dd7070Spatrick /// Parse an umbrella directory declaration.
2459e5dd7070Spatrick ///
2460e5dd7070Spatrick ///   umbrella-dir-declaration:
2461e5dd7070Spatrick ///     umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)2462e5dd7070Spatrick void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2463e5dd7070Spatrick   // Parse the directory name.
2464e5dd7070Spatrick   if (!Tok.is(MMToken::StringLiteral)) {
2465e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2466e5dd7070Spatrick       << "umbrella";
2467e5dd7070Spatrick     HadError = true;
2468e5dd7070Spatrick     return;
2469e5dd7070Spatrick   }
2470e5dd7070Spatrick 
2471ec727ea7Spatrick   std::string DirName = std::string(Tok.getString());
2472a9ac8606Spatrick   std::string DirNameAsWritten = DirName;
2473e5dd7070Spatrick   SourceLocation DirNameLoc = consumeToken();
2474e5dd7070Spatrick 
2475e5dd7070Spatrick   // Check whether we already have an umbrella.
2476e5dd7070Spatrick   if (ActiveModule->Umbrella) {
2477e5dd7070Spatrick     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2478e5dd7070Spatrick       << ActiveModule->getFullModuleName();
2479e5dd7070Spatrick     HadError = true;
2480e5dd7070Spatrick     return;
2481e5dd7070Spatrick   }
2482e5dd7070Spatrick 
2483e5dd7070Spatrick   // Look for this file.
2484e5dd7070Spatrick   const DirectoryEntry *Dir = nullptr;
2485e5dd7070Spatrick   if (llvm::sys::path::is_absolute(DirName)) {
2486e5dd7070Spatrick     if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
2487e5dd7070Spatrick       Dir = *D;
2488e5dd7070Spatrick   } else {
2489e5dd7070Spatrick     SmallString<128> PathName;
2490e5dd7070Spatrick     PathName = Directory->getName();
2491e5dd7070Spatrick     llvm::sys::path::append(PathName, DirName);
2492e5dd7070Spatrick     if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
2493e5dd7070Spatrick       Dir = *D;
2494e5dd7070Spatrick   }
2495e5dd7070Spatrick 
2496e5dd7070Spatrick   if (!Dir) {
2497e5dd7070Spatrick     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2498e5dd7070Spatrick       << DirName;
2499e5dd7070Spatrick     return;
2500e5dd7070Spatrick   }
2501e5dd7070Spatrick 
2502e5dd7070Spatrick   if (UsesRequiresExcludedHack.count(ActiveModule)) {
2503e5dd7070Spatrick     // Mark this header 'textual' (see doc comment for
2504e5dd7070Spatrick     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
2505e5dd7070Spatrick     // directory is relatively expensive, in practice this only applies to the
2506e5dd7070Spatrick     // uncommonly used Tcl module on Darwin platforms.
2507e5dd7070Spatrick     std::error_code EC;
2508e5dd7070Spatrick     SmallVector<Module::Header, 6> Headers;
2509e5dd7070Spatrick     llvm::vfs::FileSystem &FS =
2510e5dd7070Spatrick         SourceMgr.getFileManager().getVirtualFileSystem();
2511e5dd7070Spatrick     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
2512e5dd7070Spatrick          I != E && !EC; I.increment(EC)) {
2513*12c85518Srobert       if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2514*12c85518Srobert         Module::Header Header = {"", std::string(I->path()), FE};
2515e5dd7070Spatrick         Headers.push_back(std::move(Header));
2516e5dd7070Spatrick       }
2517e5dd7070Spatrick     }
2518e5dd7070Spatrick 
2519e5dd7070Spatrick     // Sort header paths so that the pcm doesn't depend on iteration order.
2520e5dd7070Spatrick     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
2521e5dd7070Spatrick 
2522e5dd7070Spatrick     for (auto &Header : Headers)
2523e5dd7070Spatrick       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
2524e5dd7070Spatrick     return;
2525e5dd7070Spatrick   }
2526e5dd7070Spatrick 
2527e5dd7070Spatrick   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2528e5dd7070Spatrick     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2529e5dd7070Spatrick       << OwningModule->getFullModuleName();
2530e5dd7070Spatrick     HadError = true;
2531e5dd7070Spatrick     return;
2532e5dd7070Spatrick   }
2533e5dd7070Spatrick 
2534e5dd7070Spatrick   // Record this umbrella directory.
2535a9ac8606Spatrick   Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
2536e5dd7070Spatrick }
2537e5dd7070Spatrick 
2538e5dd7070Spatrick /// Parse a module export declaration.
2539e5dd7070Spatrick ///
2540e5dd7070Spatrick ///   export-declaration:
2541e5dd7070Spatrick ///     'export' wildcard-module-id
2542e5dd7070Spatrick ///
2543e5dd7070Spatrick ///   wildcard-module-id:
2544e5dd7070Spatrick ///     identifier
2545e5dd7070Spatrick ///     '*'
2546e5dd7070Spatrick ///     identifier '.' wildcard-module-id
parseExportDecl()2547e5dd7070Spatrick void ModuleMapParser::parseExportDecl() {
2548e5dd7070Spatrick   assert(Tok.is(MMToken::ExportKeyword));
2549e5dd7070Spatrick   SourceLocation ExportLoc = consumeToken();
2550e5dd7070Spatrick 
2551e5dd7070Spatrick   // Parse the module-id with an optional wildcard at the end.
2552e5dd7070Spatrick   ModuleId ParsedModuleId;
2553e5dd7070Spatrick   bool Wildcard = false;
2554e5dd7070Spatrick   do {
2555e5dd7070Spatrick     // FIXME: Support string-literal module names here.
2556e5dd7070Spatrick     if (Tok.is(MMToken::Identifier)) {
2557ec727ea7Spatrick       ParsedModuleId.push_back(
2558ec727ea7Spatrick           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
2559e5dd7070Spatrick       consumeToken();
2560e5dd7070Spatrick 
2561e5dd7070Spatrick       if (Tok.is(MMToken::Period)) {
2562e5dd7070Spatrick         consumeToken();
2563e5dd7070Spatrick         continue;
2564e5dd7070Spatrick       }
2565e5dd7070Spatrick 
2566e5dd7070Spatrick       break;
2567e5dd7070Spatrick     }
2568e5dd7070Spatrick 
2569e5dd7070Spatrick     if(Tok.is(MMToken::Star)) {
2570e5dd7070Spatrick       Wildcard = true;
2571e5dd7070Spatrick       consumeToken();
2572e5dd7070Spatrick       break;
2573e5dd7070Spatrick     }
2574e5dd7070Spatrick 
2575e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2576e5dd7070Spatrick     HadError = true;
2577e5dd7070Spatrick     return;
2578e5dd7070Spatrick   } while (true);
2579e5dd7070Spatrick 
2580e5dd7070Spatrick   Module::UnresolvedExportDecl Unresolved = {
2581e5dd7070Spatrick     ExportLoc, ParsedModuleId, Wildcard
2582e5dd7070Spatrick   };
2583e5dd7070Spatrick   ActiveModule->UnresolvedExports.push_back(Unresolved);
2584e5dd7070Spatrick }
2585e5dd7070Spatrick 
2586e5dd7070Spatrick /// Parse a module export_as declaration.
2587e5dd7070Spatrick ///
2588e5dd7070Spatrick ///   export-as-declaration:
2589e5dd7070Spatrick ///     'export_as' identifier
parseExportAsDecl()2590e5dd7070Spatrick void ModuleMapParser::parseExportAsDecl() {
2591e5dd7070Spatrick   assert(Tok.is(MMToken::ExportAsKeyword));
2592e5dd7070Spatrick   consumeToken();
2593e5dd7070Spatrick 
2594e5dd7070Spatrick   if (!Tok.is(MMToken::Identifier)) {
2595e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2596e5dd7070Spatrick     HadError = true;
2597e5dd7070Spatrick     return;
2598e5dd7070Spatrick   }
2599e5dd7070Spatrick 
2600e5dd7070Spatrick   if (ActiveModule->Parent) {
2601e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2602e5dd7070Spatrick     consumeToken();
2603e5dd7070Spatrick     return;
2604e5dd7070Spatrick   }
2605e5dd7070Spatrick 
2606e5dd7070Spatrick   if (!ActiveModule->ExportAsModule.empty()) {
2607e5dd7070Spatrick     if (ActiveModule->ExportAsModule == Tok.getString()) {
2608e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2609e5dd7070Spatrick         << ActiveModule->Name << Tok.getString();
2610e5dd7070Spatrick     } else {
2611e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2612e5dd7070Spatrick         << ActiveModule->Name << ActiveModule->ExportAsModule
2613e5dd7070Spatrick         << Tok.getString();
2614e5dd7070Spatrick     }
2615e5dd7070Spatrick   }
2616e5dd7070Spatrick 
2617ec727ea7Spatrick   ActiveModule->ExportAsModule = std::string(Tok.getString());
2618e5dd7070Spatrick   Map.addLinkAsDependency(ActiveModule);
2619e5dd7070Spatrick 
2620e5dd7070Spatrick   consumeToken();
2621e5dd7070Spatrick }
2622e5dd7070Spatrick 
2623e5dd7070Spatrick /// Parse a module use declaration.
2624e5dd7070Spatrick ///
2625e5dd7070Spatrick ///   use-declaration:
2626e5dd7070Spatrick ///     'use' wildcard-module-id
parseUseDecl()2627e5dd7070Spatrick void ModuleMapParser::parseUseDecl() {
2628e5dd7070Spatrick   assert(Tok.is(MMToken::UseKeyword));
2629e5dd7070Spatrick   auto KWLoc = consumeToken();
2630e5dd7070Spatrick   // Parse the module-id.
2631e5dd7070Spatrick   ModuleId ParsedModuleId;
2632e5dd7070Spatrick   parseModuleId(ParsedModuleId);
2633e5dd7070Spatrick 
2634e5dd7070Spatrick   if (ActiveModule->Parent)
2635e5dd7070Spatrick     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
2636e5dd7070Spatrick   else
2637e5dd7070Spatrick     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2638e5dd7070Spatrick }
2639e5dd7070Spatrick 
2640e5dd7070Spatrick /// Parse a link declaration.
2641e5dd7070Spatrick ///
2642e5dd7070Spatrick ///   module-declaration:
2643e5dd7070Spatrick ///     'link' 'framework'[opt] string-literal
parseLinkDecl()2644e5dd7070Spatrick void ModuleMapParser::parseLinkDecl() {
2645e5dd7070Spatrick   assert(Tok.is(MMToken::LinkKeyword));
2646e5dd7070Spatrick   SourceLocation LinkLoc = consumeToken();
2647e5dd7070Spatrick 
2648e5dd7070Spatrick   // Parse the optional 'framework' keyword.
2649e5dd7070Spatrick   bool IsFramework = false;
2650e5dd7070Spatrick   if (Tok.is(MMToken::FrameworkKeyword)) {
2651e5dd7070Spatrick     consumeToken();
2652e5dd7070Spatrick     IsFramework = true;
2653e5dd7070Spatrick   }
2654e5dd7070Spatrick 
2655e5dd7070Spatrick   // Parse the library name
2656e5dd7070Spatrick   if (!Tok.is(MMToken::StringLiteral)) {
2657e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
2658e5dd7070Spatrick       << IsFramework << SourceRange(LinkLoc);
2659e5dd7070Spatrick     HadError = true;
2660e5dd7070Spatrick     return;
2661e5dd7070Spatrick   }
2662e5dd7070Spatrick 
2663ec727ea7Spatrick   std::string LibraryName = std::string(Tok.getString());
2664e5dd7070Spatrick   consumeToken();
2665e5dd7070Spatrick   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
2666e5dd7070Spatrick                                                             IsFramework));
2667e5dd7070Spatrick }
2668e5dd7070Spatrick 
2669e5dd7070Spatrick /// Parse a configuration macro declaration.
2670e5dd7070Spatrick ///
2671e5dd7070Spatrick ///   module-declaration:
2672e5dd7070Spatrick ///     'config_macros' attributes[opt] config-macro-list?
2673e5dd7070Spatrick ///
2674e5dd7070Spatrick ///   config-macro-list:
2675e5dd7070Spatrick ///     identifier (',' identifier)?
parseConfigMacros()2676e5dd7070Spatrick void ModuleMapParser::parseConfigMacros() {
2677e5dd7070Spatrick   assert(Tok.is(MMToken::ConfigMacros));
2678e5dd7070Spatrick   SourceLocation ConfigMacrosLoc = consumeToken();
2679e5dd7070Spatrick 
2680e5dd7070Spatrick   // Only top-level modules can have configuration macros.
2681e5dd7070Spatrick   if (ActiveModule->Parent) {
2682e5dd7070Spatrick     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
2683e5dd7070Spatrick   }
2684e5dd7070Spatrick 
2685e5dd7070Spatrick   // Parse the optional attributes.
2686e5dd7070Spatrick   Attributes Attrs;
2687e5dd7070Spatrick   if (parseOptionalAttributes(Attrs))
2688e5dd7070Spatrick     return;
2689e5dd7070Spatrick 
2690e5dd7070Spatrick   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
2691e5dd7070Spatrick     ActiveModule->ConfigMacrosExhaustive = true;
2692e5dd7070Spatrick   }
2693e5dd7070Spatrick 
2694e5dd7070Spatrick   // If we don't have an identifier, we're done.
2695e5dd7070Spatrick   // FIXME: Support macros with the same name as a keyword here.
2696e5dd7070Spatrick   if (!Tok.is(MMToken::Identifier))
2697e5dd7070Spatrick     return;
2698e5dd7070Spatrick 
2699e5dd7070Spatrick   // Consume the first identifier.
2700e5dd7070Spatrick   if (!ActiveModule->Parent) {
2701e5dd7070Spatrick     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2702e5dd7070Spatrick   }
2703e5dd7070Spatrick   consumeToken();
2704e5dd7070Spatrick 
2705e5dd7070Spatrick   do {
2706e5dd7070Spatrick     // If there's a comma, consume it.
2707e5dd7070Spatrick     if (!Tok.is(MMToken::Comma))
2708e5dd7070Spatrick       break;
2709e5dd7070Spatrick     consumeToken();
2710e5dd7070Spatrick 
2711e5dd7070Spatrick     // We expect to see a macro name here.
2712e5dd7070Spatrick     // FIXME: Support macros with the same name as a keyword here.
2713e5dd7070Spatrick     if (!Tok.is(MMToken::Identifier)) {
2714e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
2715e5dd7070Spatrick       break;
2716e5dd7070Spatrick     }
2717e5dd7070Spatrick 
2718e5dd7070Spatrick     // Consume the macro name.
2719e5dd7070Spatrick     if (!ActiveModule->Parent) {
2720e5dd7070Spatrick       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2721e5dd7070Spatrick     }
2722e5dd7070Spatrick     consumeToken();
2723e5dd7070Spatrick   } while (true);
2724e5dd7070Spatrick }
2725e5dd7070Spatrick 
2726e5dd7070Spatrick /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)2727e5dd7070Spatrick static std::string formatModuleId(const ModuleId &Id) {
2728e5dd7070Spatrick   std::string result;
2729e5dd7070Spatrick   {
2730e5dd7070Spatrick     llvm::raw_string_ostream OS(result);
2731e5dd7070Spatrick 
2732e5dd7070Spatrick     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2733e5dd7070Spatrick       if (I)
2734e5dd7070Spatrick         OS << ".";
2735e5dd7070Spatrick       OS << Id[I].first;
2736e5dd7070Spatrick     }
2737e5dd7070Spatrick   }
2738e5dd7070Spatrick 
2739e5dd7070Spatrick   return result;
2740e5dd7070Spatrick }
2741e5dd7070Spatrick 
2742e5dd7070Spatrick /// Parse a conflict declaration.
2743e5dd7070Spatrick ///
2744e5dd7070Spatrick ///   module-declaration:
2745e5dd7070Spatrick ///     'conflict' module-id ',' string-literal
parseConflict()2746e5dd7070Spatrick void ModuleMapParser::parseConflict() {
2747e5dd7070Spatrick   assert(Tok.is(MMToken::Conflict));
2748e5dd7070Spatrick   SourceLocation ConflictLoc = consumeToken();
2749e5dd7070Spatrick   Module::UnresolvedConflict Conflict;
2750e5dd7070Spatrick 
2751e5dd7070Spatrick   // Parse the module-id.
2752e5dd7070Spatrick   if (parseModuleId(Conflict.Id))
2753e5dd7070Spatrick     return;
2754e5dd7070Spatrick 
2755e5dd7070Spatrick   // Parse the ','.
2756e5dd7070Spatrick   if (!Tok.is(MMToken::Comma)) {
2757e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2758e5dd7070Spatrick       << SourceRange(ConflictLoc);
2759e5dd7070Spatrick     return;
2760e5dd7070Spatrick   }
2761e5dd7070Spatrick   consumeToken();
2762e5dd7070Spatrick 
2763e5dd7070Spatrick   // Parse the message.
2764e5dd7070Spatrick   if (!Tok.is(MMToken::StringLiteral)) {
2765e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2766e5dd7070Spatrick       << formatModuleId(Conflict.Id);
2767e5dd7070Spatrick     return;
2768e5dd7070Spatrick   }
2769e5dd7070Spatrick   Conflict.Message = Tok.getString().str();
2770e5dd7070Spatrick   consumeToken();
2771e5dd7070Spatrick 
2772e5dd7070Spatrick   // Add this unresolved conflict.
2773e5dd7070Spatrick   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2774e5dd7070Spatrick }
2775e5dd7070Spatrick 
2776e5dd7070Spatrick /// Parse an inferred module declaration (wildcard modules).
2777e5dd7070Spatrick ///
2778e5dd7070Spatrick ///   module-declaration:
2779e5dd7070Spatrick ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
2780e5dd7070Spatrick ///       { inferred-module-member* }
2781e5dd7070Spatrick ///
2782e5dd7070Spatrick ///   inferred-module-member:
2783e5dd7070Spatrick ///     'export' '*'
2784e5dd7070Spatrick ///     'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)2785e5dd7070Spatrick void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
2786e5dd7070Spatrick   assert(Tok.is(MMToken::Star));
2787e5dd7070Spatrick   SourceLocation StarLoc = consumeToken();
2788e5dd7070Spatrick   bool Failed = false;
2789e5dd7070Spatrick 
2790e5dd7070Spatrick   // Inferred modules must be submodules.
2791e5dd7070Spatrick   if (!ActiveModule && !Framework) {
2792e5dd7070Spatrick     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2793e5dd7070Spatrick     Failed = true;
2794e5dd7070Spatrick   }
2795e5dd7070Spatrick 
2796e5dd7070Spatrick   if (ActiveModule) {
2797e5dd7070Spatrick     // Inferred modules must have umbrella directories.
2798e5dd7070Spatrick     if (!Failed && ActiveModule->IsAvailable &&
2799e5dd7070Spatrick         !ActiveModule->getUmbrellaDir()) {
2800e5dd7070Spatrick       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2801e5dd7070Spatrick       Failed = true;
2802e5dd7070Spatrick     }
2803e5dd7070Spatrick 
2804e5dd7070Spatrick     // Check for redefinition of an inferred module.
2805e5dd7070Spatrick     if (!Failed && ActiveModule->InferSubmodules) {
2806e5dd7070Spatrick       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2807e5dd7070Spatrick       if (ActiveModule->InferredSubmoduleLoc.isValid())
2808e5dd7070Spatrick         Diags.Report(ActiveModule->InferredSubmoduleLoc,
2809e5dd7070Spatrick                      diag::note_mmap_prev_definition);
2810e5dd7070Spatrick       Failed = true;
2811e5dd7070Spatrick     }
2812e5dd7070Spatrick 
2813e5dd7070Spatrick     // Check for the 'framework' keyword, which is not permitted here.
2814e5dd7070Spatrick     if (Framework) {
2815e5dd7070Spatrick       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2816e5dd7070Spatrick       Framework = false;
2817e5dd7070Spatrick     }
2818e5dd7070Spatrick   } else if (Explicit) {
2819e5dd7070Spatrick     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2820e5dd7070Spatrick     Explicit = false;
2821e5dd7070Spatrick   }
2822e5dd7070Spatrick 
2823e5dd7070Spatrick   // If there were any problems with this inferred submodule, skip its body.
2824e5dd7070Spatrick   if (Failed) {
2825e5dd7070Spatrick     if (Tok.is(MMToken::LBrace)) {
2826e5dd7070Spatrick       consumeToken();
2827e5dd7070Spatrick       skipUntil(MMToken::RBrace);
2828e5dd7070Spatrick       if (Tok.is(MMToken::RBrace))
2829e5dd7070Spatrick         consumeToken();
2830e5dd7070Spatrick     }
2831e5dd7070Spatrick     HadError = true;
2832e5dd7070Spatrick     return;
2833e5dd7070Spatrick   }
2834e5dd7070Spatrick 
2835e5dd7070Spatrick   // Parse optional attributes.
2836e5dd7070Spatrick   Attributes Attrs;
2837e5dd7070Spatrick   if (parseOptionalAttributes(Attrs))
2838e5dd7070Spatrick     return;
2839e5dd7070Spatrick 
2840e5dd7070Spatrick   if (ActiveModule) {
2841e5dd7070Spatrick     // Note that we have an inferred submodule.
2842e5dd7070Spatrick     ActiveModule->InferSubmodules = true;
2843e5dd7070Spatrick     ActiveModule->InferredSubmoduleLoc = StarLoc;
2844e5dd7070Spatrick     ActiveModule->InferExplicitSubmodules = Explicit;
2845e5dd7070Spatrick   } else {
2846e5dd7070Spatrick     // We'll be inferring framework modules for this directory.
2847e5dd7070Spatrick     Map.InferredDirectories[Directory].InferModules = true;
2848e5dd7070Spatrick     Map.InferredDirectories[Directory].Attrs = Attrs;
2849e5dd7070Spatrick     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2850e5dd7070Spatrick     // FIXME: Handle the 'framework' keyword.
2851e5dd7070Spatrick   }
2852e5dd7070Spatrick 
2853e5dd7070Spatrick   // Parse the opening brace.
2854e5dd7070Spatrick   if (!Tok.is(MMToken::LBrace)) {
2855e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
2856e5dd7070Spatrick     HadError = true;
2857e5dd7070Spatrick     return;
2858e5dd7070Spatrick   }
2859e5dd7070Spatrick   SourceLocation LBraceLoc = consumeToken();
2860e5dd7070Spatrick 
2861e5dd7070Spatrick   // Parse the body of the inferred submodule.
2862e5dd7070Spatrick   bool Done = false;
2863e5dd7070Spatrick   do {
2864e5dd7070Spatrick     switch (Tok.Kind) {
2865e5dd7070Spatrick     case MMToken::EndOfFile:
2866e5dd7070Spatrick     case MMToken::RBrace:
2867e5dd7070Spatrick       Done = true;
2868e5dd7070Spatrick       break;
2869e5dd7070Spatrick 
2870e5dd7070Spatrick     case MMToken::ExcludeKeyword:
2871e5dd7070Spatrick       if (ActiveModule) {
2872e5dd7070Spatrick         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2873e5dd7070Spatrick           << (ActiveModule != nullptr);
2874e5dd7070Spatrick         consumeToken();
2875e5dd7070Spatrick         break;
2876e5dd7070Spatrick       }
2877e5dd7070Spatrick 
2878e5dd7070Spatrick       consumeToken();
2879e5dd7070Spatrick       // FIXME: Support string-literal module names here.
2880e5dd7070Spatrick       if (!Tok.is(MMToken::Identifier)) {
2881e5dd7070Spatrick         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
2882e5dd7070Spatrick         break;
2883e5dd7070Spatrick       }
2884e5dd7070Spatrick 
2885ec727ea7Spatrick       Map.InferredDirectories[Directory].ExcludedModules.push_back(
2886ec727ea7Spatrick           std::string(Tok.getString()));
2887e5dd7070Spatrick       consumeToken();
2888e5dd7070Spatrick       break;
2889e5dd7070Spatrick 
2890e5dd7070Spatrick     case MMToken::ExportKeyword:
2891e5dd7070Spatrick       if (!ActiveModule) {
2892e5dd7070Spatrick         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2893e5dd7070Spatrick           << (ActiveModule != nullptr);
2894e5dd7070Spatrick         consumeToken();
2895e5dd7070Spatrick         break;
2896e5dd7070Spatrick       }
2897e5dd7070Spatrick 
2898e5dd7070Spatrick       consumeToken();
2899e5dd7070Spatrick       if (Tok.is(MMToken::Star))
2900e5dd7070Spatrick         ActiveModule->InferExportWildcard = true;
2901e5dd7070Spatrick       else
2902e5dd7070Spatrick         Diags.Report(Tok.getLocation(),
2903e5dd7070Spatrick                      diag::err_mmap_expected_export_wildcard);
2904e5dd7070Spatrick       consumeToken();
2905e5dd7070Spatrick       break;
2906e5dd7070Spatrick 
2907e5dd7070Spatrick     case MMToken::ExplicitKeyword:
2908e5dd7070Spatrick     case MMToken::ModuleKeyword:
2909e5dd7070Spatrick     case MMToken::HeaderKeyword:
2910e5dd7070Spatrick     case MMToken::PrivateKeyword:
2911e5dd7070Spatrick     case MMToken::UmbrellaKeyword:
2912e5dd7070Spatrick     default:
2913e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2914e5dd7070Spatrick           << (ActiveModule != nullptr);
2915e5dd7070Spatrick       consumeToken();
2916e5dd7070Spatrick       break;
2917e5dd7070Spatrick     }
2918e5dd7070Spatrick   } while (!Done);
2919e5dd7070Spatrick 
2920e5dd7070Spatrick   if (Tok.is(MMToken::RBrace))
2921e5dd7070Spatrick     consumeToken();
2922e5dd7070Spatrick   else {
2923e5dd7070Spatrick     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2924e5dd7070Spatrick     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2925e5dd7070Spatrick     HadError = true;
2926e5dd7070Spatrick   }
2927e5dd7070Spatrick }
2928e5dd7070Spatrick 
2929e5dd7070Spatrick /// Parse optional attributes.
2930e5dd7070Spatrick ///
2931e5dd7070Spatrick ///   attributes:
2932e5dd7070Spatrick ///     attribute attributes
2933e5dd7070Spatrick ///     attribute
2934e5dd7070Spatrick ///
2935e5dd7070Spatrick ///   attribute:
2936e5dd7070Spatrick ///     [ identifier ]
2937e5dd7070Spatrick ///
2938e5dd7070Spatrick /// \param Attrs Will be filled in with the parsed attributes.
2939e5dd7070Spatrick ///
2940e5dd7070Spatrick /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)2941e5dd7070Spatrick bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
2942e5dd7070Spatrick   bool HadError = false;
2943e5dd7070Spatrick 
2944e5dd7070Spatrick   while (Tok.is(MMToken::LSquare)) {
2945e5dd7070Spatrick     // Consume the '['.
2946e5dd7070Spatrick     SourceLocation LSquareLoc = consumeToken();
2947e5dd7070Spatrick 
2948e5dd7070Spatrick     // Check whether we have an attribute name here.
2949e5dd7070Spatrick     if (!Tok.is(MMToken::Identifier)) {
2950e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
2951e5dd7070Spatrick       skipUntil(MMToken::RSquare);
2952e5dd7070Spatrick       if (Tok.is(MMToken::RSquare))
2953e5dd7070Spatrick         consumeToken();
2954e5dd7070Spatrick       HadError = true;
2955e5dd7070Spatrick     }
2956e5dd7070Spatrick 
2957e5dd7070Spatrick     // Decode the attribute name.
2958e5dd7070Spatrick     AttributeKind Attribute
2959e5dd7070Spatrick       = llvm::StringSwitch<AttributeKind>(Tok.getString())
2960e5dd7070Spatrick           .Case("exhaustive", AT_exhaustive)
2961e5dd7070Spatrick           .Case("extern_c", AT_extern_c)
2962e5dd7070Spatrick           .Case("no_undeclared_includes", AT_no_undeclared_includes)
2963e5dd7070Spatrick           .Case("system", AT_system)
2964e5dd7070Spatrick           .Default(AT_unknown);
2965e5dd7070Spatrick     switch (Attribute) {
2966e5dd7070Spatrick     case AT_unknown:
2967e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
2968e5dd7070Spatrick         << Tok.getString();
2969e5dd7070Spatrick       break;
2970e5dd7070Spatrick 
2971e5dd7070Spatrick     case AT_system:
2972e5dd7070Spatrick       Attrs.IsSystem = true;
2973e5dd7070Spatrick       break;
2974e5dd7070Spatrick 
2975e5dd7070Spatrick     case AT_extern_c:
2976e5dd7070Spatrick       Attrs.IsExternC = true;
2977e5dd7070Spatrick       break;
2978e5dd7070Spatrick 
2979e5dd7070Spatrick     case AT_exhaustive:
2980e5dd7070Spatrick       Attrs.IsExhaustive = true;
2981e5dd7070Spatrick       break;
2982e5dd7070Spatrick 
2983e5dd7070Spatrick     case AT_no_undeclared_includes:
2984e5dd7070Spatrick       Attrs.NoUndeclaredIncludes = true;
2985e5dd7070Spatrick       break;
2986e5dd7070Spatrick     }
2987e5dd7070Spatrick     consumeToken();
2988e5dd7070Spatrick 
2989e5dd7070Spatrick     // Consume the ']'.
2990e5dd7070Spatrick     if (!Tok.is(MMToken::RSquare)) {
2991e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
2992e5dd7070Spatrick       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
2993e5dd7070Spatrick       skipUntil(MMToken::RSquare);
2994e5dd7070Spatrick       HadError = true;
2995e5dd7070Spatrick     }
2996e5dd7070Spatrick 
2997e5dd7070Spatrick     if (Tok.is(MMToken::RSquare))
2998e5dd7070Spatrick       consumeToken();
2999e5dd7070Spatrick   }
3000e5dd7070Spatrick 
3001e5dd7070Spatrick   return HadError;
3002e5dd7070Spatrick }
3003e5dd7070Spatrick 
3004e5dd7070Spatrick /// Parse a module map file.
3005e5dd7070Spatrick ///
3006e5dd7070Spatrick ///   module-map-file:
3007e5dd7070Spatrick ///     module-declaration*
parseModuleMapFile()3008e5dd7070Spatrick bool ModuleMapParser::parseModuleMapFile() {
3009e5dd7070Spatrick   do {
3010e5dd7070Spatrick     switch (Tok.Kind) {
3011e5dd7070Spatrick     case MMToken::EndOfFile:
3012e5dd7070Spatrick       return HadError;
3013e5dd7070Spatrick 
3014e5dd7070Spatrick     case MMToken::ExplicitKeyword:
3015e5dd7070Spatrick     case MMToken::ExternKeyword:
3016e5dd7070Spatrick     case MMToken::ModuleKeyword:
3017e5dd7070Spatrick     case MMToken::FrameworkKeyword:
3018e5dd7070Spatrick       parseModuleDecl();
3019e5dd7070Spatrick       break;
3020e5dd7070Spatrick 
3021e5dd7070Spatrick     case MMToken::Comma:
3022e5dd7070Spatrick     case MMToken::ConfigMacros:
3023e5dd7070Spatrick     case MMToken::Conflict:
3024e5dd7070Spatrick     case MMToken::Exclaim:
3025e5dd7070Spatrick     case MMToken::ExcludeKeyword:
3026e5dd7070Spatrick     case MMToken::ExportKeyword:
3027e5dd7070Spatrick     case MMToken::ExportAsKeyword:
3028e5dd7070Spatrick     case MMToken::HeaderKeyword:
3029e5dd7070Spatrick     case MMToken::Identifier:
3030e5dd7070Spatrick     case MMToken::LBrace:
3031e5dd7070Spatrick     case MMToken::LinkKeyword:
3032e5dd7070Spatrick     case MMToken::LSquare:
3033e5dd7070Spatrick     case MMToken::Period:
3034e5dd7070Spatrick     case MMToken::PrivateKeyword:
3035e5dd7070Spatrick     case MMToken::RBrace:
3036e5dd7070Spatrick     case MMToken::RSquare:
3037e5dd7070Spatrick     case MMToken::RequiresKeyword:
3038e5dd7070Spatrick     case MMToken::Star:
3039e5dd7070Spatrick     case MMToken::StringLiteral:
3040e5dd7070Spatrick     case MMToken::IntegerLiteral:
3041e5dd7070Spatrick     case MMToken::TextualKeyword:
3042e5dd7070Spatrick     case MMToken::UmbrellaKeyword:
3043e5dd7070Spatrick     case MMToken::UseKeyword:
3044e5dd7070Spatrick       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
3045e5dd7070Spatrick       HadError = true;
3046e5dd7070Spatrick       consumeToken();
3047e5dd7070Spatrick       break;
3048e5dd7070Spatrick     }
3049e5dd7070Spatrick   } while (true);
3050e5dd7070Spatrick }
3051e5dd7070Spatrick 
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)3052e5dd7070Spatrick bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
3053e5dd7070Spatrick                                    const DirectoryEntry *Dir, FileID ID,
3054e5dd7070Spatrick                                    unsigned *Offset,
3055e5dd7070Spatrick                                    SourceLocation ExternModuleLoc) {
3056e5dd7070Spatrick   assert(Target && "Missing target information");
3057e5dd7070Spatrick   llvm::DenseMap<const FileEntry *, bool>::iterator Known
3058e5dd7070Spatrick     = ParsedModuleMap.find(File);
3059e5dd7070Spatrick   if (Known != ParsedModuleMap.end())
3060e5dd7070Spatrick     return Known->second;
3061e5dd7070Spatrick 
3062e5dd7070Spatrick   // If the module map file wasn't already entered, do so now.
3063e5dd7070Spatrick   if (ID.isInvalid()) {
3064e5dd7070Spatrick     auto FileCharacter =
3065e5dd7070Spatrick         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
3066e5dd7070Spatrick     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
3067e5dd7070Spatrick   }
3068e5dd7070Spatrick 
3069e5dd7070Spatrick   assert(Target && "Missing target information");
3070*12c85518Srobert   std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
3071e5dd7070Spatrick   if (!Buffer)
3072e5dd7070Spatrick     return ParsedModuleMap[File] = true;
3073e5dd7070Spatrick   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
3074e5dd7070Spatrick          "invalid buffer offset");
3075e5dd7070Spatrick 
3076e5dd7070Spatrick   // Parse this module map file.
3077e5dd7070Spatrick   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
3078e5dd7070Spatrick           Buffer->getBufferStart(),
3079e5dd7070Spatrick           Buffer->getBufferStart() + (Offset ? *Offset : 0),
3080e5dd7070Spatrick           Buffer->getBufferEnd());
3081e5dd7070Spatrick   SourceLocation Start = L.getSourceLocation();
3082e5dd7070Spatrick   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
3083e5dd7070Spatrick                          IsSystem);
3084e5dd7070Spatrick   bool Result = Parser.parseModuleMapFile();
3085e5dd7070Spatrick   ParsedModuleMap[File] = Result;
3086e5dd7070Spatrick 
3087e5dd7070Spatrick   if (Offset) {
3088e5dd7070Spatrick     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
3089e5dd7070Spatrick     assert(Loc.first == ID && "stopped in a different file?");
3090e5dd7070Spatrick     *Offset = Loc.second;
3091e5dd7070Spatrick   }
3092e5dd7070Spatrick 
3093e5dd7070Spatrick   // Notify callbacks that we parsed it.
3094e5dd7070Spatrick   for (const auto &Cb : Callbacks)
3095e5dd7070Spatrick     Cb->moduleMapFileRead(Start, *File, IsSystem);
3096e5dd7070Spatrick 
3097e5dd7070Spatrick   return Result;
3098e5dd7070Spatrick }
3099