xref: /minix3/external/bsd/llvm/dist/clang/lib/Lex/ModuleMap.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file defines the ModuleMap implementation, which describes the layout
11f4a2713aSLionel Sambuc // of a module as it relates to headers.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc #include "clang/Lex/ModuleMap.h"
15f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/Diagnostic.h"
17f4a2713aSLionel Sambuc #include "clang/Basic/DiagnosticOptions.h"
18f4a2713aSLionel Sambuc #include "clang/Basic/FileManager.h"
19f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
20f4a2713aSLionel Sambuc #include "clang/Basic/TargetOptions.h"
21f4a2713aSLionel Sambuc #include "clang/Lex/HeaderSearch.h"
22*0a6a1f1dSLionel Sambuc #include "clang/Lex/HeaderSearchOptions.h"
23f4a2713aSLionel Sambuc #include "clang/Lex/LexDiagnostic.h"
24f4a2713aSLionel Sambuc #include "clang/Lex/Lexer.h"
25f4a2713aSLionel Sambuc #include "clang/Lex/LiteralSupport.h"
26f4a2713aSLionel Sambuc #include "llvm/ADT/StringRef.h"
27f4a2713aSLionel Sambuc #include "llvm/ADT/StringSwitch.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/Allocator.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/FileSystem.h"
30f4a2713aSLionel Sambuc #include "llvm/Support/Host.h"
31f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
32f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
33f4a2713aSLionel Sambuc #include <stdlib.h>
34f4a2713aSLionel Sambuc #if defined(LLVM_ON_UNIX)
35f4a2713aSLionel Sambuc #include <limits.h>
36f4a2713aSLionel Sambuc #endif
37f4a2713aSLionel Sambuc using namespace clang;
38f4a2713aSLionel Sambuc 
39f4a2713aSLionel Sambuc Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const40f4a2713aSLionel Sambuc ModuleMap::resolveExport(Module *Mod,
41f4a2713aSLionel Sambuc                          const Module::UnresolvedExportDecl &Unresolved,
42f4a2713aSLionel Sambuc                          bool Complain) const {
43f4a2713aSLionel Sambuc   // We may have just a wildcard.
44f4a2713aSLionel Sambuc   if (Unresolved.Id.empty()) {
45f4a2713aSLionel Sambuc     assert(Unresolved.Wildcard && "Invalid unresolved export");
46*0a6a1f1dSLionel Sambuc     return Module::ExportDecl(nullptr, true);
47f4a2713aSLionel Sambuc   }
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc   // Resolve the module-id.
50f4a2713aSLionel Sambuc   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
51f4a2713aSLionel Sambuc   if (!Context)
52f4a2713aSLionel Sambuc     return Module::ExportDecl();
53f4a2713aSLionel Sambuc 
54f4a2713aSLionel Sambuc   return Module::ExportDecl(Context, Unresolved.Wildcard);
55f4a2713aSLionel Sambuc }
56f4a2713aSLionel Sambuc 
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const57f4a2713aSLionel Sambuc Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
58f4a2713aSLionel Sambuc                                    bool Complain) const {
59f4a2713aSLionel Sambuc   // Find the starting module.
60f4a2713aSLionel Sambuc   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
61f4a2713aSLionel Sambuc   if (!Context) {
62f4a2713aSLionel Sambuc     if (Complain)
63*0a6a1f1dSLionel Sambuc       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
64f4a2713aSLionel Sambuc       << Id[0].first << Mod->getFullModuleName();
65f4a2713aSLionel Sambuc 
66*0a6a1f1dSLionel Sambuc     return nullptr;
67f4a2713aSLionel Sambuc   }
68f4a2713aSLionel Sambuc 
69f4a2713aSLionel Sambuc   // Dig into the module path.
70f4a2713aSLionel Sambuc   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
71f4a2713aSLionel Sambuc     Module *Sub = lookupModuleQualified(Id[I].first, Context);
72f4a2713aSLionel Sambuc     if (!Sub) {
73f4a2713aSLionel Sambuc       if (Complain)
74*0a6a1f1dSLionel Sambuc         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
75f4a2713aSLionel Sambuc         << Id[I].first << Context->getFullModuleName()
76f4a2713aSLionel Sambuc         << SourceRange(Id[0].second, Id[I-1].second);
77f4a2713aSLionel Sambuc 
78*0a6a1f1dSLionel Sambuc       return nullptr;
79f4a2713aSLionel Sambuc     }
80f4a2713aSLionel Sambuc 
81f4a2713aSLionel Sambuc     Context = Sub;
82f4a2713aSLionel Sambuc   }
83f4a2713aSLionel Sambuc 
84f4a2713aSLionel Sambuc   return Context;
85f4a2713aSLionel Sambuc }
86f4a2713aSLionel Sambuc 
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)87*0a6a1f1dSLionel Sambuc ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
88f4a2713aSLionel Sambuc                      const LangOptions &LangOpts, const TargetInfo *Target,
89f4a2713aSLionel Sambuc                      HeaderSearch &HeaderInfo)
90*0a6a1f1dSLionel Sambuc     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
91*0a6a1f1dSLionel Sambuc       HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
92*0a6a1f1dSLionel Sambuc       CompilingModule(nullptr), SourceModule(nullptr) {}
93f4a2713aSLionel Sambuc 
~ModuleMap()94f4a2713aSLionel Sambuc ModuleMap::~ModuleMap() {
95f4a2713aSLionel Sambuc   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
96f4a2713aSLionel Sambuc                                         IEnd = Modules.end();
97f4a2713aSLionel Sambuc        I != IEnd; ++I) {
98f4a2713aSLionel Sambuc     delete I->getValue();
99f4a2713aSLionel Sambuc   }
100f4a2713aSLionel Sambuc }
101f4a2713aSLionel Sambuc 
setTarget(const TargetInfo & Target)102f4a2713aSLionel Sambuc void ModuleMap::setTarget(const TargetInfo &Target) {
103f4a2713aSLionel Sambuc   assert((!this->Target || this->Target == &Target) &&
104f4a2713aSLionel Sambuc          "Improper target override");
105f4a2713aSLionel Sambuc   this->Target = &Target;
106f4a2713aSLionel Sambuc }
107f4a2713aSLionel Sambuc 
108f4a2713aSLionel Sambuc /// \brief "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)109f4a2713aSLionel Sambuc static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
110f4a2713aSLionel Sambuc                                               SmallVectorImpl<char> &Buffer) {
111f4a2713aSLionel Sambuc   if (Name.empty())
112f4a2713aSLionel Sambuc     return Name;
113f4a2713aSLionel Sambuc 
114f4a2713aSLionel Sambuc   if (!isValidIdentifier(Name)) {
115f4a2713aSLionel Sambuc     // If we don't already have something with the form of an identifier,
116f4a2713aSLionel Sambuc     // create a buffer with the sanitized name.
117f4a2713aSLionel Sambuc     Buffer.clear();
118f4a2713aSLionel Sambuc     if (isDigit(Name[0]))
119f4a2713aSLionel Sambuc       Buffer.push_back('_');
120f4a2713aSLionel Sambuc     Buffer.reserve(Buffer.size() + Name.size());
121f4a2713aSLionel Sambuc     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
122f4a2713aSLionel Sambuc       if (isIdentifierBody(Name[I]))
123f4a2713aSLionel Sambuc         Buffer.push_back(Name[I]);
124f4a2713aSLionel Sambuc       else
125f4a2713aSLionel Sambuc         Buffer.push_back('_');
126f4a2713aSLionel Sambuc     }
127f4a2713aSLionel Sambuc 
128f4a2713aSLionel Sambuc     Name = StringRef(Buffer.data(), Buffer.size());
129f4a2713aSLionel Sambuc   }
130f4a2713aSLionel Sambuc 
131f4a2713aSLionel Sambuc   while (llvm::StringSwitch<bool>(Name)
132f4a2713aSLionel Sambuc #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
133f4a2713aSLionel Sambuc #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
134f4a2713aSLionel Sambuc #include "clang/Basic/TokenKinds.def"
135f4a2713aSLionel Sambuc            .Default(false)) {
136f4a2713aSLionel Sambuc     if (Name.data() != Buffer.data())
137f4a2713aSLionel Sambuc       Buffer.append(Name.begin(), Name.end());
138f4a2713aSLionel Sambuc     Buffer.push_back('_');
139f4a2713aSLionel Sambuc     Name = StringRef(Buffer.data(), Buffer.size());
140f4a2713aSLionel Sambuc   }
141f4a2713aSLionel Sambuc 
142f4a2713aSLionel Sambuc   return Name;
143f4a2713aSLionel Sambuc }
144f4a2713aSLionel Sambuc 
145f4a2713aSLionel Sambuc /// \brief Determine whether the given file name is the name of a builtin
146f4a2713aSLionel Sambuc /// header, supplied by Clang to replace, override, or augment existing system
147f4a2713aSLionel Sambuc /// headers.
isBuiltinHeader(StringRef FileName)148f4a2713aSLionel Sambuc static bool isBuiltinHeader(StringRef FileName) {
149f4a2713aSLionel Sambuc   return llvm::StringSwitch<bool>(FileName)
150f4a2713aSLionel Sambuc            .Case("float.h", true)
151f4a2713aSLionel Sambuc            .Case("iso646.h", true)
152f4a2713aSLionel Sambuc            .Case("limits.h", true)
153f4a2713aSLionel Sambuc            .Case("stdalign.h", true)
154f4a2713aSLionel Sambuc            .Case("stdarg.h", true)
155f4a2713aSLionel Sambuc            .Case("stdbool.h", true)
156f4a2713aSLionel Sambuc            .Case("stddef.h", true)
157f4a2713aSLionel Sambuc            .Case("stdint.h", true)
158f4a2713aSLionel Sambuc            .Case("tgmath.h", true)
159f4a2713aSLionel Sambuc            .Case("unwind.h", true)
160f4a2713aSLionel Sambuc            .Default(false);
161f4a2713aSLionel Sambuc }
162f4a2713aSLionel Sambuc 
163*0a6a1f1dSLionel Sambuc ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)164*0a6a1f1dSLionel Sambuc ModuleMap::findKnownHeader(const FileEntry *File) {
165f4a2713aSLionel Sambuc   HeadersMap::iterator Known = Headers.find(File);
166*0a6a1f1dSLionel Sambuc   if (Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
167f4a2713aSLionel Sambuc       isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
168f4a2713aSLionel Sambuc     HeaderInfo.loadTopLevelSystemModules();
169*0a6a1f1dSLionel Sambuc     return Headers.find(File);
170*0a6a1f1dSLionel Sambuc   }
171*0a6a1f1dSLionel Sambuc   return Known;
172f4a2713aSLionel Sambuc }
173f4a2713aSLionel Sambuc 
174*0a6a1f1dSLionel Sambuc ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)175*0a6a1f1dSLionel Sambuc ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
176*0a6a1f1dSLionel Sambuc                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
177f4a2713aSLionel Sambuc   const DirectoryEntry *Dir = File->getDir();
178*0a6a1f1dSLionel Sambuc   assert(Dir && "file in no directory");
179f4a2713aSLionel Sambuc 
180f4a2713aSLionel Sambuc   // Note: as an egregious but useful hack we use the real path here, because
181f4a2713aSLionel Sambuc   // frameworks moving from top-level frameworks to embedded frameworks tend
182f4a2713aSLionel Sambuc   // to be symlinked from the top-level location to the embedded location,
183f4a2713aSLionel Sambuc   // and we need to resolve lookups as if we had found the embedded location.
184f4a2713aSLionel Sambuc   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
185f4a2713aSLionel Sambuc 
186f4a2713aSLionel Sambuc   // Keep walking up the directory hierarchy, looking for a directory with
187f4a2713aSLionel Sambuc   // an umbrella header.
188f4a2713aSLionel Sambuc   do {
189*0a6a1f1dSLionel Sambuc     auto KnownDir = UmbrellaDirs.find(Dir);
190*0a6a1f1dSLionel Sambuc     if (KnownDir != UmbrellaDirs.end())
191*0a6a1f1dSLionel Sambuc       return KnownHeader(KnownDir->second, NormalHeader);
192*0a6a1f1dSLionel Sambuc 
193*0a6a1f1dSLionel Sambuc     IntermediateDirs.push_back(Dir);
194*0a6a1f1dSLionel Sambuc 
195*0a6a1f1dSLionel Sambuc     // Retrieve our parent path.
196*0a6a1f1dSLionel Sambuc     DirName = llvm::sys::path::parent_path(DirName);
197*0a6a1f1dSLionel Sambuc     if (DirName.empty())
198*0a6a1f1dSLionel Sambuc       break;
199*0a6a1f1dSLionel Sambuc 
200*0a6a1f1dSLionel Sambuc     // Resolve the parent path to a directory entry.
201*0a6a1f1dSLionel Sambuc     Dir = SourceMgr.getFileManager().getDirectory(DirName);
202*0a6a1f1dSLionel Sambuc   } while (Dir);
203*0a6a1f1dSLionel Sambuc   return KnownHeader();
204*0a6a1f1dSLionel Sambuc }
205*0a6a1f1dSLionel Sambuc 
206*0a6a1f1dSLionel Sambuc // Returns true if RequestingModule directly uses RequestedModule.
directlyUses(const Module * RequestingModule,const Module * RequestedModule)207*0a6a1f1dSLionel Sambuc static bool directlyUses(const Module *RequestingModule,
208*0a6a1f1dSLionel Sambuc                          const Module *RequestedModule) {
209*0a6a1f1dSLionel Sambuc   return std::find(RequestingModule->DirectUses.begin(),
210*0a6a1f1dSLionel Sambuc                    RequestingModule->DirectUses.end(),
211*0a6a1f1dSLionel Sambuc                    RequestedModule) != RequestingModule->DirectUses.end();
212*0a6a1f1dSLionel Sambuc }
213*0a6a1f1dSLionel Sambuc 
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::ModuleHeaderRole Role,Module * RequestedModule)214*0a6a1f1dSLionel Sambuc static bool violatesPrivateInclude(Module *RequestingModule,
215*0a6a1f1dSLionel Sambuc                                    const FileEntry *IncFileEnt,
216*0a6a1f1dSLionel Sambuc                                    ModuleMap::ModuleHeaderRole Role,
217*0a6a1f1dSLionel Sambuc                                    Module *RequestedModule) {
218*0a6a1f1dSLionel Sambuc   bool IsPrivateRole = Role & ModuleMap::PrivateHeader;
219*0a6a1f1dSLionel Sambuc #ifndef NDEBUG
220*0a6a1f1dSLionel Sambuc   // Check for consistency between the module header role
221*0a6a1f1dSLionel Sambuc   // as obtained from the lookup and as obtained from the module.
222*0a6a1f1dSLionel Sambuc   // This check is not cheap, so enable it only for debugging.
223*0a6a1f1dSLionel Sambuc   bool IsPrivate = false;
224*0a6a1f1dSLionel Sambuc   SmallVectorImpl<Module::Header> *HeaderList[] =
225*0a6a1f1dSLionel Sambuc       {&RequestedModule->Headers[Module::HK_Private],
226*0a6a1f1dSLionel Sambuc        &RequestedModule->Headers[Module::HK_PrivateTextual]};
227*0a6a1f1dSLionel Sambuc   for (auto *Hdrs : HeaderList)
228*0a6a1f1dSLionel Sambuc     IsPrivate |=
229*0a6a1f1dSLionel Sambuc         std::find_if(Hdrs->begin(), Hdrs->end(), [&](const Module::Header &H) {
230*0a6a1f1dSLionel Sambuc           return H.Entry == IncFileEnt;
231*0a6a1f1dSLionel Sambuc         }) != Hdrs->end();
232*0a6a1f1dSLionel Sambuc   assert(IsPrivate == IsPrivateRole && "inconsistent headers and roles");
233*0a6a1f1dSLionel Sambuc #endif
234*0a6a1f1dSLionel Sambuc   return IsPrivateRole &&
235*0a6a1f1dSLionel Sambuc          RequestedModule->getTopLevelModule() != RequestingModule;
236*0a6a1f1dSLionel Sambuc }
237*0a6a1f1dSLionel Sambuc 
getTopLevelOrNull(Module * M)238*0a6a1f1dSLionel Sambuc static Module *getTopLevelOrNull(Module *M) {
239*0a6a1f1dSLionel Sambuc   return M ? M->getTopLevelModule() : nullptr;
240*0a6a1f1dSLionel Sambuc }
241*0a6a1f1dSLionel Sambuc 
diagnoseHeaderInclusion(Module * RequestingModule,SourceLocation FilenameLoc,StringRef Filename,const FileEntry * File)242*0a6a1f1dSLionel Sambuc void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
243*0a6a1f1dSLionel Sambuc                                         SourceLocation FilenameLoc,
244*0a6a1f1dSLionel Sambuc                                         StringRef Filename,
245*0a6a1f1dSLionel Sambuc                                         const FileEntry *File) {
246*0a6a1f1dSLionel Sambuc   // No errors for indirect modules. This may be a bit of a problem for modules
247*0a6a1f1dSLionel Sambuc   // with no source files.
248*0a6a1f1dSLionel Sambuc   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
249*0a6a1f1dSLionel Sambuc     return;
250*0a6a1f1dSLionel Sambuc 
251*0a6a1f1dSLionel Sambuc   if (RequestingModule)
252*0a6a1f1dSLionel Sambuc     resolveUses(RequestingModule, /*Complain=*/false);
253*0a6a1f1dSLionel Sambuc 
254*0a6a1f1dSLionel Sambuc   bool Excluded = false;
255*0a6a1f1dSLionel Sambuc   Module *Private = nullptr;
256*0a6a1f1dSLionel Sambuc   Module *NotUsed = nullptr;
257*0a6a1f1dSLionel Sambuc 
258*0a6a1f1dSLionel Sambuc   HeadersMap::iterator Known = findKnownHeader(File);
259*0a6a1f1dSLionel Sambuc   if (Known != Headers.end()) {
260*0a6a1f1dSLionel Sambuc     for (const KnownHeader &Header : Known->second) {
261*0a6a1f1dSLionel Sambuc       // If 'File' is part of 'RequestingModule' we can definitely include it.
262*0a6a1f1dSLionel Sambuc       if (Header.getModule() == RequestingModule)
263*0a6a1f1dSLionel Sambuc         return;
264*0a6a1f1dSLionel Sambuc 
265*0a6a1f1dSLionel Sambuc       // Remember private headers for later printing of a diagnostic.
266*0a6a1f1dSLionel Sambuc       if (violatesPrivateInclude(RequestingModule, File, Header.getRole(),
267*0a6a1f1dSLionel Sambuc                                  Header.getModule())) {
268*0a6a1f1dSLionel Sambuc         Private = Header.getModule();
269*0a6a1f1dSLionel Sambuc         continue;
270*0a6a1f1dSLionel Sambuc       }
271*0a6a1f1dSLionel Sambuc 
272*0a6a1f1dSLionel Sambuc       // If uses need to be specified explicitly, we are only allowed to return
273*0a6a1f1dSLionel Sambuc       // modules that are explicitly used by the requesting module.
274*0a6a1f1dSLionel Sambuc       if (RequestingModule && LangOpts.ModulesDeclUse &&
275*0a6a1f1dSLionel Sambuc           !directlyUses(RequestingModule, Header.getModule())) {
276*0a6a1f1dSLionel Sambuc         NotUsed = Header.getModule();
277*0a6a1f1dSLionel Sambuc         continue;
278*0a6a1f1dSLionel Sambuc       }
279*0a6a1f1dSLionel Sambuc 
280*0a6a1f1dSLionel Sambuc       // We have found a module that we can happily use.
281*0a6a1f1dSLionel Sambuc       return;
282*0a6a1f1dSLionel Sambuc     }
283*0a6a1f1dSLionel Sambuc 
284*0a6a1f1dSLionel Sambuc     Excluded = true;
285*0a6a1f1dSLionel Sambuc   }
286*0a6a1f1dSLionel Sambuc 
287*0a6a1f1dSLionel Sambuc   // We have found a header, but it is private.
288*0a6a1f1dSLionel Sambuc   if (Private) {
289*0a6a1f1dSLionel Sambuc     Diags.Report(FilenameLoc, diag::error_use_of_private_header_outside_module)
290*0a6a1f1dSLionel Sambuc         << Filename;
291*0a6a1f1dSLionel Sambuc     return;
292*0a6a1f1dSLionel Sambuc   }
293*0a6a1f1dSLionel Sambuc 
294*0a6a1f1dSLionel Sambuc   // We have found a module, but we don't use it.
295*0a6a1f1dSLionel Sambuc   if (NotUsed) {
296*0a6a1f1dSLionel Sambuc     Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
297*0a6a1f1dSLionel Sambuc         << RequestingModule->getFullModuleName() << Filename;
298*0a6a1f1dSLionel Sambuc     return;
299*0a6a1f1dSLionel Sambuc   }
300*0a6a1f1dSLionel Sambuc 
301*0a6a1f1dSLionel Sambuc   if (Excluded || isHeaderInUmbrellaDirs(File))
302*0a6a1f1dSLionel Sambuc     return;
303*0a6a1f1dSLionel Sambuc 
304*0a6a1f1dSLionel Sambuc   // At this point, only non-modular includes remain.
305*0a6a1f1dSLionel Sambuc 
306*0a6a1f1dSLionel Sambuc   if (LangOpts.ModulesStrictDeclUse) {
307*0a6a1f1dSLionel Sambuc     Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
308*0a6a1f1dSLionel Sambuc         << RequestingModule->getFullModuleName() << Filename;
309*0a6a1f1dSLionel Sambuc   } else if (RequestingModule) {
310*0a6a1f1dSLionel Sambuc     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
311*0a6a1f1dSLionel Sambuc         diag::warn_non_modular_include_in_framework_module :
312*0a6a1f1dSLionel Sambuc         diag::warn_non_modular_include_in_module;
313*0a6a1f1dSLionel Sambuc     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName();
314*0a6a1f1dSLionel Sambuc   }
315*0a6a1f1dSLionel Sambuc }
316*0a6a1f1dSLionel Sambuc 
317*0a6a1f1dSLionel Sambuc ModuleMap::KnownHeader
findModuleForHeader(const FileEntry * File,Module * RequestingModule,bool IncludeTextualHeaders)318*0a6a1f1dSLionel Sambuc ModuleMap::findModuleForHeader(const FileEntry *File,
319*0a6a1f1dSLionel Sambuc                                Module *RequestingModule,
320*0a6a1f1dSLionel Sambuc                                bool IncludeTextualHeaders) {
321*0a6a1f1dSLionel Sambuc   HeadersMap::iterator Known = findKnownHeader(File);
322*0a6a1f1dSLionel Sambuc 
323*0a6a1f1dSLionel Sambuc   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
324*0a6a1f1dSLionel Sambuc     if (!IncludeTextualHeaders && (R.getRole() & ModuleMap::TextualHeader))
325*0a6a1f1dSLionel Sambuc       return ModuleMap::KnownHeader();
326*0a6a1f1dSLionel Sambuc     return R;
327*0a6a1f1dSLionel Sambuc   };
328*0a6a1f1dSLionel Sambuc 
329*0a6a1f1dSLionel Sambuc   if (Known != Headers.end()) {
330*0a6a1f1dSLionel Sambuc     ModuleMap::KnownHeader Result;
331*0a6a1f1dSLionel Sambuc 
332*0a6a1f1dSLionel Sambuc     // Iterate over all modules that 'File' is part of to find the best fit.
333*0a6a1f1dSLionel Sambuc     for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(),
334*0a6a1f1dSLionel Sambuc                                                 E = Known->second.end();
335*0a6a1f1dSLionel Sambuc          I != E; ++I) {
336*0a6a1f1dSLionel Sambuc       // Cannot use a module if it is unavailable.
337*0a6a1f1dSLionel Sambuc       if (!I->getModule()->isAvailable())
338*0a6a1f1dSLionel Sambuc         continue;
339*0a6a1f1dSLionel Sambuc 
340*0a6a1f1dSLionel Sambuc       // If 'File' is part of 'RequestingModule', 'RequestingModule' is the
341*0a6a1f1dSLionel Sambuc       // module we are looking for.
342*0a6a1f1dSLionel Sambuc       if (I->getModule() == RequestingModule)
343*0a6a1f1dSLionel Sambuc         return MakeResult(*I);
344*0a6a1f1dSLionel Sambuc 
345*0a6a1f1dSLionel Sambuc       // If uses need to be specified explicitly, we are only allowed to return
346*0a6a1f1dSLionel Sambuc       // modules that are explicitly used by the requesting module.
347*0a6a1f1dSLionel Sambuc       if (RequestingModule && LangOpts.ModulesDeclUse &&
348*0a6a1f1dSLionel Sambuc           !directlyUses(RequestingModule, I->getModule()))
349*0a6a1f1dSLionel Sambuc         continue;
350*0a6a1f1dSLionel Sambuc 
351*0a6a1f1dSLionel Sambuc       // Prefer a public header over a private header.
352*0a6a1f1dSLionel Sambuc       if (!Result || (Result.getRole() & ModuleMap::PrivateHeader))
353*0a6a1f1dSLionel Sambuc         Result = *I;
354*0a6a1f1dSLionel Sambuc     }
355*0a6a1f1dSLionel Sambuc     return MakeResult(Result);
356*0a6a1f1dSLionel Sambuc   }
357*0a6a1f1dSLionel Sambuc 
358*0a6a1f1dSLionel Sambuc   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
359*0a6a1f1dSLionel Sambuc   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
360*0a6a1f1dSLionel Sambuc   if (H) {
361*0a6a1f1dSLionel Sambuc     Module *Result = H.getModule();
362f4a2713aSLionel Sambuc 
363f4a2713aSLionel Sambuc     // Search up the module stack until we find a module with an umbrella
364f4a2713aSLionel Sambuc     // directory.
365f4a2713aSLionel Sambuc     Module *UmbrellaModule = Result;
366f4a2713aSLionel Sambuc     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
367f4a2713aSLionel Sambuc       UmbrellaModule = UmbrellaModule->Parent;
368f4a2713aSLionel Sambuc 
369f4a2713aSLionel Sambuc     if (UmbrellaModule->InferSubmodules) {
370*0a6a1f1dSLionel Sambuc       const FileEntry *UmbrellaModuleMap =
371*0a6a1f1dSLionel Sambuc           getModuleMapFileForUniquing(UmbrellaModule);
372*0a6a1f1dSLionel Sambuc 
373f4a2713aSLionel Sambuc       // Infer submodules for each of the directories we found between
374f4a2713aSLionel Sambuc       // the directory of the umbrella header and the directory where
375f4a2713aSLionel Sambuc       // the actual header is located.
376f4a2713aSLionel Sambuc       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
377f4a2713aSLionel Sambuc 
378f4a2713aSLionel Sambuc       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
379f4a2713aSLionel Sambuc         // Find or create the module that corresponds to this directory name.
380f4a2713aSLionel Sambuc         SmallString<32> NameBuf;
381f4a2713aSLionel Sambuc         StringRef Name = sanitizeFilenameAsIdentifier(
382*0a6a1f1dSLionel Sambuc             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
383f4a2713aSLionel Sambuc         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
384f4a2713aSLionel Sambuc                                     Explicit).first;
385*0a6a1f1dSLionel Sambuc         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
386*0a6a1f1dSLionel Sambuc         Result->IsInferred = true;
387f4a2713aSLionel Sambuc 
388f4a2713aSLionel Sambuc         // Associate the module and the directory.
389f4a2713aSLionel Sambuc         UmbrellaDirs[SkippedDirs[I-1]] = Result;
390f4a2713aSLionel Sambuc 
391f4a2713aSLionel Sambuc         // If inferred submodules export everything they import, add a
392f4a2713aSLionel Sambuc         // wildcard to the set of exports.
393f4a2713aSLionel Sambuc         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
394*0a6a1f1dSLionel Sambuc           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
395f4a2713aSLionel Sambuc       }
396f4a2713aSLionel Sambuc 
397f4a2713aSLionel Sambuc       // Infer a submodule with the same name as this header file.
398f4a2713aSLionel Sambuc       SmallString<32> NameBuf;
399f4a2713aSLionel Sambuc       StringRef Name = sanitizeFilenameAsIdentifier(
400f4a2713aSLionel Sambuc                          llvm::sys::path::stem(File->getName()), NameBuf);
401f4a2713aSLionel Sambuc       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
402f4a2713aSLionel Sambuc                                   Explicit).first;
403*0a6a1f1dSLionel Sambuc       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
404*0a6a1f1dSLionel Sambuc       Result->IsInferred = true;
405f4a2713aSLionel Sambuc       Result->addTopHeader(File);
406f4a2713aSLionel Sambuc 
407f4a2713aSLionel Sambuc       // If inferred submodules export everything they import, add a
408f4a2713aSLionel Sambuc       // wildcard to the set of exports.
409f4a2713aSLionel Sambuc       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
410*0a6a1f1dSLionel Sambuc         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
411f4a2713aSLionel Sambuc     } else {
412f4a2713aSLionel Sambuc       // Record each of the directories we stepped through as being part of
413f4a2713aSLionel Sambuc       // the module we found, since the umbrella header covers them all.
414f4a2713aSLionel Sambuc       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
415f4a2713aSLionel Sambuc         UmbrellaDirs[SkippedDirs[I]] = Result;
416f4a2713aSLionel Sambuc     }
417f4a2713aSLionel Sambuc 
418f4a2713aSLionel Sambuc     Headers[File].push_back(KnownHeader(Result, NormalHeader));
419f4a2713aSLionel Sambuc 
420f4a2713aSLionel Sambuc     // If a header corresponds to an unavailable module, don't report
421f4a2713aSLionel Sambuc     // that it maps to anything.
422f4a2713aSLionel Sambuc     if (!Result->isAvailable())
423f4a2713aSLionel Sambuc       return KnownHeader();
424f4a2713aSLionel Sambuc 
425*0a6a1f1dSLionel Sambuc     return MakeResult(Headers[File].back());
426f4a2713aSLionel Sambuc   }
427f4a2713aSLionel Sambuc 
428f4a2713aSLionel Sambuc   return KnownHeader();
429f4a2713aSLionel Sambuc }
430f4a2713aSLionel Sambuc 
isHeaderInUnavailableModule(const FileEntry * Header) const431f4a2713aSLionel Sambuc bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
432*0a6a1f1dSLionel Sambuc   return isHeaderUnavailableInModule(Header, nullptr);
433*0a6a1f1dSLionel Sambuc }
434*0a6a1f1dSLionel Sambuc 
435*0a6a1f1dSLionel Sambuc bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const436*0a6a1f1dSLionel Sambuc ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
437*0a6a1f1dSLionel Sambuc                                        const Module *RequestingModule) const {
438f4a2713aSLionel Sambuc   HeadersMap::const_iterator Known = Headers.find(Header);
439f4a2713aSLionel Sambuc   if (Known != Headers.end()) {
440f4a2713aSLionel Sambuc     for (SmallVectorImpl<KnownHeader>::const_iterator
441f4a2713aSLionel Sambuc              I = Known->second.begin(),
442f4a2713aSLionel Sambuc              E = Known->second.end();
443f4a2713aSLionel Sambuc          I != E; ++I) {
444*0a6a1f1dSLionel Sambuc       if (I->isAvailable() && (!RequestingModule ||
445*0a6a1f1dSLionel Sambuc                                I->getModule()->isSubModuleOf(RequestingModule)))
446f4a2713aSLionel Sambuc         return false;
447f4a2713aSLionel Sambuc     }
448f4a2713aSLionel Sambuc     return true;
449f4a2713aSLionel Sambuc   }
450f4a2713aSLionel Sambuc 
451f4a2713aSLionel Sambuc   const DirectoryEntry *Dir = Header->getDir();
452f4a2713aSLionel Sambuc   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
453f4a2713aSLionel Sambuc   StringRef DirName = Dir->getName();
454f4a2713aSLionel Sambuc 
455*0a6a1f1dSLionel Sambuc   auto IsUnavailable = [&](const Module *M) {
456*0a6a1f1dSLionel Sambuc     return !M->isAvailable() && (!RequestingModule ||
457*0a6a1f1dSLionel Sambuc                                  M->isSubModuleOf(RequestingModule));
458*0a6a1f1dSLionel Sambuc   };
459*0a6a1f1dSLionel Sambuc 
460f4a2713aSLionel Sambuc   // Keep walking up the directory hierarchy, looking for a directory with
461f4a2713aSLionel Sambuc   // an umbrella header.
462f4a2713aSLionel Sambuc   do {
463f4a2713aSLionel Sambuc     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
464f4a2713aSLionel Sambuc       = UmbrellaDirs.find(Dir);
465f4a2713aSLionel Sambuc     if (KnownDir != UmbrellaDirs.end()) {
466f4a2713aSLionel Sambuc       Module *Found = KnownDir->second;
467*0a6a1f1dSLionel Sambuc       if (IsUnavailable(Found))
468f4a2713aSLionel Sambuc         return true;
469f4a2713aSLionel Sambuc 
470f4a2713aSLionel Sambuc       // Search up the module stack until we find a module with an umbrella
471f4a2713aSLionel Sambuc       // directory.
472f4a2713aSLionel Sambuc       Module *UmbrellaModule = Found;
473f4a2713aSLionel Sambuc       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
474f4a2713aSLionel Sambuc         UmbrellaModule = UmbrellaModule->Parent;
475f4a2713aSLionel Sambuc 
476f4a2713aSLionel Sambuc       if (UmbrellaModule->InferSubmodules) {
477f4a2713aSLionel Sambuc         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
478f4a2713aSLionel Sambuc           // Find or create the module that corresponds to this directory name.
479f4a2713aSLionel Sambuc           SmallString<32> NameBuf;
480f4a2713aSLionel Sambuc           StringRef Name = sanitizeFilenameAsIdentifier(
481f4a2713aSLionel Sambuc                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
482f4a2713aSLionel Sambuc                              NameBuf);
483f4a2713aSLionel Sambuc           Found = lookupModuleQualified(Name, Found);
484f4a2713aSLionel Sambuc           if (!Found)
485f4a2713aSLionel Sambuc             return false;
486*0a6a1f1dSLionel Sambuc           if (IsUnavailable(Found))
487f4a2713aSLionel Sambuc             return true;
488f4a2713aSLionel Sambuc         }
489f4a2713aSLionel Sambuc 
490f4a2713aSLionel Sambuc         // Infer a submodule with the same name as this header file.
491f4a2713aSLionel Sambuc         SmallString<32> NameBuf;
492f4a2713aSLionel Sambuc         StringRef Name = sanitizeFilenameAsIdentifier(
493f4a2713aSLionel Sambuc                            llvm::sys::path::stem(Header->getName()),
494f4a2713aSLionel Sambuc                            NameBuf);
495f4a2713aSLionel Sambuc         Found = lookupModuleQualified(Name, Found);
496f4a2713aSLionel Sambuc         if (!Found)
497f4a2713aSLionel Sambuc           return false;
498f4a2713aSLionel Sambuc       }
499f4a2713aSLionel Sambuc 
500*0a6a1f1dSLionel Sambuc       return IsUnavailable(Found);
501f4a2713aSLionel Sambuc     }
502f4a2713aSLionel Sambuc 
503f4a2713aSLionel Sambuc     SkippedDirs.push_back(Dir);
504f4a2713aSLionel Sambuc 
505f4a2713aSLionel Sambuc     // Retrieve our parent path.
506f4a2713aSLionel Sambuc     DirName = llvm::sys::path::parent_path(DirName);
507f4a2713aSLionel Sambuc     if (DirName.empty())
508f4a2713aSLionel Sambuc       break;
509f4a2713aSLionel Sambuc 
510f4a2713aSLionel Sambuc     // Resolve the parent path to a directory entry.
511f4a2713aSLionel Sambuc     Dir = SourceMgr.getFileManager().getDirectory(DirName);
512f4a2713aSLionel Sambuc   } while (Dir);
513f4a2713aSLionel Sambuc 
514f4a2713aSLionel Sambuc   return false;
515f4a2713aSLionel Sambuc }
516f4a2713aSLionel Sambuc 
findModule(StringRef Name) const517f4a2713aSLionel Sambuc Module *ModuleMap::findModule(StringRef Name) const {
518f4a2713aSLionel Sambuc   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
519f4a2713aSLionel Sambuc   if (Known != Modules.end())
520f4a2713aSLionel Sambuc     return Known->getValue();
521f4a2713aSLionel Sambuc 
522*0a6a1f1dSLionel Sambuc   return nullptr;
523f4a2713aSLionel Sambuc }
524f4a2713aSLionel Sambuc 
lookupModuleUnqualified(StringRef Name,Module * Context) const525f4a2713aSLionel Sambuc Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
526f4a2713aSLionel Sambuc                                            Module *Context) const {
527f4a2713aSLionel Sambuc   for(; Context; Context = Context->Parent) {
528f4a2713aSLionel Sambuc     if (Module *Sub = lookupModuleQualified(Name, Context))
529f4a2713aSLionel Sambuc       return Sub;
530f4a2713aSLionel Sambuc   }
531f4a2713aSLionel Sambuc 
532f4a2713aSLionel Sambuc   return findModule(Name);
533f4a2713aSLionel Sambuc }
534f4a2713aSLionel Sambuc 
lookupModuleQualified(StringRef Name,Module * Context) const535f4a2713aSLionel Sambuc Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
536f4a2713aSLionel Sambuc   if (!Context)
537f4a2713aSLionel Sambuc     return findModule(Name);
538f4a2713aSLionel Sambuc 
539f4a2713aSLionel Sambuc   return Context->findSubmodule(Name);
540f4a2713aSLionel Sambuc }
541f4a2713aSLionel Sambuc 
542f4a2713aSLionel Sambuc std::pair<Module *, bool>
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)543f4a2713aSLionel Sambuc ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
544f4a2713aSLionel Sambuc                               bool IsExplicit) {
545f4a2713aSLionel Sambuc   // Try to find an existing module with this name.
546f4a2713aSLionel Sambuc   if (Module *Sub = lookupModuleQualified(Name, Parent))
547f4a2713aSLionel Sambuc     return std::make_pair(Sub, false);
548f4a2713aSLionel Sambuc 
549f4a2713aSLionel Sambuc   // Create a new module with this name.
550*0a6a1f1dSLionel Sambuc   Module *Result = new Module(Name, SourceLocation(), Parent,
551*0a6a1f1dSLionel Sambuc                               IsFramework, IsExplicit);
552f4a2713aSLionel Sambuc   if (LangOpts.CurrentModule == Name) {
553f4a2713aSLionel Sambuc     SourceModule = Result;
554f4a2713aSLionel Sambuc     SourceModuleName = Name;
555f4a2713aSLionel Sambuc   }
556f4a2713aSLionel Sambuc   if (!Parent) {
557f4a2713aSLionel Sambuc     Modules[Name] = Result;
558f4a2713aSLionel Sambuc     if (!LangOpts.CurrentModule.empty() && !CompilingModule &&
559f4a2713aSLionel Sambuc         Name == LangOpts.CurrentModule) {
560f4a2713aSLionel Sambuc       CompilingModule = Result;
561f4a2713aSLionel Sambuc     }
562f4a2713aSLionel Sambuc   }
563f4a2713aSLionel Sambuc   return std::make_pair(Result, true);
564f4a2713aSLionel Sambuc }
565f4a2713aSLionel Sambuc 
566f4a2713aSLionel Sambuc /// \brief For a framework module, infer the framework against which we
567f4a2713aSLionel Sambuc /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)568f4a2713aSLionel Sambuc static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
569f4a2713aSLionel Sambuc                                FileManager &FileMgr) {
570f4a2713aSLionel Sambuc   assert(Mod->IsFramework && "Can only infer linking for framework modules");
571f4a2713aSLionel Sambuc   assert(!Mod->isSubFramework() &&
572f4a2713aSLionel Sambuc          "Can only infer linking for top-level frameworks");
573f4a2713aSLionel Sambuc 
574f4a2713aSLionel Sambuc   SmallString<128> LibName;
575f4a2713aSLionel Sambuc   LibName += FrameworkDir->getName();
576f4a2713aSLionel Sambuc   llvm::sys::path::append(LibName, Mod->Name);
577f4a2713aSLionel Sambuc   if (FileMgr.getFile(LibName)) {
578f4a2713aSLionel Sambuc     Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
579f4a2713aSLionel Sambuc                                                      /*IsFramework=*/true));
580f4a2713aSLionel Sambuc   }
581f4a2713aSLionel Sambuc }
582f4a2713aSLionel Sambuc 
583f4a2713aSLionel Sambuc Module *
inferFrameworkModule(StringRef ModuleName,const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)584f4a2713aSLionel Sambuc ModuleMap::inferFrameworkModule(StringRef ModuleName,
585f4a2713aSLionel Sambuc                                 const DirectoryEntry *FrameworkDir,
586f4a2713aSLionel Sambuc                                 bool IsSystem,
587f4a2713aSLionel Sambuc                                 Module *Parent) {
588*0a6a1f1dSLionel Sambuc   Attributes Attrs;
589*0a6a1f1dSLionel Sambuc   Attrs.IsSystem = IsSystem;
590*0a6a1f1dSLionel Sambuc   return inferFrameworkModule(ModuleName, FrameworkDir, Attrs, Parent);
591*0a6a1f1dSLionel Sambuc }
592*0a6a1f1dSLionel Sambuc 
inferFrameworkModule(StringRef ModuleName,const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)593*0a6a1f1dSLionel Sambuc Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
594*0a6a1f1dSLionel Sambuc                                         const DirectoryEntry *FrameworkDir,
595*0a6a1f1dSLionel Sambuc                                         Attributes Attrs, Module *Parent) {
596*0a6a1f1dSLionel Sambuc 
597f4a2713aSLionel Sambuc   // Check whether we've already found this module.
598f4a2713aSLionel Sambuc   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
599f4a2713aSLionel Sambuc     return Mod;
600f4a2713aSLionel Sambuc 
601f4a2713aSLionel Sambuc   FileManager &FileMgr = SourceMgr.getFileManager();
602f4a2713aSLionel Sambuc 
603f4a2713aSLionel Sambuc   // If the framework has a parent path from which we're allowed to infer
604f4a2713aSLionel Sambuc   // a framework module, do so.
605*0a6a1f1dSLionel Sambuc   const FileEntry *ModuleMapFile = nullptr;
606f4a2713aSLionel Sambuc   if (!Parent) {
607f4a2713aSLionel Sambuc     // Determine whether we're allowed to infer a module map.
608f4a2713aSLionel Sambuc 
609f4a2713aSLionel Sambuc     // Note: as an egregious but useful hack we use the real path here, because
610f4a2713aSLionel Sambuc     // we might be looking at an embedded framework that symlinks out to a
611f4a2713aSLionel Sambuc     // top-level framework, and we need to infer as if we were naming the
612f4a2713aSLionel Sambuc     // top-level framework.
613f4a2713aSLionel Sambuc     StringRef FrameworkDirName
614f4a2713aSLionel Sambuc       = SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
615f4a2713aSLionel Sambuc 
616*0a6a1f1dSLionel Sambuc     // In case this is a case-insensitive filesystem, make sure the canonical
617*0a6a1f1dSLionel Sambuc     // directory name matches ModuleName exactly. Modules are case-sensitive.
618*0a6a1f1dSLionel Sambuc     // FIXME: we should be able to give a fix-it hint for the correct spelling.
619*0a6a1f1dSLionel Sambuc     if (llvm::sys::path::stem(FrameworkDirName) != ModuleName)
620*0a6a1f1dSLionel Sambuc       return nullptr;
621*0a6a1f1dSLionel Sambuc 
622f4a2713aSLionel Sambuc     bool canInfer = false;
623f4a2713aSLionel Sambuc     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
624f4a2713aSLionel Sambuc       // Figure out the parent path.
625f4a2713aSLionel Sambuc       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
626f4a2713aSLionel Sambuc       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
627f4a2713aSLionel Sambuc         // Check whether we have already looked into the parent directory
628f4a2713aSLionel Sambuc         // for a module map.
629f4a2713aSLionel Sambuc         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
630f4a2713aSLionel Sambuc           inferred = InferredDirectories.find(ParentDir);
631f4a2713aSLionel Sambuc         if (inferred == InferredDirectories.end()) {
632f4a2713aSLionel Sambuc           // We haven't looked here before. Load a module map, if there is
633f4a2713aSLionel Sambuc           // one.
634*0a6a1f1dSLionel Sambuc           bool IsFrameworkDir = Parent.endswith(".framework");
635*0a6a1f1dSLionel Sambuc           if (const FileEntry *ModMapFile =
636*0a6a1f1dSLionel Sambuc                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
637*0a6a1f1dSLionel Sambuc             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
638f4a2713aSLionel Sambuc             inferred = InferredDirectories.find(ParentDir);
639f4a2713aSLionel Sambuc           }
640f4a2713aSLionel Sambuc 
641f4a2713aSLionel Sambuc           if (inferred == InferredDirectories.end())
642f4a2713aSLionel Sambuc             inferred = InferredDirectories.insert(
643f4a2713aSLionel Sambuc                          std::make_pair(ParentDir, InferredDirectory())).first;
644f4a2713aSLionel Sambuc         }
645f4a2713aSLionel Sambuc 
646f4a2713aSLionel Sambuc         if (inferred->second.InferModules) {
647f4a2713aSLionel Sambuc           // We're allowed to infer for this directory, but make sure it's okay
648f4a2713aSLionel Sambuc           // to infer this particular module.
649f4a2713aSLionel Sambuc           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
650f4a2713aSLionel Sambuc           canInfer = std::find(inferred->second.ExcludedModules.begin(),
651f4a2713aSLionel Sambuc                                inferred->second.ExcludedModules.end(),
652f4a2713aSLionel Sambuc                                Name) == inferred->second.ExcludedModules.end();
653f4a2713aSLionel Sambuc 
654*0a6a1f1dSLionel Sambuc           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
655*0a6a1f1dSLionel Sambuc           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
656*0a6a1f1dSLionel Sambuc           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
657*0a6a1f1dSLionel Sambuc           ModuleMapFile = inferred->second.ModuleMapFile;
658f4a2713aSLionel Sambuc         }
659f4a2713aSLionel Sambuc       }
660f4a2713aSLionel Sambuc     }
661f4a2713aSLionel Sambuc 
662f4a2713aSLionel Sambuc     // If we're not allowed to infer a framework module, don't.
663f4a2713aSLionel Sambuc     if (!canInfer)
664*0a6a1f1dSLionel Sambuc       return nullptr;
665*0a6a1f1dSLionel Sambuc   } else
666*0a6a1f1dSLionel Sambuc     ModuleMapFile = getModuleMapFileForUniquing(Parent);
667f4a2713aSLionel Sambuc 
668f4a2713aSLionel Sambuc 
669f4a2713aSLionel Sambuc   // Look for an umbrella header.
670f4a2713aSLionel Sambuc   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
671f4a2713aSLionel Sambuc   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
672f4a2713aSLionel Sambuc   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
673f4a2713aSLionel Sambuc 
674f4a2713aSLionel Sambuc   // FIXME: If there's no umbrella header, we could probably scan the
675f4a2713aSLionel Sambuc   // framework to load *everything*. But, it's not clear that this is a good
676f4a2713aSLionel Sambuc   // idea.
677f4a2713aSLionel Sambuc   if (!UmbrellaHeader)
678*0a6a1f1dSLionel Sambuc     return nullptr;
679f4a2713aSLionel Sambuc 
680f4a2713aSLionel Sambuc   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
681f4a2713aSLionel Sambuc                               /*IsFramework=*/true, /*IsExplicit=*/false);
682*0a6a1f1dSLionel Sambuc   InferredModuleAllowedBy[Result] = ModuleMapFile;
683*0a6a1f1dSLionel Sambuc   Result->IsInferred = true;
684f4a2713aSLionel Sambuc   if (LangOpts.CurrentModule == ModuleName) {
685f4a2713aSLionel Sambuc     SourceModule = Result;
686f4a2713aSLionel Sambuc     SourceModuleName = ModuleName;
687f4a2713aSLionel Sambuc   }
688*0a6a1f1dSLionel Sambuc 
689*0a6a1f1dSLionel Sambuc   Result->IsSystem |= Attrs.IsSystem;
690*0a6a1f1dSLionel Sambuc   Result->IsExternC |= Attrs.IsExternC;
691*0a6a1f1dSLionel Sambuc   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
692f4a2713aSLionel Sambuc 
693f4a2713aSLionel Sambuc   if (!Parent)
694f4a2713aSLionel Sambuc     Modules[ModuleName] = Result;
695f4a2713aSLionel Sambuc 
696f4a2713aSLionel Sambuc   // umbrella header "umbrella-header-name"
697f4a2713aSLionel Sambuc   Result->Umbrella = UmbrellaHeader;
698f4a2713aSLionel Sambuc   Headers[UmbrellaHeader].push_back(KnownHeader(Result, NormalHeader));
699f4a2713aSLionel Sambuc   UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
700f4a2713aSLionel Sambuc 
701f4a2713aSLionel Sambuc   // export *
702*0a6a1f1dSLionel Sambuc   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
703f4a2713aSLionel Sambuc 
704f4a2713aSLionel Sambuc   // module * { export * }
705f4a2713aSLionel Sambuc   Result->InferSubmodules = true;
706f4a2713aSLionel Sambuc   Result->InferExportWildcard = true;
707f4a2713aSLionel Sambuc 
708f4a2713aSLionel Sambuc   // Look for subframeworks.
709*0a6a1f1dSLionel Sambuc   std::error_code EC;
710f4a2713aSLionel Sambuc   SmallString<128> SubframeworksDirName
711f4a2713aSLionel Sambuc     = StringRef(FrameworkDir->getName());
712f4a2713aSLionel Sambuc   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
713f4a2713aSLionel Sambuc   llvm::sys::path::native(SubframeworksDirName);
714f4a2713aSLionel Sambuc   for (llvm::sys::fs::directory_iterator
715f4a2713aSLionel Sambuc          Dir(SubframeworksDirName.str(), EC), DirEnd;
716f4a2713aSLionel Sambuc        Dir != DirEnd && !EC; Dir.increment(EC)) {
717f4a2713aSLionel Sambuc     if (!StringRef(Dir->path()).endswith(".framework"))
718f4a2713aSLionel Sambuc       continue;
719f4a2713aSLionel Sambuc 
720f4a2713aSLionel Sambuc     if (const DirectoryEntry *SubframeworkDir
721f4a2713aSLionel Sambuc           = FileMgr.getDirectory(Dir->path())) {
722f4a2713aSLionel Sambuc       // Note: as an egregious but useful hack, we use the real path here and
723f4a2713aSLionel Sambuc       // check whether it is actually a subdirectory of the parent directory.
724f4a2713aSLionel Sambuc       // This will not be the case if the 'subframework' is actually a symlink
725f4a2713aSLionel Sambuc       // out to a top-level framework.
726f4a2713aSLionel Sambuc       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
727f4a2713aSLionel Sambuc       bool FoundParent = false;
728f4a2713aSLionel Sambuc       do {
729f4a2713aSLionel Sambuc         // Get the parent directory name.
730f4a2713aSLionel Sambuc         SubframeworkDirName
731f4a2713aSLionel Sambuc           = llvm::sys::path::parent_path(SubframeworkDirName);
732f4a2713aSLionel Sambuc         if (SubframeworkDirName.empty())
733f4a2713aSLionel Sambuc           break;
734f4a2713aSLionel Sambuc 
735f4a2713aSLionel Sambuc         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
736f4a2713aSLionel Sambuc           FoundParent = true;
737f4a2713aSLionel Sambuc           break;
738f4a2713aSLionel Sambuc         }
739f4a2713aSLionel Sambuc       } while (true);
740f4a2713aSLionel Sambuc 
741f4a2713aSLionel Sambuc       if (!FoundParent)
742f4a2713aSLionel Sambuc         continue;
743f4a2713aSLionel Sambuc 
744f4a2713aSLionel Sambuc       // FIXME: Do we want to warn about subframeworks without umbrella headers?
745f4a2713aSLionel Sambuc       SmallString<32> NameBuf;
746f4a2713aSLionel Sambuc       inferFrameworkModule(sanitizeFilenameAsIdentifier(
747f4a2713aSLionel Sambuc                                llvm::sys::path::stem(Dir->path()), NameBuf),
748*0a6a1f1dSLionel Sambuc                            SubframeworkDir, Attrs, Result);
749f4a2713aSLionel Sambuc     }
750f4a2713aSLionel Sambuc   }
751f4a2713aSLionel Sambuc 
752f4a2713aSLionel Sambuc   // If the module is a top-level framework, automatically link against the
753f4a2713aSLionel Sambuc   // framework.
754f4a2713aSLionel Sambuc   if (!Result->isSubFramework()) {
755f4a2713aSLionel Sambuc     inferFrameworkLink(Result, FrameworkDir, FileMgr);
756f4a2713aSLionel Sambuc   }
757f4a2713aSLionel Sambuc 
758f4a2713aSLionel Sambuc   return Result;
759f4a2713aSLionel Sambuc }
760f4a2713aSLionel Sambuc 
setUmbrellaHeader(Module * Mod,const FileEntry * UmbrellaHeader)761f4a2713aSLionel Sambuc void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
762f4a2713aSLionel Sambuc   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
763f4a2713aSLionel Sambuc   Mod->Umbrella = UmbrellaHeader;
764f4a2713aSLionel Sambuc   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
765f4a2713aSLionel Sambuc }
766f4a2713aSLionel Sambuc 
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir)767f4a2713aSLionel Sambuc void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
768f4a2713aSLionel Sambuc   Mod->Umbrella = UmbrellaDir;
769f4a2713aSLionel Sambuc   UmbrellaDirs[UmbrellaDir] = Mod;
770f4a2713aSLionel Sambuc }
771f4a2713aSLionel Sambuc 
headerRoleToKind(ModuleMap::ModuleHeaderRole Role)772*0a6a1f1dSLionel Sambuc static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) {
773*0a6a1f1dSLionel Sambuc   switch ((int)Role) {
774*0a6a1f1dSLionel Sambuc   default: llvm_unreachable("unknown header role");
775*0a6a1f1dSLionel Sambuc   case ModuleMap::NormalHeader:
776*0a6a1f1dSLionel Sambuc     return Module::HK_Normal;
777*0a6a1f1dSLionel Sambuc   case ModuleMap::PrivateHeader:
778*0a6a1f1dSLionel Sambuc     return Module::HK_Private;
779*0a6a1f1dSLionel Sambuc   case ModuleMap::TextualHeader:
780*0a6a1f1dSLionel Sambuc     return Module::HK_Textual;
781*0a6a1f1dSLionel Sambuc   case ModuleMap::PrivateHeader | ModuleMap::TextualHeader:
782*0a6a1f1dSLionel Sambuc     return Module::HK_PrivateTextual;
783f4a2713aSLionel Sambuc   }
784*0a6a1f1dSLionel Sambuc }
785*0a6a1f1dSLionel Sambuc 
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role)786*0a6a1f1dSLionel Sambuc void ModuleMap::addHeader(Module *Mod, Module::Header Header,
787*0a6a1f1dSLionel Sambuc                           ModuleHeaderRole Role) {
788*0a6a1f1dSLionel Sambuc   if (!(Role & TextualHeader)) {
789*0a6a1f1dSLionel Sambuc     bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
790*0a6a1f1dSLionel Sambuc     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
791*0a6a1f1dSLionel Sambuc                                     isCompilingModuleHeader);
792*0a6a1f1dSLionel Sambuc   }
793*0a6a1f1dSLionel Sambuc   Headers[Header.Entry].push_back(KnownHeader(Mod, Role));
794*0a6a1f1dSLionel Sambuc 
795*0a6a1f1dSLionel Sambuc   Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header));
796*0a6a1f1dSLionel Sambuc }
797*0a6a1f1dSLionel Sambuc 
excludeHeader(Module * Mod,Module::Header Header)798*0a6a1f1dSLionel Sambuc void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
799*0a6a1f1dSLionel Sambuc   // Add this as a known header so we won't implicitly add it to any
800*0a6a1f1dSLionel Sambuc   // umbrella directory module.
801*0a6a1f1dSLionel Sambuc   // FIXME: Should we only exclude it from umbrella modules within the
802*0a6a1f1dSLionel Sambuc   // specified module?
803*0a6a1f1dSLionel Sambuc   (void) Headers[Header.Entry];
804*0a6a1f1dSLionel Sambuc 
805*0a6a1f1dSLionel Sambuc   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
806f4a2713aSLionel Sambuc }
807f4a2713aSLionel Sambuc 
808f4a2713aSLionel Sambuc const FileEntry *
getContainingModuleMapFile(const Module * Module) const809*0a6a1f1dSLionel Sambuc ModuleMap::getContainingModuleMapFile(const Module *Module) const {
810f4a2713aSLionel Sambuc   if (Module->DefinitionLoc.isInvalid())
811*0a6a1f1dSLionel Sambuc     return nullptr;
812f4a2713aSLionel Sambuc 
813f4a2713aSLionel Sambuc   return SourceMgr.getFileEntryForID(
814f4a2713aSLionel Sambuc            SourceMgr.getFileID(Module->DefinitionLoc));
815f4a2713aSLionel Sambuc }
816f4a2713aSLionel Sambuc 
getModuleMapFileForUniquing(const Module * M) const817*0a6a1f1dSLionel Sambuc const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
818*0a6a1f1dSLionel Sambuc   if (M->IsInferred) {
819*0a6a1f1dSLionel Sambuc     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
820*0a6a1f1dSLionel Sambuc     return InferredModuleAllowedBy.find(M)->second;
821*0a6a1f1dSLionel Sambuc   }
822*0a6a1f1dSLionel Sambuc   return getContainingModuleMapFile(M);
823*0a6a1f1dSLionel Sambuc }
824*0a6a1f1dSLionel Sambuc 
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)825*0a6a1f1dSLionel Sambuc void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
826*0a6a1f1dSLionel Sambuc   assert(M->IsInferred && "module not inferred");
827*0a6a1f1dSLionel Sambuc   InferredModuleAllowedBy[M] = ModMap;
828*0a6a1f1dSLionel Sambuc }
829*0a6a1f1dSLionel Sambuc 
dump()830f4a2713aSLionel Sambuc void ModuleMap::dump() {
831f4a2713aSLionel Sambuc   llvm::errs() << "Modules:";
832f4a2713aSLionel Sambuc   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
833f4a2713aSLionel Sambuc                                         MEnd = Modules.end();
834f4a2713aSLionel Sambuc        M != MEnd; ++M)
835f4a2713aSLionel Sambuc     M->getValue()->print(llvm::errs(), 2);
836f4a2713aSLionel Sambuc 
837f4a2713aSLionel Sambuc   llvm::errs() << "Headers:";
838f4a2713aSLionel Sambuc   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
839f4a2713aSLionel Sambuc        H != HEnd; ++H) {
840f4a2713aSLionel Sambuc     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
841f4a2713aSLionel Sambuc     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
842f4a2713aSLionel Sambuc                                                       E = H->second.end();
843f4a2713aSLionel Sambuc          I != E; ++I) {
844f4a2713aSLionel Sambuc       if (I != H->second.begin())
845f4a2713aSLionel Sambuc         llvm::errs() << ",";
846f4a2713aSLionel Sambuc       llvm::errs() << I->getModule()->getFullModuleName();
847f4a2713aSLionel Sambuc     }
848f4a2713aSLionel Sambuc     llvm::errs() << "\n";
849f4a2713aSLionel Sambuc   }
850f4a2713aSLionel Sambuc }
851f4a2713aSLionel Sambuc 
resolveExports(Module * Mod,bool Complain)852f4a2713aSLionel Sambuc bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
853f4a2713aSLionel Sambuc   bool HadError = false;
854f4a2713aSLionel Sambuc   for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
855f4a2713aSLionel Sambuc     Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
856f4a2713aSLionel Sambuc                                               Complain);
857f4a2713aSLionel Sambuc     if (Export.getPointer() || Export.getInt())
858f4a2713aSLionel Sambuc       Mod->Exports.push_back(Export);
859f4a2713aSLionel Sambuc     else
860f4a2713aSLionel Sambuc       HadError = true;
861f4a2713aSLionel Sambuc   }
862f4a2713aSLionel Sambuc   Mod->UnresolvedExports.clear();
863f4a2713aSLionel Sambuc   return HadError;
864f4a2713aSLionel Sambuc }
865f4a2713aSLionel Sambuc 
resolveUses(Module * Mod,bool Complain)866f4a2713aSLionel Sambuc bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
867f4a2713aSLionel Sambuc   bool HadError = false;
868f4a2713aSLionel Sambuc   for (unsigned I = 0, N = Mod->UnresolvedDirectUses.size(); I != N; ++I) {
869f4a2713aSLionel Sambuc     Module *DirectUse =
870f4a2713aSLionel Sambuc         resolveModuleId(Mod->UnresolvedDirectUses[I], Mod, Complain);
871f4a2713aSLionel Sambuc     if (DirectUse)
872f4a2713aSLionel Sambuc       Mod->DirectUses.push_back(DirectUse);
873f4a2713aSLionel Sambuc     else
874f4a2713aSLionel Sambuc       HadError = true;
875f4a2713aSLionel Sambuc   }
876f4a2713aSLionel Sambuc   Mod->UnresolvedDirectUses.clear();
877f4a2713aSLionel Sambuc   return HadError;
878f4a2713aSLionel Sambuc }
879f4a2713aSLionel Sambuc 
resolveConflicts(Module * Mod,bool Complain)880f4a2713aSLionel Sambuc bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
881f4a2713aSLionel Sambuc   bool HadError = false;
882f4a2713aSLionel Sambuc   for (unsigned I = 0, N = Mod->UnresolvedConflicts.size(); I != N; ++I) {
883f4a2713aSLionel Sambuc     Module *OtherMod = resolveModuleId(Mod->UnresolvedConflicts[I].Id,
884f4a2713aSLionel Sambuc                                        Mod, Complain);
885f4a2713aSLionel Sambuc     if (!OtherMod) {
886f4a2713aSLionel Sambuc       HadError = true;
887f4a2713aSLionel Sambuc       continue;
888f4a2713aSLionel Sambuc     }
889f4a2713aSLionel Sambuc 
890f4a2713aSLionel Sambuc     Module::Conflict Conflict;
891f4a2713aSLionel Sambuc     Conflict.Other = OtherMod;
892f4a2713aSLionel Sambuc     Conflict.Message = Mod->UnresolvedConflicts[I].Message;
893f4a2713aSLionel Sambuc     Mod->Conflicts.push_back(Conflict);
894f4a2713aSLionel Sambuc   }
895f4a2713aSLionel Sambuc   Mod->UnresolvedConflicts.clear();
896f4a2713aSLionel Sambuc   return HadError;
897f4a2713aSLionel Sambuc }
898f4a2713aSLionel Sambuc 
inferModuleFromLocation(FullSourceLoc Loc)899f4a2713aSLionel Sambuc Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
900f4a2713aSLionel Sambuc   if (Loc.isInvalid())
901*0a6a1f1dSLionel Sambuc     return nullptr;
902f4a2713aSLionel Sambuc 
903f4a2713aSLionel Sambuc   // Use the expansion location to determine which module we're in.
904f4a2713aSLionel Sambuc   FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
905f4a2713aSLionel Sambuc   if (!ExpansionLoc.isFileID())
906*0a6a1f1dSLionel Sambuc     return nullptr;
907f4a2713aSLionel Sambuc 
908f4a2713aSLionel Sambuc   const SourceManager &SrcMgr = Loc.getManager();
909f4a2713aSLionel Sambuc   FileID ExpansionFileID = ExpansionLoc.getFileID();
910f4a2713aSLionel Sambuc 
911f4a2713aSLionel Sambuc   while (const FileEntry *ExpansionFile
912f4a2713aSLionel Sambuc            = SrcMgr.getFileEntryForID(ExpansionFileID)) {
913f4a2713aSLionel Sambuc     // Find the module that owns this header (if any).
914f4a2713aSLionel Sambuc     if (Module *Mod = findModuleForHeader(ExpansionFile).getModule())
915f4a2713aSLionel Sambuc       return Mod;
916f4a2713aSLionel Sambuc 
917f4a2713aSLionel Sambuc     // No module owns this header, so look up the inclusion chain to see if
918f4a2713aSLionel Sambuc     // any included header has an associated module.
919f4a2713aSLionel Sambuc     SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
920f4a2713aSLionel Sambuc     if (IncludeLoc.isInvalid())
921*0a6a1f1dSLionel Sambuc       return nullptr;
922f4a2713aSLionel Sambuc 
923f4a2713aSLionel Sambuc     ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
924f4a2713aSLionel Sambuc   }
925f4a2713aSLionel Sambuc 
926*0a6a1f1dSLionel Sambuc   return nullptr;
927f4a2713aSLionel Sambuc }
928f4a2713aSLionel Sambuc 
929f4a2713aSLionel Sambuc //----------------------------------------------------------------------------//
930f4a2713aSLionel Sambuc // Module map file parser
931f4a2713aSLionel Sambuc //----------------------------------------------------------------------------//
932f4a2713aSLionel Sambuc 
933f4a2713aSLionel Sambuc namespace clang {
934f4a2713aSLionel Sambuc   /// \brief A token in a module map file.
935f4a2713aSLionel Sambuc   struct MMToken {
936f4a2713aSLionel Sambuc     enum TokenKind {
937f4a2713aSLionel Sambuc       Comma,
938f4a2713aSLionel Sambuc       ConfigMacros,
939f4a2713aSLionel Sambuc       Conflict,
940f4a2713aSLionel Sambuc       EndOfFile,
941f4a2713aSLionel Sambuc       HeaderKeyword,
942f4a2713aSLionel Sambuc       Identifier,
943f4a2713aSLionel Sambuc       Exclaim,
944f4a2713aSLionel Sambuc       ExcludeKeyword,
945f4a2713aSLionel Sambuc       ExplicitKeyword,
946f4a2713aSLionel Sambuc       ExportKeyword,
947f4a2713aSLionel Sambuc       ExternKeyword,
948f4a2713aSLionel Sambuc       FrameworkKeyword,
949f4a2713aSLionel Sambuc       LinkKeyword,
950f4a2713aSLionel Sambuc       ModuleKeyword,
951f4a2713aSLionel Sambuc       Period,
952f4a2713aSLionel Sambuc       PrivateKeyword,
953f4a2713aSLionel Sambuc       UmbrellaKeyword,
954f4a2713aSLionel Sambuc       UseKeyword,
955f4a2713aSLionel Sambuc       RequiresKeyword,
956f4a2713aSLionel Sambuc       Star,
957f4a2713aSLionel Sambuc       StringLiteral,
958*0a6a1f1dSLionel Sambuc       TextualKeyword,
959f4a2713aSLionel Sambuc       LBrace,
960f4a2713aSLionel Sambuc       RBrace,
961f4a2713aSLionel Sambuc       LSquare,
962f4a2713aSLionel Sambuc       RSquare
963f4a2713aSLionel Sambuc     } Kind;
964f4a2713aSLionel Sambuc 
965f4a2713aSLionel Sambuc     unsigned Location;
966f4a2713aSLionel Sambuc     unsigned StringLength;
967f4a2713aSLionel Sambuc     const char *StringData;
968f4a2713aSLionel Sambuc 
clearclang::MMToken969f4a2713aSLionel Sambuc     void clear() {
970f4a2713aSLionel Sambuc       Kind = EndOfFile;
971f4a2713aSLionel Sambuc       Location = 0;
972f4a2713aSLionel Sambuc       StringLength = 0;
973*0a6a1f1dSLionel Sambuc       StringData = nullptr;
974f4a2713aSLionel Sambuc     }
975f4a2713aSLionel Sambuc 
isclang::MMToken976f4a2713aSLionel Sambuc     bool is(TokenKind K) const { return Kind == K; }
977f4a2713aSLionel Sambuc 
getLocationclang::MMToken978f4a2713aSLionel Sambuc     SourceLocation getLocation() const {
979f4a2713aSLionel Sambuc       return SourceLocation::getFromRawEncoding(Location);
980f4a2713aSLionel Sambuc     }
981f4a2713aSLionel Sambuc 
getStringclang::MMToken982f4a2713aSLionel Sambuc     StringRef getString() const {
983f4a2713aSLionel Sambuc       return StringRef(StringData, StringLength);
984f4a2713aSLionel Sambuc     }
985f4a2713aSLionel Sambuc   };
986f4a2713aSLionel Sambuc 
987f4a2713aSLionel Sambuc   class ModuleMapParser {
988f4a2713aSLionel Sambuc     Lexer &L;
989f4a2713aSLionel Sambuc     SourceManager &SourceMgr;
990f4a2713aSLionel Sambuc 
991f4a2713aSLionel Sambuc     /// \brief Default target information, used only for string literal
992f4a2713aSLionel Sambuc     /// parsing.
993f4a2713aSLionel Sambuc     const TargetInfo *Target;
994f4a2713aSLionel Sambuc 
995f4a2713aSLionel Sambuc     DiagnosticsEngine &Diags;
996f4a2713aSLionel Sambuc     ModuleMap &Map;
997f4a2713aSLionel Sambuc 
998*0a6a1f1dSLionel Sambuc     /// \brief The current module map file.
999*0a6a1f1dSLionel Sambuc     const FileEntry *ModuleMapFile;
1000*0a6a1f1dSLionel Sambuc 
1001*0a6a1f1dSLionel Sambuc     /// \brief The directory that file names in this module map file should
1002*0a6a1f1dSLionel Sambuc     /// be resolved relative to.
1003f4a2713aSLionel Sambuc     const DirectoryEntry *Directory;
1004f4a2713aSLionel Sambuc 
1005f4a2713aSLionel Sambuc     /// \brief The directory containing Clang-supplied headers.
1006f4a2713aSLionel Sambuc     const DirectoryEntry *BuiltinIncludeDir;
1007f4a2713aSLionel Sambuc 
1008f4a2713aSLionel Sambuc     /// \brief Whether this module map is in a system header directory.
1009f4a2713aSLionel Sambuc     bool IsSystem;
1010f4a2713aSLionel Sambuc 
1011f4a2713aSLionel Sambuc     /// \brief Whether an error occurred.
1012f4a2713aSLionel Sambuc     bool HadError;
1013f4a2713aSLionel Sambuc 
1014f4a2713aSLionel Sambuc     /// \brief Stores string data for the various string literals referenced
1015f4a2713aSLionel Sambuc     /// during parsing.
1016f4a2713aSLionel Sambuc     llvm::BumpPtrAllocator StringData;
1017f4a2713aSLionel Sambuc 
1018f4a2713aSLionel Sambuc     /// \brief The current token.
1019f4a2713aSLionel Sambuc     MMToken Tok;
1020f4a2713aSLionel Sambuc 
1021f4a2713aSLionel Sambuc     /// \brief The active module.
1022f4a2713aSLionel Sambuc     Module *ActiveModule;
1023f4a2713aSLionel Sambuc 
1024f4a2713aSLionel Sambuc     /// \brief Consume the current token and return its location.
1025f4a2713aSLionel Sambuc     SourceLocation consumeToken();
1026f4a2713aSLionel Sambuc 
1027f4a2713aSLionel Sambuc     /// \brief Skip tokens until we reach the a token with the given kind
1028f4a2713aSLionel Sambuc     /// (or the end of the file).
1029f4a2713aSLionel Sambuc     void skipUntil(MMToken::TokenKind K);
1030f4a2713aSLionel Sambuc 
1031f4a2713aSLionel Sambuc     typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
1032f4a2713aSLionel Sambuc     bool parseModuleId(ModuleId &Id);
1033f4a2713aSLionel Sambuc     void parseModuleDecl();
1034f4a2713aSLionel Sambuc     void parseExternModuleDecl();
1035f4a2713aSLionel Sambuc     void parseRequiresDecl();
1036f4a2713aSLionel Sambuc     void parseHeaderDecl(clang::MMToken::TokenKind,
1037f4a2713aSLionel Sambuc                          SourceLocation LeadingLoc);
1038f4a2713aSLionel Sambuc     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
1039f4a2713aSLionel Sambuc     void parseExportDecl();
1040f4a2713aSLionel Sambuc     void parseUseDecl();
1041f4a2713aSLionel Sambuc     void parseLinkDecl();
1042f4a2713aSLionel Sambuc     void parseConfigMacros();
1043f4a2713aSLionel Sambuc     void parseConflict();
1044f4a2713aSLionel Sambuc     void parseInferredModuleDecl(bool Framework, bool Explicit);
1045f4a2713aSLionel Sambuc 
1046*0a6a1f1dSLionel Sambuc     typedef ModuleMap::Attributes Attributes;
1047*0a6a1f1dSLionel Sambuc     bool parseOptionalAttributes(Attributes &Attrs);
1048f4a2713aSLionel Sambuc 
1049f4a2713aSLionel Sambuc   public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,const DirectoryEntry * BuiltinIncludeDir,bool IsSystem)1050f4a2713aSLionel Sambuc     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
1051f4a2713aSLionel Sambuc                              const TargetInfo *Target,
1052f4a2713aSLionel Sambuc                              DiagnosticsEngine &Diags,
1053f4a2713aSLionel Sambuc                              ModuleMap &Map,
1054*0a6a1f1dSLionel Sambuc                              const FileEntry *ModuleMapFile,
1055f4a2713aSLionel Sambuc                              const DirectoryEntry *Directory,
1056f4a2713aSLionel Sambuc                              const DirectoryEntry *BuiltinIncludeDir,
1057f4a2713aSLionel Sambuc                              bool IsSystem)
1058f4a2713aSLionel Sambuc       : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1059*0a6a1f1dSLionel Sambuc         ModuleMapFile(ModuleMapFile), Directory(Directory),
1060*0a6a1f1dSLionel Sambuc         BuiltinIncludeDir(BuiltinIncludeDir), IsSystem(IsSystem),
1061*0a6a1f1dSLionel Sambuc         HadError(false), ActiveModule(nullptr)
1062f4a2713aSLionel Sambuc     {
1063f4a2713aSLionel Sambuc       Tok.clear();
1064f4a2713aSLionel Sambuc       consumeToken();
1065f4a2713aSLionel Sambuc     }
1066f4a2713aSLionel Sambuc 
1067f4a2713aSLionel Sambuc     bool parseModuleMapFile();
1068f4a2713aSLionel Sambuc   };
1069f4a2713aSLionel Sambuc }
1070f4a2713aSLionel Sambuc 
consumeToken()1071f4a2713aSLionel Sambuc SourceLocation ModuleMapParser::consumeToken() {
1072f4a2713aSLionel Sambuc retry:
1073f4a2713aSLionel Sambuc   SourceLocation Result = Tok.getLocation();
1074f4a2713aSLionel Sambuc   Tok.clear();
1075f4a2713aSLionel Sambuc 
1076f4a2713aSLionel Sambuc   Token LToken;
1077f4a2713aSLionel Sambuc   L.LexFromRawLexer(LToken);
1078f4a2713aSLionel Sambuc   Tok.Location = LToken.getLocation().getRawEncoding();
1079f4a2713aSLionel Sambuc   switch (LToken.getKind()) {
1080*0a6a1f1dSLionel Sambuc   case tok::raw_identifier: {
1081*0a6a1f1dSLionel Sambuc     StringRef RI = LToken.getRawIdentifier();
1082*0a6a1f1dSLionel Sambuc     Tok.StringData = RI.data();
1083*0a6a1f1dSLionel Sambuc     Tok.StringLength = RI.size();
1084*0a6a1f1dSLionel Sambuc     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
1085f4a2713aSLionel Sambuc                  .Case("config_macros", MMToken::ConfigMacros)
1086f4a2713aSLionel Sambuc                  .Case("conflict", MMToken::Conflict)
1087f4a2713aSLionel Sambuc                  .Case("exclude", MMToken::ExcludeKeyword)
1088f4a2713aSLionel Sambuc                  .Case("explicit", MMToken::ExplicitKeyword)
1089f4a2713aSLionel Sambuc                  .Case("export", MMToken::ExportKeyword)
1090f4a2713aSLionel Sambuc                  .Case("extern", MMToken::ExternKeyword)
1091f4a2713aSLionel Sambuc                  .Case("framework", MMToken::FrameworkKeyword)
1092f4a2713aSLionel Sambuc                  .Case("header", MMToken::HeaderKeyword)
1093f4a2713aSLionel Sambuc                  .Case("link", MMToken::LinkKeyword)
1094f4a2713aSLionel Sambuc                  .Case("module", MMToken::ModuleKeyword)
1095f4a2713aSLionel Sambuc                  .Case("private", MMToken::PrivateKeyword)
1096f4a2713aSLionel Sambuc                  .Case("requires", MMToken::RequiresKeyword)
1097*0a6a1f1dSLionel Sambuc                  .Case("textual", MMToken::TextualKeyword)
1098f4a2713aSLionel Sambuc                  .Case("umbrella", MMToken::UmbrellaKeyword)
1099f4a2713aSLionel Sambuc                  .Case("use", MMToken::UseKeyword)
1100f4a2713aSLionel Sambuc                  .Default(MMToken::Identifier);
1101f4a2713aSLionel Sambuc     break;
1102*0a6a1f1dSLionel Sambuc   }
1103f4a2713aSLionel Sambuc 
1104f4a2713aSLionel Sambuc   case tok::comma:
1105f4a2713aSLionel Sambuc     Tok.Kind = MMToken::Comma;
1106f4a2713aSLionel Sambuc     break;
1107f4a2713aSLionel Sambuc 
1108f4a2713aSLionel Sambuc   case tok::eof:
1109f4a2713aSLionel Sambuc     Tok.Kind = MMToken::EndOfFile;
1110f4a2713aSLionel Sambuc     break;
1111f4a2713aSLionel Sambuc 
1112f4a2713aSLionel Sambuc   case tok::l_brace:
1113f4a2713aSLionel Sambuc     Tok.Kind = MMToken::LBrace;
1114f4a2713aSLionel Sambuc     break;
1115f4a2713aSLionel Sambuc 
1116f4a2713aSLionel Sambuc   case tok::l_square:
1117f4a2713aSLionel Sambuc     Tok.Kind = MMToken::LSquare;
1118f4a2713aSLionel Sambuc     break;
1119f4a2713aSLionel Sambuc 
1120f4a2713aSLionel Sambuc   case tok::period:
1121f4a2713aSLionel Sambuc     Tok.Kind = MMToken::Period;
1122f4a2713aSLionel Sambuc     break;
1123f4a2713aSLionel Sambuc 
1124f4a2713aSLionel Sambuc   case tok::r_brace:
1125f4a2713aSLionel Sambuc     Tok.Kind = MMToken::RBrace;
1126f4a2713aSLionel Sambuc     break;
1127f4a2713aSLionel Sambuc 
1128f4a2713aSLionel Sambuc   case tok::r_square:
1129f4a2713aSLionel Sambuc     Tok.Kind = MMToken::RSquare;
1130f4a2713aSLionel Sambuc     break;
1131f4a2713aSLionel Sambuc 
1132f4a2713aSLionel Sambuc   case tok::star:
1133f4a2713aSLionel Sambuc     Tok.Kind = MMToken::Star;
1134f4a2713aSLionel Sambuc     break;
1135f4a2713aSLionel Sambuc 
1136f4a2713aSLionel Sambuc   case tok::exclaim:
1137f4a2713aSLionel Sambuc     Tok.Kind = MMToken::Exclaim;
1138f4a2713aSLionel Sambuc     break;
1139f4a2713aSLionel Sambuc 
1140f4a2713aSLionel Sambuc   case tok::string_literal: {
1141f4a2713aSLionel Sambuc     if (LToken.hasUDSuffix()) {
1142f4a2713aSLionel Sambuc       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1143f4a2713aSLionel Sambuc       HadError = true;
1144f4a2713aSLionel Sambuc       goto retry;
1145f4a2713aSLionel Sambuc     }
1146f4a2713aSLionel Sambuc 
1147f4a2713aSLionel Sambuc     // Parse the string literal.
1148f4a2713aSLionel Sambuc     LangOptions LangOpts;
1149*0a6a1f1dSLionel Sambuc     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1150f4a2713aSLionel Sambuc     if (StringLiteral.hadError)
1151f4a2713aSLionel Sambuc       goto retry;
1152f4a2713aSLionel Sambuc 
1153f4a2713aSLionel Sambuc     // Copy the string literal into our string data allocator.
1154f4a2713aSLionel Sambuc     unsigned Length = StringLiteral.GetStringLength();
1155f4a2713aSLionel Sambuc     char *Saved = StringData.Allocate<char>(Length + 1);
1156f4a2713aSLionel Sambuc     memcpy(Saved, StringLiteral.GetString().data(), Length);
1157f4a2713aSLionel Sambuc     Saved[Length] = 0;
1158f4a2713aSLionel Sambuc 
1159f4a2713aSLionel Sambuc     // Form the token.
1160f4a2713aSLionel Sambuc     Tok.Kind = MMToken::StringLiteral;
1161f4a2713aSLionel Sambuc     Tok.StringData = Saved;
1162f4a2713aSLionel Sambuc     Tok.StringLength = Length;
1163f4a2713aSLionel Sambuc     break;
1164f4a2713aSLionel Sambuc   }
1165f4a2713aSLionel Sambuc 
1166f4a2713aSLionel Sambuc   case tok::comment:
1167f4a2713aSLionel Sambuc     goto retry;
1168f4a2713aSLionel Sambuc 
1169f4a2713aSLionel Sambuc   default:
1170f4a2713aSLionel Sambuc     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
1171f4a2713aSLionel Sambuc     HadError = true;
1172f4a2713aSLionel Sambuc     goto retry;
1173f4a2713aSLionel Sambuc   }
1174f4a2713aSLionel Sambuc 
1175f4a2713aSLionel Sambuc   return Result;
1176f4a2713aSLionel Sambuc }
1177f4a2713aSLionel Sambuc 
skipUntil(MMToken::TokenKind K)1178f4a2713aSLionel Sambuc void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1179f4a2713aSLionel Sambuc   unsigned braceDepth = 0;
1180f4a2713aSLionel Sambuc   unsigned squareDepth = 0;
1181f4a2713aSLionel Sambuc   do {
1182f4a2713aSLionel Sambuc     switch (Tok.Kind) {
1183f4a2713aSLionel Sambuc     case MMToken::EndOfFile:
1184f4a2713aSLionel Sambuc       return;
1185f4a2713aSLionel Sambuc 
1186f4a2713aSLionel Sambuc     case MMToken::LBrace:
1187f4a2713aSLionel Sambuc       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1188f4a2713aSLionel Sambuc         return;
1189f4a2713aSLionel Sambuc 
1190f4a2713aSLionel Sambuc       ++braceDepth;
1191f4a2713aSLionel Sambuc       break;
1192f4a2713aSLionel Sambuc 
1193f4a2713aSLionel Sambuc     case MMToken::LSquare:
1194f4a2713aSLionel Sambuc       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1195f4a2713aSLionel Sambuc         return;
1196f4a2713aSLionel Sambuc 
1197f4a2713aSLionel Sambuc       ++squareDepth;
1198f4a2713aSLionel Sambuc       break;
1199f4a2713aSLionel Sambuc 
1200f4a2713aSLionel Sambuc     case MMToken::RBrace:
1201f4a2713aSLionel Sambuc       if (braceDepth > 0)
1202f4a2713aSLionel Sambuc         --braceDepth;
1203f4a2713aSLionel Sambuc       else if (Tok.is(K))
1204f4a2713aSLionel Sambuc         return;
1205f4a2713aSLionel Sambuc       break;
1206f4a2713aSLionel Sambuc 
1207f4a2713aSLionel Sambuc     case MMToken::RSquare:
1208f4a2713aSLionel Sambuc       if (squareDepth > 0)
1209f4a2713aSLionel Sambuc         --squareDepth;
1210f4a2713aSLionel Sambuc       else if (Tok.is(K))
1211f4a2713aSLionel Sambuc         return;
1212f4a2713aSLionel Sambuc       break;
1213f4a2713aSLionel Sambuc 
1214f4a2713aSLionel Sambuc     default:
1215f4a2713aSLionel Sambuc       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1216f4a2713aSLionel Sambuc         return;
1217f4a2713aSLionel Sambuc       break;
1218f4a2713aSLionel Sambuc     }
1219f4a2713aSLionel Sambuc 
1220f4a2713aSLionel Sambuc    consumeToken();
1221f4a2713aSLionel Sambuc   } while (true);
1222f4a2713aSLionel Sambuc }
1223f4a2713aSLionel Sambuc 
1224f4a2713aSLionel Sambuc /// \brief Parse a module-id.
1225f4a2713aSLionel Sambuc ///
1226f4a2713aSLionel Sambuc ///   module-id:
1227f4a2713aSLionel Sambuc ///     identifier
1228f4a2713aSLionel Sambuc ///     identifier '.' module-id
1229f4a2713aSLionel Sambuc ///
1230f4a2713aSLionel Sambuc /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)1231f4a2713aSLionel Sambuc bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1232f4a2713aSLionel Sambuc   Id.clear();
1233f4a2713aSLionel Sambuc   do {
1234*0a6a1f1dSLionel Sambuc     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1235f4a2713aSLionel Sambuc       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1236f4a2713aSLionel Sambuc       consumeToken();
1237f4a2713aSLionel Sambuc     } else {
1238f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1239f4a2713aSLionel Sambuc       return true;
1240f4a2713aSLionel Sambuc     }
1241f4a2713aSLionel Sambuc 
1242f4a2713aSLionel Sambuc     if (!Tok.is(MMToken::Period))
1243f4a2713aSLionel Sambuc       break;
1244f4a2713aSLionel Sambuc 
1245f4a2713aSLionel Sambuc     consumeToken();
1246f4a2713aSLionel Sambuc   } while (true);
1247f4a2713aSLionel Sambuc 
1248f4a2713aSLionel Sambuc   return false;
1249f4a2713aSLionel Sambuc }
1250f4a2713aSLionel Sambuc 
1251f4a2713aSLionel Sambuc namespace {
1252f4a2713aSLionel Sambuc   /// \brief Enumerates the known attributes.
1253f4a2713aSLionel Sambuc   enum AttributeKind {
1254f4a2713aSLionel Sambuc     /// \brief An unknown attribute.
1255f4a2713aSLionel Sambuc     AT_unknown,
1256f4a2713aSLionel Sambuc     /// \brief The 'system' attribute.
1257f4a2713aSLionel Sambuc     AT_system,
1258*0a6a1f1dSLionel Sambuc     /// \brief The 'extern_c' attribute.
1259*0a6a1f1dSLionel Sambuc     AT_extern_c,
1260f4a2713aSLionel Sambuc     /// \brief The 'exhaustive' attribute.
1261f4a2713aSLionel Sambuc     AT_exhaustive
1262f4a2713aSLionel Sambuc   };
1263f4a2713aSLionel Sambuc }
1264f4a2713aSLionel Sambuc 
1265f4a2713aSLionel Sambuc /// \brief Parse a module declaration.
1266f4a2713aSLionel Sambuc ///
1267f4a2713aSLionel Sambuc ///   module-declaration:
1268f4a2713aSLionel Sambuc ///     'extern' 'module' module-id string-literal
1269f4a2713aSLionel Sambuc ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1270f4a2713aSLionel Sambuc ///       { module-member* }
1271f4a2713aSLionel Sambuc ///
1272f4a2713aSLionel Sambuc ///   module-member:
1273f4a2713aSLionel Sambuc ///     requires-declaration
1274f4a2713aSLionel Sambuc ///     header-declaration
1275f4a2713aSLionel Sambuc ///     submodule-declaration
1276f4a2713aSLionel Sambuc ///     export-declaration
1277f4a2713aSLionel Sambuc ///     link-declaration
1278f4a2713aSLionel Sambuc ///
1279f4a2713aSLionel Sambuc ///   submodule-declaration:
1280f4a2713aSLionel Sambuc ///     module-declaration
1281f4a2713aSLionel Sambuc ///     inferred-submodule-declaration
parseModuleDecl()1282f4a2713aSLionel Sambuc void ModuleMapParser::parseModuleDecl() {
1283f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
1284f4a2713aSLionel Sambuc          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
1285f4a2713aSLionel Sambuc   if (Tok.is(MMToken::ExternKeyword)) {
1286f4a2713aSLionel Sambuc     parseExternModuleDecl();
1287f4a2713aSLionel Sambuc     return;
1288f4a2713aSLionel Sambuc   }
1289f4a2713aSLionel Sambuc 
1290f4a2713aSLionel Sambuc   // Parse 'explicit' or 'framework' keyword, if present.
1291f4a2713aSLionel Sambuc   SourceLocation ExplicitLoc;
1292f4a2713aSLionel Sambuc   bool Explicit = false;
1293f4a2713aSLionel Sambuc   bool Framework = false;
1294f4a2713aSLionel Sambuc 
1295f4a2713aSLionel Sambuc   // Parse 'explicit' keyword, if present.
1296f4a2713aSLionel Sambuc   if (Tok.is(MMToken::ExplicitKeyword)) {
1297f4a2713aSLionel Sambuc     ExplicitLoc = consumeToken();
1298f4a2713aSLionel Sambuc     Explicit = true;
1299f4a2713aSLionel Sambuc   }
1300f4a2713aSLionel Sambuc 
1301f4a2713aSLionel Sambuc   // Parse 'framework' keyword, if present.
1302f4a2713aSLionel Sambuc   if (Tok.is(MMToken::FrameworkKeyword)) {
1303f4a2713aSLionel Sambuc     consumeToken();
1304f4a2713aSLionel Sambuc     Framework = true;
1305f4a2713aSLionel Sambuc   }
1306f4a2713aSLionel Sambuc 
1307f4a2713aSLionel Sambuc   // Parse 'module' keyword.
1308f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::ModuleKeyword)) {
1309f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1310f4a2713aSLionel Sambuc     consumeToken();
1311f4a2713aSLionel Sambuc     HadError = true;
1312f4a2713aSLionel Sambuc     return;
1313f4a2713aSLionel Sambuc   }
1314f4a2713aSLionel Sambuc   consumeToken(); // 'module' keyword
1315f4a2713aSLionel Sambuc 
1316f4a2713aSLionel Sambuc   // If we have a wildcard for the module name, this is an inferred submodule.
1317f4a2713aSLionel Sambuc   // Parse it.
1318f4a2713aSLionel Sambuc   if (Tok.is(MMToken::Star))
1319f4a2713aSLionel Sambuc     return parseInferredModuleDecl(Framework, Explicit);
1320f4a2713aSLionel Sambuc 
1321f4a2713aSLionel Sambuc   // Parse the module name.
1322f4a2713aSLionel Sambuc   ModuleId Id;
1323f4a2713aSLionel Sambuc   if (parseModuleId(Id)) {
1324f4a2713aSLionel Sambuc     HadError = true;
1325f4a2713aSLionel Sambuc     return;
1326f4a2713aSLionel Sambuc   }
1327f4a2713aSLionel Sambuc 
1328f4a2713aSLionel Sambuc   if (ActiveModule) {
1329f4a2713aSLionel Sambuc     if (Id.size() > 1) {
1330f4a2713aSLionel Sambuc       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1331f4a2713aSLionel Sambuc         << SourceRange(Id.front().second, Id.back().second);
1332f4a2713aSLionel Sambuc 
1333f4a2713aSLionel Sambuc       HadError = true;
1334f4a2713aSLionel Sambuc       return;
1335f4a2713aSLionel Sambuc     }
1336f4a2713aSLionel Sambuc   } else if (Id.size() == 1 && Explicit) {
1337f4a2713aSLionel Sambuc     // Top-level modules can't be explicit.
1338f4a2713aSLionel Sambuc     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1339f4a2713aSLionel Sambuc     Explicit = false;
1340f4a2713aSLionel Sambuc     ExplicitLoc = SourceLocation();
1341f4a2713aSLionel Sambuc     HadError = true;
1342f4a2713aSLionel Sambuc   }
1343f4a2713aSLionel Sambuc 
1344f4a2713aSLionel Sambuc   Module *PreviousActiveModule = ActiveModule;
1345f4a2713aSLionel Sambuc   if (Id.size() > 1) {
1346f4a2713aSLionel Sambuc     // This module map defines a submodule. Go find the module of which it
1347f4a2713aSLionel Sambuc     // is a submodule.
1348*0a6a1f1dSLionel Sambuc     ActiveModule = nullptr;
1349*0a6a1f1dSLionel Sambuc     const Module *TopLevelModule = nullptr;
1350f4a2713aSLionel Sambuc     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1351f4a2713aSLionel Sambuc       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1352*0a6a1f1dSLionel Sambuc         if (I == 0)
1353*0a6a1f1dSLionel Sambuc           TopLevelModule = Next;
1354f4a2713aSLionel Sambuc         ActiveModule = Next;
1355f4a2713aSLionel Sambuc         continue;
1356f4a2713aSLionel Sambuc       }
1357f4a2713aSLionel Sambuc 
1358f4a2713aSLionel Sambuc       if (ActiveModule) {
1359f4a2713aSLionel Sambuc         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1360*0a6a1f1dSLionel Sambuc           << Id[I].first
1361*0a6a1f1dSLionel Sambuc           << ActiveModule->getTopLevelModule()->getFullModuleName();
1362f4a2713aSLionel Sambuc       } else {
1363f4a2713aSLionel Sambuc         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1364f4a2713aSLionel Sambuc       }
1365f4a2713aSLionel Sambuc       HadError = true;
1366f4a2713aSLionel Sambuc       return;
1367f4a2713aSLionel Sambuc     }
1368*0a6a1f1dSLionel Sambuc 
1369*0a6a1f1dSLionel Sambuc     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
1370*0a6a1f1dSLionel Sambuc       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
1371*0a6a1f1dSLionel Sambuc              "submodule defined in same file as 'module *' that allowed its "
1372*0a6a1f1dSLionel Sambuc              "top-level module");
1373*0a6a1f1dSLionel Sambuc       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
1374*0a6a1f1dSLionel Sambuc     }
1375f4a2713aSLionel Sambuc   }
1376f4a2713aSLionel Sambuc 
1377f4a2713aSLionel Sambuc   StringRef ModuleName = Id.back().first;
1378f4a2713aSLionel Sambuc   SourceLocation ModuleNameLoc = Id.back().second;
1379f4a2713aSLionel Sambuc 
1380f4a2713aSLionel Sambuc   // Parse the optional attribute list.
1381f4a2713aSLionel Sambuc   Attributes Attrs;
1382f4a2713aSLionel Sambuc   parseOptionalAttributes(Attrs);
1383f4a2713aSLionel Sambuc 
1384f4a2713aSLionel Sambuc   // Parse the opening brace.
1385f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::LBrace)) {
1386f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1387f4a2713aSLionel Sambuc       << ModuleName;
1388f4a2713aSLionel Sambuc     HadError = true;
1389f4a2713aSLionel Sambuc     return;
1390f4a2713aSLionel Sambuc   }
1391f4a2713aSLionel Sambuc   SourceLocation LBraceLoc = consumeToken();
1392f4a2713aSLionel Sambuc 
1393f4a2713aSLionel Sambuc   // Determine whether this (sub)module has already been defined.
1394f4a2713aSLionel Sambuc   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1395f4a2713aSLionel Sambuc     if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1396f4a2713aSLionel Sambuc       // Skip the module definition.
1397f4a2713aSLionel Sambuc       skipUntil(MMToken::RBrace);
1398f4a2713aSLionel Sambuc       if (Tok.is(MMToken::RBrace))
1399f4a2713aSLionel Sambuc         consumeToken();
1400f4a2713aSLionel Sambuc       else {
1401f4a2713aSLionel Sambuc         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1402f4a2713aSLionel Sambuc         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1403f4a2713aSLionel Sambuc         HadError = true;
1404f4a2713aSLionel Sambuc       }
1405f4a2713aSLionel Sambuc       return;
1406f4a2713aSLionel Sambuc     }
1407f4a2713aSLionel Sambuc 
1408f4a2713aSLionel Sambuc     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1409f4a2713aSLionel Sambuc       << ModuleName;
1410f4a2713aSLionel Sambuc     Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1411f4a2713aSLionel Sambuc 
1412f4a2713aSLionel Sambuc     // Skip the module definition.
1413f4a2713aSLionel Sambuc     skipUntil(MMToken::RBrace);
1414f4a2713aSLionel Sambuc     if (Tok.is(MMToken::RBrace))
1415f4a2713aSLionel Sambuc       consumeToken();
1416f4a2713aSLionel Sambuc 
1417f4a2713aSLionel Sambuc     HadError = true;
1418f4a2713aSLionel Sambuc     return;
1419f4a2713aSLionel Sambuc   }
1420f4a2713aSLionel Sambuc 
1421f4a2713aSLionel Sambuc   // Start defining this module.
1422f4a2713aSLionel Sambuc   ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1423f4a2713aSLionel Sambuc                                         Explicit).first;
1424f4a2713aSLionel Sambuc   ActiveModule->DefinitionLoc = ModuleNameLoc;
1425f4a2713aSLionel Sambuc   if (Attrs.IsSystem || IsSystem)
1426f4a2713aSLionel Sambuc     ActiveModule->IsSystem = true;
1427*0a6a1f1dSLionel Sambuc   if (Attrs.IsExternC)
1428*0a6a1f1dSLionel Sambuc     ActiveModule->IsExternC = true;
1429*0a6a1f1dSLionel Sambuc   ActiveModule->Directory = Directory;
1430f4a2713aSLionel Sambuc 
1431f4a2713aSLionel Sambuc   bool Done = false;
1432f4a2713aSLionel Sambuc   do {
1433f4a2713aSLionel Sambuc     switch (Tok.Kind) {
1434f4a2713aSLionel Sambuc     case MMToken::EndOfFile:
1435f4a2713aSLionel Sambuc     case MMToken::RBrace:
1436f4a2713aSLionel Sambuc       Done = true;
1437f4a2713aSLionel Sambuc       break;
1438f4a2713aSLionel Sambuc 
1439f4a2713aSLionel Sambuc     case MMToken::ConfigMacros:
1440f4a2713aSLionel Sambuc       parseConfigMacros();
1441f4a2713aSLionel Sambuc       break;
1442f4a2713aSLionel Sambuc 
1443f4a2713aSLionel Sambuc     case MMToken::Conflict:
1444f4a2713aSLionel Sambuc       parseConflict();
1445f4a2713aSLionel Sambuc       break;
1446f4a2713aSLionel Sambuc 
1447f4a2713aSLionel Sambuc     case MMToken::ExplicitKeyword:
1448f4a2713aSLionel Sambuc     case MMToken::ExternKeyword:
1449f4a2713aSLionel Sambuc     case MMToken::FrameworkKeyword:
1450f4a2713aSLionel Sambuc     case MMToken::ModuleKeyword:
1451f4a2713aSLionel Sambuc       parseModuleDecl();
1452f4a2713aSLionel Sambuc       break;
1453f4a2713aSLionel Sambuc 
1454f4a2713aSLionel Sambuc     case MMToken::ExportKeyword:
1455f4a2713aSLionel Sambuc       parseExportDecl();
1456f4a2713aSLionel Sambuc       break;
1457f4a2713aSLionel Sambuc 
1458f4a2713aSLionel Sambuc     case MMToken::UseKeyword:
1459f4a2713aSLionel Sambuc       parseUseDecl();
1460f4a2713aSLionel Sambuc       break;
1461f4a2713aSLionel Sambuc 
1462f4a2713aSLionel Sambuc     case MMToken::RequiresKeyword:
1463f4a2713aSLionel Sambuc       parseRequiresDecl();
1464f4a2713aSLionel Sambuc       break;
1465f4a2713aSLionel Sambuc 
1466*0a6a1f1dSLionel Sambuc     case MMToken::TextualKeyword:
1467*0a6a1f1dSLionel Sambuc       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
1468*0a6a1f1dSLionel Sambuc       break;
1469*0a6a1f1dSLionel Sambuc 
1470f4a2713aSLionel Sambuc     case MMToken::UmbrellaKeyword: {
1471f4a2713aSLionel Sambuc       SourceLocation UmbrellaLoc = consumeToken();
1472f4a2713aSLionel Sambuc       if (Tok.is(MMToken::HeaderKeyword))
1473f4a2713aSLionel Sambuc         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
1474f4a2713aSLionel Sambuc       else
1475f4a2713aSLionel Sambuc         parseUmbrellaDirDecl(UmbrellaLoc);
1476f4a2713aSLionel Sambuc       break;
1477f4a2713aSLionel Sambuc     }
1478f4a2713aSLionel Sambuc 
1479*0a6a1f1dSLionel Sambuc     case MMToken::ExcludeKeyword:
1480*0a6a1f1dSLionel Sambuc       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
1481f4a2713aSLionel Sambuc       break;
1482f4a2713aSLionel Sambuc 
1483*0a6a1f1dSLionel Sambuc     case MMToken::PrivateKeyword:
1484*0a6a1f1dSLionel Sambuc       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
1485f4a2713aSLionel Sambuc       break;
1486f4a2713aSLionel Sambuc 
1487f4a2713aSLionel Sambuc     case MMToken::HeaderKeyword:
1488*0a6a1f1dSLionel Sambuc       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
1489f4a2713aSLionel Sambuc       break;
1490f4a2713aSLionel Sambuc 
1491f4a2713aSLionel Sambuc     case MMToken::LinkKeyword:
1492f4a2713aSLionel Sambuc       parseLinkDecl();
1493f4a2713aSLionel Sambuc       break;
1494f4a2713aSLionel Sambuc 
1495f4a2713aSLionel Sambuc     default:
1496f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1497f4a2713aSLionel Sambuc       consumeToken();
1498f4a2713aSLionel Sambuc       break;
1499f4a2713aSLionel Sambuc     }
1500f4a2713aSLionel Sambuc   } while (!Done);
1501f4a2713aSLionel Sambuc 
1502f4a2713aSLionel Sambuc   if (Tok.is(MMToken::RBrace))
1503f4a2713aSLionel Sambuc     consumeToken();
1504f4a2713aSLionel Sambuc   else {
1505f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1506f4a2713aSLionel Sambuc     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1507f4a2713aSLionel Sambuc     HadError = true;
1508f4a2713aSLionel Sambuc   }
1509f4a2713aSLionel Sambuc 
1510f4a2713aSLionel Sambuc   // If the active module is a top-level framework, and there are no link
1511f4a2713aSLionel Sambuc   // libraries, automatically link against the framework.
1512f4a2713aSLionel Sambuc   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
1513f4a2713aSLionel Sambuc       ActiveModule->LinkLibraries.empty()) {
1514f4a2713aSLionel Sambuc     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
1515f4a2713aSLionel Sambuc   }
1516f4a2713aSLionel Sambuc 
1517*0a6a1f1dSLionel Sambuc   // If the module meets all requirements but is still unavailable, mark the
1518*0a6a1f1dSLionel Sambuc   // whole tree as unavailable to prevent it from building.
1519*0a6a1f1dSLionel Sambuc   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
1520*0a6a1f1dSLionel Sambuc       ActiveModule->Parent) {
1521*0a6a1f1dSLionel Sambuc     ActiveModule->getTopLevelModule()->markUnavailable();
1522*0a6a1f1dSLionel Sambuc     ActiveModule->getTopLevelModule()->MissingHeaders.append(
1523*0a6a1f1dSLionel Sambuc       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
1524*0a6a1f1dSLionel Sambuc   }
1525*0a6a1f1dSLionel Sambuc 
1526f4a2713aSLionel Sambuc   // We're done parsing this module. Pop back to the previous module.
1527f4a2713aSLionel Sambuc   ActiveModule = PreviousActiveModule;
1528f4a2713aSLionel Sambuc }
1529f4a2713aSLionel Sambuc 
1530f4a2713aSLionel Sambuc /// \brief Parse an extern module declaration.
1531f4a2713aSLionel Sambuc ///
1532f4a2713aSLionel Sambuc ///   extern module-declaration:
1533f4a2713aSLionel Sambuc ///     'extern' 'module' module-id string-literal
parseExternModuleDecl()1534f4a2713aSLionel Sambuc void ModuleMapParser::parseExternModuleDecl() {
1535f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::ExternKeyword));
1536f4a2713aSLionel Sambuc   consumeToken(); // 'extern' keyword
1537f4a2713aSLionel Sambuc 
1538f4a2713aSLionel Sambuc   // Parse 'module' keyword.
1539f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::ModuleKeyword)) {
1540f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1541f4a2713aSLionel Sambuc     consumeToken();
1542f4a2713aSLionel Sambuc     HadError = true;
1543f4a2713aSLionel Sambuc     return;
1544f4a2713aSLionel Sambuc   }
1545f4a2713aSLionel Sambuc   consumeToken(); // 'module' keyword
1546f4a2713aSLionel Sambuc 
1547f4a2713aSLionel Sambuc   // Parse the module name.
1548f4a2713aSLionel Sambuc   ModuleId Id;
1549f4a2713aSLionel Sambuc   if (parseModuleId(Id)) {
1550f4a2713aSLionel Sambuc     HadError = true;
1551f4a2713aSLionel Sambuc     return;
1552f4a2713aSLionel Sambuc   }
1553f4a2713aSLionel Sambuc 
1554f4a2713aSLionel Sambuc   // Parse the referenced module map file name.
1555f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::StringLiteral)) {
1556f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
1557f4a2713aSLionel Sambuc     HadError = true;
1558f4a2713aSLionel Sambuc     return;
1559f4a2713aSLionel Sambuc   }
1560f4a2713aSLionel Sambuc   std::string FileName = Tok.getString();
1561f4a2713aSLionel Sambuc   consumeToken(); // filename
1562f4a2713aSLionel Sambuc 
1563f4a2713aSLionel Sambuc   StringRef FileNameRef = FileName;
1564f4a2713aSLionel Sambuc   SmallString<128> ModuleMapFileName;
1565f4a2713aSLionel Sambuc   if (llvm::sys::path::is_relative(FileNameRef)) {
1566f4a2713aSLionel Sambuc     ModuleMapFileName += Directory->getName();
1567f4a2713aSLionel Sambuc     llvm::sys::path::append(ModuleMapFileName, FileName);
1568f4a2713aSLionel Sambuc     FileNameRef = ModuleMapFileName.str();
1569f4a2713aSLionel Sambuc   }
1570f4a2713aSLionel Sambuc   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
1571*0a6a1f1dSLionel Sambuc     Map.parseModuleMapFile(
1572*0a6a1f1dSLionel Sambuc         File, /*IsSystem=*/false,
1573*0a6a1f1dSLionel Sambuc         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
1574*0a6a1f1dSLionel Sambuc             ? Directory
1575*0a6a1f1dSLionel Sambuc             : File->getDir());
1576f4a2713aSLionel Sambuc }
1577f4a2713aSLionel Sambuc 
1578f4a2713aSLionel Sambuc /// \brief Parse a requires declaration.
1579f4a2713aSLionel Sambuc ///
1580f4a2713aSLionel Sambuc ///   requires-declaration:
1581f4a2713aSLionel Sambuc ///     'requires' feature-list
1582f4a2713aSLionel Sambuc ///
1583f4a2713aSLionel Sambuc ///   feature-list:
1584f4a2713aSLionel Sambuc ///     feature ',' feature-list
1585f4a2713aSLionel Sambuc ///     feature
1586f4a2713aSLionel Sambuc ///
1587f4a2713aSLionel Sambuc ///   feature:
1588f4a2713aSLionel Sambuc ///     '!'[opt] identifier
parseRequiresDecl()1589f4a2713aSLionel Sambuc void ModuleMapParser::parseRequiresDecl() {
1590f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::RequiresKeyword));
1591f4a2713aSLionel Sambuc 
1592f4a2713aSLionel Sambuc   // Parse 'requires' keyword.
1593f4a2713aSLionel Sambuc   consumeToken();
1594f4a2713aSLionel Sambuc 
1595f4a2713aSLionel Sambuc   // Parse the feature-list.
1596f4a2713aSLionel Sambuc   do {
1597f4a2713aSLionel Sambuc     bool RequiredState = true;
1598f4a2713aSLionel Sambuc     if (Tok.is(MMToken::Exclaim)) {
1599f4a2713aSLionel Sambuc       RequiredState = false;
1600f4a2713aSLionel Sambuc       consumeToken();
1601f4a2713aSLionel Sambuc     }
1602f4a2713aSLionel Sambuc 
1603f4a2713aSLionel Sambuc     if (!Tok.is(MMToken::Identifier)) {
1604f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1605f4a2713aSLionel Sambuc       HadError = true;
1606f4a2713aSLionel Sambuc       return;
1607f4a2713aSLionel Sambuc     }
1608f4a2713aSLionel Sambuc 
1609f4a2713aSLionel Sambuc     // Consume the feature name.
1610f4a2713aSLionel Sambuc     std::string Feature = Tok.getString();
1611f4a2713aSLionel Sambuc     consumeToken();
1612f4a2713aSLionel Sambuc 
1613f4a2713aSLionel Sambuc     // Add this feature.
1614f4a2713aSLionel Sambuc     ActiveModule->addRequirement(Feature, RequiredState,
1615f4a2713aSLionel Sambuc                                  Map.LangOpts, *Map.Target);
1616f4a2713aSLionel Sambuc 
1617f4a2713aSLionel Sambuc     if (!Tok.is(MMToken::Comma))
1618f4a2713aSLionel Sambuc       break;
1619f4a2713aSLionel Sambuc 
1620f4a2713aSLionel Sambuc     // Consume the comma.
1621f4a2713aSLionel Sambuc     consumeToken();
1622f4a2713aSLionel Sambuc   } while (true);
1623f4a2713aSLionel Sambuc }
1624f4a2713aSLionel Sambuc 
1625f4a2713aSLionel Sambuc /// \brief Append to \p Paths the set of paths needed to get to the
1626f4a2713aSLionel Sambuc /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)1627f4a2713aSLionel Sambuc static void appendSubframeworkPaths(Module *Mod,
1628f4a2713aSLionel Sambuc                                     SmallVectorImpl<char> &Path) {
1629f4a2713aSLionel Sambuc   // Collect the framework names from the given module to the top-level module.
1630f4a2713aSLionel Sambuc   SmallVector<StringRef, 2> Paths;
1631f4a2713aSLionel Sambuc   for (; Mod; Mod = Mod->Parent) {
1632f4a2713aSLionel Sambuc     if (Mod->IsFramework)
1633f4a2713aSLionel Sambuc       Paths.push_back(Mod->Name);
1634f4a2713aSLionel Sambuc   }
1635f4a2713aSLionel Sambuc 
1636f4a2713aSLionel Sambuc   if (Paths.empty())
1637f4a2713aSLionel Sambuc     return;
1638f4a2713aSLionel Sambuc 
1639f4a2713aSLionel Sambuc   // Add Frameworks/Name.framework for each subframework.
1640f4a2713aSLionel Sambuc   for (unsigned I = Paths.size() - 1; I != 0; --I)
1641f4a2713aSLionel Sambuc     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1642f4a2713aSLionel Sambuc }
1643f4a2713aSLionel Sambuc 
1644f4a2713aSLionel Sambuc /// \brief Parse a header declaration.
1645f4a2713aSLionel Sambuc ///
1646f4a2713aSLionel Sambuc ///   header-declaration:
1647*0a6a1f1dSLionel Sambuc ///     'textual'[opt] 'header' string-literal
1648*0a6a1f1dSLionel Sambuc ///     'private' 'textual'[opt] 'header' string-literal
1649*0a6a1f1dSLionel Sambuc ///     'exclude' 'header' string-literal
1650*0a6a1f1dSLionel Sambuc ///     'umbrella' 'header' string-literal
1651*0a6a1f1dSLionel Sambuc ///
1652*0a6a1f1dSLionel Sambuc /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)1653f4a2713aSLionel Sambuc void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
1654f4a2713aSLionel Sambuc                                       SourceLocation LeadingLoc) {
1655*0a6a1f1dSLionel Sambuc   // We've already consumed the first token.
1656*0a6a1f1dSLionel Sambuc   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
1657*0a6a1f1dSLionel Sambuc   if (LeadingToken == MMToken::PrivateKeyword) {
1658*0a6a1f1dSLionel Sambuc     Role = ModuleMap::PrivateHeader;
1659*0a6a1f1dSLionel Sambuc     // 'private' may optionally be followed by 'textual'.
1660*0a6a1f1dSLionel Sambuc     if (Tok.is(MMToken::TextualKeyword)) {
1661*0a6a1f1dSLionel Sambuc       LeadingToken = Tok.Kind;
1662f4a2713aSLionel Sambuc       consumeToken();
1663*0a6a1f1dSLionel Sambuc     }
1664*0a6a1f1dSLionel Sambuc   }
1665*0a6a1f1dSLionel Sambuc   if (LeadingToken == MMToken::TextualKeyword)
1666*0a6a1f1dSLionel Sambuc     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
1667*0a6a1f1dSLionel Sambuc 
1668*0a6a1f1dSLionel Sambuc   if (LeadingToken != MMToken::HeaderKeyword) {
1669*0a6a1f1dSLionel Sambuc     if (!Tok.is(MMToken::HeaderKeyword)) {
1670*0a6a1f1dSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1671*0a6a1f1dSLionel Sambuc           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
1672*0a6a1f1dSLionel Sambuc               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
1673*0a6a1f1dSLionel Sambuc               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
1674*0a6a1f1dSLionel Sambuc       return;
1675*0a6a1f1dSLionel Sambuc     }
1676*0a6a1f1dSLionel Sambuc     consumeToken();
1677*0a6a1f1dSLionel Sambuc   }
1678f4a2713aSLionel Sambuc 
1679f4a2713aSLionel Sambuc   // Parse the header name.
1680f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::StringLiteral)) {
1681f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1682f4a2713aSLionel Sambuc       << "header";
1683f4a2713aSLionel Sambuc     HadError = true;
1684f4a2713aSLionel Sambuc     return;
1685f4a2713aSLionel Sambuc   }
1686*0a6a1f1dSLionel Sambuc   Module::UnresolvedHeaderDirective Header;
1687*0a6a1f1dSLionel Sambuc   Header.FileName = Tok.getString();
1688*0a6a1f1dSLionel Sambuc   Header.FileNameLoc = consumeToken();
1689f4a2713aSLionel Sambuc 
1690f4a2713aSLionel Sambuc   // Check whether we already have an umbrella.
1691f4a2713aSLionel Sambuc   if (LeadingToken == MMToken::UmbrellaKeyword && ActiveModule->Umbrella) {
1692*0a6a1f1dSLionel Sambuc     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
1693f4a2713aSLionel Sambuc       << ActiveModule->getFullModuleName();
1694f4a2713aSLionel Sambuc     HadError = true;
1695f4a2713aSLionel Sambuc     return;
1696f4a2713aSLionel Sambuc   }
1697f4a2713aSLionel Sambuc 
1698f4a2713aSLionel Sambuc   // Look for this file.
1699*0a6a1f1dSLionel Sambuc   const FileEntry *File = nullptr;
1700*0a6a1f1dSLionel Sambuc   const FileEntry *BuiltinFile = nullptr;
1701*0a6a1f1dSLionel Sambuc   SmallString<128> RelativePathName;
1702*0a6a1f1dSLionel Sambuc   if (llvm::sys::path::is_absolute(Header.FileName)) {
1703*0a6a1f1dSLionel Sambuc     RelativePathName = Header.FileName;
1704*0a6a1f1dSLionel Sambuc     File = SourceMgr.getFileManager().getFile(RelativePathName);
1705f4a2713aSLionel Sambuc   } else {
1706f4a2713aSLionel Sambuc     // Search for the header file within the search directory.
1707*0a6a1f1dSLionel Sambuc     SmallString<128> FullPathName(Directory->getName());
1708*0a6a1f1dSLionel Sambuc     unsigned FullPathLength = FullPathName.size();
1709f4a2713aSLionel Sambuc 
1710f4a2713aSLionel Sambuc     if (ActiveModule->isPartOfFramework()) {
1711*0a6a1f1dSLionel Sambuc       appendSubframeworkPaths(ActiveModule, RelativePathName);
1712f4a2713aSLionel Sambuc 
1713f4a2713aSLionel Sambuc       // Check whether this file is in the public headers.
1714*0a6a1f1dSLionel Sambuc       llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1715*0a6a1f1dSLionel Sambuc       llvm::sys::path::append(FullPathName, RelativePathName.str());
1716*0a6a1f1dSLionel Sambuc       File = SourceMgr.getFileManager().getFile(FullPathName);
1717f4a2713aSLionel Sambuc 
1718f4a2713aSLionel Sambuc       if (!File) {
1719f4a2713aSLionel Sambuc         // Check whether this file is in the private headers.
1720*0a6a1f1dSLionel Sambuc         // FIXME: Should we retain the subframework paths here?
1721*0a6a1f1dSLionel Sambuc         RelativePathName.clear();
1722*0a6a1f1dSLionel Sambuc         FullPathName.resize(FullPathLength);
1723*0a6a1f1dSLionel Sambuc         llvm::sys::path::append(RelativePathName, "PrivateHeaders",
1724*0a6a1f1dSLionel Sambuc                                 Header.FileName);
1725*0a6a1f1dSLionel Sambuc         llvm::sys::path::append(FullPathName, RelativePathName.str());
1726*0a6a1f1dSLionel Sambuc         File = SourceMgr.getFileManager().getFile(FullPathName);
1727f4a2713aSLionel Sambuc       }
1728f4a2713aSLionel Sambuc     } else {
1729f4a2713aSLionel Sambuc       // Lookup for normal headers.
1730*0a6a1f1dSLionel Sambuc       llvm::sys::path::append(RelativePathName, Header.FileName);
1731*0a6a1f1dSLionel Sambuc       llvm::sys::path::append(FullPathName, RelativePathName.str());
1732*0a6a1f1dSLionel Sambuc       File = SourceMgr.getFileManager().getFile(FullPathName);
1733f4a2713aSLionel Sambuc 
1734f4a2713aSLionel Sambuc       // If this is a system module with a top-level header, this header
1735f4a2713aSLionel Sambuc       // may have a counterpart (or replacement) in the set of headers
1736f4a2713aSLionel Sambuc       // supplied by Clang. Find that builtin header.
1737f4a2713aSLionel Sambuc       if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword &&
1738f4a2713aSLionel Sambuc           BuiltinIncludeDir && BuiltinIncludeDir != Directory &&
1739*0a6a1f1dSLionel Sambuc           isBuiltinHeader(Header.FileName)) {
1740f4a2713aSLionel Sambuc         SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
1741*0a6a1f1dSLionel Sambuc         llvm::sys::path::append(BuiltinPathName, Header.FileName);
1742f4a2713aSLionel Sambuc         BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1743f4a2713aSLionel Sambuc 
1744f4a2713aSLionel Sambuc         // If Clang supplies this header but the underlying system does not,
1745f4a2713aSLionel Sambuc         // just silently swap in our builtin version. Otherwise, we'll end
1746f4a2713aSLionel Sambuc         // up adding both (later).
1747f4a2713aSLionel Sambuc         if (!File && BuiltinFile) {
1748f4a2713aSLionel Sambuc           File = BuiltinFile;
1749*0a6a1f1dSLionel Sambuc           RelativePathName = BuiltinPathName;
1750*0a6a1f1dSLionel Sambuc           BuiltinFile = nullptr;
1751f4a2713aSLionel Sambuc         }
1752f4a2713aSLionel Sambuc       }
1753f4a2713aSLionel Sambuc     }
1754f4a2713aSLionel Sambuc   }
1755f4a2713aSLionel Sambuc 
1756f4a2713aSLionel Sambuc   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1757f4a2713aSLionel Sambuc   // Come up with a lazy way to do this.
1758f4a2713aSLionel Sambuc   if (File) {
1759f4a2713aSLionel Sambuc     if (LeadingToken == MMToken::UmbrellaKeyword) {
1760f4a2713aSLionel Sambuc       const DirectoryEntry *UmbrellaDir = File->getDir();
1761f4a2713aSLionel Sambuc       if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
1762f4a2713aSLionel Sambuc         Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash)
1763f4a2713aSLionel Sambuc           << UmbrellaModule->getFullModuleName();
1764f4a2713aSLionel Sambuc         HadError = true;
1765f4a2713aSLionel Sambuc       } else {
1766f4a2713aSLionel Sambuc         // Record this umbrella header.
1767f4a2713aSLionel Sambuc         Map.setUmbrellaHeader(ActiveModule, File);
1768f4a2713aSLionel Sambuc       }
1769*0a6a1f1dSLionel Sambuc     } else if (LeadingToken == MMToken::ExcludeKeyword) {
1770*0a6a1f1dSLionel Sambuc       Module::Header H = {RelativePathName.str(), File};
1771*0a6a1f1dSLionel Sambuc       Map.excludeHeader(ActiveModule, H);
1772f4a2713aSLionel Sambuc     } else {
1773*0a6a1f1dSLionel Sambuc       // If there is a builtin counterpart to this file, add it now, before
1774*0a6a1f1dSLionel Sambuc       // the "real" header, so we build the built-in one first when building
1775*0a6a1f1dSLionel Sambuc       // the module.
1776*0a6a1f1dSLionel Sambuc       if (BuiltinFile) {
1777*0a6a1f1dSLionel Sambuc         // FIXME: Taking the name from the FileEntry is unstable and can give
1778*0a6a1f1dSLionel Sambuc         // different results depending on how we've previously named that file
1779*0a6a1f1dSLionel Sambuc         // in this build.
1780*0a6a1f1dSLionel Sambuc         Module::Header H = { BuiltinFile->getName(), BuiltinFile };
1781*0a6a1f1dSLionel Sambuc         Map.addHeader(ActiveModule, H, Role);
1782*0a6a1f1dSLionel Sambuc       }
1783*0a6a1f1dSLionel Sambuc 
1784f4a2713aSLionel Sambuc       // Record this header.
1785*0a6a1f1dSLionel Sambuc       Module::Header H = { RelativePathName.str(), File };
1786*0a6a1f1dSLionel Sambuc       Map.addHeader(ActiveModule, H, Role);
1787f4a2713aSLionel Sambuc     }
1788f4a2713aSLionel Sambuc   } else if (LeadingToken != MMToken::ExcludeKeyword) {
1789f4a2713aSLionel Sambuc     // Ignore excluded header files. They're optional anyway.
1790f4a2713aSLionel Sambuc 
1791*0a6a1f1dSLionel Sambuc     // If we find a module that has a missing header, we mark this module as
1792*0a6a1f1dSLionel Sambuc     // unavailable and store the header directive for displaying diagnostics.
1793*0a6a1f1dSLionel Sambuc     Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
1794*0a6a1f1dSLionel Sambuc     ActiveModule->markUnavailable();
1795*0a6a1f1dSLionel Sambuc     ActiveModule->MissingHeaders.push_back(Header);
1796f4a2713aSLionel Sambuc   }
1797f4a2713aSLionel Sambuc }
1798f4a2713aSLionel Sambuc 
1799f4a2713aSLionel Sambuc /// \brief Parse an umbrella directory declaration.
1800f4a2713aSLionel Sambuc ///
1801f4a2713aSLionel Sambuc ///   umbrella-dir-declaration:
1802f4a2713aSLionel Sambuc ///     umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)1803f4a2713aSLionel Sambuc void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1804f4a2713aSLionel Sambuc   // Parse the directory name.
1805f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::StringLiteral)) {
1806f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1807f4a2713aSLionel Sambuc       << "umbrella";
1808f4a2713aSLionel Sambuc     HadError = true;
1809f4a2713aSLionel Sambuc     return;
1810f4a2713aSLionel Sambuc   }
1811f4a2713aSLionel Sambuc 
1812f4a2713aSLionel Sambuc   std::string DirName = Tok.getString();
1813f4a2713aSLionel Sambuc   SourceLocation DirNameLoc = consumeToken();
1814f4a2713aSLionel Sambuc 
1815f4a2713aSLionel Sambuc   // Check whether we already have an umbrella.
1816f4a2713aSLionel Sambuc   if (ActiveModule->Umbrella) {
1817f4a2713aSLionel Sambuc     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1818f4a2713aSLionel Sambuc       << ActiveModule->getFullModuleName();
1819f4a2713aSLionel Sambuc     HadError = true;
1820f4a2713aSLionel Sambuc     return;
1821f4a2713aSLionel Sambuc   }
1822f4a2713aSLionel Sambuc 
1823f4a2713aSLionel Sambuc   // Look for this file.
1824*0a6a1f1dSLionel Sambuc   const DirectoryEntry *Dir = nullptr;
1825f4a2713aSLionel Sambuc   if (llvm::sys::path::is_absolute(DirName))
1826f4a2713aSLionel Sambuc     Dir = SourceMgr.getFileManager().getDirectory(DirName);
1827f4a2713aSLionel Sambuc   else {
1828f4a2713aSLionel Sambuc     SmallString<128> PathName;
1829f4a2713aSLionel Sambuc     PathName = Directory->getName();
1830f4a2713aSLionel Sambuc     llvm::sys::path::append(PathName, DirName);
1831f4a2713aSLionel Sambuc     Dir = SourceMgr.getFileManager().getDirectory(PathName);
1832f4a2713aSLionel Sambuc   }
1833f4a2713aSLionel Sambuc 
1834f4a2713aSLionel Sambuc   if (!Dir) {
1835f4a2713aSLionel Sambuc     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1836f4a2713aSLionel Sambuc       << DirName;
1837f4a2713aSLionel Sambuc     HadError = true;
1838f4a2713aSLionel Sambuc     return;
1839f4a2713aSLionel Sambuc   }
1840f4a2713aSLionel Sambuc 
1841f4a2713aSLionel Sambuc   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1842f4a2713aSLionel Sambuc     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1843f4a2713aSLionel Sambuc       << OwningModule->getFullModuleName();
1844f4a2713aSLionel Sambuc     HadError = true;
1845f4a2713aSLionel Sambuc     return;
1846f4a2713aSLionel Sambuc   }
1847f4a2713aSLionel Sambuc 
1848f4a2713aSLionel Sambuc   // Record this umbrella directory.
1849f4a2713aSLionel Sambuc   Map.setUmbrellaDir(ActiveModule, Dir);
1850f4a2713aSLionel Sambuc }
1851f4a2713aSLionel Sambuc 
1852f4a2713aSLionel Sambuc /// \brief Parse a module export declaration.
1853f4a2713aSLionel Sambuc ///
1854f4a2713aSLionel Sambuc ///   export-declaration:
1855f4a2713aSLionel Sambuc ///     'export' wildcard-module-id
1856f4a2713aSLionel Sambuc ///
1857f4a2713aSLionel Sambuc ///   wildcard-module-id:
1858f4a2713aSLionel Sambuc ///     identifier
1859f4a2713aSLionel Sambuc ///     '*'
1860f4a2713aSLionel Sambuc ///     identifier '.' wildcard-module-id
parseExportDecl()1861f4a2713aSLionel Sambuc void ModuleMapParser::parseExportDecl() {
1862f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::ExportKeyword));
1863f4a2713aSLionel Sambuc   SourceLocation ExportLoc = consumeToken();
1864f4a2713aSLionel Sambuc 
1865f4a2713aSLionel Sambuc   // Parse the module-id with an optional wildcard at the end.
1866f4a2713aSLionel Sambuc   ModuleId ParsedModuleId;
1867f4a2713aSLionel Sambuc   bool Wildcard = false;
1868f4a2713aSLionel Sambuc   do {
1869*0a6a1f1dSLionel Sambuc     // FIXME: Support string-literal module names here.
1870f4a2713aSLionel Sambuc     if (Tok.is(MMToken::Identifier)) {
1871f4a2713aSLionel Sambuc       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1872f4a2713aSLionel Sambuc                                               Tok.getLocation()));
1873f4a2713aSLionel Sambuc       consumeToken();
1874f4a2713aSLionel Sambuc 
1875f4a2713aSLionel Sambuc       if (Tok.is(MMToken::Period)) {
1876f4a2713aSLionel Sambuc         consumeToken();
1877f4a2713aSLionel Sambuc         continue;
1878f4a2713aSLionel Sambuc       }
1879f4a2713aSLionel Sambuc 
1880f4a2713aSLionel Sambuc       break;
1881f4a2713aSLionel Sambuc     }
1882f4a2713aSLionel Sambuc 
1883f4a2713aSLionel Sambuc     if(Tok.is(MMToken::Star)) {
1884f4a2713aSLionel Sambuc       Wildcard = true;
1885f4a2713aSLionel Sambuc       consumeToken();
1886f4a2713aSLionel Sambuc       break;
1887f4a2713aSLionel Sambuc     }
1888f4a2713aSLionel Sambuc 
1889f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
1890f4a2713aSLionel Sambuc     HadError = true;
1891f4a2713aSLionel Sambuc     return;
1892f4a2713aSLionel Sambuc   } while (true);
1893f4a2713aSLionel Sambuc 
1894f4a2713aSLionel Sambuc   Module::UnresolvedExportDecl Unresolved = {
1895f4a2713aSLionel Sambuc     ExportLoc, ParsedModuleId, Wildcard
1896f4a2713aSLionel Sambuc   };
1897f4a2713aSLionel Sambuc   ActiveModule->UnresolvedExports.push_back(Unresolved);
1898f4a2713aSLionel Sambuc }
1899f4a2713aSLionel Sambuc 
1900f4a2713aSLionel Sambuc /// \brief Parse a module uses declaration.
1901f4a2713aSLionel Sambuc ///
1902f4a2713aSLionel Sambuc ///   uses-declaration:
1903f4a2713aSLionel Sambuc ///     'uses' wildcard-module-id
parseUseDecl()1904f4a2713aSLionel Sambuc void ModuleMapParser::parseUseDecl() {
1905f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::UseKeyword));
1906f4a2713aSLionel Sambuc   consumeToken();
1907f4a2713aSLionel Sambuc   // Parse the module-id.
1908f4a2713aSLionel Sambuc   ModuleId ParsedModuleId;
1909*0a6a1f1dSLionel Sambuc   parseModuleId(ParsedModuleId);
1910f4a2713aSLionel Sambuc 
1911f4a2713aSLionel Sambuc   ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
1912f4a2713aSLionel Sambuc }
1913f4a2713aSLionel Sambuc 
1914f4a2713aSLionel Sambuc /// \brief Parse a link declaration.
1915f4a2713aSLionel Sambuc ///
1916f4a2713aSLionel Sambuc ///   module-declaration:
1917f4a2713aSLionel Sambuc ///     'link' 'framework'[opt] string-literal
parseLinkDecl()1918f4a2713aSLionel Sambuc void ModuleMapParser::parseLinkDecl() {
1919f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::LinkKeyword));
1920f4a2713aSLionel Sambuc   SourceLocation LinkLoc = consumeToken();
1921f4a2713aSLionel Sambuc 
1922f4a2713aSLionel Sambuc   // Parse the optional 'framework' keyword.
1923f4a2713aSLionel Sambuc   bool IsFramework = false;
1924f4a2713aSLionel Sambuc   if (Tok.is(MMToken::FrameworkKeyword)) {
1925f4a2713aSLionel Sambuc     consumeToken();
1926f4a2713aSLionel Sambuc     IsFramework = true;
1927f4a2713aSLionel Sambuc   }
1928f4a2713aSLionel Sambuc 
1929f4a2713aSLionel Sambuc   // Parse the library name
1930f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::StringLiteral)) {
1931f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
1932f4a2713aSLionel Sambuc       << IsFramework << SourceRange(LinkLoc);
1933f4a2713aSLionel Sambuc     HadError = true;
1934f4a2713aSLionel Sambuc     return;
1935f4a2713aSLionel Sambuc   }
1936f4a2713aSLionel Sambuc 
1937f4a2713aSLionel Sambuc   std::string LibraryName = Tok.getString();
1938f4a2713aSLionel Sambuc   consumeToken();
1939f4a2713aSLionel Sambuc   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
1940f4a2713aSLionel Sambuc                                                             IsFramework));
1941f4a2713aSLionel Sambuc }
1942f4a2713aSLionel Sambuc 
1943f4a2713aSLionel Sambuc /// \brief Parse a configuration macro declaration.
1944f4a2713aSLionel Sambuc ///
1945f4a2713aSLionel Sambuc ///   module-declaration:
1946f4a2713aSLionel Sambuc ///     'config_macros' attributes[opt] config-macro-list?
1947f4a2713aSLionel Sambuc ///
1948f4a2713aSLionel Sambuc ///   config-macro-list:
1949f4a2713aSLionel Sambuc ///     identifier (',' identifier)?
parseConfigMacros()1950f4a2713aSLionel Sambuc void ModuleMapParser::parseConfigMacros() {
1951f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::ConfigMacros));
1952f4a2713aSLionel Sambuc   SourceLocation ConfigMacrosLoc = consumeToken();
1953f4a2713aSLionel Sambuc 
1954f4a2713aSLionel Sambuc   // Only top-level modules can have configuration macros.
1955f4a2713aSLionel Sambuc   if (ActiveModule->Parent) {
1956f4a2713aSLionel Sambuc     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
1957f4a2713aSLionel Sambuc   }
1958f4a2713aSLionel Sambuc 
1959f4a2713aSLionel Sambuc   // Parse the optional attributes.
1960f4a2713aSLionel Sambuc   Attributes Attrs;
1961f4a2713aSLionel Sambuc   parseOptionalAttributes(Attrs);
1962f4a2713aSLionel Sambuc   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
1963f4a2713aSLionel Sambuc     ActiveModule->ConfigMacrosExhaustive = true;
1964f4a2713aSLionel Sambuc   }
1965f4a2713aSLionel Sambuc 
1966f4a2713aSLionel Sambuc   // If we don't have an identifier, we're done.
1967*0a6a1f1dSLionel Sambuc   // FIXME: Support macros with the same name as a keyword here.
1968f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::Identifier))
1969f4a2713aSLionel Sambuc     return;
1970f4a2713aSLionel Sambuc 
1971f4a2713aSLionel Sambuc   // Consume the first identifier.
1972f4a2713aSLionel Sambuc   if (!ActiveModule->Parent) {
1973f4a2713aSLionel Sambuc     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
1974f4a2713aSLionel Sambuc   }
1975f4a2713aSLionel Sambuc   consumeToken();
1976f4a2713aSLionel Sambuc 
1977f4a2713aSLionel Sambuc   do {
1978f4a2713aSLionel Sambuc     // If there's a comma, consume it.
1979f4a2713aSLionel Sambuc     if (!Tok.is(MMToken::Comma))
1980f4a2713aSLionel Sambuc       break;
1981f4a2713aSLionel Sambuc     consumeToken();
1982f4a2713aSLionel Sambuc 
1983f4a2713aSLionel Sambuc     // We expect to see a macro name here.
1984*0a6a1f1dSLionel Sambuc     // FIXME: Support macros with the same name as a keyword here.
1985f4a2713aSLionel Sambuc     if (!Tok.is(MMToken::Identifier)) {
1986f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
1987f4a2713aSLionel Sambuc       break;
1988f4a2713aSLionel Sambuc     }
1989f4a2713aSLionel Sambuc 
1990f4a2713aSLionel Sambuc     // Consume the macro name.
1991f4a2713aSLionel Sambuc     if (!ActiveModule->Parent) {
1992f4a2713aSLionel Sambuc       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
1993f4a2713aSLionel Sambuc     }
1994f4a2713aSLionel Sambuc     consumeToken();
1995f4a2713aSLionel Sambuc   } while (true);
1996f4a2713aSLionel Sambuc }
1997f4a2713aSLionel Sambuc 
1998f4a2713aSLionel Sambuc /// \brief Format a module-id into a string.
formatModuleId(const ModuleId & Id)1999f4a2713aSLionel Sambuc static std::string formatModuleId(const ModuleId &Id) {
2000f4a2713aSLionel Sambuc   std::string result;
2001f4a2713aSLionel Sambuc   {
2002f4a2713aSLionel Sambuc     llvm::raw_string_ostream OS(result);
2003f4a2713aSLionel Sambuc 
2004f4a2713aSLionel Sambuc     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2005f4a2713aSLionel Sambuc       if (I)
2006f4a2713aSLionel Sambuc         OS << ".";
2007f4a2713aSLionel Sambuc       OS << Id[I].first;
2008f4a2713aSLionel Sambuc     }
2009f4a2713aSLionel Sambuc   }
2010f4a2713aSLionel Sambuc 
2011f4a2713aSLionel Sambuc   return result;
2012f4a2713aSLionel Sambuc }
2013f4a2713aSLionel Sambuc 
2014f4a2713aSLionel Sambuc /// \brief Parse a conflict declaration.
2015f4a2713aSLionel Sambuc ///
2016f4a2713aSLionel Sambuc ///   module-declaration:
2017f4a2713aSLionel Sambuc ///     'conflict' module-id ',' string-literal
parseConflict()2018f4a2713aSLionel Sambuc void ModuleMapParser::parseConflict() {
2019f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::Conflict));
2020f4a2713aSLionel Sambuc   SourceLocation ConflictLoc = consumeToken();
2021f4a2713aSLionel Sambuc   Module::UnresolvedConflict Conflict;
2022f4a2713aSLionel Sambuc 
2023f4a2713aSLionel Sambuc   // Parse the module-id.
2024f4a2713aSLionel Sambuc   if (parseModuleId(Conflict.Id))
2025f4a2713aSLionel Sambuc     return;
2026f4a2713aSLionel Sambuc 
2027f4a2713aSLionel Sambuc   // Parse the ','.
2028f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::Comma)) {
2029f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2030f4a2713aSLionel Sambuc       << SourceRange(ConflictLoc);
2031f4a2713aSLionel Sambuc     return;
2032f4a2713aSLionel Sambuc   }
2033f4a2713aSLionel Sambuc   consumeToken();
2034f4a2713aSLionel Sambuc 
2035f4a2713aSLionel Sambuc   // Parse the message.
2036f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::StringLiteral)) {
2037f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2038f4a2713aSLionel Sambuc       << formatModuleId(Conflict.Id);
2039f4a2713aSLionel Sambuc     return;
2040f4a2713aSLionel Sambuc   }
2041f4a2713aSLionel Sambuc   Conflict.Message = Tok.getString().str();
2042f4a2713aSLionel Sambuc   consumeToken();
2043f4a2713aSLionel Sambuc 
2044f4a2713aSLionel Sambuc   // Add this unresolved conflict.
2045f4a2713aSLionel Sambuc   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2046f4a2713aSLionel Sambuc }
2047f4a2713aSLionel Sambuc 
2048f4a2713aSLionel Sambuc /// \brief Parse an inferred module declaration (wildcard modules).
2049f4a2713aSLionel Sambuc ///
2050f4a2713aSLionel Sambuc ///   module-declaration:
2051f4a2713aSLionel Sambuc ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
2052f4a2713aSLionel Sambuc ///       { inferred-module-member* }
2053f4a2713aSLionel Sambuc ///
2054f4a2713aSLionel Sambuc ///   inferred-module-member:
2055f4a2713aSLionel Sambuc ///     'export' '*'
2056f4a2713aSLionel Sambuc ///     'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)2057f4a2713aSLionel Sambuc void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
2058f4a2713aSLionel Sambuc   assert(Tok.is(MMToken::Star));
2059f4a2713aSLionel Sambuc   SourceLocation StarLoc = consumeToken();
2060f4a2713aSLionel Sambuc   bool Failed = false;
2061f4a2713aSLionel Sambuc 
2062f4a2713aSLionel Sambuc   // Inferred modules must be submodules.
2063f4a2713aSLionel Sambuc   if (!ActiveModule && !Framework) {
2064f4a2713aSLionel Sambuc     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2065f4a2713aSLionel Sambuc     Failed = true;
2066f4a2713aSLionel Sambuc   }
2067f4a2713aSLionel Sambuc 
2068f4a2713aSLionel Sambuc   if (ActiveModule) {
2069f4a2713aSLionel Sambuc     // Inferred modules must have umbrella directories.
2070*0a6a1f1dSLionel Sambuc     if (!Failed && ActiveModule->IsAvailable &&
2071*0a6a1f1dSLionel Sambuc         !ActiveModule->getUmbrellaDir()) {
2072f4a2713aSLionel Sambuc       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2073f4a2713aSLionel Sambuc       Failed = true;
2074f4a2713aSLionel Sambuc     }
2075f4a2713aSLionel Sambuc 
2076f4a2713aSLionel Sambuc     // Check for redefinition of an inferred module.
2077f4a2713aSLionel Sambuc     if (!Failed && ActiveModule->InferSubmodules) {
2078f4a2713aSLionel Sambuc       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2079f4a2713aSLionel Sambuc       if (ActiveModule->InferredSubmoduleLoc.isValid())
2080f4a2713aSLionel Sambuc         Diags.Report(ActiveModule->InferredSubmoduleLoc,
2081f4a2713aSLionel Sambuc                      diag::note_mmap_prev_definition);
2082f4a2713aSLionel Sambuc       Failed = true;
2083f4a2713aSLionel Sambuc     }
2084f4a2713aSLionel Sambuc 
2085f4a2713aSLionel Sambuc     // Check for the 'framework' keyword, which is not permitted here.
2086f4a2713aSLionel Sambuc     if (Framework) {
2087f4a2713aSLionel Sambuc       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2088f4a2713aSLionel Sambuc       Framework = false;
2089f4a2713aSLionel Sambuc     }
2090f4a2713aSLionel Sambuc   } else if (Explicit) {
2091f4a2713aSLionel Sambuc     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2092f4a2713aSLionel Sambuc     Explicit = false;
2093f4a2713aSLionel Sambuc   }
2094f4a2713aSLionel Sambuc 
2095f4a2713aSLionel Sambuc   // If there were any problems with this inferred submodule, skip its body.
2096f4a2713aSLionel Sambuc   if (Failed) {
2097f4a2713aSLionel Sambuc     if (Tok.is(MMToken::LBrace)) {
2098f4a2713aSLionel Sambuc       consumeToken();
2099f4a2713aSLionel Sambuc       skipUntil(MMToken::RBrace);
2100f4a2713aSLionel Sambuc       if (Tok.is(MMToken::RBrace))
2101f4a2713aSLionel Sambuc         consumeToken();
2102f4a2713aSLionel Sambuc     }
2103f4a2713aSLionel Sambuc     HadError = true;
2104f4a2713aSLionel Sambuc     return;
2105f4a2713aSLionel Sambuc   }
2106f4a2713aSLionel Sambuc 
2107f4a2713aSLionel Sambuc   // Parse optional attributes.
2108f4a2713aSLionel Sambuc   Attributes Attrs;
2109f4a2713aSLionel Sambuc   parseOptionalAttributes(Attrs);
2110f4a2713aSLionel Sambuc 
2111f4a2713aSLionel Sambuc   if (ActiveModule) {
2112f4a2713aSLionel Sambuc     // Note that we have an inferred submodule.
2113f4a2713aSLionel Sambuc     ActiveModule->InferSubmodules = true;
2114f4a2713aSLionel Sambuc     ActiveModule->InferredSubmoduleLoc = StarLoc;
2115f4a2713aSLionel Sambuc     ActiveModule->InferExplicitSubmodules = Explicit;
2116f4a2713aSLionel Sambuc   } else {
2117f4a2713aSLionel Sambuc     // We'll be inferring framework modules for this directory.
2118f4a2713aSLionel Sambuc     Map.InferredDirectories[Directory].InferModules = true;
2119*0a6a1f1dSLionel Sambuc     Map.InferredDirectories[Directory].Attrs = Attrs;
2120*0a6a1f1dSLionel Sambuc     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2121*0a6a1f1dSLionel Sambuc     // FIXME: Handle the 'framework' keyword.
2122f4a2713aSLionel Sambuc   }
2123f4a2713aSLionel Sambuc 
2124f4a2713aSLionel Sambuc   // Parse the opening brace.
2125f4a2713aSLionel Sambuc   if (!Tok.is(MMToken::LBrace)) {
2126f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
2127f4a2713aSLionel Sambuc     HadError = true;
2128f4a2713aSLionel Sambuc     return;
2129f4a2713aSLionel Sambuc   }
2130f4a2713aSLionel Sambuc   SourceLocation LBraceLoc = consumeToken();
2131f4a2713aSLionel Sambuc 
2132f4a2713aSLionel Sambuc   // Parse the body of the inferred submodule.
2133f4a2713aSLionel Sambuc   bool Done = false;
2134f4a2713aSLionel Sambuc   do {
2135f4a2713aSLionel Sambuc     switch (Tok.Kind) {
2136f4a2713aSLionel Sambuc     case MMToken::EndOfFile:
2137f4a2713aSLionel Sambuc     case MMToken::RBrace:
2138f4a2713aSLionel Sambuc       Done = true;
2139f4a2713aSLionel Sambuc       break;
2140f4a2713aSLionel Sambuc 
2141f4a2713aSLionel Sambuc     case MMToken::ExcludeKeyword: {
2142f4a2713aSLionel Sambuc       if (ActiveModule) {
2143f4a2713aSLionel Sambuc         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2144*0a6a1f1dSLionel Sambuc           << (ActiveModule != nullptr);
2145f4a2713aSLionel Sambuc         consumeToken();
2146f4a2713aSLionel Sambuc         break;
2147f4a2713aSLionel Sambuc       }
2148f4a2713aSLionel Sambuc 
2149f4a2713aSLionel Sambuc       consumeToken();
2150*0a6a1f1dSLionel Sambuc       // FIXME: Support string-literal module names here.
2151f4a2713aSLionel Sambuc       if (!Tok.is(MMToken::Identifier)) {
2152f4a2713aSLionel Sambuc         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
2153f4a2713aSLionel Sambuc         break;
2154f4a2713aSLionel Sambuc       }
2155f4a2713aSLionel Sambuc 
2156f4a2713aSLionel Sambuc       Map.InferredDirectories[Directory].ExcludedModules
2157f4a2713aSLionel Sambuc         .push_back(Tok.getString());
2158f4a2713aSLionel Sambuc       consumeToken();
2159f4a2713aSLionel Sambuc       break;
2160f4a2713aSLionel Sambuc     }
2161f4a2713aSLionel Sambuc 
2162f4a2713aSLionel Sambuc     case MMToken::ExportKeyword:
2163f4a2713aSLionel Sambuc       if (!ActiveModule) {
2164f4a2713aSLionel Sambuc         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2165*0a6a1f1dSLionel Sambuc           << (ActiveModule != nullptr);
2166f4a2713aSLionel Sambuc         consumeToken();
2167f4a2713aSLionel Sambuc         break;
2168f4a2713aSLionel Sambuc       }
2169f4a2713aSLionel Sambuc 
2170f4a2713aSLionel Sambuc       consumeToken();
2171f4a2713aSLionel Sambuc       if (Tok.is(MMToken::Star))
2172f4a2713aSLionel Sambuc         ActiveModule->InferExportWildcard = true;
2173f4a2713aSLionel Sambuc       else
2174f4a2713aSLionel Sambuc         Diags.Report(Tok.getLocation(),
2175f4a2713aSLionel Sambuc                      diag::err_mmap_expected_export_wildcard);
2176f4a2713aSLionel Sambuc       consumeToken();
2177f4a2713aSLionel Sambuc       break;
2178f4a2713aSLionel Sambuc 
2179f4a2713aSLionel Sambuc     case MMToken::ExplicitKeyword:
2180f4a2713aSLionel Sambuc     case MMToken::ModuleKeyword:
2181f4a2713aSLionel Sambuc     case MMToken::HeaderKeyword:
2182f4a2713aSLionel Sambuc     case MMToken::PrivateKeyword:
2183f4a2713aSLionel Sambuc     case MMToken::UmbrellaKeyword:
2184f4a2713aSLionel Sambuc     default:
2185f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2186*0a6a1f1dSLionel Sambuc           << (ActiveModule != nullptr);
2187f4a2713aSLionel Sambuc       consumeToken();
2188f4a2713aSLionel Sambuc       break;
2189f4a2713aSLionel Sambuc     }
2190f4a2713aSLionel Sambuc   } while (!Done);
2191f4a2713aSLionel Sambuc 
2192f4a2713aSLionel Sambuc   if (Tok.is(MMToken::RBrace))
2193f4a2713aSLionel Sambuc     consumeToken();
2194f4a2713aSLionel Sambuc   else {
2195f4a2713aSLionel Sambuc     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2196f4a2713aSLionel Sambuc     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2197f4a2713aSLionel Sambuc     HadError = true;
2198f4a2713aSLionel Sambuc   }
2199f4a2713aSLionel Sambuc }
2200f4a2713aSLionel Sambuc 
2201f4a2713aSLionel Sambuc /// \brief Parse optional attributes.
2202f4a2713aSLionel Sambuc ///
2203f4a2713aSLionel Sambuc ///   attributes:
2204f4a2713aSLionel Sambuc ///     attribute attributes
2205f4a2713aSLionel Sambuc ///     attribute
2206f4a2713aSLionel Sambuc ///
2207f4a2713aSLionel Sambuc ///   attribute:
2208f4a2713aSLionel Sambuc ///     [ identifier ]
2209f4a2713aSLionel Sambuc ///
2210f4a2713aSLionel Sambuc /// \param Attrs Will be filled in with the parsed attributes.
2211f4a2713aSLionel Sambuc ///
2212f4a2713aSLionel Sambuc /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)2213f4a2713aSLionel Sambuc bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
2214f4a2713aSLionel Sambuc   bool HadError = false;
2215f4a2713aSLionel Sambuc 
2216f4a2713aSLionel Sambuc   while (Tok.is(MMToken::LSquare)) {
2217f4a2713aSLionel Sambuc     // Consume the '['.
2218f4a2713aSLionel Sambuc     SourceLocation LSquareLoc = consumeToken();
2219f4a2713aSLionel Sambuc 
2220f4a2713aSLionel Sambuc     // Check whether we have an attribute name here.
2221f4a2713aSLionel Sambuc     if (!Tok.is(MMToken::Identifier)) {
2222f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
2223f4a2713aSLionel Sambuc       skipUntil(MMToken::RSquare);
2224f4a2713aSLionel Sambuc       if (Tok.is(MMToken::RSquare))
2225f4a2713aSLionel Sambuc         consumeToken();
2226f4a2713aSLionel Sambuc       HadError = true;
2227f4a2713aSLionel Sambuc     }
2228f4a2713aSLionel Sambuc 
2229f4a2713aSLionel Sambuc     // Decode the attribute name.
2230f4a2713aSLionel Sambuc     AttributeKind Attribute
2231f4a2713aSLionel Sambuc       = llvm::StringSwitch<AttributeKind>(Tok.getString())
2232f4a2713aSLionel Sambuc           .Case("exhaustive", AT_exhaustive)
2233*0a6a1f1dSLionel Sambuc           .Case("extern_c", AT_extern_c)
2234f4a2713aSLionel Sambuc           .Case("system", AT_system)
2235f4a2713aSLionel Sambuc           .Default(AT_unknown);
2236f4a2713aSLionel Sambuc     switch (Attribute) {
2237f4a2713aSLionel Sambuc     case AT_unknown:
2238f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
2239f4a2713aSLionel Sambuc         << Tok.getString();
2240f4a2713aSLionel Sambuc       break;
2241f4a2713aSLionel Sambuc 
2242f4a2713aSLionel Sambuc     case AT_system:
2243f4a2713aSLionel Sambuc       Attrs.IsSystem = true;
2244f4a2713aSLionel Sambuc       break;
2245f4a2713aSLionel Sambuc 
2246*0a6a1f1dSLionel Sambuc     case AT_extern_c:
2247*0a6a1f1dSLionel Sambuc       Attrs.IsExternC = true;
2248*0a6a1f1dSLionel Sambuc       break;
2249*0a6a1f1dSLionel Sambuc 
2250f4a2713aSLionel Sambuc     case AT_exhaustive:
2251f4a2713aSLionel Sambuc       Attrs.IsExhaustive = true;
2252f4a2713aSLionel Sambuc       break;
2253f4a2713aSLionel Sambuc     }
2254f4a2713aSLionel Sambuc     consumeToken();
2255f4a2713aSLionel Sambuc 
2256f4a2713aSLionel Sambuc     // Consume the ']'.
2257f4a2713aSLionel Sambuc     if (!Tok.is(MMToken::RSquare)) {
2258f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
2259f4a2713aSLionel Sambuc       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
2260f4a2713aSLionel Sambuc       skipUntil(MMToken::RSquare);
2261f4a2713aSLionel Sambuc       HadError = true;
2262f4a2713aSLionel Sambuc     }
2263f4a2713aSLionel Sambuc 
2264f4a2713aSLionel Sambuc     if (Tok.is(MMToken::RSquare))
2265f4a2713aSLionel Sambuc       consumeToken();
2266f4a2713aSLionel Sambuc   }
2267f4a2713aSLionel Sambuc 
2268f4a2713aSLionel Sambuc   return HadError;
2269f4a2713aSLionel Sambuc }
2270f4a2713aSLionel Sambuc 
2271f4a2713aSLionel Sambuc /// \brief Parse a module map file.
2272f4a2713aSLionel Sambuc ///
2273f4a2713aSLionel Sambuc ///   module-map-file:
2274f4a2713aSLionel Sambuc ///     module-declaration*
parseModuleMapFile()2275f4a2713aSLionel Sambuc bool ModuleMapParser::parseModuleMapFile() {
2276f4a2713aSLionel Sambuc   do {
2277f4a2713aSLionel Sambuc     switch (Tok.Kind) {
2278f4a2713aSLionel Sambuc     case MMToken::EndOfFile:
2279f4a2713aSLionel Sambuc       return HadError;
2280f4a2713aSLionel Sambuc 
2281f4a2713aSLionel Sambuc     case MMToken::ExplicitKeyword:
2282f4a2713aSLionel Sambuc     case MMToken::ExternKeyword:
2283f4a2713aSLionel Sambuc     case MMToken::ModuleKeyword:
2284f4a2713aSLionel Sambuc     case MMToken::FrameworkKeyword:
2285f4a2713aSLionel Sambuc       parseModuleDecl();
2286f4a2713aSLionel Sambuc       break;
2287f4a2713aSLionel Sambuc 
2288f4a2713aSLionel Sambuc     case MMToken::Comma:
2289f4a2713aSLionel Sambuc     case MMToken::ConfigMacros:
2290f4a2713aSLionel Sambuc     case MMToken::Conflict:
2291f4a2713aSLionel Sambuc     case MMToken::Exclaim:
2292f4a2713aSLionel Sambuc     case MMToken::ExcludeKeyword:
2293f4a2713aSLionel Sambuc     case MMToken::ExportKeyword:
2294f4a2713aSLionel Sambuc     case MMToken::HeaderKeyword:
2295f4a2713aSLionel Sambuc     case MMToken::Identifier:
2296f4a2713aSLionel Sambuc     case MMToken::LBrace:
2297f4a2713aSLionel Sambuc     case MMToken::LinkKeyword:
2298f4a2713aSLionel Sambuc     case MMToken::LSquare:
2299f4a2713aSLionel Sambuc     case MMToken::Period:
2300f4a2713aSLionel Sambuc     case MMToken::PrivateKeyword:
2301f4a2713aSLionel Sambuc     case MMToken::RBrace:
2302f4a2713aSLionel Sambuc     case MMToken::RSquare:
2303f4a2713aSLionel Sambuc     case MMToken::RequiresKeyword:
2304f4a2713aSLionel Sambuc     case MMToken::Star:
2305f4a2713aSLionel Sambuc     case MMToken::StringLiteral:
2306*0a6a1f1dSLionel Sambuc     case MMToken::TextualKeyword:
2307f4a2713aSLionel Sambuc     case MMToken::UmbrellaKeyword:
2308f4a2713aSLionel Sambuc     case MMToken::UseKeyword:
2309f4a2713aSLionel Sambuc       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2310f4a2713aSLionel Sambuc       HadError = true;
2311f4a2713aSLionel Sambuc       consumeToken();
2312f4a2713aSLionel Sambuc       break;
2313f4a2713aSLionel Sambuc     }
2314f4a2713aSLionel Sambuc   } while (true);
2315f4a2713aSLionel Sambuc }
2316f4a2713aSLionel Sambuc 
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir)2317*0a6a1f1dSLionel Sambuc bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2318*0a6a1f1dSLionel Sambuc                                    const DirectoryEntry *Dir) {
2319f4a2713aSLionel Sambuc   llvm::DenseMap<const FileEntry *, bool>::iterator Known
2320f4a2713aSLionel Sambuc     = ParsedModuleMap.find(File);
2321f4a2713aSLionel Sambuc   if (Known != ParsedModuleMap.end())
2322f4a2713aSLionel Sambuc     return Known->second;
2323f4a2713aSLionel Sambuc 
2324*0a6a1f1dSLionel Sambuc   assert(Target && "Missing target information");
2325*0a6a1f1dSLionel Sambuc   auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
2326*0a6a1f1dSLionel Sambuc   FileID ID = SourceMgr.createFileID(File, SourceLocation(), FileCharacter);
2327f4a2713aSLionel Sambuc   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2328f4a2713aSLionel Sambuc   if (!Buffer)
2329f4a2713aSLionel Sambuc     return ParsedModuleMap[File] = true;
2330f4a2713aSLionel Sambuc 
2331f4a2713aSLionel Sambuc   // Parse this module map file.
2332f4a2713aSLionel Sambuc   Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts);
2333*0a6a1f1dSLionel Sambuc   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2334f4a2713aSLionel Sambuc                          BuiltinIncludeDir, IsSystem);
2335f4a2713aSLionel Sambuc   bool Result = Parser.parseModuleMapFile();
2336f4a2713aSLionel Sambuc   ParsedModuleMap[File] = Result;
2337f4a2713aSLionel Sambuc   return Result;
2338f4a2713aSLionel Sambuc }
2339