blob: d7bf45152d9d9653a5db54efbe3f69f00320f42a [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"
Douglas Gregora30cfe52011-11-11 19:10:28 +000015#include "clang/Basic/Diagnostic.h"
Douglas Gregor02c23eb2012-10-23 22:26:28 +000016#include "clang/Basic/DiagnosticOptions.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000017#include "clang/Basic/FileManager.h"
18#include "clang/Basic/TargetInfo.h"
19#include "clang/Basic/TargetOptions.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000020#include "clang/Lex/LexDiagnostic.h"
21#include "clang/Lex/Lexer.h"
22#include "clang/Lex/LiteralSupport.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/ADT/StringSwitch.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000025#include "llvm/Support/Allocator.h"
Douglas Gregorac252a32011-12-06 19:39:29 +000026#include "llvm/Support/FileSystem.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000027#include "llvm/Support/Host.h"
Douglas Gregor8b6d3de2011-11-11 21:55:48 +000028#include "llvm/Support/PathV2.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000029#include "llvm/Support/raw_ostream.h"
Douglas Gregor98cfcbf2012-09-27 14:50:15 +000030#include <stdlib.h>
Douglas Gregora30cfe52011-11-11 19:10:28 +000031using namespace clang;
32
Douglas Gregor90db2602011-12-02 01:47:07 +000033Module::ExportDecl
34ModuleMap::resolveExport(Module *Mod,
35 const Module::UnresolvedExportDecl &Unresolved,
36 bool Complain) {
Douglas Gregor0adaa882011-12-05 17:28:06 +000037 // We may have just a wildcard.
38 if (Unresolved.Id.empty()) {
39 assert(Unresolved.Wildcard && "Invalid unresolved export");
40 return Module::ExportDecl(0, true);
41 }
42
Douglas Gregor90db2602011-12-02 01:47:07 +000043 // Find the starting module.
44 Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
45 if (!Context) {
46 if (Complain)
47 Diags->Report(Unresolved.Id[0].second,
48 diag::err_mmap_missing_module_unqualified)
49 << Unresolved.Id[0].first << Mod->getFullModuleName();
50
51 return Module::ExportDecl();
52 }
53
54 // Dig into the module path.
55 for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
56 Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
57 Context);
58 if (!Sub) {
59 if (Complain)
60 Diags->Report(Unresolved.Id[I].second,
61 diag::err_mmap_missing_module_qualified)
62 << Unresolved.Id[I].first << Context->getFullModuleName()
63 << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
64
65 return Module::ExportDecl();
66 }
67
68 Context = Sub;
69 }
70
71 return Module::ExportDecl(Context, Unresolved.Wildcard);
72}
73
Douglas Gregor51f564f2011-12-31 04:05:44 +000074ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
Douglas Gregordc58aa72012-01-30 06:01:29 +000075 const LangOptions &LangOpts, const TargetInfo *Target)
Douglas Gregor2f04f182012-02-02 18:42:48 +000076 : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0)
Douglas Gregor51f564f2011-12-31 04:05:44 +000077{
Dylan Noblesmithc93dc782012-02-20 14:00:23 +000078 IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
79 Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
Douglas Gregor02c23eb2012-10-23 22:26:28 +000080 new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
Douglas Gregora30cfe52011-11-11 19:10:28 +000081 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
82 SourceMgr = new SourceManager(*Diags, FileMgr);
83}
84
85ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +000086 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
87 IEnd = Modules.end();
88 I != IEnd; ++I) {
89 delete I->getValue();
90 }
91
Douglas Gregora30cfe52011-11-11 19:10:28 +000092 delete SourceMgr;
93}
94
Douglas Gregordc58aa72012-01-30 06:01:29 +000095void ModuleMap::setTarget(const TargetInfo &Target) {
96 assert((!this->Target || this->Target == &Target) &&
97 "Improper target override");
98 this->Target = &Target;
99}
100
Douglas Gregor8b48e082012-10-12 21:15:50 +0000101/// \brief "Sanitize" a filename so that it can be used as an identifier.
102static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
103 SmallVectorImpl<char> &Buffer) {
104 if (Name.empty())
105 return Name;
106
107 // Check whether the filename is already an identifier; this is the common
108 // case.
109 bool isIdentifier = true;
110 for (unsigned I = 0, N = Name.size(); I != N; ++I) {
111 if (isalpha(Name[I]) || Name[I] == '_' || (isdigit(Name[I]) && I > 0))
112 continue;
113
114 isIdentifier = false;
115 break;
116 }
117
118 if (!isIdentifier) {
119 // If we don't already have something with the form of an identifier,
120 // create a buffer with the sanitized name.
121 Buffer.clear();
122 if (isdigit(Name[0]))
123 Buffer.push_back('_');
124 Buffer.reserve(Buffer.size() + Name.size());
125 for (unsigned I = 0, N = Name.size(); I != N; ++I) {
126 if (isalnum(Name[I]) || isspace(Name[I]))
127 Buffer.push_back(Name[I]);
128 else
129 Buffer.push_back('_');
130 }
131
132 Name = StringRef(Buffer.data(), Buffer.size());
133 }
134
135 while (llvm::StringSwitch<bool>(Name)
136#define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
137#define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
138#include "clang/Basic/TokenKinds.def"
139 .Default(false)) {
140 if (Name.data() != Buffer.data())
141 Buffer.append(Name.begin(), Name.end());
142 Buffer.push_back('_');
143 Name = StringRef(Buffer.data(), Buffer.size());
144 }
145
146 return Name;
147}
148
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000149Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000150 HeadersMap::iterator Known = Headers.find(File);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000151 if (Known != Headers.end()) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000152 // If a header is not available, don't report that it maps to anything.
153 if (!Known->second.isAvailable())
Douglas Gregor51f564f2011-12-31 04:05:44 +0000154 return 0;
155
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000156 return Known->second.getModule();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000157 }
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000158
Douglas Gregoradb97992011-11-16 23:02:25 +0000159 const DirectoryEntry *Dir = File->getDir();
Douglas Gregoradb97992011-11-16 23:02:25 +0000160 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
Douglas Gregoraa60f9c2013-01-04 19:44:26 +0000161#ifdef LLVM_ON_UNIX
162 // Note: as an egregious but useful hack we use the real path here, because
163 // frameworks moving from top-level frameworks to embedded frameworks tend
164 // to be symlinked from the top-level location to the embedded location,
165 // and we need to resolve lookups as if we had found the embedded location.
166 char RealDirName[PATH_MAX];
167 StringRef DirName;
168 if (realpath(Dir->getName(), RealDirName))
169 DirName = RealDirName;
170 else
171 DirName = Dir->getName();
172#else
Douglas Gregoradb97992011-11-16 23:02:25 +0000173 StringRef DirName = Dir->getName();
Douglas Gregoraa60f9c2013-01-04 19:44:26 +0000174#endif
Douglas Gregore209e502011-12-06 01:10:29 +0000175
176 // Keep walking up the directory hierarchy, looking for a directory with
177 // an umbrella header.
178 do {
179 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
180 = UmbrellaDirs.find(Dir);
181 if (KnownDir != UmbrellaDirs.end()) {
182 Module *Result = KnownDir->second;
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000183
184 // Search up the module stack until we find a module with an umbrella
Douglas Gregor10694ce2011-12-08 17:39:04 +0000185 // directory.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000186 Module *UmbrellaModule = Result;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000187 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000188 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000189
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000190 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-12-06 01:10:29 +0000191 // Infer submodules for each of the directories we found between
192 // the directory of the umbrella header and the directory where
193 // the actual header is located.
Douglas Gregor23af6d52011-12-07 22:05:21 +0000194 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregore209e502011-12-06 01:10:29 +0000195
Douglas Gregor6a1db482011-12-09 02:04:43 +0000196 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregore209e502011-12-06 01:10:29 +0000197 // Find or create the module that corresponds to this directory name.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000198 SmallString<32> NameBuf;
199 StringRef Name = sanitizeFilenameAsIdentifier(
200 llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
201 NameBuf);
Douglas Gregore209e502011-12-06 01:10:29 +0000202 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000203 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000204
205 // Associate the module and the directory.
206 UmbrellaDirs[SkippedDirs[I-1]] = Result;
207
208 // If inferred submodules export everything they import, add a
209 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000210 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000211 Result->Exports.push_back(Module::ExportDecl(0, true));
212 }
213
214 // Infer a submodule with the same name as this header file.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000215 SmallString<32> NameBuf;
216 StringRef Name = sanitizeFilenameAsIdentifier(
217 llvm::sys::path::stem(File->getName()), NameBuf);
Douglas Gregore209e502011-12-06 01:10:29 +0000218 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000219 Explicit).first;
Argyrios Kyrtzidisc7782d92012-10-05 00:22:33 +0000220 Result->TopHeaders.insert(File);
Douglas Gregore209e502011-12-06 01:10:29 +0000221
222 // If inferred submodules export everything they import, add a
223 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000224 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000225 Result->Exports.push_back(Module::ExportDecl(0, true));
226 } else {
227 // Record each of the directories we stepped through as being part of
228 // the module we found, since the umbrella header covers them all.
229 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
230 UmbrellaDirs[SkippedDirs[I]] = Result;
231 }
232
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000233 Headers[File] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000234
235 // If a header corresponds to an unavailable module, don't report
236 // that it maps to anything.
237 if (!Result->isAvailable())
238 return 0;
239
Douglas Gregore209e502011-12-06 01:10:29 +0000240 return Result;
241 }
242
243 SkippedDirs.push_back(Dir);
244
Douglas Gregoradb97992011-11-16 23:02:25 +0000245 // Retrieve our parent path.
246 DirName = llvm::sys::path::parent_path(DirName);
247 if (DirName.empty())
248 break;
249
250 // Resolve the parent path to a directory entry.
251 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000252 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000253
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000254 return 0;
255}
256
Douglas Gregor51f564f2011-12-31 04:05:44 +0000257bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000258 HeadersMap::iterator Known = Headers.find(Header);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000259 if (Known != Headers.end())
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000260 return !Known->second.isAvailable();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000261
262 const DirectoryEntry *Dir = Header->getDir();
263 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
264 StringRef DirName = Dir->getName();
265
266 // Keep walking up the directory hierarchy, looking for a directory with
267 // an umbrella header.
268 do {
269 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
270 = UmbrellaDirs.find(Dir);
271 if (KnownDir != UmbrellaDirs.end()) {
272 Module *Found = KnownDir->second;
273 if (!Found->isAvailable())
274 return true;
275
276 // Search up the module stack until we find a module with an umbrella
277 // directory.
278 Module *UmbrellaModule = Found;
279 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
280 UmbrellaModule = UmbrellaModule->Parent;
281
282 if (UmbrellaModule->InferSubmodules) {
283 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
284 // Find or create the module that corresponds to this directory name.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000285 SmallString<32> NameBuf;
286 StringRef Name = sanitizeFilenameAsIdentifier(
287 llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
288 NameBuf);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000289 Found = lookupModuleQualified(Name, Found);
290 if (!Found)
291 return false;
292 if (!Found->isAvailable())
293 return true;
294 }
295
296 // Infer a submodule with the same name as this header file.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000297 SmallString<32> NameBuf;
298 StringRef Name = sanitizeFilenameAsIdentifier(
299 llvm::sys::path::stem(Header->getName()),
300 NameBuf);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000301 Found = lookupModuleQualified(Name, Found);
302 if (!Found)
303 return false;
304 }
305
306 return !Found->isAvailable();
307 }
308
309 SkippedDirs.push_back(Dir);
310
311 // Retrieve our parent path.
312 DirName = llvm::sys::path::parent_path(DirName);
313 if (DirName.empty())
314 break;
315
316 // Resolve the parent path to a directory entry.
317 Dir = SourceMgr->getFileManager().getDirectory(DirName);
318 } while (Dir);
319
320 return false;
321}
322
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000323Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000324 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
325 if (Known != Modules.end())
326 return Known->getValue();
327
328 return 0;
329}
330
Douglas Gregor90db2602011-12-02 01:47:07 +0000331Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
332 for(; Context; Context = Context->Parent) {
333 if (Module *Sub = lookupModuleQualified(Name, Context))
334 return Sub;
335 }
336
337 return findModule(Name);
338}
339
340Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
341 if (!Context)
342 return findModule(Name);
343
Douglas Gregorb7a78192012-01-04 23:32:19 +0000344 return Context->findSubmodule(Name);
Douglas Gregor90db2602011-12-02 01:47:07 +0000345}
346
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000347std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000348ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
349 bool IsExplicit) {
350 // Try to find an existing module with this name.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000351 if (Module *Sub = lookupModuleQualified(Name, Parent))
352 return std::make_pair(Sub, false);
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000353
354 // Create a new module with this name.
355 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
356 IsExplicit);
Douglas Gregorb7a78192012-01-04 23:32:19 +0000357 if (!Parent)
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000358 Modules[Name] = Result;
359 return std::make_pair(Result, true);
360}
361
Douglas Gregor82e52372012-11-06 19:39:40 +0000362bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
363 StringRef Name, bool &IsSystem) {
364 // Check whether we have already looked into the parent directory
365 // for a module map.
366 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
367 inferred = InferredDirectories.find(ParentDir);
368 if (inferred == InferredDirectories.end())
369 return false;
370
371 if (!inferred->second.InferModules)
372 return false;
373
374 // We're allowed to infer for this directory, but make sure it's okay
375 // to infer this particular module.
376 bool canInfer = std::find(inferred->second.ExcludedModules.begin(),
377 inferred->second.ExcludedModules.end(),
378 Name) == inferred->second.ExcludedModules.end();
379
380 if (canInfer && inferred->second.InferSystemModules)
381 IsSystem = true;
382
383 return canInfer;
384}
385
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000386Module *
Douglas Gregor82e52372012-11-06 19:39:40 +0000387ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000388 const DirectoryEntry *FrameworkDir,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000389 bool IsSystem,
Douglas Gregorac252a32011-12-06 19:39:29 +0000390 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000391 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000392 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
393 return Mod;
394
395 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor82e52372012-11-06 19:39:40 +0000396
397 // If the framework has a parent path from which we're allowed to infer
398 // a framework module, do so.
399 if (!Parent) {
400 bool canInfer = false;
401 if (llvm::sys::path::has_parent_path(FrameworkDir->getName())) {
402 // Figure out the parent path.
403 StringRef Parent = llvm::sys::path::parent_path(FrameworkDir->getName());
404 if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
405 // Check whether we have already looked into the parent directory
406 // for a module map.
407 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
408 inferred = InferredDirectories.find(ParentDir);
409 if (inferred == InferredDirectories.end()) {
410 // We haven't looked here before. Load a module map, if there is
411 // one.
412 SmallString<128> ModMapPath = Parent;
413 llvm::sys::path::append(ModMapPath, "module.map");
414 if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
415 parseModuleMapFile(ModMapFile);
416 inferred = InferredDirectories.find(ParentDir);
417 }
418
419 if (inferred == InferredDirectories.end())
420 inferred = InferredDirectories.insert(
421 std::make_pair(ParentDir, InferredDirectory())).first;
422 }
423
424 if (inferred->second.InferModules) {
425 // We're allowed to infer for this directory, but make sure it's okay
426 // to infer this particular module.
427 StringRef Name = llvm::sys::path::filename(FrameworkDir->getName());
428 canInfer = std::find(inferred->second.ExcludedModules.begin(),
429 inferred->second.ExcludedModules.end(),
430 Name) == inferred->second.ExcludedModules.end();
431
432 if (inferred->second.InferSystemModules)
433 IsSystem = true;
434 }
435 }
436 }
437
438 // If we're not allowed to infer a framework module, don't.
439 if (!canInfer)
440 return 0;
441 }
442
443
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000444 // Look for an umbrella header.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000445 SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000446 llvm::sys::path::append(UmbrellaName, "Headers");
447 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000448 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000449
450 // FIXME: If there's no umbrella header, we could probably scan the
451 // framework to load *everything*. But, it's not clear that this is a good
452 // idea.
453 if (!UmbrellaHeader)
454 return 0;
455
Douglas Gregorac252a32011-12-06 19:39:29 +0000456 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
457 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000458 if (IsSystem)
459 Result->IsSystem = IsSystem;
460
Douglas Gregorb7a78192012-01-04 23:32:19 +0000461 if (!Parent)
Douglas Gregorac252a32011-12-06 19:39:29 +0000462 Modules[ModuleName] = Result;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000463
Douglas Gregor489ad432011-12-08 18:00:48 +0000464 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000465 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000466 Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor3cee31e2011-12-12 23:55:05 +0000467 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000468
469 // export *
470 Result->Exports.push_back(Module::ExportDecl(0, true));
471
Douglas Gregore209e502011-12-06 01:10:29 +0000472 // module * { export * }
473 Result->InferSubmodules = true;
474 Result->InferExportWildcard = true;
475
Douglas Gregorac252a32011-12-06 19:39:29 +0000476 // Look for subframeworks.
477 llvm::error_code EC;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000478 SmallString<128> SubframeworksDirName
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000479 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000480 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000481 SmallString<128> SubframeworksDirNameNative;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000482 llvm::sys::path::native(SubframeworksDirName.str(),
483 SubframeworksDirNameNative);
484 for (llvm::sys::fs::directory_iterator
485 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregorac252a32011-12-06 19:39:29 +0000486 Dir != DirEnd && !EC; Dir.increment(EC)) {
487 if (!StringRef(Dir->path()).endswith(".framework"))
488 continue;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000489
Douglas Gregorac252a32011-12-06 19:39:29 +0000490 if (const DirectoryEntry *SubframeworkDir
491 = FileMgr.getDirectory(Dir->path())) {
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000492 // Note: as an egregious but useful hack, we use the real path here and
493 // check whether it is actually a subdirectory of the parent directory.
494 // This will not be the case if the 'subframework' is actually a symlink
495 // out to a top-level framework.
496#ifdef LLVM_ON_UNIX
497 char RealSubframeworkDirName[PATH_MAX];
498 if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) {
499 StringRef SubframeworkDirName = RealSubframeworkDirName;
500
501 bool FoundParent = false;
502 do {
503 // Get the parent directory name.
504 SubframeworkDirName
505 = llvm::sys::path::parent_path(SubframeworkDirName);
506 if (SubframeworkDirName.empty())
507 break;
508
509 if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
510 FoundParent = true;
511 break;
512 }
513 } while (true);
514
515 if (!FoundParent)
516 continue;
517 }
518#endif
519
Douglas Gregorac252a32011-12-06 19:39:29 +0000520 // FIXME: Do we want to warn about subframeworks without umbrella headers?
Douglas Gregor8b48e082012-10-12 21:15:50 +0000521 SmallString<32> NameBuf;
522 inferFrameworkModule(sanitizeFilenameAsIdentifier(
523 llvm::sys::path::stem(Dir->path()), NameBuf),
524 SubframeworkDir, IsSystem, Result);
Douglas Gregorac252a32011-12-06 19:39:29 +0000525 }
526 }
Douglas Gregor3a110f72012-01-13 16:54:27 +0000527
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000528 return Result;
529}
530
Douglas Gregore209e502011-12-06 01:10:29 +0000531void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000532 Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
Douglas Gregor10694ce2011-12-08 17:39:04 +0000533 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000534 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000535}
536
Douglas Gregor77d029f2011-12-08 19:11:24 +0000537void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
538 Mod->Umbrella = UmbrellaDir;
539 UmbrellaDirs[UmbrellaDir] = Mod;
540}
541
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000542void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
543 bool Excluded) {
544 if (Excluded)
545 Mod->ExcludedHeaders.push_back(Header);
546 else
547 Mod->Headers.push_back(Header);
548 Headers[Header] = KnownHeader(Mod, Excluded);
Douglas Gregore209e502011-12-06 01:10:29 +0000549}
550
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000551const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000552ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000553 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
554 return 0;
555
556 return SourceMgr->getFileEntryForID(
557 SourceMgr->getFileID(Module->DefinitionLoc));
558}
559
Douglas Gregora30cfe52011-11-11 19:10:28 +0000560void ModuleMap::dump() {
561 llvm::errs() << "Modules:";
562 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
563 MEnd = Modules.end();
564 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000565 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000566
567 llvm::errs() << "Headers:";
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000568 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000569 H != HEnd; ++H) {
570 llvm::errs() << " \"" << H->first->getName() << "\" -> "
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000571 << H->second.getModule()->getFullModuleName() << "\n";
Douglas Gregora30cfe52011-11-11 19:10:28 +0000572 }
573}
574
Douglas Gregor90db2602011-12-02 01:47:07 +0000575bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
576 bool HadError = false;
577 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
578 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
579 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000580 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000581 Mod->Exports.push_back(Export);
582 else
583 HadError = true;
584 }
585 Mod->UnresolvedExports.clear();
586 return HadError;
587}
588
Douglas Gregor55988682011-12-05 16:33:54 +0000589Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
590 if (Loc.isInvalid())
591 return 0;
592
593 // Use the expansion location to determine which module we're in.
594 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
595 if (!ExpansionLoc.isFileID())
596 return 0;
597
598
599 const SourceManager &SrcMgr = Loc.getManager();
600 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor55988682011-12-05 16:33:54 +0000601
Douglas Gregor303aae92012-01-06 17:19:32 +0000602 while (const FileEntry *ExpansionFile
603 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
604 // Find the module that owns this header (if any).
605 if (Module *Mod = findModuleForHeader(ExpansionFile))
606 return Mod;
607
608 // No module owns this header, so look up the inclusion chain to see if
609 // any included header has an associated module.
610 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
611 if (IncludeLoc.isInvalid())
612 return 0;
613
614 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
615 }
616
617 return 0;
Douglas Gregor55988682011-12-05 16:33:54 +0000618}
619
Douglas Gregora30cfe52011-11-11 19:10:28 +0000620//----------------------------------------------------------------------------//
621// Module map file parser
622//----------------------------------------------------------------------------//
623
624namespace clang {
625 /// \brief A token in a module map file.
626 struct MMToken {
627 enum TokenKind {
Douglas Gregor51f564f2011-12-31 04:05:44 +0000628 Comma,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000629 EndOfFile,
630 HeaderKeyword,
631 Identifier,
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000632 ExcludeKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000633 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000634 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000635 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000636 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000637 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000638 UmbrellaKeyword,
Douglas Gregor51f564f2011-12-31 04:05:44 +0000639 RequiresKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000640 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000641 StringLiteral,
642 LBrace,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000643 RBrace,
644 LSquare,
645 RSquare
Douglas Gregora30cfe52011-11-11 19:10:28 +0000646 } Kind;
647
648 unsigned Location;
649 unsigned StringLength;
650 const char *StringData;
651
652 void clear() {
653 Kind = EndOfFile;
654 Location = 0;
655 StringLength = 0;
656 StringData = 0;
657 }
658
659 bool is(TokenKind K) const { return Kind == K; }
660
661 SourceLocation getLocation() const {
662 return SourceLocation::getFromRawEncoding(Location);
663 }
664
665 StringRef getString() const {
666 return StringRef(StringData, StringLength);
667 }
668 };
Douglas Gregor82e52372012-11-06 19:39:40 +0000669
670 /// \brief The set of attributes that can be attached to a module.
Bill Wendlingad017fa2012-12-20 19:22:21 +0000671 struct Attributes {
672 Attributes() : IsSystem() { }
Douglas Gregor82e52372012-11-06 19:39:40 +0000673
674 /// \brief Whether this is a system module.
675 unsigned IsSystem : 1;
676 };
Douglas Gregora30cfe52011-11-11 19:10:28 +0000677
Douglas Gregor82e52372012-11-06 19:39:40 +0000678
Douglas Gregora30cfe52011-11-11 19:10:28 +0000679 class ModuleMapParser {
680 Lexer &L;
681 SourceManager &SourceMgr;
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000682
683 /// \brief Default target information, used only for string literal
684 /// parsing.
685 const TargetInfo *Target;
686
Douglas Gregora30cfe52011-11-11 19:10:28 +0000687 DiagnosticsEngine &Diags;
688 ModuleMap &Map;
689
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000690 /// \brief The directory that this module map resides in.
691 const DirectoryEntry *Directory;
Douglas Gregor2f04f182012-02-02 18:42:48 +0000692
693 /// \brief The directory containing Clang-supplied headers.
694 const DirectoryEntry *BuiltinIncludeDir;
695
Douglas Gregora30cfe52011-11-11 19:10:28 +0000696 /// \brief Whether an error occurred.
697 bool HadError;
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000698
Douglas Gregora30cfe52011-11-11 19:10:28 +0000699 /// \brief Stores string data for the various string literals referenced
700 /// during parsing.
701 llvm::BumpPtrAllocator StringData;
702
703 /// \brief The current token.
704 MMToken Tok;
705
706 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000707 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000708
709 /// \brief Consume the current token and return its location.
710 SourceLocation consumeToken();
711
712 /// \brief Skip tokens until we reach the a token with the given kind
713 /// (or the end of the file).
714 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000715
716 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
717 ModuleId;
718 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000719 void parseModuleDecl();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000720 void parseRequiresDecl();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000721 void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000722 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000723 void parseExportDecl();
Douglas Gregor82e52372012-11-06 19:39:40 +0000724 void parseInferredModuleDecl(bool Framework, bool Explicit);
Bill Wendlingad017fa2012-12-20 19:22:21 +0000725 bool parseOptionalAttributes(Attributes &Attrs);
Douglas Gregor82e52372012-11-06 19:39:40 +0000726
Douglas Gregor6a1db482011-12-09 02:04:43 +0000727 const DirectoryEntry *getOverriddenHeaderSearchDir();
728
Douglas Gregora30cfe52011-11-11 19:10:28 +0000729 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000730 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000731 const TargetInfo *Target,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000732 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000733 ModuleMap &Map,
Douglas Gregor2f04f182012-02-02 18:42:48 +0000734 const DirectoryEntry *Directory,
735 const DirectoryEntry *BuiltinIncludeDir)
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000736 : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
Douglas Gregor2f04f182012-02-02 18:42:48 +0000737 Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
738 HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000739 {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000740 Tok.clear();
741 consumeToken();
742 }
743
744 bool parseModuleMapFile();
745 };
746}
747
748SourceLocation ModuleMapParser::consumeToken() {
749retry:
750 SourceLocation Result = Tok.getLocation();
751 Tok.clear();
752
753 Token LToken;
754 L.LexFromRawLexer(LToken);
755 Tok.Location = LToken.getLocation().getRawEncoding();
756 switch (LToken.getKind()) {
757 case tok::raw_identifier:
758 Tok.StringData = LToken.getRawIdentifierData();
759 Tok.StringLength = LToken.getLength();
760 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
761 .Case("header", MMToken::HeaderKeyword)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000762 .Case("exclude", MMToken::ExcludeKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000763 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000764 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000765 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000766 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor51f564f2011-12-31 04:05:44 +0000767 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000768 .Case("umbrella", MMToken::UmbrellaKeyword)
769 .Default(MMToken::Identifier);
770 break;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000771
772 case tok::comma:
773 Tok.Kind = MMToken::Comma;
774 break;
775
Douglas Gregora30cfe52011-11-11 19:10:28 +0000776 case tok::eof:
777 Tok.Kind = MMToken::EndOfFile;
778 break;
779
780 case tok::l_brace:
781 Tok.Kind = MMToken::LBrace;
782 break;
783
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000784 case tok::l_square:
785 Tok.Kind = MMToken::LSquare;
786 break;
787
Douglas Gregor90db2602011-12-02 01:47:07 +0000788 case tok::period:
789 Tok.Kind = MMToken::Period;
790 break;
791
Douglas Gregora30cfe52011-11-11 19:10:28 +0000792 case tok::r_brace:
793 Tok.Kind = MMToken::RBrace;
794 break;
795
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000796 case tok::r_square:
797 Tok.Kind = MMToken::RSquare;
798 break;
799
Douglas Gregor90db2602011-12-02 01:47:07 +0000800 case tok::star:
801 Tok.Kind = MMToken::Star;
802 break;
803
Douglas Gregora30cfe52011-11-11 19:10:28 +0000804 case tok::string_literal: {
Richard Smith99831e42012-03-06 03:21:47 +0000805 if (LToken.hasUDSuffix()) {
806 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
807 HadError = true;
808 goto retry;
809 }
810
Douglas Gregora30cfe52011-11-11 19:10:28 +0000811 // Parse the string literal.
812 LangOptions LangOpts;
813 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
814 if (StringLiteral.hadError)
815 goto retry;
816
817 // Copy the string literal into our string data allocator.
818 unsigned Length = StringLiteral.GetStringLength();
819 char *Saved = StringData.Allocate<char>(Length + 1);
820 memcpy(Saved, StringLiteral.GetString().data(), Length);
821 Saved[Length] = 0;
822
823 // Form the token.
824 Tok.Kind = MMToken::StringLiteral;
825 Tok.StringData = Saved;
826 Tok.StringLength = Length;
827 break;
828 }
829
830 case tok::comment:
831 goto retry;
832
833 default:
834 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
835 HadError = true;
836 goto retry;
837 }
838
839 return Result;
840}
841
842void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
843 unsigned braceDepth = 0;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000844 unsigned squareDepth = 0;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000845 do {
846 switch (Tok.Kind) {
847 case MMToken::EndOfFile:
848 return;
849
850 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000851 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000852 return;
853
854 ++braceDepth;
855 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000856
857 case MMToken::LSquare:
858 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
859 return;
860
861 ++squareDepth;
862 break;
863
Douglas Gregora30cfe52011-11-11 19:10:28 +0000864 case MMToken::RBrace:
865 if (braceDepth > 0)
866 --braceDepth;
867 else if (Tok.is(K))
868 return;
869 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000870
871 case MMToken::RSquare:
872 if (squareDepth > 0)
873 --squareDepth;
874 else if (Tok.is(K))
875 return;
876 break;
877
Douglas Gregora30cfe52011-11-11 19:10:28 +0000878 default:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000879 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregora30cfe52011-11-11 19:10:28 +0000880 return;
881 break;
882 }
883
884 consumeToken();
885 } while (true);
886}
887
Douglas Gregor587986e2011-12-07 02:23:45 +0000888/// \brief Parse a module-id.
889///
890/// module-id:
891/// identifier
892/// identifier '.' module-id
893///
894/// \returns true if an error occurred, false otherwise.
895bool ModuleMapParser::parseModuleId(ModuleId &Id) {
896 Id.clear();
897 do {
898 if (Tok.is(MMToken::Identifier)) {
899 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
900 consumeToken();
901 } else {
902 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
903 return true;
904 }
905
906 if (!Tok.is(MMToken::Period))
907 break;
908
909 consumeToken();
910 } while (true);
911
912 return false;
913}
914
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000915namespace {
916 /// \brief Enumerates the known attributes.
917 enum AttributeKind {
918 /// \brief An unknown attribute.
919 AT_unknown,
920 /// \brief The 'system' attribute.
921 AT_system
922 };
923}
924
Douglas Gregora30cfe52011-11-11 19:10:28 +0000925/// \brief Parse a module declaration.
926///
927/// module-declaration:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000928/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
929/// { module-member* }
930///
Douglas Gregora30cfe52011-11-11 19:10:28 +0000931/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +0000932/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000933/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000934/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000935/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000936///
937/// submodule-declaration:
938/// module-declaration
939/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000940void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000941 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
942 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000943 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000944 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000945 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000946 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000947
Douglas Gregord620a842011-12-06 17:16:41 +0000948 // Parse 'explicit' keyword, if present.
949 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000950 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000951 Explicit = true;
952 }
953
954 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000955 if (Tok.is(MMToken::FrameworkKeyword)) {
956 consumeToken();
957 Framework = true;
958 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000959
960 // Parse 'module' keyword.
961 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000962 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000963 consumeToken();
964 HadError = true;
965 return;
966 }
967 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000968
969 // If we have a wildcard for the module name, this is an inferred submodule.
970 // Parse it.
971 if (Tok.is(MMToken::Star))
Douglas Gregor82e52372012-11-06 19:39:40 +0000972 return parseInferredModuleDecl(Framework, Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000973
974 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000975 ModuleId Id;
976 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000977 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000978 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000979 }
Douglas Gregor82e52372012-11-06 19:39:40 +0000980
Douglas Gregor587986e2011-12-07 02:23:45 +0000981 if (ActiveModule) {
982 if (Id.size() > 1) {
983 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
984 << SourceRange(Id.front().second, Id.back().second);
985
986 HadError = true;
987 return;
988 }
989 } else if (Id.size() == 1 && Explicit) {
990 // Top-level modules can't be explicit.
991 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
992 Explicit = false;
993 ExplicitLoc = SourceLocation();
994 HadError = true;
995 }
996
997 Module *PreviousActiveModule = ActiveModule;
998 if (Id.size() > 1) {
999 // This module map defines a submodule. Go find the module of which it
1000 // is a submodule.
1001 ActiveModule = 0;
1002 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1003 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1004 ActiveModule = Next;
1005 continue;
1006 }
1007
1008 if (ActiveModule) {
1009 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1010 << Id[I].first << ActiveModule->getTopLevelModule();
1011 } else {
1012 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1013 }
1014 HadError = true;
1015 return;
1016 }
1017 }
1018
1019 StringRef ModuleName = Id.back().first;
1020 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001021
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001022 // Parse the optional attribute list.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001023 Attributes Attrs;
Douglas Gregor82e52372012-11-06 19:39:40 +00001024 parseOptionalAttributes(Attrs);
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001025
Douglas Gregora30cfe52011-11-11 19:10:28 +00001026 // Parse the opening brace.
1027 if (!Tok.is(MMToken::LBrace)) {
1028 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1029 << ModuleName;
1030 HadError = true;
1031 return;
1032 }
1033 SourceLocation LBraceLoc = consumeToken();
1034
1035 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +00001036 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +00001037 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1038 // Skip the module definition.
1039 skipUntil(MMToken::RBrace);
1040 if (Tok.is(MMToken::RBrace))
1041 consumeToken();
1042 else {
1043 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1044 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1045 HadError = true;
1046 }
1047 return;
1048 }
1049
Douglas Gregora30cfe52011-11-11 19:10:28 +00001050 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1051 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +00001052 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001053
1054 // Skip the module definition.
1055 skipUntil(MMToken::RBrace);
1056 if (Tok.is(MMToken::RBrace))
1057 consumeToken();
1058
1059 HadError = true;
1060 return;
1061 }
1062
1063 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +00001064 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1065 Explicit).first;
1066 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregor82e52372012-11-06 19:39:40 +00001067 if (Attrs.IsSystem)
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001068 ActiveModule->IsSystem = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001069
1070 bool Done = false;
1071 do {
1072 switch (Tok.Kind) {
1073 case MMToken::EndOfFile:
1074 case MMToken::RBrace:
1075 Done = true;
1076 break;
1077
1078 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +00001079 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001080 case MMToken::ModuleKeyword:
1081 parseModuleDecl();
1082 break;
1083
Douglas Gregor90db2602011-12-02 01:47:07 +00001084 case MMToken::ExportKeyword:
1085 parseExportDecl();
1086 break;
1087
Douglas Gregor51f564f2011-12-31 04:05:44 +00001088 case MMToken::RequiresKeyword:
1089 parseRequiresDecl();
1090 break;
1091
Douglas Gregor77d029f2011-12-08 19:11:24 +00001092 case MMToken::UmbrellaKeyword: {
1093 SourceLocation UmbrellaLoc = consumeToken();
1094 if (Tok.is(MMToken::HeaderKeyword))
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001095 parseHeaderDecl(UmbrellaLoc, SourceLocation());
Douglas Gregor77d029f2011-12-08 19:11:24 +00001096 else
1097 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001098 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001099 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001100
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001101 case MMToken::ExcludeKeyword: {
1102 SourceLocation ExcludeLoc = consumeToken();
1103 if (Tok.is(MMToken::HeaderKeyword)) {
1104 parseHeaderDecl(SourceLocation(), ExcludeLoc);
1105 } else {
1106 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1107 << "exclude";
1108 }
1109 break;
1110 }
1111
Douglas Gregor489ad432011-12-08 18:00:48 +00001112 case MMToken::HeaderKeyword:
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001113 parseHeaderDecl(SourceLocation(), SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001114 break;
Douglas Gregor489ad432011-12-08 18:00:48 +00001115
Douglas Gregora30cfe52011-11-11 19:10:28 +00001116 default:
1117 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1118 consumeToken();
1119 break;
1120 }
1121 } while (!Done);
1122
1123 if (Tok.is(MMToken::RBrace))
1124 consumeToken();
1125 else {
1126 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1127 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1128 HadError = true;
1129 }
1130
Douglas Gregor587986e2011-12-07 02:23:45 +00001131 // We're done parsing this module. Pop back to the previous module.
1132 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001133}
Douglas Gregord620a842011-12-06 17:16:41 +00001134
Douglas Gregor51f564f2011-12-31 04:05:44 +00001135/// \brief Parse a requires declaration.
1136///
1137/// requires-declaration:
1138/// 'requires' feature-list
1139///
1140/// feature-list:
1141/// identifier ',' feature-list
1142/// identifier
1143void ModuleMapParser::parseRequiresDecl() {
1144 assert(Tok.is(MMToken::RequiresKeyword));
1145
1146 // Parse 'requires' keyword.
1147 consumeToken();
1148
1149 // Parse the feature-list.
1150 do {
1151 if (!Tok.is(MMToken::Identifier)) {
1152 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1153 HadError = true;
1154 return;
1155 }
1156
1157 // Consume the feature name.
1158 std::string Feature = Tok.getString();
1159 consumeToken();
1160
1161 // Add this feature.
Douglas Gregordc58aa72012-01-30 06:01:29 +00001162 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor51f564f2011-12-31 04:05:44 +00001163
1164 if (!Tok.is(MMToken::Comma))
1165 break;
1166
1167 // Consume the comma.
1168 consumeToken();
1169 } while (true);
1170}
1171
Douglas Gregord620a842011-12-06 17:16:41 +00001172/// \brief Append to \p Paths the set of paths needed to get to the
1173/// subframework in which the given module lives.
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001174static void appendSubframeworkPaths(Module *Mod,
1175 llvm::SmallVectorImpl<char> &Path) {
Douglas Gregord620a842011-12-06 17:16:41 +00001176 // Collect the framework names from the given module to the top-level module.
1177 llvm::SmallVector<StringRef, 2> Paths;
1178 for (; Mod; Mod = Mod->Parent) {
1179 if (Mod->IsFramework)
1180 Paths.push_back(Mod->Name);
1181 }
1182
1183 if (Paths.empty())
1184 return;
1185
1186 // Add Frameworks/Name.framework for each subframework.
1187 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1188 llvm::sys::path::append(Path, "Frameworks");
1189 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1190 }
1191}
1192
Douglas Gregor2f04f182012-02-02 18:42:48 +00001193/// \brief Determine whether the given file name is the name of a builtin
1194/// header, supplied by Clang to replace, override, or augment existing system
1195/// headers.
1196static bool isBuiltinHeader(StringRef FileName) {
1197 return llvm::StringSwitch<bool>(FileName)
1198 .Case("float.h", true)
1199 .Case("iso646.h", true)
1200 .Case("limits.h", true)
1201 .Case("stdalign.h", true)
1202 .Case("stdarg.h", true)
1203 .Case("stdbool.h", true)
1204 .Case("stddef.h", true)
1205 .Case("stdint.h", true)
1206 .Case("tgmath.h", true)
1207 .Case("unwind.h", true)
1208 .Default(false);
1209}
1210
Douglas Gregora30cfe52011-11-11 19:10:28 +00001211/// \brief Parse a header declaration.
1212///
1213/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +00001214/// 'umbrella'[opt] 'header' string-literal
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001215/// 'exclude'[opt] 'header' string-literal
1216void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
1217 SourceLocation ExcludeLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001218 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +00001219 consumeToken();
1220
Douglas Gregor489ad432011-12-08 18:00:48 +00001221 bool Umbrella = UmbrellaLoc.isValid();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001222 bool Exclude = ExcludeLoc.isValid();
1223 assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001224 // Parse the header name.
1225 if (!Tok.is(MMToken::StringLiteral)) {
1226 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1227 << "header";
1228 HadError = true;
1229 return;
1230 }
Douglas Gregor587986e2011-12-07 02:23:45 +00001231 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +00001232 SourceLocation FileNameLoc = consumeToken();
1233
Douglas Gregor77d029f2011-12-08 19:11:24 +00001234 // Check whether we already have an umbrella.
1235 if (Umbrella && ActiveModule->Umbrella) {
1236 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1237 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001238 HadError = true;
1239 return;
1240 }
1241
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001242 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +00001243 const FileEntry *File = 0;
Douglas Gregor2f04f182012-02-02 18:42:48 +00001244 const FileEntry *BuiltinFile = 0;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001245 SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +00001246 if (llvm::sys::path::is_absolute(FileName)) {
1247 PathName = FileName;
1248 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +00001249 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1250 PathName = Dir->getName();
1251 llvm::sys::path::append(PathName, FileName);
1252 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001253 } else {
1254 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +00001255 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +00001256 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +00001257
Douglas Gregord620a842011-12-06 17:16:41 +00001258 if (ActiveModule->isPartOfFramework()) {
1259 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001260
1261 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +00001262 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +00001263 llvm::sys::path::append(PathName, FileName);
1264 File = SourceMgr.getFileManager().getFile(PathName);
1265
1266 if (!File) {
1267 // Check whether this file is in the private headers.
1268 PathName.resize(PathLength);
1269 llvm::sys::path::append(PathName, "PrivateHeaders");
1270 llvm::sys::path::append(PathName, FileName);
1271 File = SourceMgr.getFileManager().getFile(PathName);
1272 }
1273 } else {
1274 // Lookup for normal headers.
1275 llvm::sys::path::append(PathName, FileName);
1276 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001277
1278 // If this is a system module with a top-level header, this header
1279 // may have a counterpart (or replacement) in the set of headers
1280 // supplied by Clang. Find that builtin header.
1281 if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
1282 BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001283 SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
Douglas Gregor2f04f182012-02-02 18:42:48 +00001284 llvm::sys::path::append(BuiltinPathName, FileName);
1285 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1286
1287 // If Clang supplies this header but the underlying system does not,
1288 // just silently swap in our builtin version. Otherwise, we'll end
1289 // up adding both (later).
1290 if (!File && BuiltinFile) {
1291 File = BuiltinFile;
1292 BuiltinFile = 0;
1293 }
1294 }
Douglas Gregord620a842011-12-06 17:16:41 +00001295 }
Douglas Gregor18ee5472011-11-29 21:59:16 +00001296 }
Douglas Gregora8654052011-11-17 22:09:43 +00001297
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001298 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1299 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001300 if (File) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001301 if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001302 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001303 << FileName << OwningModule.getModule()->getFullModuleName();
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001304 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +00001305 } else if (Umbrella) {
1306 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001307 if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Douglas Gregor489ad432011-12-08 18:00:48 +00001308 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001309 << UmbrellaModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001310 HadError = true;
1311 } else {
1312 // Record this umbrella header.
1313 Map.setUmbrellaHeader(ActiveModule, File);
1314 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001315 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001316 // Record this header.
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001317 Map.addHeader(ActiveModule, File, Exclude);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001318
1319 // If there is a builtin counterpart to this file, add it now.
1320 if (BuiltinFile)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001321 Map.addHeader(ActiveModule, BuiltinFile, Exclude);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001322 }
Douglas Gregor71f49f52012-11-15 19:47:16 +00001323 } else if (!Exclude) {
1324 // Ignore excluded header files. They're optional anyway.
1325
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001326 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +00001327 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001328 HadError = true;
1329 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001330}
1331
Douglas Gregor77d029f2011-12-08 19:11:24 +00001332/// \brief Parse an umbrella directory declaration.
1333///
1334/// umbrella-dir-declaration:
1335/// umbrella string-literal
1336void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1337 // Parse the directory name.
1338 if (!Tok.is(MMToken::StringLiteral)) {
1339 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1340 << "umbrella";
1341 HadError = true;
1342 return;
1343 }
1344
1345 std::string DirName = Tok.getString();
1346 SourceLocation DirNameLoc = consumeToken();
1347
1348 // Check whether we already have an umbrella.
1349 if (ActiveModule->Umbrella) {
1350 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1351 << ActiveModule->getFullModuleName();
1352 HadError = true;
1353 return;
1354 }
1355
1356 // Look for this file.
1357 const DirectoryEntry *Dir = 0;
1358 if (llvm::sys::path::is_absolute(DirName))
1359 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1360 else {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001361 SmallString<128> PathName;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001362 PathName = Directory->getName();
1363 llvm::sys::path::append(PathName, DirName);
1364 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1365 }
1366
1367 if (!Dir) {
1368 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1369 << DirName;
1370 HadError = true;
1371 return;
1372 }
1373
1374 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1375 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1376 << OwningModule->getFullModuleName();
1377 HadError = true;
1378 return;
1379 }
1380
1381 // Record this umbrella directory.
1382 Map.setUmbrellaDir(ActiveModule, Dir);
1383}
1384
Douglas Gregor90db2602011-12-02 01:47:07 +00001385/// \brief Parse a module export declaration.
1386///
1387/// export-declaration:
1388/// 'export' wildcard-module-id
1389///
1390/// wildcard-module-id:
1391/// identifier
1392/// '*'
1393/// identifier '.' wildcard-module-id
1394void ModuleMapParser::parseExportDecl() {
1395 assert(Tok.is(MMToken::ExportKeyword));
1396 SourceLocation ExportLoc = consumeToken();
1397
1398 // Parse the module-id with an optional wildcard at the end.
1399 ModuleId ParsedModuleId;
1400 bool Wildcard = false;
1401 do {
1402 if (Tok.is(MMToken::Identifier)) {
1403 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1404 Tok.getLocation()));
1405 consumeToken();
1406
1407 if (Tok.is(MMToken::Period)) {
1408 consumeToken();
1409 continue;
1410 }
1411
1412 break;
1413 }
1414
1415 if(Tok.is(MMToken::Star)) {
1416 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001417 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001418 break;
1419 }
1420
1421 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1422 HadError = true;
1423 return;
1424 } while (true);
1425
1426 Module::UnresolvedExportDecl Unresolved = {
1427 ExportLoc, ParsedModuleId, Wildcard
1428 };
1429 ActiveModule->UnresolvedExports.push_back(Unresolved);
1430}
1431
Douglas Gregor82e52372012-11-06 19:39:40 +00001432/// \brief Parse an inferried module declaration (wildcard modules).
1433///
1434/// module-declaration:
1435/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
1436/// { inferred-module-member* }
1437///
1438/// inferred-module-member:
1439/// 'export' '*'
1440/// 'exclude' identifier
1441void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001442 assert(Tok.is(MMToken::Star));
1443 SourceLocation StarLoc = consumeToken();
1444 bool Failed = false;
Douglas Gregor82e52372012-11-06 19:39:40 +00001445
Douglas Gregor1e123682011-12-05 22:27:44 +00001446 // Inferred modules must be submodules.
Douglas Gregor82e52372012-11-06 19:39:40 +00001447 if (!ActiveModule && !Framework) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001448 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1449 Failed = true;
1450 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001451
1452 if (ActiveModule) {
1453 // Inferred modules must have umbrella directories.
1454 if (!Failed && !ActiveModule->getUmbrellaDir()) {
1455 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1456 Failed = true;
1457 }
1458
1459 // Check for redefinition of an inferred module.
1460 if (!Failed && ActiveModule->InferSubmodules) {
1461 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1462 if (ActiveModule->InferredSubmoduleLoc.isValid())
1463 Diags.Report(ActiveModule->InferredSubmoduleLoc,
1464 diag::note_mmap_prev_definition);
1465 Failed = true;
1466 }
1467
1468 // Check for the 'framework' keyword, which is not permitted here.
1469 if (Framework) {
1470 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
1471 Framework = false;
1472 }
1473 } else if (Explicit) {
1474 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
1475 Explicit = false;
Douglas Gregor1e123682011-12-05 22:27:44 +00001476 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001477
Douglas Gregor1e123682011-12-05 22:27:44 +00001478 // If there were any problems with this inferred submodule, skip its body.
1479 if (Failed) {
1480 if (Tok.is(MMToken::LBrace)) {
1481 consumeToken();
1482 skipUntil(MMToken::RBrace);
1483 if (Tok.is(MMToken::RBrace))
1484 consumeToken();
1485 }
1486 HadError = true;
1487 return;
1488 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001489
1490 // Parse optional attributes.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001491 Attributes Attrs;
Douglas Gregor82e52372012-11-06 19:39:40 +00001492 parseOptionalAttributes(Attrs);
1493
1494 if (ActiveModule) {
1495 // Note that we have an inferred submodule.
1496 ActiveModule->InferSubmodules = true;
1497 ActiveModule->InferredSubmoduleLoc = StarLoc;
1498 ActiveModule->InferExplicitSubmodules = Explicit;
1499 } else {
1500 // We'll be inferring framework modules for this directory.
1501 Map.InferredDirectories[Directory].InferModules = true;
1502 Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
1503 }
1504
Douglas Gregor1e123682011-12-05 22:27:44 +00001505 // Parse the opening brace.
1506 if (!Tok.is(MMToken::LBrace)) {
1507 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1508 HadError = true;
1509 return;
1510 }
1511 SourceLocation LBraceLoc = consumeToken();
1512
1513 // Parse the body of the inferred submodule.
1514 bool Done = false;
1515 do {
1516 switch (Tok.Kind) {
1517 case MMToken::EndOfFile:
1518 case MMToken::RBrace:
1519 Done = true;
1520 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001521
1522 case MMToken::ExcludeKeyword: {
1523 if (ActiveModule) {
1524 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001525 << (ActiveModule != 0);
Douglas Gregor82e52372012-11-06 19:39:40 +00001526 consumeToken();
1527 break;
1528 }
1529
1530 consumeToken();
1531 if (!Tok.is(MMToken::Identifier)) {
1532 Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
1533 break;
1534 }
1535
1536 Map.InferredDirectories[Directory].ExcludedModules
1537 .push_back(Tok.getString());
1538 consumeToken();
1539 break;
1540 }
1541
1542 case MMToken::ExportKeyword:
1543 if (!ActiveModule) {
1544 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001545 << (ActiveModule != 0);
Douglas Gregor82e52372012-11-06 19:39:40 +00001546 consumeToken();
1547 break;
1548 }
1549
Douglas Gregor1e123682011-12-05 22:27:44 +00001550 consumeToken();
1551 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001552 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001553 else
1554 Diags.Report(Tok.getLocation(),
1555 diag::err_mmap_expected_export_wildcard);
1556 consumeToken();
1557 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001558
Douglas Gregor1e123682011-12-05 22:27:44 +00001559 case MMToken::ExplicitKeyword:
1560 case MMToken::ModuleKeyword:
1561 case MMToken::HeaderKeyword:
1562 case MMToken::UmbrellaKeyword:
1563 default:
Douglas Gregor82e52372012-11-06 19:39:40 +00001564 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001565 << (ActiveModule != 0);
Douglas Gregor1e123682011-12-05 22:27:44 +00001566 consumeToken();
1567 break;
1568 }
1569 } while (!Done);
1570
1571 if (Tok.is(MMToken::RBrace))
1572 consumeToken();
1573 else {
1574 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1575 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1576 HadError = true;
1577 }
1578}
1579
Douglas Gregor82e52372012-11-06 19:39:40 +00001580/// \brief Parse optional attributes.
1581///
1582/// attributes:
1583/// attribute attributes
1584/// attribute
1585///
1586/// attribute:
1587/// [ identifier ]
1588///
1589/// \param Attrs Will be filled in with the parsed attributes.
1590///
1591/// \returns true if an error occurred, false otherwise.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001592bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
Douglas Gregor82e52372012-11-06 19:39:40 +00001593 bool HadError = false;
1594
1595 while (Tok.is(MMToken::LSquare)) {
1596 // Consume the '['.
1597 SourceLocation LSquareLoc = consumeToken();
1598
1599 // Check whether we have an attribute name here.
1600 if (!Tok.is(MMToken::Identifier)) {
1601 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
1602 skipUntil(MMToken::RSquare);
1603 if (Tok.is(MMToken::RSquare))
1604 consumeToken();
1605 HadError = true;
1606 }
1607
1608 // Decode the attribute name.
1609 AttributeKind Attribute
1610 = llvm::StringSwitch<AttributeKind>(Tok.getString())
1611 .Case("system", AT_system)
1612 .Default(AT_unknown);
1613 switch (Attribute) {
1614 case AT_unknown:
1615 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
1616 << Tok.getString();
1617 break;
1618
1619 case AT_system:
1620 Attrs.IsSystem = true;
1621 break;
1622 }
1623 consumeToken();
1624
1625 // Consume the ']'.
1626 if (!Tok.is(MMToken::RSquare)) {
1627 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
1628 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
1629 skipUntil(MMToken::RSquare);
1630 HadError = true;
1631 }
1632
1633 if (Tok.is(MMToken::RSquare))
1634 consumeToken();
1635 }
1636
1637 return HadError;
1638}
1639
Douglas Gregor6a1db482011-12-09 02:04:43 +00001640/// \brief If there is a specific header search directory due the presence
1641/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1642const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1643 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1644 // If we have an umbrella directory, use that.
1645 if (Mod->hasUmbrellaDir())
1646 return Mod->getUmbrellaDir();
1647
1648 // If we have a framework directory, stop looking.
1649 if (Mod->IsFramework)
1650 return 0;
1651 }
1652
1653 return 0;
1654}
1655
Douglas Gregora30cfe52011-11-11 19:10:28 +00001656/// \brief Parse a module map file.
1657///
1658/// module-map-file:
1659/// module-declaration*
1660bool ModuleMapParser::parseModuleMapFile() {
1661 do {
1662 switch (Tok.Kind) {
1663 case MMToken::EndOfFile:
1664 return HadError;
1665
Douglas Gregor587986e2011-12-07 02:23:45 +00001666 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001667 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001668 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001669 parseModuleDecl();
1670 break;
1671
Douglas Gregor51f564f2011-12-31 04:05:44 +00001672 case MMToken::Comma:
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001673 case MMToken::ExcludeKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001674 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001675 case MMToken::HeaderKeyword:
1676 case MMToken::Identifier:
1677 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001678 case MMToken::LSquare:
Douglas Gregor90db2602011-12-02 01:47:07 +00001679 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001680 case MMToken::RBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001681 case MMToken::RSquare:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001682 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001683 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001684 case MMToken::StringLiteral:
1685 case MMToken::UmbrellaKeyword:
1686 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1687 HadError = true;
1688 consumeToken();
1689 break;
1690 }
1691 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001692}
1693
1694bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregordc58aa72012-01-30 06:01:29 +00001695 assert(Target != 0 && "Missing target information");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001696 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1697 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1698 if (!Buffer)
1699 return true;
1700
1701 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00001702 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1703 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor9a022bb2012-10-15 16:45:32 +00001704 ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
Douglas Gregor2f04f182012-02-02 18:42:48 +00001705 BuiltinIncludeDir);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001706 bool Result = Parser.parseModuleMapFile();
1707 Diags->getClient()->EndSourceFile();
1708
1709 return Result;
1710}