blob: de234853fbf3793f12a40f8aef2183eedccbfe10 [file] [log] [blame]
Douglas Gregora30cfe52011-11-11 19:10:28 +00001//===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the ModuleMap implementation, which describes the layout
11// of a module as it relates to headers.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/Lex/ModuleMap.h"
Jordan Rose3f6f51e2013-02-08 22:30:41 +000015#include "clang/Basic/CharInfo.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000016#include "clang/Basic/Diagnostic.h"
Douglas Gregor02c23eb2012-10-23 22:26:28 +000017#include "clang/Basic/DiagnosticOptions.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000018#include "clang/Basic/FileManager.h"
19#include "clang/Basic/TargetInfo.h"
20#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +000021#include "clang/Lex/HeaderSearch.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000022#include "clang/Lex/LexDiagnostic.h"
23#include "clang/Lex/Lexer.h"
24#include "clang/Lex/LiteralSupport.h"
25#include "llvm/ADT/StringRef.h"
26#include "llvm/ADT/StringSwitch.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000027#include "llvm/Support/Allocator.h"
Douglas Gregorac252a32011-12-06 19:39:29 +000028#include "llvm/Support/FileSystem.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000029#include "llvm/Support/Host.h"
Douglas Gregor8b6d3de2011-11-11 21:55:48 +000030#include "llvm/Support/PathV2.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000031#include "llvm/Support/raw_ostream.h"
Douglas Gregor98cfcbf2012-09-27 14:50:15 +000032#include <stdlib.h>
Douglas Gregor3cc62772013-01-22 23:49:45 +000033#if defined(LLVM_ON_UNIX)
Dmitri Gribenkoadeb7822013-01-26 16:29:36 +000034#include <limits.h>
Douglas Gregor3cc62772013-01-22 23:49:45 +000035#endif
Douglas Gregora30cfe52011-11-11 19:10:28 +000036using namespace clang;
37
Douglas Gregor90db2602011-12-02 01:47:07 +000038Module::ExportDecl
39ModuleMap::resolveExport(Module *Mod,
40 const Module::UnresolvedExportDecl &Unresolved,
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +000041 bool Complain) const {
Douglas Gregor0adaa882011-12-05 17:28:06 +000042 // We may have just a wildcard.
43 if (Unresolved.Id.empty()) {
44 assert(Unresolved.Wildcard && "Invalid unresolved export");
45 return Module::ExportDecl(0, true);
46 }
47
Douglas Gregor906d66a2013-03-20 21:10:35 +000048 // Resolve the module-id.
49 Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
50 if (!Context)
51 return Module::ExportDecl();
52
53 return Module::ExportDecl(Context, Unresolved.Wildcard);
54}
55
56Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
57 bool Complain) const {
Douglas Gregor90db2602011-12-02 01:47:07 +000058 // Find the starting module.
Douglas Gregor906d66a2013-03-20 21:10:35 +000059 Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
Douglas Gregor90db2602011-12-02 01:47:07 +000060 if (!Context) {
61 if (Complain)
Douglas Gregor906d66a2013-03-20 21:10:35 +000062 Diags->Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
63 << Id[0].first << Mod->getFullModuleName();
64
65 return 0;
Douglas Gregor90db2602011-12-02 01:47:07 +000066 }
67
68 // Dig into the module path.
Douglas Gregor906d66a2013-03-20 21:10:35 +000069 for (unsigned I = 1, N = Id.size(); I != N; ++I) {
70 Module *Sub = lookupModuleQualified(Id[I].first, Context);
Douglas Gregor90db2602011-12-02 01:47:07 +000071 if (!Sub) {
72 if (Complain)
Douglas Gregor906d66a2013-03-20 21:10:35 +000073 Diags->Report(Id[I].second, diag::err_mmap_missing_module_qualified)
74 << Id[I].first << Context->getFullModuleName()
75 << SourceRange(Id[0].second, Id[I-1].second);
76
77 return 0;
Douglas Gregor90db2602011-12-02 01:47:07 +000078 }
Douglas Gregor906d66a2013-03-20 21:10:35 +000079
Douglas Gregor90db2602011-12-02 01:47:07 +000080 Context = Sub;
81 }
Douglas Gregor906d66a2013-03-20 21:10:35 +000082
83 return Context;
Douglas Gregor90db2602011-12-02 01:47:07 +000084}
85
Douglas Gregora4a90ca2013-05-03 22:58:43 +000086ModuleMap::ModuleMap(FileManager &FileMgr, DiagnosticConsumer &DC,
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +000087 const LangOptions &LangOpts, const TargetInfo *Target,
88 HeaderSearch &HeaderInfo)
89 : LangOpts(LangOpts), Target(Target), HeaderInfo(HeaderInfo),
Argyrios Kyrtzidisd3220db2013-05-08 23:46:46 +000090 BuiltinIncludeDir(0), CompilingModule(0)
Douglas Gregor51f564f2011-12-31 04:05:44 +000091{
Dylan Noblesmithc93dc782012-02-20 14:00:23 +000092 IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
93 Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
Douglas Gregor02c23eb2012-10-23 22:26:28 +000094 new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
Douglas Gregora4a90ca2013-05-03 22:58:43 +000095 Diags->setClient(new ForwardingDiagnosticConsumer(DC),
96 /*ShouldOwnClient=*/true);
Douglas Gregora30cfe52011-11-11 19:10:28 +000097 SourceMgr = new SourceManager(*Diags, FileMgr);
98}
99
100ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +0000101 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
102 IEnd = Modules.end();
103 I != IEnd; ++I) {
104 delete I->getValue();
105 }
106
Douglas Gregora30cfe52011-11-11 19:10:28 +0000107 delete SourceMgr;
108}
109
Douglas Gregordc58aa72012-01-30 06:01:29 +0000110void ModuleMap::setTarget(const TargetInfo &Target) {
111 assert((!this->Target || this->Target == &Target) &&
112 "Improper target override");
113 this->Target = &Target;
114}
115
Douglas Gregor8b48e082012-10-12 21:15:50 +0000116/// \brief "Sanitize" a filename so that it can be used as an identifier.
117static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
118 SmallVectorImpl<char> &Buffer) {
119 if (Name.empty())
120 return Name;
121
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000122 if (!isValidIdentifier(Name)) {
Douglas Gregor8b48e082012-10-12 21:15:50 +0000123 // If we don't already have something with the form of an identifier,
124 // create a buffer with the sanitized name.
125 Buffer.clear();
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000126 if (isDigit(Name[0]))
Douglas Gregor8b48e082012-10-12 21:15:50 +0000127 Buffer.push_back('_');
128 Buffer.reserve(Buffer.size() + Name.size());
129 for (unsigned I = 0, N = Name.size(); I != N; ++I) {
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000130 if (isIdentifierBody(Name[I]))
Douglas Gregor8b48e082012-10-12 21:15:50 +0000131 Buffer.push_back(Name[I]);
132 else
133 Buffer.push_back('_');
134 }
135
136 Name = StringRef(Buffer.data(), Buffer.size());
137 }
138
139 while (llvm::StringSwitch<bool>(Name)
140#define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
141#define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
142#include "clang/Basic/TokenKinds.def"
143 .Default(false)) {
144 if (Name.data() != Buffer.data())
145 Buffer.append(Name.begin(), Name.end());
146 Buffer.push_back('_');
147 Name = StringRef(Buffer.data(), Buffer.size());
148 }
149
150 return Name;
151}
152
Douglas Gregordb3910b2013-05-02 17:58:30 +0000153/// \brief Determine whether the given file name is the name of a builtin
154/// header, supplied by Clang to replace, override, or augment existing system
155/// headers.
156static bool isBuiltinHeader(StringRef FileName) {
157 return llvm::StringSwitch<bool>(FileName)
158 .Case("float.h", true)
159 .Case("iso646.h", true)
160 .Case("limits.h", true)
161 .Case("stdalign.h", true)
162 .Case("stdarg.h", true)
163 .Case("stdbool.h", true)
164 .Case("stddef.h", true)
165 .Case("stdint.h", true)
166 .Case("tgmath.h", true)
167 .Case("unwind.h", true)
168 .Default(false);
169}
170
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000171Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000172 HeadersMap::iterator Known = Headers.find(File);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000173 if (Known != Headers.end()) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000174 // If a header is not available, don't report that it maps to anything.
175 if (!Known->second.isAvailable())
Douglas Gregor51f564f2011-12-31 04:05:44 +0000176 return 0;
177
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000178 return Known->second.getModule();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000179 }
Douglas Gregordb3910b2013-05-02 17:58:30 +0000180
181 // If we've found a builtin header within Clang's builtin include directory,
182 // load all of the module maps to see if it will get associated with a
183 // specific module (e.g., in /usr/include).
184 if (File->getDir() == BuiltinIncludeDir &&
185 isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
186 SmallVector<Module *, 4> AllModules;
187 HeaderInfo.collectAllModules(AllModules);
188
189 // Check again.
190 Known = Headers.find(File);
191 if (Known != Headers.end()) {
192 // If a header is not available, don't report that it maps to anything.
193 if (!Known->second.isAvailable())
194 return 0;
195
196 return Known->second.getModule();
197 }
198 }
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000199
Douglas Gregoradb97992011-11-16 23:02:25 +0000200 const DirectoryEntry *Dir = File->getDir();
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000201 SmallVector<const DirectoryEntry *, 2> SkippedDirs;
Douglas Gregor713b7c02013-01-26 00:55:12 +0000202
Douglas Gregoraa60f9c2013-01-04 19:44:26 +0000203 // Note: as an egregious but useful hack we use the real path here, because
204 // frameworks moving from top-level frameworks to embedded frameworks tend
205 // to be symlinked from the top-level location to the embedded location,
206 // and we need to resolve lookups as if we had found the embedded location.
Douglas Gregor713b7c02013-01-26 00:55:12 +0000207 StringRef DirName = SourceMgr->getFileManager().getCanonicalName(Dir);
Douglas Gregore209e502011-12-06 01:10:29 +0000208
209 // Keep walking up the directory hierarchy, looking for a directory with
210 // an umbrella header.
211 do {
212 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
213 = UmbrellaDirs.find(Dir);
214 if (KnownDir != UmbrellaDirs.end()) {
215 Module *Result = KnownDir->second;
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000216
217 // Search up the module stack until we find a module with an umbrella
Douglas Gregor10694ce2011-12-08 17:39:04 +0000218 // directory.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000219 Module *UmbrellaModule = Result;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000220 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000221 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000222
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000223 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-12-06 01:10:29 +0000224 // Infer submodules for each of the directories we found between
225 // the directory of the umbrella header and the directory where
226 // the actual header is located.
Douglas Gregor23af6d52011-12-07 22:05:21 +0000227 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregore209e502011-12-06 01:10:29 +0000228
Douglas Gregor6a1db482011-12-09 02:04:43 +0000229 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregore209e502011-12-06 01:10:29 +0000230 // Find or create the module that corresponds to this directory name.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000231 SmallString<32> NameBuf;
232 StringRef Name = sanitizeFilenameAsIdentifier(
233 llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
234 NameBuf);
Douglas Gregore209e502011-12-06 01:10:29 +0000235 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000236 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000237
238 // Associate the module and the directory.
239 UmbrellaDirs[SkippedDirs[I-1]] = Result;
240
241 // If inferred submodules export everything they import, add a
242 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000243 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000244 Result->Exports.push_back(Module::ExportDecl(0, true));
245 }
246
247 // Infer a submodule with the same name as this header file.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000248 SmallString<32> NameBuf;
249 StringRef Name = sanitizeFilenameAsIdentifier(
250 llvm::sys::path::stem(File->getName()), NameBuf);
Douglas Gregore209e502011-12-06 01:10:29 +0000251 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000252 Explicit).first;
Argyrios Kyrtzidisc1d22392013-03-13 21:13:43 +0000253 Result->addTopHeader(File);
Douglas Gregore209e502011-12-06 01:10:29 +0000254
255 // If inferred submodules export everything they import, add a
256 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000257 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000258 Result->Exports.push_back(Module::ExportDecl(0, true));
259 } else {
260 // Record each of the directories we stepped through as being part of
261 // the module we found, since the umbrella header covers them all.
262 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
263 UmbrellaDirs[SkippedDirs[I]] = Result;
264 }
265
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000266 Headers[File] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000267
268 // If a header corresponds to an unavailable module, don't report
269 // that it maps to anything.
270 if (!Result->isAvailable())
271 return 0;
272
Douglas Gregore209e502011-12-06 01:10:29 +0000273 return Result;
274 }
275
276 SkippedDirs.push_back(Dir);
277
Douglas Gregoradb97992011-11-16 23:02:25 +0000278 // Retrieve our parent path.
279 DirName = llvm::sys::path::parent_path(DirName);
280 if (DirName.empty())
281 break;
282
283 // Resolve the parent path to a directory entry.
284 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000285 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000286
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000287 return 0;
288}
289
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000290bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
291 HeadersMap::const_iterator Known = Headers.find(Header);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000292 if (Known != Headers.end())
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000293 return !Known->second.isAvailable();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000294
295 const DirectoryEntry *Dir = Header->getDir();
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000296 SmallVector<const DirectoryEntry *, 2> SkippedDirs;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000297 StringRef DirName = Dir->getName();
298
299 // Keep walking up the directory hierarchy, looking for a directory with
300 // an umbrella header.
301 do {
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000302 llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
Douglas Gregor51f564f2011-12-31 04:05:44 +0000303 = UmbrellaDirs.find(Dir);
304 if (KnownDir != UmbrellaDirs.end()) {
305 Module *Found = KnownDir->second;
306 if (!Found->isAvailable())
307 return true;
308
309 // Search up the module stack until we find a module with an umbrella
310 // directory.
311 Module *UmbrellaModule = Found;
312 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
313 UmbrellaModule = UmbrellaModule->Parent;
314
315 if (UmbrellaModule->InferSubmodules) {
316 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
317 // Find or create the module that corresponds to this directory name.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000318 SmallString<32> NameBuf;
319 StringRef Name = sanitizeFilenameAsIdentifier(
320 llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
321 NameBuf);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000322 Found = lookupModuleQualified(Name, Found);
323 if (!Found)
324 return false;
325 if (!Found->isAvailable())
326 return true;
327 }
328
329 // Infer a submodule with the same name as this header file.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000330 SmallString<32> NameBuf;
331 StringRef Name = sanitizeFilenameAsIdentifier(
332 llvm::sys::path::stem(Header->getName()),
333 NameBuf);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000334 Found = lookupModuleQualified(Name, Found);
335 if (!Found)
336 return false;
337 }
338
339 return !Found->isAvailable();
340 }
341
342 SkippedDirs.push_back(Dir);
343
344 // Retrieve our parent path.
345 DirName = llvm::sys::path::parent_path(DirName);
346 if (DirName.empty())
347 break;
348
349 // Resolve the parent path to a directory entry.
350 Dir = SourceMgr->getFileManager().getDirectory(DirName);
351 } while (Dir);
352
353 return false;
354}
355
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000356Module *ModuleMap::findModule(StringRef Name) const {
357 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
Douglas Gregor484535e2011-11-11 23:20:24 +0000358 if (Known != Modules.end())
359 return Known->getValue();
360
361 return 0;
362}
363
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000364Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
365 Module *Context) const {
Douglas Gregor90db2602011-12-02 01:47:07 +0000366 for(; Context; Context = Context->Parent) {
367 if (Module *Sub = lookupModuleQualified(Name, Context))
368 return Sub;
369 }
370
371 return findModule(Name);
372}
373
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000374Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
Douglas Gregor90db2602011-12-02 01:47:07 +0000375 if (!Context)
376 return findModule(Name);
377
Douglas Gregorb7a78192012-01-04 23:32:19 +0000378 return Context->findSubmodule(Name);
Douglas Gregor90db2602011-12-02 01:47:07 +0000379}
380
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000381std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000382ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
383 bool IsExplicit) {
384 // Try to find an existing module with this name.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000385 if (Module *Sub = lookupModuleQualified(Name, Parent))
386 return std::make_pair(Sub, false);
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000387
388 // Create a new module with this name.
389 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
390 IsExplicit);
Argyrios Kyrtzidisd3220db2013-05-08 23:46:46 +0000391 if (!Parent) {
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000392 Modules[Name] = Result;
Argyrios Kyrtzidisd3220db2013-05-08 23:46:46 +0000393 if (!LangOpts.CurrentModule.empty() && !CompilingModule &&
394 Name == LangOpts.CurrentModule) {
395 CompilingModule = Result;
396 }
397 }
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000398 return std::make_pair(Result, true);
399}
400
Douglas Gregor82e52372012-11-06 19:39:40 +0000401bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000402 StringRef Name, bool &IsSystem) const {
Douglas Gregor82e52372012-11-06 19:39:40 +0000403 // Check whether we have already looked into the parent directory
404 // for a module map.
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000405 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
Douglas Gregor82e52372012-11-06 19:39:40 +0000406 inferred = InferredDirectories.find(ParentDir);
407 if (inferred == InferredDirectories.end())
408 return false;
409
410 if (!inferred->second.InferModules)
411 return false;
412
413 // We're allowed to infer for this directory, but make sure it's okay
414 // to infer this particular module.
415 bool canInfer = std::find(inferred->second.ExcludedModules.begin(),
416 inferred->second.ExcludedModules.end(),
417 Name) == inferred->second.ExcludedModules.end();
418
419 if (canInfer && inferred->second.InferSystemModules)
420 IsSystem = true;
421
422 return canInfer;
423}
424
Douglas Gregor8767dc22013-01-14 17:57:51 +0000425/// \brief For a framework module, infer the framework against which we
426/// should link.
427static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
428 FileManager &FileMgr) {
429 assert(Mod->IsFramework && "Can only infer linking for framework modules");
430 assert(!Mod->isSubFramework() &&
431 "Can only infer linking for top-level frameworks");
432
433 SmallString<128> LibName;
434 LibName += FrameworkDir->getName();
435 llvm::sys::path::append(LibName, Mod->Name);
436 if (FileMgr.getFile(LibName)) {
437 Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
438 /*IsFramework=*/true));
439 }
440}
441
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000442Module *
Douglas Gregor82e52372012-11-06 19:39:40 +0000443ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000444 const DirectoryEntry *FrameworkDir,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000445 bool IsSystem,
Douglas Gregorac252a32011-12-06 19:39:29 +0000446 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000447 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000448 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
449 return Mod;
450
451 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor82e52372012-11-06 19:39:40 +0000452
453 // If the framework has a parent path from which we're allowed to infer
454 // a framework module, do so.
455 if (!Parent) {
Douglas Gregor7005b902013-01-10 01:43:00 +0000456 // Determine whether we're allowed to infer a module map.
Douglas Gregor713b7c02013-01-26 00:55:12 +0000457
Douglas Gregor7005b902013-01-10 01:43:00 +0000458 // Note: as an egregious but useful hack we use the real path here, because
459 // we might be looking at an embedded framework that symlinks out to a
460 // top-level framework, and we need to infer as if we were naming the
461 // top-level framework.
Douglas Gregor713b7c02013-01-26 00:55:12 +0000462 StringRef FrameworkDirName
463 = SourceMgr->getFileManager().getCanonicalName(FrameworkDir);
Douglas Gregor7005b902013-01-10 01:43:00 +0000464
Douglas Gregor82e52372012-11-06 19:39:40 +0000465 bool canInfer = false;
Douglas Gregor7005b902013-01-10 01:43:00 +0000466 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
Douglas Gregor82e52372012-11-06 19:39:40 +0000467 // Figure out the parent path.
Douglas Gregor7005b902013-01-10 01:43:00 +0000468 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
Douglas Gregor82e52372012-11-06 19:39:40 +0000469 if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
470 // Check whether we have already looked into the parent directory
471 // for a module map.
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000472 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
Douglas Gregor82e52372012-11-06 19:39:40 +0000473 inferred = InferredDirectories.find(ParentDir);
474 if (inferred == InferredDirectories.end()) {
475 // We haven't looked here before. Load a module map, if there is
476 // one.
477 SmallString<128> ModMapPath = Parent;
478 llvm::sys::path::append(ModMapPath, "module.map");
479 if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
480 parseModuleMapFile(ModMapFile);
481 inferred = InferredDirectories.find(ParentDir);
482 }
483
484 if (inferred == InferredDirectories.end())
485 inferred = InferredDirectories.insert(
486 std::make_pair(ParentDir, InferredDirectory())).first;
487 }
488
489 if (inferred->second.InferModules) {
490 // We're allowed to infer for this directory, but make sure it's okay
491 // to infer this particular module.
Douglas Gregor7005b902013-01-10 01:43:00 +0000492 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
Douglas Gregor82e52372012-11-06 19:39:40 +0000493 canInfer = std::find(inferred->second.ExcludedModules.begin(),
494 inferred->second.ExcludedModules.end(),
495 Name) == inferred->second.ExcludedModules.end();
496
497 if (inferred->second.InferSystemModules)
498 IsSystem = true;
499 }
500 }
501 }
502
503 // If we're not allowed to infer a framework module, don't.
504 if (!canInfer)
505 return 0;
506 }
507
508
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000509 // Look for an umbrella header.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000510 SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000511 llvm::sys::path::append(UmbrellaName, "Headers");
512 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000513 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000514
515 // FIXME: If there's no umbrella header, we could probably scan the
516 // framework to load *everything*. But, it's not clear that this is a good
517 // idea.
518 if (!UmbrellaHeader)
519 return 0;
520
Douglas Gregorac252a32011-12-06 19:39:29 +0000521 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
522 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000523 if (IsSystem)
524 Result->IsSystem = IsSystem;
525
Douglas Gregorb7a78192012-01-04 23:32:19 +0000526 if (!Parent)
Douglas Gregorac252a32011-12-06 19:39:29 +0000527 Modules[ModuleName] = Result;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000528
Douglas Gregor489ad432011-12-08 18:00:48 +0000529 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000530 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000531 Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor3cee31e2011-12-12 23:55:05 +0000532 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000533
534 // export *
535 Result->Exports.push_back(Module::ExportDecl(0, true));
536
Douglas Gregore209e502011-12-06 01:10:29 +0000537 // module * { export * }
538 Result->InferSubmodules = true;
539 Result->InferExportWildcard = true;
540
Douglas Gregorac252a32011-12-06 19:39:29 +0000541 // Look for subframeworks.
542 llvm::error_code EC;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000543 SmallString<128> SubframeworksDirName
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000544 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000545 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000546 SmallString<128> SubframeworksDirNameNative;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000547 llvm::sys::path::native(SubframeworksDirName.str(),
548 SubframeworksDirNameNative);
549 for (llvm::sys::fs::directory_iterator
550 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregorac252a32011-12-06 19:39:29 +0000551 Dir != DirEnd && !EC; Dir.increment(EC)) {
552 if (!StringRef(Dir->path()).endswith(".framework"))
553 continue;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000554
Douglas Gregorac252a32011-12-06 19:39:29 +0000555 if (const DirectoryEntry *SubframeworkDir
556 = FileMgr.getDirectory(Dir->path())) {
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000557 // Note: as an egregious but useful hack, we use the real path here and
558 // check whether it is actually a subdirectory of the parent directory.
559 // This will not be the case if the 'subframework' is actually a symlink
560 // out to a top-level framework.
Douglas Gregor713b7c02013-01-26 00:55:12 +0000561 StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
562 bool FoundParent = false;
563 do {
564 // Get the parent directory name.
565 SubframeworkDirName
566 = llvm::sys::path::parent_path(SubframeworkDirName);
567 if (SubframeworkDirName.empty())
568 break;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000569
Douglas Gregor713b7c02013-01-26 00:55:12 +0000570 if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
571 FoundParent = true;
572 break;
573 }
574 } while (true);
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000575
Douglas Gregor713b7c02013-01-26 00:55:12 +0000576 if (!FoundParent)
577 continue;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000578
Douglas Gregorac252a32011-12-06 19:39:29 +0000579 // FIXME: Do we want to warn about subframeworks without umbrella headers?
Douglas Gregor8b48e082012-10-12 21:15:50 +0000580 SmallString<32> NameBuf;
581 inferFrameworkModule(sanitizeFilenameAsIdentifier(
582 llvm::sys::path::stem(Dir->path()), NameBuf),
583 SubframeworkDir, IsSystem, Result);
Douglas Gregorac252a32011-12-06 19:39:29 +0000584 }
585 }
Douglas Gregor3a110f72012-01-13 16:54:27 +0000586
Douglas Gregor8767dc22013-01-14 17:57:51 +0000587 // If the module is a top-level framework, automatically link against the
588 // framework.
589 if (!Result->isSubFramework()) {
590 inferFrameworkLink(Result, FrameworkDir, FileMgr);
591 }
592
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000593 return Result;
594}
595
Douglas Gregore209e502011-12-06 01:10:29 +0000596void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000597 Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
Douglas Gregor10694ce2011-12-08 17:39:04 +0000598 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000599 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000600}
601
Douglas Gregor77d029f2011-12-08 19:11:24 +0000602void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
603 Mod->Umbrella = UmbrellaDir;
604 UmbrellaDirs[UmbrellaDir] = Mod;
605}
606
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000607void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
608 bool Excluded) {
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +0000609 if (Excluded) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000610 Mod->ExcludedHeaders.push_back(Header);
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +0000611 } else {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000612 Mod->Headers.push_back(Header);
Argyrios Kyrtzidisd3220db2013-05-08 23:46:46 +0000613 bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
614 HeaderInfo.MarkFileModuleHeader(Header, isCompilingModuleHeader);
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +0000615 }
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000616 Headers[Header] = KnownHeader(Mod, Excluded);
Douglas Gregore209e502011-12-06 01:10:29 +0000617}
618
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000619const FileEntry *
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000620ModuleMap::getContainingModuleMapFile(Module *Module) const {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000621 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
622 return 0;
623
624 return SourceMgr->getFileEntryForID(
625 SourceMgr->getFileID(Module->DefinitionLoc));
626}
627
Douglas Gregora30cfe52011-11-11 19:10:28 +0000628void ModuleMap::dump() {
629 llvm::errs() << "Modules:";
630 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
631 MEnd = Modules.end();
632 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000633 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000634
635 llvm::errs() << "Headers:";
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000636 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000637 H != HEnd; ++H) {
638 llvm::errs() << " \"" << H->first->getName() << "\" -> "
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000639 << H->second.getModule()->getFullModuleName() << "\n";
Douglas Gregora30cfe52011-11-11 19:10:28 +0000640 }
641}
642
Douglas Gregor90db2602011-12-02 01:47:07 +0000643bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
644 bool HadError = false;
645 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
646 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
647 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000648 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000649 Mod->Exports.push_back(Export);
650 else
651 HadError = true;
652 }
653 Mod->UnresolvedExports.clear();
654 return HadError;
655}
656
Douglas Gregor906d66a2013-03-20 21:10:35 +0000657bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
658 bool HadError = false;
659 for (unsigned I = 0, N = Mod->UnresolvedConflicts.size(); I != N; ++I) {
660 Module *OtherMod = resolveModuleId(Mod->UnresolvedConflicts[I].Id,
661 Mod, Complain);
662 if (!OtherMod) {
663 HadError = true;
664 continue;
665 }
666
667 Module::Conflict Conflict;
668 Conflict.Other = OtherMod;
669 Conflict.Message = Mod->UnresolvedConflicts[I].Message;
670 Mod->Conflicts.push_back(Conflict);
671 }
672 Mod->UnresolvedConflicts.clear();
673 return HadError;
674}
675
Douglas Gregor55988682011-12-05 16:33:54 +0000676Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
677 if (Loc.isInvalid())
678 return 0;
679
680 // Use the expansion location to determine which module we're in.
681 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
682 if (!ExpansionLoc.isFileID())
683 return 0;
684
685
686 const SourceManager &SrcMgr = Loc.getManager();
687 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor55988682011-12-05 16:33:54 +0000688
Douglas Gregor303aae92012-01-06 17:19:32 +0000689 while (const FileEntry *ExpansionFile
690 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
691 // Find the module that owns this header (if any).
692 if (Module *Mod = findModuleForHeader(ExpansionFile))
693 return Mod;
694
695 // No module owns this header, so look up the inclusion chain to see if
696 // any included header has an associated module.
697 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
698 if (IncludeLoc.isInvalid())
699 return 0;
700
701 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
702 }
703
704 return 0;
Douglas Gregor55988682011-12-05 16:33:54 +0000705}
706
Douglas Gregora30cfe52011-11-11 19:10:28 +0000707//----------------------------------------------------------------------------//
708// Module map file parser
709//----------------------------------------------------------------------------//
710
711namespace clang {
712 /// \brief A token in a module map file.
713 struct MMToken {
714 enum TokenKind {
Douglas Gregor51f564f2011-12-31 04:05:44 +0000715 Comma,
Douglas Gregor63a72682013-03-20 00:22:05 +0000716 ConfigMacros,
Douglas Gregor906d66a2013-03-20 21:10:35 +0000717 Conflict,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000718 EndOfFile,
719 HeaderKeyword,
720 Identifier,
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000721 ExcludeKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000722 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000723 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000724 FrameworkKeyword,
Douglas Gregorb6cbe512013-01-14 17:21:00 +0000725 LinkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000726 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000727 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000728 UmbrellaKeyword,
Douglas Gregor51f564f2011-12-31 04:05:44 +0000729 RequiresKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000730 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000731 StringLiteral,
732 LBrace,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000733 RBrace,
734 LSquare,
735 RSquare
Douglas Gregora30cfe52011-11-11 19:10:28 +0000736 } Kind;
737
738 unsigned Location;
739 unsigned StringLength;
740 const char *StringData;
741
742 void clear() {
743 Kind = EndOfFile;
744 Location = 0;
745 StringLength = 0;
746 StringData = 0;
747 }
748
749 bool is(TokenKind K) const { return Kind == K; }
750
751 SourceLocation getLocation() const {
752 return SourceLocation::getFromRawEncoding(Location);
753 }
754
755 StringRef getString() const {
756 return StringRef(StringData, StringLength);
757 }
758 };
Douglas Gregor82e52372012-11-06 19:39:40 +0000759
760 /// \brief The set of attributes that can be attached to a module.
Bill Wendlingad017fa2012-12-20 19:22:21 +0000761 struct Attributes {
Douglas Gregor63a72682013-03-20 00:22:05 +0000762 Attributes() : IsSystem(), IsExhaustive() { }
Douglas Gregor82e52372012-11-06 19:39:40 +0000763
764 /// \brief Whether this is a system module.
765 unsigned IsSystem : 1;
Douglas Gregor63a72682013-03-20 00:22:05 +0000766
767 /// \brief Whether this is an exhaustive set of configuration macros.
768 unsigned IsExhaustive : 1;
Douglas Gregor82e52372012-11-06 19:39:40 +0000769 };
Douglas Gregora30cfe52011-11-11 19:10:28 +0000770
Douglas Gregor82e52372012-11-06 19:39:40 +0000771
Douglas Gregora30cfe52011-11-11 19:10:28 +0000772 class ModuleMapParser {
773 Lexer &L;
774 SourceManager &SourceMgr;
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000775
776 /// \brief Default target information, used only for string literal
777 /// parsing.
778 const TargetInfo *Target;
779
Douglas Gregora30cfe52011-11-11 19:10:28 +0000780 DiagnosticsEngine &Diags;
781 ModuleMap &Map;
782
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000783 /// \brief The directory that this module map resides in.
784 const DirectoryEntry *Directory;
Douglas Gregor2f04f182012-02-02 18:42:48 +0000785
786 /// \brief The directory containing Clang-supplied headers.
787 const DirectoryEntry *BuiltinIncludeDir;
788
Douglas Gregora30cfe52011-11-11 19:10:28 +0000789 /// \brief Whether an error occurred.
790 bool HadError;
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000791
Douglas Gregora30cfe52011-11-11 19:10:28 +0000792 /// \brief Stores string data for the various string literals referenced
793 /// during parsing.
794 llvm::BumpPtrAllocator StringData;
795
796 /// \brief The current token.
797 MMToken Tok;
798
799 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000800 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000801
802 /// \brief Consume the current token and return its location.
803 SourceLocation consumeToken();
804
805 /// \brief Skip tokens until we reach the a token with the given kind
806 /// (or the end of the file).
807 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000808
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000809 typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
Douglas Gregor587986e2011-12-07 02:23:45 +0000810 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000811 void parseModuleDecl();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000812 void parseRequiresDecl();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000813 void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000814 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000815 void parseExportDecl();
Douglas Gregorb6cbe512013-01-14 17:21:00 +0000816 void parseLinkDecl();
Douglas Gregor63a72682013-03-20 00:22:05 +0000817 void parseConfigMacros();
Douglas Gregor906d66a2013-03-20 21:10:35 +0000818 void parseConflict();
Douglas Gregor82e52372012-11-06 19:39:40 +0000819 void parseInferredModuleDecl(bool Framework, bool Explicit);
Bill Wendlingad017fa2012-12-20 19:22:21 +0000820 bool parseOptionalAttributes(Attributes &Attrs);
Douglas Gregor82e52372012-11-06 19:39:40 +0000821
Douglas Gregor6a1db482011-12-09 02:04:43 +0000822 const DirectoryEntry *getOverriddenHeaderSearchDir();
823
Douglas Gregora30cfe52011-11-11 19:10:28 +0000824 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000825 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000826 const TargetInfo *Target,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000827 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000828 ModuleMap &Map,
Douglas Gregor2f04f182012-02-02 18:42:48 +0000829 const DirectoryEntry *Directory,
830 const DirectoryEntry *BuiltinIncludeDir)
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000831 : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
Douglas Gregor2f04f182012-02-02 18:42:48 +0000832 Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
833 HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000834 {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000835 Tok.clear();
836 consumeToken();
837 }
838
839 bool parseModuleMapFile();
840 };
841}
842
843SourceLocation ModuleMapParser::consumeToken() {
844retry:
845 SourceLocation Result = Tok.getLocation();
846 Tok.clear();
847
848 Token LToken;
849 L.LexFromRawLexer(LToken);
850 Tok.Location = LToken.getLocation().getRawEncoding();
851 switch (LToken.getKind()) {
852 case tok::raw_identifier:
853 Tok.StringData = LToken.getRawIdentifierData();
854 Tok.StringLength = LToken.getLength();
855 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
Douglas Gregor63a72682013-03-20 00:22:05 +0000856 .Case("config_macros", MMToken::ConfigMacros)
Douglas Gregor906d66a2013-03-20 21:10:35 +0000857 .Case("conflict", MMToken::Conflict)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000858 .Case("exclude", MMToken::ExcludeKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000859 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000860 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000861 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregor63a72682013-03-20 00:22:05 +0000862 .Case("header", MMToken::HeaderKeyword)
Douglas Gregorb6cbe512013-01-14 17:21:00 +0000863 .Case("link", MMToken::LinkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000864 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor51f564f2011-12-31 04:05:44 +0000865 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000866 .Case("umbrella", MMToken::UmbrellaKeyword)
867 .Default(MMToken::Identifier);
868 break;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000869
870 case tok::comma:
871 Tok.Kind = MMToken::Comma;
872 break;
873
Douglas Gregora30cfe52011-11-11 19:10:28 +0000874 case tok::eof:
875 Tok.Kind = MMToken::EndOfFile;
876 break;
877
878 case tok::l_brace:
879 Tok.Kind = MMToken::LBrace;
880 break;
881
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000882 case tok::l_square:
883 Tok.Kind = MMToken::LSquare;
884 break;
885
Douglas Gregor90db2602011-12-02 01:47:07 +0000886 case tok::period:
887 Tok.Kind = MMToken::Period;
888 break;
889
Douglas Gregora30cfe52011-11-11 19:10:28 +0000890 case tok::r_brace:
891 Tok.Kind = MMToken::RBrace;
892 break;
893
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000894 case tok::r_square:
895 Tok.Kind = MMToken::RSquare;
896 break;
897
Douglas Gregor90db2602011-12-02 01:47:07 +0000898 case tok::star:
899 Tok.Kind = MMToken::Star;
900 break;
901
Douglas Gregora30cfe52011-11-11 19:10:28 +0000902 case tok::string_literal: {
Richard Smith99831e42012-03-06 03:21:47 +0000903 if (LToken.hasUDSuffix()) {
904 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
905 HadError = true;
906 goto retry;
907 }
908
Douglas Gregora30cfe52011-11-11 19:10:28 +0000909 // Parse the string literal.
910 LangOptions LangOpts;
911 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
912 if (StringLiteral.hadError)
913 goto retry;
914
915 // Copy the string literal into our string data allocator.
916 unsigned Length = StringLiteral.GetStringLength();
917 char *Saved = StringData.Allocate<char>(Length + 1);
918 memcpy(Saved, StringLiteral.GetString().data(), Length);
919 Saved[Length] = 0;
920
921 // Form the token.
922 Tok.Kind = MMToken::StringLiteral;
923 Tok.StringData = Saved;
924 Tok.StringLength = Length;
925 break;
926 }
927
928 case tok::comment:
929 goto retry;
930
931 default:
932 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
933 HadError = true;
934 goto retry;
935 }
936
937 return Result;
938}
939
940void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
941 unsigned braceDepth = 0;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000942 unsigned squareDepth = 0;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000943 do {
944 switch (Tok.Kind) {
945 case MMToken::EndOfFile:
946 return;
947
948 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000949 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000950 return;
951
952 ++braceDepth;
953 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000954
955 case MMToken::LSquare:
956 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
957 return;
958
959 ++squareDepth;
960 break;
961
Douglas Gregora30cfe52011-11-11 19:10:28 +0000962 case MMToken::RBrace:
963 if (braceDepth > 0)
964 --braceDepth;
965 else if (Tok.is(K))
966 return;
967 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000968
969 case MMToken::RSquare:
970 if (squareDepth > 0)
971 --squareDepth;
972 else if (Tok.is(K))
973 return;
974 break;
975
Douglas Gregora30cfe52011-11-11 19:10:28 +0000976 default:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000977 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregora30cfe52011-11-11 19:10:28 +0000978 return;
979 break;
980 }
981
982 consumeToken();
983 } while (true);
984}
985
Douglas Gregor587986e2011-12-07 02:23:45 +0000986/// \brief Parse a module-id.
987///
988/// module-id:
989/// identifier
990/// identifier '.' module-id
991///
992/// \returns true if an error occurred, false otherwise.
993bool ModuleMapParser::parseModuleId(ModuleId &Id) {
994 Id.clear();
995 do {
996 if (Tok.is(MMToken::Identifier)) {
997 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
998 consumeToken();
999 } else {
1000 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1001 return true;
1002 }
1003
1004 if (!Tok.is(MMToken::Period))
1005 break;
1006
1007 consumeToken();
1008 } while (true);
1009
1010 return false;
1011}
1012
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001013namespace {
1014 /// \brief Enumerates the known attributes.
1015 enum AttributeKind {
1016 /// \brief An unknown attribute.
1017 AT_unknown,
1018 /// \brief The 'system' attribute.
Douglas Gregor63a72682013-03-20 00:22:05 +00001019 AT_system,
1020 /// \brief The 'exhaustive' attribute.
1021 AT_exhaustive
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001022 };
1023}
1024
Douglas Gregora30cfe52011-11-11 19:10:28 +00001025/// \brief Parse a module declaration.
1026///
1027/// module-declaration:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001028/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1029/// { module-member* }
1030///
Douglas Gregora30cfe52011-11-11 19:10:28 +00001031/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001032/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +00001033/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +00001034/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +00001035/// export-declaration
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001036/// link-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +00001037///
1038/// submodule-declaration:
1039/// module-declaration
1040/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +00001041void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +00001042 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
1043 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +00001044 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +00001045 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001046 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +00001047 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +00001048
Douglas Gregord620a842011-12-06 17:16:41 +00001049 // Parse 'explicit' keyword, if present.
1050 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +00001051 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +00001052 Explicit = true;
1053 }
1054
1055 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +00001056 if (Tok.is(MMToken::FrameworkKeyword)) {
1057 consumeToken();
1058 Framework = true;
1059 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001060
1061 // Parse 'module' keyword.
1062 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +00001063 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001064 consumeToken();
1065 HadError = true;
1066 return;
1067 }
1068 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +00001069
1070 // If we have a wildcard for the module name, this is an inferred submodule.
1071 // Parse it.
1072 if (Tok.is(MMToken::Star))
Douglas Gregor82e52372012-11-06 19:39:40 +00001073 return parseInferredModuleDecl(Framework, Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001074
1075 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +00001076 ModuleId Id;
1077 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001078 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +00001079 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001080 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001081
Douglas Gregor587986e2011-12-07 02:23:45 +00001082 if (ActiveModule) {
1083 if (Id.size() > 1) {
1084 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1085 << SourceRange(Id.front().second, Id.back().second);
1086
1087 HadError = true;
1088 return;
1089 }
1090 } else if (Id.size() == 1 && Explicit) {
1091 // Top-level modules can't be explicit.
1092 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1093 Explicit = false;
1094 ExplicitLoc = SourceLocation();
1095 HadError = true;
1096 }
1097
1098 Module *PreviousActiveModule = ActiveModule;
1099 if (Id.size() > 1) {
1100 // This module map defines a submodule. Go find the module of which it
1101 // is a submodule.
1102 ActiveModule = 0;
1103 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1104 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1105 ActiveModule = Next;
1106 continue;
1107 }
1108
1109 if (ActiveModule) {
1110 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1111 << Id[I].first << ActiveModule->getTopLevelModule();
1112 } else {
1113 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1114 }
1115 HadError = true;
1116 return;
1117 }
1118 }
1119
1120 StringRef ModuleName = Id.back().first;
1121 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001122
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001123 // Parse the optional attribute list.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001124 Attributes Attrs;
Douglas Gregor82e52372012-11-06 19:39:40 +00001125 parseOptionalAttributes(Attrs);
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001126
Douglas Gregora30cfe52011-11-11 19:10:28 +00001127 // Parse the opening brace.
1128 if (!Tok.is(MMToken::LBrace)) {
1129 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1130 << ModuleName;
1131 HadError = true;
1132 return;
1133 }
1134 SourceLocation LBraceLoc = consumeToken();
1135
1136 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +00001137 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +00001138 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1139 // Skip the module definition.
1140 skipUntil(MMToken::RBrace);
1141 if (Tok.is(MMToken::RBrace))
1142 consumeToken();
1143 else {
1144 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1145 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1146 HadError = true;
1147 }
1148 return;
1149 }
1150
Douglas Gregora30cfe52011-11-11 19:10:28 +00001151 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1152 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +00001153 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001154
1155 // Skip the module definition.
1156 skipUntil(MMToken::RBrace);
1157 if (Tok.is(MMToken::RBrace))
1158 consumeToken();
1159
1160 HadError = true;
1161 return;
1162 }
1163
1164 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +00001165 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1166 Explicit).first;
1167 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregor82e52372012-11-06 19:39:40 +00001168 if (Attrs.IsSystem)
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001169 ActiveModule->IsSystem = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001170
1171 bool Done = false;
1172 do {
1173 switch (Tok.Kind) {
1174 case MMToken::EndOfFile:
1175 case MMToken::RBrace:
1176 Done = true;
1177 break;
Douglas Gregor63a72682013-03-20 00:22:05 +00001178
1179 case MMToken::ConfigMacros:
1180 parseConfigMacros();
1181 break;
1182
Douglas Gregor906d66a2013-03-20 21:10:35 +00001183 case MMToken::Conflict:
1184 parseConflict();
1185 break;
1186
Douglas Gregora30cfe52011-11-11 19:10:28 +00001187 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +00001188 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001189 case MMToken::ModuleKeyword:
1190 parseModuleDecl();
1191 break;
1192
Douglas Gregor90db2602011-12-02 01:47:07 +00001193 case MMToken::ExportKeyword:
1194 parseExportDecl();
1195 break;
1196
Douglas Gregor51f564f2011-12-31 04:05:44 +00001197 case MMToken::RequiresKeyword:
1198 parseRequiresDecl();
1199 break;
1200
Douglas Gregor77d029f2011-12-08 19:11:24 +00001201 case MMToken::UmbrellaKeyword: {
1202 SourceLocation UmbrellaLoc = consumeToken();
1203 if (Tok.is(MMToken::HeaderKeyword))
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001204 parseHeaderDecl(UmbrellaLoc, SourceLocation());
Douglas Gregor77d029f2011-12-08 19:11:24 +00001205 else
1206 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001207 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001208 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001209
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001210 case MMToken::ExcludeKeyword: {
1211 SourceLocation ExcludeLoc = consumeToken();
1212 if (Tok.is(MMToken::HeaderKeyword)) {
1213 parseHeaderDecl(SourceLocation(), ExcludeLoc);
1214 } else {
1215 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1216 << "exclude";
1217 }
1218 break;
1219 }
1220
Douglas Gregor489ad432011-12-08 18:00:48 +00001221 case MMToken::HeaderKeyword:
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001222 parseHeaderDecl(SourceLocation(), SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001223 break;
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001224
1225 case MMToken::LinkKeyword:
1226 parseLinkDecl();
1227 break;
1228
Douglas Gregora30cfe52011-11-11 19:10:28 +00001229 default:
1230 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1231 consumeToken();
1232 break;
1233 }
1234 } while (!Done);
1235
1236 if (Tok.is(MMToken::RBrace))
1237 consumeToken();
1238 else {
1239 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1240 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1241 HadError = true;
1242 }
1243
Douglas Gregor8767dc22013-01-14 17:57:51 +00001244 // If the active module is a top-level framework, and there are no link
1245 // libraries, automatically link against the framework.
1246 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
1247 ActiveModule->LinkLibraries.empty()) {
1248 inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
1249 }
1250
Douglas Gregor587986e2011-12-07 02:23:45 +00001251 // We're done parsing this module. Pop back to the previous module.
1252 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001253}
Douglas Gregord620a842011-12-06 17:16:41 +00001254
Douglas Gregor51f564f2011-12-31 04:05:44 +00001255/// \brief Parse a requires declaration.
1256///
1257/// requires-declaration:
1258/// 'requires' feature-list
1259///
1260/// feature-list:
1261/// identifier ',' feature-list
1262/// identifier
1263void ModuleMapParser::parseRequiresDecl() {
1264 assert(Tok.is(MMToken::RequiresKeyword));
1265
1266 // Parse 'requires' keyword.
1267 consumeToken();
1268
1269 // Parse the feature-list.
1270 do {
1271 if (!Tok.is(MMToken::Identifier)) {
1272 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1273 HadError = true;
1274 return;
1275 }
1276
1277 // Consume the feature name.
1278 std::string Feature = Tok.getString();
1279 consumeToken();
1280
1281 // Add this feature.
Douglas Gregordc58aa72012-01-30 06:01:29 +00001282 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor51f564f2011-12-31 04:05:44 +00001283
1284 if (!Tok.is(MMToken::Comma))
1285 break;
1286
1287 // Consume the comma.
1288 consumeToken();
1289 } while (true);
1290}
1291
Douglas Gregord620a842011-12-06 17:16:41 +00001292/// \brief Append to \p Paths the set of paths needed to get to the
1293/// subframework in which the given module lives.
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001294static void appendSubframeworkPaths(Module *Mod,
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00001295 SmallVectorImpl<char> &Path) {
Douglas Gregord620a842011-12-06 17:16:41 +00001296 // Collect the framework names from the given module to the top-level module.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00001297 SmallVector<StringRef, 2> Paths;
Douglas Gregord620a842011-12-06 17:16:41 +00001298 for (; Mod; Mod = Mod->Parent) {
1299 if (Mod->IsFramework)
1300 Paths.push_back(Mod->Name);
1301 }
1302
1303 if (Paths.empty())
1304 return;
1305
1306 // Add Frameworks/Name.framework for each subframework.
1307 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1308 llvm::sys::path::append(Path, "Frameworks");
1309 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1310 }
1311}
1312
Douglas Gregora30cfe52011-11-11 19:10:28 +00001313/// \brief Parse a header declaration.
1314///
1315/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +00001316/// 'umbrella'[opt] 'header' string-literal
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001317/// 'exclude'[opt] 'header' string-literal
1318void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
1319 SourceLocation ExcludeLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001320 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +00001321 consumeToken();
1322
Douglas Gregor489ad432011-12-08 18:00:48 +00001323 bool Umbrella = UmbrellaLoc.isValid();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001324 bool Exclude = ExcludeLoc.isValid();
1325 assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001326 // Parse the header name.
1327 if (!Tok.is(MMToken::StringLiteral)) {
1328 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1329 << "header";
1330 HadError = true;
1331 return;
1332 }
Douglas Gregor587986e2011-12-07 02:23:45 +00001333 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +00001334 SourceLocation FileNameLoc = consumeToken();
1335
Douglas Gregor77d029f2011-12-08 19:11:24 +00001336 // Check whether we already have an umbrella.
1337 if (Umbrella && ActiveModule->Umbrella) {
1338 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1339 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001340 HadError = true;
1341 return;
1342 }
1343
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001344 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +00001345 const FileEntry *File = 0;
Douglas Gregor2f04f182012-02-02 18:42:48 +00001346 const FileEntry *BuiltinFile = 0;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001347 SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +00001348 if (llvm::sys::path::is_absolute(FileName)) {
1349 PathName = FileName;
1350 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +00001351 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1352 PathName = Dir->getName();
1353 llvm::sys::path::append(PathName, FileName);
1354 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001355 } else {
1356 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +00001357 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +00001358 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +00001359
Douglas Gregord620a842011-12-06 17:16:41 +00001360 if (ActiveModule->isPartOfFramework()) {
1361 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001362
1363 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +00001364 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +00001365 llvm::sys::path::append(PathName, FileName);
1366 File = SourceMgr.getFileManager().getFile(PathName);
1367
1368 if (!File) {
1369 // Check whether this file is in the private headers.
1370 PathName.resize(PathLength);
1371 llvm::sys::path::append(PathName, "PrivateHeaders");
1372 llvm::sys::path::append(PathName, FileName);
1373 File = SourceMgr.getFileManager().getFile(PathName);
1374 }
1375 } else {
1376 // Lookup for normal headers.
1377 llvm::sys::path::append(PathName, FileName);
1378 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001379
1380 // If this is a system module with a top-level header, this header
1381 // may have a counterpart (or replacement) in the set of headers
1382 // supplied by Clang. Find that builtin header.
1383 if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
1384 BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001385 SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
Douglas Gregor2f04f182012-02-02 18:42:48 +00001386 llvm::sys::path::append(BuiltinPathName, FileName);
1387 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1388
1389 // If Clang supplies this header but the underlying system does not,
1390 // just silently swap in our builtin version. Otherwise, we'll end
1391 // up adding both (later).
1392 if (!File && BuiltinFile) {
1393 File = BuiltinFile;
1394 BuiltinFile = 0;
1395 }
1396 }
Douglas Gregord620a842011-12-06 17:16:41 +00001397 }
Douglas Gregor18ee5472011-11-29 21:59:16 +00001398 }
Douglas Gregora8654052011-11-17 22:09:43 +00001399
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001400 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1401 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001402 if (File) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001403 if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001404 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001405 << FileName << OwningModule.getModule()->getFullModuleName();
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001406 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +00001407 } else if (Umbrella) {
1408 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001409 if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Douglas Gregor489ad432011-12-08 18:00:48 +00001410 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001411 << UmbrellaModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001412 HadError = true;
1413 } else {
1414 // Record this umbrella header.
1415 Map.setUmbrellaHeader(ActiveModule, File);
1416 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001417 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001418 // Record this header.
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001419 Map.addHeader(ActiveModule, File, Exclude);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001420
1421 // If there is a builtin counterpart to this file, add it now.
1422 if (BuiltinFile)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001423 Map.addHeader(ActiveModule, BuiltinFile, Exclude);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001424 }
Douglas Gregor71f49f52012-11-15 19:47:16 +00001425 } else if (!Exclude) {
1426 // Ignore excluded header files. They're optional anyway.
1427
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001428 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +00001429 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001430 HadError = true;
1431 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001432}
1433
Douglas Gregor77d029f2011-12-08 19:11:24 +00001434/// \brief Parse an umbrella directory declaration.
1435///
1436/// umbrella-dir-declaration:
1437/// umbrella string-literal
1438void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1439 // Parse the directory name.
1440 if (!Tok.is(MMToken::StringLiteral)) {
1441 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1442 << "umbrella";
1443 HadError = true;
1444 return;
1445 }
1446
1447 std::string DirName = Tok.getString();
1448 SourceLocation DirNameLoc = consumeToken();
1449
1450 // Check whether we already have an umbrella.
1451 if (ActiveModule->Umbrella) {
1452 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1453 << ActiveModule->getFullModuleName();
1454 HadError = true;
1455 return;
1456 }
1457
1458 // Look for this file.
1459 const DirectoryEntry *Dir = 0;
1460 if (llvm::sys::path::is_absolute(DirName))
1461 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1462 else {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001463 SmallString<128> PathName;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001464 PathName = Directory->getName();
1465 llvm::sys::path::append(PathName, DirName);
1466 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1467 }
1468
1469 if (!Dir) {
1470 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1471 << DirName;
1472 HadError = true;
1473 return;
1474 }
1475
1476 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1477 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1478 << OwningModule->getFullModuleName();
1479 HadError = true;
1480 return;
1481 }
1482
1483 // Record this umbrella directory.
1484 Map.setUmbrellaDir(ActiveModule, Dir);
1485}
1486
Douglas Gregor90db2602011-12-02 01:47:07 +00001487/// \brief Parse a module export declaration.
1488///
1489/// export-declaration:
1490/// 'export' wildcard-module-id
1491///
1492/// wildcard-module-id:
1493/// identifier
1494/// '*'
1495/// identifier '.' wildcard-module-id
1496void ModuleMapParser::parseExportDecl() {
1497 assert(Tok.is(MMToken::ExportKeyword));
1498 SourceLocation ExportLoc = consumeToken();
1499
1500 // Parse the module-id with an optional wildcard at the end.
1501 ModuleId ParsedModuleId;
1502 bool Wildcard = false;
1503 do {
1504 if (Tok.is(MMToken::Identifier)) {
1505 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1506 Tok.getLocation()));
1507 consumeToken();
1508
1509 if (Tok.is(MMToken::Period)) {
1510 consumeToken();
1511 continue;
1512 }
1513
1514 break;
1515 }
1516
1517 if(Tok.is(MMToken::Star)) {
1518 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001519 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001520 break;
1521 }
1522
1523 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1524 HadError = true;
1525 return;
1526 } while (true);
1527
1528 Module::UnresolvedExportDecl Unresolved = {
1529 ExportLoc, ParsedModuleId, Wildcard
1530 };
1531 ActiveModule->UnresolvedExports.push_back(Unresolved);
1532}
1533
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001534/// \brief Parse a link declaration.
1535///
1536/// module-declaration:
1537/// 'link' 'framework'[opt] string-literal
1538void ModuleMapParser::parseLinkDecl() {
1539 assert(Tok.is(MMToken::LinkKeyword));
1540 SourceLocation LinkLoc = consumeToken();
1541
1542 // Parse the optional 'framework' keyword.
1543 bool IsFramework = false;
1544 if (Tok.is(MMToken::FrameworkKeyword)) {
1545 consumeToken();
1546 IsFramework = true;
1547 }
1548
1549 // Parse the library name
1550 if (!Tok.is(MMToken::StringLiteral)) {
1551 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
1552 << IsFramework << SourceRange(LinkLoc);
1553 HadError = true;
1554 return;
1555 }
1556
1557 std::string LibraryName = Tok.getString();
1558 consumeToken();
1559 ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
1560 IsFramework));
1561}
1562
Douglas Gregor63a72682013-03-20 00:22:05 +00001563/// \brief Parse a configuration macro declaration.
1564///
1565/// module-declaration:
1566/// 'config_macros' attributes[opt] config-macro-list?
1567///
1568/// config-macro-list:
1569/// identifier (',' identifier)?
1570void ModuleMapParser::parseConfigMacros() {
1571 assert(Tok.is(MMToken::ConfigMacros));
1572 SourceLocation ConfigMacrosLoc = consumeToken();
1573
1574 // Only top-level modules can have configuration macros.
1575 if (ActiveModule->Parent) {
1576 Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
1577 }
1578
1579 // Parse the optional attributes.
1580 Attributes Attrs;
1581 parseOptionalAttributes(Attrs);
1582 if (Attrs.IsExhaustive && !ActiveModule->Parent) {
1583 ActiveModule->ConfigMacrosExhaustive = true;
1584 }
1585
1586 // If we don't have an identifier, we're done.
1587 if (!Tok.is(MMToken::Identifier))
1588 return;
1589
1590 // Consume the first identifier.
1591 if (!ActiveModule->Parent) {
1592 ActiveModule->ConfigMacros.push_back(Tok.getString().str());
1593 }
1594 consumeToken();
1595
1596 do {
1597 // If there's a comma, consume it.
1598 if (!Tok.is(MMToken::Comma))
1599 break;
1600 consumeToken();
1601
1602 // We expect to see a macro name here.
1603 if (!Tok.is(MMToken::Identifier)) {
1604 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
1605 break;
1606 }
1607
1608 // Consume the macro name.
1609 if (!ActiveModule->Parent) {
1610 ActiveModule->ConfigMacros.push_back(Tok.getString().str());
1611 }
1612 consumeToken();
1613 } while (true);
1614}
1615
Douglas Gregor906d66a2013-03-20 21:10:35 +00001616/// \brief Format a module-id into a string.
1617static std::string formatModuleId(const ModuleId &Id) {
1618 std::string result;
1619 {
1620 llvm::raw_string_ostream OS(result);
1621
1622 for (unsigned I = 0, N = Id.size(); I != N; ++I) {
1623 if (I)
1624 OS << ".";
1625 OS << Id[I].first;
1626 }
1627 }
1628
1629 return result;
1630}
1631
1632/// \brief Parse a conflict declaration.
1633///
1634/// module-declaration:
1635/// 'conflict' module-id ',' string-literal
1636void ModuleMapParser::parseConflict() {
1637 assert(Tok.is(MMToken::Conflict));
1638 SourceLocation ConflictLoc = consumeToken();
1639 Module::UnresolvedConflict Conflict;
1640
1641 // Parse the module-id.
1642 if (parseModuleId(Conflict.Id))
1643 return;
1644
1645 // Parse the ','.
1646 if (!Tok.is(MMToken::Comma)) {
1647 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
1648 << SourceRange(ConflictLoc);
1649 return;
1650 }
1651 consumeToken();
1652
1653 // Parse the message.
1654 if (!Tok.is(MMToken::StringLiteral)) {
1655 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
1656 << formatModuleId(Conflict.Id);
1657 return;
1658 }
1659 Conflict.Message = Tok.getString().str();
1660 consumeToken();
1661
1662 // Add this unresolved conflict.
1663 ActiveModule->UnresolvedConflicts.push_back(Conflict);
1664}
1665
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001666/// \brief Parse an inferred module declaration (wildcard modules).
Douglas Gregor82e52372012-11-06 19:39:40 +00001667///
1668/// module-declaration:
1669/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
1670/// { inferred-module-member* }
1671///
1672/// inferred-module-member:
1673/// 'export' '*'
1674/// 'exclude' identifier
1675void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001676 assert(Tok.is(MMToken::Star));
1677 SourceLocation StarLoc = consumeToken();
1678 bool Failed = false;
Douglas Gregor82e52372012-11-06 19:39:40 +00001679
Douglas Gregor1e123682011-12-05 22:27:44 +00001680 // Inferred modules must be submodules.
Douglas Gregor82e52372012-11-06 19:39:40 +00001681 if (!ActiveModule && !Framework) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001682 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1683 Failed = true;
1684 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001685
1686 if (ActiveModule) {
1687 // Inferred modules must have umbrella directories.
1688 if (!Failed && !ActiveModule->getUmbrellaDir()) {
1689 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1690 Failed = true;
1691 }
1692
1693 // Check for redefinition of an inferred module.
1694 if (!Failed && ActiveModule->InferSubmodules) {
1695 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1696 if (ActiveModule->InferredSubmoduleLoc.isValid())
1697 Diags.Report(ActiveModule->InferredSubmoduleLoc,
1698 diag::note_mmap_prev_definition);
1699 Failed = true;
1700 }
1701
1702 // Check for the 'framework' keyword, which is not permitted here.
1703 if (Framework) {
1704 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
1705 Framework = false;
1706 }
1707 } else if (Explicit) {
1708 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
1709 Explicit = false;
Douglas Gregor1e123682011-12-05 22:27:44 +00001710 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001711
Douglas Gregor1e123682011-12-05 22:27:44 +00001712 // If there were any problems with this inferred submodule, skip its body.
1713 if (Failed) {
1714 if (Tok.is(MMToken::LBrace)) {
1715 consumeToken();
1716 skipUntil(MMToken::RBrace);
1717 if (Tok.is(MMToken::RBrace))
1718 consumeToken();
1719 }
1720 HadError = true;
1721 return;
1722 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001723
1724 // Parse optional attributes.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001725 Attributes Attrs;
Douglas Gregor82e52372012-11-06 19:39:40 +00001726 parseOptionalAttributes(Attrs);
1727
1728 if (ActiveModule) {
1729 // Note that we have an inferred submodule.
1730 ActiveModule->InferSubmodules = true;
1731 ActiveModule->InferredSubmoduleLoc = StarLoc;
1732 ActiveModule->InferExplicitSubmodules = Explicit;
1733 } else {
1734 // We'll be inferring framework modules for this directory.
1735 Map.InferredDirectories[Directory].InferModules = true;
1736 Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
1737 }
1738
Douglas Gregor1e123682011-12-05 22:27:44 +00001739 // Parse the opening brace.
1740 if (!Tok.is(MMToken::LBrace)) {
1741 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1742 HadError = true;
1743 return;
1744 }
1745 SourceLocation LBraceLoc = consumeToken();
1746
1747 // Parse the body of the inferred submodule.
1748 bool Done = false;
1749 do {
1750 switch (Tok.Kind) {
1751 case MMToken::EndOfFile:
1752 case MMToken::RBrace:
1753 Done = true;
1754 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001755
1756 case MMToken::ExcludeKeyword: {
1757 if (ActiveModule) {
1758 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001759 << (ActiveModule != 0);
Douglas Gregor82e52372012-11-06 19:39:40 +00001760 consumeToken();
1761 break;
1762 }
1763
1764 consumeToken();
1765 if (!Tok.is(MMToken::Identifier)) {
1766 Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
1767 break;
1768 }
1769
1770 Map.InferredDirectories[Directory].ExcludedModules
1771 .push_back(Tok.getString());
1772 consumeToken();
1773 break;
1774 }
1775
1776 case MMToken::ExportKeyword:
1777 if (!ActiveModule) {
1778 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001779 << (ActiveModule != 0);
Douglas Gregor82e52372012-11-06 19:39:40 +00001780 consumeToken();
1781 break;
1782 }
1783
Douglas Gregor1e123682011-12-05 22:27:44 +00001784 consumeToken();
1785 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001786 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001787 else
1788 Diags.Report(Tok.getLocation(),
1789 diag::err_mmap_expected_export_wildcard);
1790 consumeToken();
1791 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001792
Douglas Gregor1e123682011-12-05 22:27:44 +00001793 case MMToken::ExplicitKeyword:
1794 case MMToken::ModuleKeyword:
1795 case MMToken::HeaderKeyword:
1796 case MMToken::UmbrellaKeyword:
1797 default:
Douglas Gregor82e52372012-11-06 19:39:40 +00001798 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001799 << (ActiveModule != 0);
Douglas Gregor1e123682011-12-05 22:27:44 +00001800 consumeToken();
1801 break;
1802 }
1803 } while (!Done);
1804
1805 if (Tok.is(MMToken::RBrace))
1806 consumeToken();
1807 else {
1808 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1809 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1810 HadError = true;
1811 }
1812}
1813
Douglas Gregor82e52372012-11-06 19:39:40 +00001814/// \brief Parse optional attributes.
1815///
1816/// attributes:
1817/// attribute attributes
1818/// attribute
1819///
1820/// attribute:
1821/// [ identifier ]
1822///
1823/// \param Attrs Will be filled in with the parsed attributes.
1824///
1825/// \returns true if an error occurred, false otherwise.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001826bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
Douglas Gregor82e52372012-11-06 19:39:40 +00001827 bool HadError = false;
1828
1829 while (Tok.is(MMToken::LSquare)) {
1830 // Consume the '['.
1831 SourceLocation LSquareLoc = consumeToken();
1832
1833 // Check whether we have an attribute name here.
1834 if (!Tok.is(MMToken::Identifier)) {
1835 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
1836 skipUntil(MMToken::RSquare);
1837 if (Tok.is(MMToken::RSquare))
1838 consumeToken();
1839 HadError = true;
1840 }
1841
1842 // Decode the attribute name.
1843 AttributeKind Attribute
1844 = llvm::StringSwitch<AttributeKind>(Tok.getString())
Douglas Gregor63a72682013-03-20 00:22:05 +00001845 .Case("exhaustive", AT_exhaustive)
Douglas Gregor82e52372012-11-06 19:39:40 +00001846 .Case("system", AT_system)
1847 .Default(AT_unknown);
1848 switch (Attribute) {
1849 case AT_unknown:
1850 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
1851 << Tok.getString();
1852 break;
1853
1854 case AT_system:
1855 Attrs.IsSystem = true;
1856 break;
Douglas Gregor63a72682013-03-20 00:22:05 +00001857
1858 case AT_exhaustive:
1859 Attrs.IsExhaustive = true;
1860 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001861 }
1862 consumeToken();
1863
1864 // Consume the ']'.
1865 if (!Tok.is(MMToken::RSquare)) {
1866 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
1867 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
1868 skipUntil(MMToken::RSquare);
1869 HadError = true;
1870 }
1871
1872 if (Tok.is(MMToken::RSquare))
1873 consumeToken();
1874 }
1875
1876 return HadError;
1877}
1878
Douglas Gregor6a1db482011-12-09 02:04:43 +00001879/// \brief If there is a specific header search directory due the presence
1880/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1881const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1882 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1883 // If we have an umbrella directory, use that.
1884 if (Mod->hasUmbrellaDir())
1885 return Mod->getUmbrellaDir();
1886
1887 // If we have a framework directory, stop looking.
1888 if (Mod->IsFramework)
1889 return 0;
1890 }
1891
1892 return 0;
1893}
1894
Douglas Gregora30cfe52011-11-11 19:10:28 +00001895/// \brief Parse a module map file.
1896///
1897/// module-map-file:
1898/// module-declaration*
1899bool ModuleMapParser::parseModuleMapFile() {
1900 do {
1901 switch (Tok.Kind) {
1902 case MMToken::EndOfFile:
1903 return HadError;
1904
Douglas Gregor587986e2011-12-07 02:23:45 +00001905 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001906 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001907 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001908 parseModuleDecl();
1909 break;
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001910
Douglas Gregor51f564f2011-12-31 04:05:44 +00001911 case MMToken::Comma:
Douglas Gregor63a72682013-03-20 00:22:05 +00001912 case MMToken::ConfigMacros:
Douglas Gregor906d66a2013-03-20 21:10:35 +00001913 case MMToken::Conflict:
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001914 case MMToken::ExcludeKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001915 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001916 case MMToken::HeaderKeyword:
1917 case MMToken::Identifier:
1918 case MMToken::LBrace:
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001919 case MMToken::LinkKeyword:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001920 case MMToken::LSquare:
Douglas Gregor90db2602011-12-02 01:47:07 +00001921 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001922 case MMToken::RBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001923 case MMToken::RSquare:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001924 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001925 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001926 case MMToken::StringLiteral:
1927 case MMToken::UmbrellaKeyword:
1928 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1929 HadError = true;
1930 consumeToken();
1931 break;
1932 }
1933 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001934}
1935
1936bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregor7005b902013-01-10 01:43:00 +00001937 llvm::DenseMap<const FileEntry *, bool>::iterator Known
1938 = ParsedModuleMap.find(File);
1939 if (Known != ParsedModuleMap.end())
1940 return Known->second;
1941
Douglas Gregordc58aa72012-01-30 06:01:29 +00001942 assert(Target != 0 && "Missing target information");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001943 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1944 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1945 if (!Buffer)
Douglas Gregor7005b902013-01-10 01:43:00 +00001946 return ParsedModuleMap[File] = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001947
1948 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00001949 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1950 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor9a022bb2012-10-15 16:45:32 +00001951 ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
Douglas Gregor2f04f182012-02-02 18:42:48 +00001952 BuiltinIncludeDir);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001953 bool Result = Parser.parseModuleMapFile();
1954 Diags->getClient()->EndSourceFile();
Douglas Gregor7005b902013-01-10 01:43:00 +00001955 ParsedModuleMap[File] = Result;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001956 return Result;
1957}