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