blob: b2e49ea50e9070a544a991f864339d631e764294 [file] [log] [blame]
Douglas Gregor718292f2011-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 Gregor718292f2011-11-11 19:10:28 +000015#include "clang/Basic/Diagnostic.h"
Douglas Gregor811db4e2012-10-23 22:26:28 +000016#include "clang/Basic/DiagnosticOptions.h"
Douglas Gregor718292f2011-11-11 19:10:28 +000017#include "clang/Basic/FileManager.h"
18#include "clang/Basic/TargetInfo.h"
19#include "clang/Basic/TargetOptions.h"
Chandler Carruth3a022472012-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 Gregor718292f2011-11-11 19:10:28 +000025#include "llvm/Support/Allocator.h"
Douglas Gregore89dbc12011-12-06 19:39:29 +000026#include "llvm/Support/FileSystem.h"
Douglas Gregor718292f2011-11-11 19:10:28 +000027#include "llvm/Support/Host.h"
Douglas Gregor5257fc62011-11-11 21:55:48 +000028#include "llvm/Support/PathV2.h"
Douglas Gregor718292f2011-11-11 19:10:28 +000029#include "llvm/Support/raw_ostream.h"
Douglas Gregor07c22b72012-09-27 14:50:15 +000030#include <stdlib.h>
Douglas Gregor718292f2011-11-11 19:10:28 +000031using namespace clang;
32
Douglas Gregor2b82c2a2011-12-02 01:47:07 +000033Module::ExportDecl
34ModuleMap::resolveExport(Module *Mod,
35 const Module::UnresolvedExportDecl &Unresolved,
36 bool Complain) {
Douglas Gregorf5eedd02011-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 Gregor2b82c2a2011-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 Gregor1fb5c3a2011-12-31 04:05:44 +000074ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
Douglas Gregor89929282012-01-30 06:01:29 +000075 const LangOptions &LangOpts, const TargetInfo *Target)
Douglas Gregor3ec66632012-02-02 18:42:48 +000076 : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0)
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +000077{
Dylan Noblesmithc95d8192012-02-20 14:00:23 +000078 IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
79 Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
Douglas Gregor811db4e2012-10-23 22:26:28 +000080 new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
Douglas Gregor718292f2011-11-11 19:10:28 +000081 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
82 SourceMgr = new SourceManager(*Diags, FileMgr);
83}
84
85ModuleMap::~ModuleMap() {
Douglas Gregor5acdf592011-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 Gregor718292f2011-11-11 19:10:28 +000092 delete SourceMgr;
93}
94
Douglas Gregor89929282012-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 Gregor056396a2012-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 Gregorde3ef502011-11-30 23:21:26 +0000149Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor59527662012-10-15 06:28:11 +0000150 HeadersMap::iterator Known = Headers.find(File);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000151 if (Known != Headers.end()) {
Douglas Gregor59527662012-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 Gregor1fb5c3a2011-12-31 04:05:44 +0000154 return 0;
155
Douglas Gregor59527662012-10-15 06:28:11 +0000156 return Known->second.getModule();
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000157 }
Douglas Gregorab0c8a82011-11-11 22:18:48 +0000158
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000159 const DirectoryEntry *Dir = File->getDir();
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000160 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
Douglas Gregor74260502013-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 Gregorb65dbff2011-11-16 23:02:25 +0000173 StringRef DirName = Dir->getName();
Douglas Gregor74260502013-01-04 19:44:26 +0000174#endif
Douglas Gregora89c5ac2011-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 Gregor930a85c2011-12-06 16:17:15 +0000183
184 // Search up the module stack until we find a module with an umbrella
Douglas Gregor73141fa2011-12-08 17:39:04 +0000185 // directory.
Douglas Gregor930a85c2011-12-06 16:17:15 +0000186 Module *UmbrellaModule = Result;
Douglas Gregor73141fa2011-12-08 17:39:04 +0000187 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor930a85c2011-12-06 16:17:15 +0000188 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000189
Douglas Gregor930a85c2011-12-06 16:17:15 +0000190 if (UmbrellaModule->InferSubmodules) {
Douglas Gregora89c5ac2011-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 Gregor9458f822011-12-07 22:05:21 +0000194 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000195
Douglas Gregor70331272011-12-09 02:04:43 +0000196 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000197 // Find or create the module that corresponds to this directory name.
Douglas Gregor056396a2012-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 Gregora89c5ac2011-12-06 01:10:29 +0000202 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9458f822011-12-07 22:05:21 +0000203 Explicit).first;
Douglas Gregora89c5ac2011-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 Gregor930a85c2011-12-06 16:17:15 +0000210 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregora89c5ac2011-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 Gregor056396a2012-10-12 21:15:50 +0000215 SmallString<32> NameBuf;
216 StringRef Name = sanitizeFilenameAsIdentifier(
217 llvm::sys::path::stem(File->getName()), NameBuf);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000218 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9458f822011-12-07 22:05:21 +0000219 Explicit).first;
Argyrios Kyrtzidisc597c8c2012-10-05 00:22:33 +0000220 Result->TopHeaders.insert(File);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000221
222 // If inferred submodules export everything they import, add a
223 // wildcard to the set of exports.
Douglas Gregor930a85c2011-12-06 16:17:15 +0000224 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregora89c5ac2011-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 Gregor59527662012-10-15 06:28:11 +0000233 Headers[File] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor1fb5c3a2011-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 Gregora89c5ac2011-12-06 01:10:29 +0000240 return Result;
241 }
242
243 SkippedDirs.push_back(Dir);
244
Douglas Gregorb65dbff2011-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 Gregora89c5ac2011-12-06 01:10:29 +0000252 } while (Dir);
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000253
Douglas Gregorab0c8a82011-11-11 22:18:48 +0000254 return 0;
255}
256
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000257bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
Douglas Gregor59527662012-10-15 06:28:11 +0000258 HeadersMap::iterator Known = Headers.find(Header);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000259 if (Known != Headers.end())
Douglas Gregor59527662012-10-15 06:28:11 +0000260 return !Known->second.isAvailable();
Douglas Gregor1fb5c3a2011-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 Gregor056396a2012-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 Gregor1fb5c3a2011-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 Gregor056396a2012-10-12 21:15:50 +0000297 SmallString<32> NameBuf;
298 StringRef Name = sanitizeFilenameAsIdentifier(
299 llvm::sys::path::stem(Header->getName()),
300 NameBuf);
Douglas Gregor1fb5c3a2011-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 Gregorde3ef502011-11-30 23:21:26 +0000323Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor88bdfb02011-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 Gregor2b82c2a2011-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 Gregoreb90e832012-01-04 23:32:19 +0000344 return Context->findSubmodule(Name);
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000345}
346
Douglas Gregorde3ef502011-11-30 23:21:26 +0000347std::pair<Module *, bool>
Douglas Gregor69021972011-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 Gregoreb90e832012-01-04 23:32:19 +0000351 if (Module *Sub = lookupModuleQualified(Name, Parent))
352 return std::make_pair(Sub, false);
Douglas Gregor69021972011-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 Gregoreb90e832012-01-04 23:32:19 +0000357 if (!Parent)
Douglas Gregor69021972011-11-30 17:33:56 +0000358 Modules[Name] = Result;
359 return std::make_pair(Result, true);
360}
361
Douglas Gregor9194a912012-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 Gregorde3ef502011-11-30 23:21:26 +0000386Module *
Douglas Gregor9194a912012-11-06 19:39:40 +0000387ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregore89dbc12011-12-06 19:39:29 +0000388 const DirectoryEntry *FrameworkDir,
Douglas Gregora686e1b2012-01-27 19:52:33 +0000389 bool IsSystem,
Douglas Gregore89dbc12011-12-06 19:39:29 +0000390 Module *Parent) {
Douglas Gregor56c64012011-11-17 01:41:17 +0000391 // Check whether we've already found this module.
Douglas Gregore89dbc12011-12-06 19:39:29 +0000392 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
393 return Mod;
394
395 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor9194a912012-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) {
Douglas Gregor4ddf2222013-01-10 01:43:00 +0000400 // Determine whether we're allowed to infer a module map.
401 StringRef FrameworkDirName = FrameworkDir->getName();
402#ifdef LLVM_ON_UNIX
403 // Note: as an egregious but useful hack we use the real path here, because
404 // we might be looking at an embedded framework that symlinks out to a
405 // top-level framework, and we need to infer as if we were naming the
406 // top-level framework.
407 char RealFrameworkDirName[PATH_MAX];
408 if (realpath(FrameworkDir->getName(), RealFrameworkDirName))
409 FrameworkDirName = RealFrameworkDirName;
410#endif
411
Douglas Gregor9194a912012-11-06 19:39:40 +0000412 bool canInfer = false;
Douglas Gregor4ddf2222013-01-10 01:43:00 +0000413 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
Douglas Gregor9194a912012-11-06 19:39:40 +0000414 // Figure out the parent path.
Douglas Gregor4ddf2222013-01-10 01:43:00 +0000415 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
Douglas Gregor9194a912012-11-06 19:39:40 +0000416 if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
417 // Check whether we have already looked into the parent directory
418 // for a module map.
419 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
420 inferred = InferredDirectories.find(ParentDir);
421 if (inferred == InferredDirectories.end()) {
422 // We haven't looked here before. Load a module map, if there is
423 // one.
424 SmallString<128> ModMapPath = Parent;
425 llvm::sys::path::append(ModMapPath, "module.map");
426 if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
427 parseModuleMapFile(ModMapFile);
428 inferred = InferredDirectories.find(ParentDir);
429 }
430
431 if (inferred == InferredDirectories.end())
432 inferred = InferredDirectories.insert(
433 std::make_pair(ParentDir, InferredDirectory())).first;
434 }
435
436 if (inferred->second.InferModules) {
437 // We're allowed to infer for this directory, but make sure it's okay
438 // to infer this particular module.
Douglas Gregor4ddf2222013-01-10 01:43:00 +0000439 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
Douglas Gregor9194a912012-11-06 19:39:40 +0000440 canInfer = std::find(inferred->second.ExcludedModules.begin(),
441 inferred->second.ExcludedModules.end(),
442 Name) == inferred->second.ExcludedModules.end();
443
444 if (inferred->second.InferSystemModules)
445 IsSystem = true;
446 }
447 }
448 }
449
450 // If we're not allowed to infer a framework module, don't.
451 if (!canInfer)
452 return 0;
453 }
454
455
Douglas Gregor56c64012011-11-17 01:41:17 +0000456 // Look for an umbrella header.
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +0000457 SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Douglas Gregor56c64012011-11-17 01:41:17 +0000458 llvm::sys::path::append(UmbrellaName, "Headers");
459 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregore89dbc12011-12-06 19:39:29 +0000460 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor56c64012011-11-17 01:41:17 +0000461
462 // FIXME: If there's no umbrella header, we could probably scan the
463 // framework to load *everything*. But, it's not clear that this is a good
464 // idea.
465 if (!UmbrellaHeader)
466 return 0;
467
Douglas Gregore89dbc12011-12-06 19:39:29 +0000468 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
469 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora686e1b2012-01-27 19:52:33 +0000470 if (IsSystem)
471 Result->IsSystem = IsSystem;
472
Douglas Gregoreb90e832012-01-04 23:32:19 +0000473 if (!Parent)
Douglas Gregore89dbc12011-12-06 19:39:29 +0000474 Modules[ModuleName] = Result;
Douglas Gregoreb90e832012-01-04 23:32:19 +0000475
Douglas Gregor322f6332011-12-08 18:00:48 +0000476 // umbrella header "umbrella-header-name"
Douglas Gregor73141fa2011-12-08 17:39:04 +0000477 Result->Umbrella = UmbrellaHeader;
Douglas Gregor59527662012-10-15 06:28:11 +0000478 Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor4dc71832011-12-12 23:55:05 +0000479 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregord8bd7532011-12-05 17:40:25 +0000480
481 // export *
482 Result->Exports.push_back(Module::ExportDecl(0, true));
483
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000484 // module * { export * }
485 Result->InferSubmodules = true;
486 Result->InferExportWildcard = true;
487
Douglas Gregore89dbc12011-12-06 19:39:29 +0000488 // Look for subframeworks.
489 llvm::error_code EC;
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +0000490 SmallString<128> SubframeworksDirName
Douglas Gregorddaa69c2011-12-08 16:13:24 +0000491 = StringRef(FrameworkDir->getName());
Douglas Gregore89dbc12011-12-06 19:39:29 +0000492 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +0000493 SmallString<128> SubframeworksDirNameNative;
Douglas Gregorddaa69c2011-12-08 16:13:24 +0000494 llvm::sys::path::native(SubframeworksDirName.str(),
495 SubframeworksDirNameNative);
496 for (llvm::sys::fs::directory_iterator
497 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregore89dbc12011-12-06 19:39:29 +0000498 Dir != DirEnd && !EC; Dir.increment(EC)) {
499 if (!StringRef(Dir->path()).endswith(".framework"))
500 continue;
Douglas Gregor07c22b72012-09-27 14:50:15 +0000501
Douglas Gregore89dbc12011-12-06 19:39:29 +0000502 if (const DirectoryEntry *SubframeworkDir
503 = FileMgr.getDirectory(Dir->path())) {
Douglas Gregor07c22b72012-09-27 14:50:15 +0000504 // Note: as an egregious but useful hack, we use the real path here and
505 // check whether it is actually a subdirectory of the parent directory.
506 // This will not be the case if the 'subframework' is actually a symlink
507 // out to a top-level framework.
508#ifdef LLVM_ON_UNIX
509 char RealSubframeworkDirName[PATH_MAX];
510 if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) {
511 StringRef SubframeworkDirName = RealSubframeworkDirName;
512
513 bool FoundParent = false;
514 do {
515 // Get the parent directory name.
516 SubframeworkDirName
517 = llvm::sys::path::parent_path(SubframeworkDirName);
518 if (SubframeworkDirName.empty())
519 break;
520
521 if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
522 FoundParent = true;
523 break;
524 }
525 } while (true);
526
527 if (!FoundParent)
528 continue;
529 }
530#endif
531
Douglas Gregore89dbc12011-12-06 19:39:29 +0000532 // FIXME: Do we want to warn about subframeworks without umbrella headers?
Douglas Gregor056396a2012-10-12 21:15:50 +0000533 SmallString<32> NameBuf;
534 inferFrameworkModule(sanitizeFilenameAsIdentifier(
535 llvm::sys::path::stem(Dir->path()), NameBuf),
536 SubframeworkDir, IsSystem, Result);
Douglas Gregore89dbc12011-12-06 19:39:29 +0000537 }
538 }
Douglas Gregor09a22f02012-01-13 16:54:27 +0000539
Douglas Gregor56c64012011-11-17 01:41:17 +0000540 return Result;
541}
542
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000543void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
Douglas Gregor59527662012-10-15 06:28:11 +0000544 Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
Douglas Gregor73141fa2011-12-08 17:39:04 +0000545 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor70331272011-12-09 02:04:43 +0000546 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000547}
548
Douglas Gregor524e33e2011-12-08 19:11:24 +0000549void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
550 Mod->Umbrella = UmbrellaDir;
551 UmbrellaDirs[UmbrellaDir] = Mod;
552}
553
Douglas Gregor59527662012-10-15 06:28:11 +0000554void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
555 bool Excluded) {
556 if (Excluded)
557 Mod->ExcludedHeaders.push_back(Header);
558 else
559 Mod->Headers.push_back(Header);
560 Headers[Header] = KnownHeader(Mod, Excluded);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000561}
562
Douglas Gregor514b6362011-11-29 19:06:37 +0000563const FileEntry *
Douglas Gregorde3ef502011-11-30 23:21:26 +0000564ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregor514b6362011-11-29 19:06:37 +0000565 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
566 return 0;
567
568 return SourceMgr->getFileEntryForID(
569 SourceMgr->getFileID(Module->DefinitionLoc));
570}
571
Douglas Gregor718292f2011-11-11 19:10:28 +0000572void ModuleMap::dump() {
573 llvm::errs() << "Modules:";
574 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
575 MEnd = Modules.end();
576 M != MEnd; ++M)
Douglas Gregord28d1b82011-11-29 18:17:59 +0000577 M->getValue()->print(llvm::errs(), 2);
Douglas Gregor718292f2011-11-11 19:10:28 +0000578
579 llvm::errs() << "Headers:";
Douglas Gregor59527662012-10-15 06:28:11 +0000580 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
Douglas Gregor718292f2011-11-11 19:10:28 +0000581 H != HEnd; ++H) {
582 llvm::errs() << " \"" << H->first->getName() << "\" -> "
Douglas Gregor59527662012-10-15 06:28:11 +0000583 << H->second.getModule()->getFullModuleName() << "\n";
Douglas Gregor718292f2011-11-11 19:10:28 +0000584 }
585}
586
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000587bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
588 bool HadError = false;
589 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
590 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
591 Complain);
Douglas Gregorf5eedd02011-12-05 17:28:06 +0000592 if (Export.getPointer() || Export.getInt())
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000593 Mod->Exports.push_back(Export);
594 else
595 HadError = true;
596 }
597 Mod->UnresolvedExports.clear();
598 return HadError;
599}
600
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000601Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
602 if (Loc.isInvalid())
603 return 0;
604
605 // Use the expansion location to determine which module we're in.
606 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
607 if (!ExpansionLoc.isFileID())
608 return 0;
609
610
611 const SourceManager &SrcMgr = Loc.getManager();
612 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000613
Douglas Gregor224d8a72012-01-06 17:19:32 +0000614 while (const FileEntry *ExpansionFile
615 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
616 // Find the module that owns this header (if any).
617 if (Module *Mod = findModuleForHeader(ExpansionFile))
618 return Mod;
619
620 // No module owns this header, so look up the inclusion chain to see if
621 // any included header has an associated module.
622 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
623 if (IncludeLoc.isInvalid())
624 return 0;
625
626 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
627 }
628
629 return 0;
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000630}
631
Douglas Gregor718292f2011-11-11 19:10:28 +0000632//----------------------------------------------------------------------------//
633// Module map file parser
634//----------------------------------------------------------------------------//
635
636namespace clang {
637 /// \brief A token in a module map file.
638 struct MMToken {
639 enum TokenKind {
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000640 Comma,
Douglas Gregor718292f2011-11-11 19:10:28 +0000641 EndOfFile,
642 HeaderKeyword,
643 Identifier,
Douglas Gregor59527662012-10-15 06:28:11 +0000644 ExcludeKeyword,
Douglas Gregor718292f2011-11-11 19:10:28 +0000645 ExplicitKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000646 ExportKeyword,
Douglas Gregor755b2052011-11-17 22:09:43 +0000647 FrameworkKeyword,
Douglas Gregor718292f2011-11-11 19:10:28 +0000648 ModuleKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000649 Period,
Douglas Gregor718292f2011-11-11 19:10:28 +0000650 UmbrellaKeyword,
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000651 RequiresKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000652 Star,
Douglas Gregor718292f2011-11-11 19:10:28 +0000653 StringLiteral,
654 LBrace,
Douglas Gregora686e1b2012-01-27 19:52:33 +0000655 RBrace,
656 LSquare,
657 RSquare
Douglas Gregor718292f2011-11-11 19:10:28 +0000658 } Kind;
659
660 unsigned Location;
661 unsigned StringLength;
662 const char *StringData;
663
664 void clear() {
665 Kind = EndOfFile;
666 Location = 0;
667 StringLength = 0;
668 StringData = 0;
669 }
670
671 bool is(TokenKind K) const { return Kind == K; }
672
673 SourceLocation getLocation() const {
674 return SourceLocation::getFromRawEncoding(Location);
675 }
676
677 StringRef getString() const {
678 return StringRef(StringData, StringLength);
679 }
680 };
Douglas Gregor9194a912012-11-06 19:39:40 +0000681
682 /// \brief The set of attributes that can be attached to a module.
Bill Wendling44426052012-12-20 19:22:21 +0000683 struct Attributes {
684 Attributes() : IsSystem() { }
Douglas Gregor9194a912012-11-06 19:39:40 +0000685
686 /// \brief Whether this is a system module.
687 unsigned IsSystem : 1;
688 };
Douglas Gregor718292f2011-11-11 19:10:28 +0000689
Douglas Gregor9194a912012-11-06 19:39:40 +0000690
Douglas Gregor718292f2011-11-11 19:10:28 +0000691 class ModuleMapParser {
692 Lexer &L;
693 SourceManager &SourceMgr;
Douglas Gregorbc10b9f2012-10-15 16:45:32 +0000694
695 /// \brief Default target information, used only for string literal
696 /// parsing.
697 const TargetInfo *Target;
698
Douglas Gregor718292f2011-11-11 19:10:28 +0000699 DiagnosticsEngine &Diags;
700 ModuleMap &Map;
701
Douglas Gregor5257fc62011-11-11 21:55:48 +0000702 /// \brief The directory that this module map resides in.
703 const DirectoryEntry *Directory;
Douglas Gregor3ec66632012-02-02 18:42:48 +0000704
705 /// \brief The directory containing Clang-supplied headers.
706 const DirectoryEntry *BuiltinIncludeDir;
707
Douglas Gregor718292f2011-11-11 19:10:28 +0000708 /// \brief Whether an error occurred.
709 bool HadError;
Douglas Gregorbc10b9f2012-10-15 16:45:32 +0000710
Douglas Gregor718292f2011-11-11 19:10:28 +0000711 /// \brief Stores string data for the various string literals referenced
712 /// during parsing.
713 llvm::BumpPtrAllocator StringData;
714
715 /// \brief The current token.
716 MMToken Tok;
717
718 /// \brief The active module.
Douglas Gregorde3ef502011-11-30 23:21:26 +0000719 Module *ActiveModule;
Douglas Gregor718292f2011-11-11 19:10:28 +0000720
721 /// \brief Consume the current token and return its location.
722 SourceLocation consumeToken();
723
724 /// \brief Skip tokens until we reach the a token with the given kind
725 /// (or the end of the file).
726 void skipUntil(MMToken::TokenKind K);
Douglas Gregore7ab3662011-12-07 02:23:45 +0000727
728 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
729 ModuleId;
730 bool parseModuleId(ModuleId &Id);
Douglas Gregor718292f2011-11-11 19:10:28 +0000731 void parseModuleDecl();
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000732 void parseRequiresDecl();
Douglas Gregor59527662012-10-15 06:28:11 +0000733 void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
Douglas Gregor524e33e2011-12-08 19:11:24 +0000734 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000735 void parseExportDecl();
Douglas Gregor9194a912012-11-06 19:39:40 +0000736 void parseInferredModuleDecl(bool Framework, bool Explicit);
Bill Wendling44426052012-12-20 19:22:21 +0000737 bool parseOptionalAttributes(Attributes &Attrs);
Douglas Gregor9194a912012-11-06 19:39:40 +0000738
Douglas Gregor70331272011-12-09 02:04:43 +0000739 const DirectoryEntry *getOverriddenHeaderSearchDir();
740
Douglas Gregor718292f2011-11-11 19:10:28 +0000741 public:
Douglas Gregor718292f2011-11-11 19:10:28 +0000742 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
Douglas Gregorbc10b9f2012-10-15 16:45:32 +0000743 const TargetInfo *Target,
Douglas Gregor718292f2011-11-11 19:10:28 +0000744 DiagnosticsEngine &Diags,
Douglas Gregor5257fc62011-11-11 21:55:48 +0000745 ModuleMap &Map,
Douglas Gregor3ec66632012-02-02 18:42:48 +0000746 const DirectoryEntry *Directory,
747 const DirectoryEntry *BuiltinIncludeDir)
Douglas Gregorbc10b9f2012-10-15 16:45:32 +0000748 : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
Douglas Gregor3ec66632012-02-02 18:42:48 +0000749 Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
750 HadError(false), ActiveModule(0)
Douglas Gregor718292f2011-11-11 19:10:28 +0000751 {
Douglas Gregor718292f2011-11-11 19:10:28 +0000752 Tok.clear();
753 consumeToken();
754 }
755
756 bool parseModuleMapFile();
757 };
758}
759
760SourceLocation ModuleMapParser::consumeToken() {
761retry:
762 SourceLocation Result = Tok.getLocation();
763 Tok.clear();
764
765 Token LToken;
766 L.LexFromRawLexer(LToken);
767 Tok.Location = LToken.getLocation().getRawEncoding();
768 switch (LToken.getKind()) {
769 case tok::raw_identifier:
770 Tok.StringData = LToken.getRawIdentifierData();
771 Tok.StringLength = LToken.getLength();
772 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
773 .Case("header", MMToken::HeaderKeyword)
Douglas Gregor59527662012-10-15 06:28:11 +0000774 .Case("exclude", MMToken::ExcludeKeyword)
Douglas Gregor718292f2011-11-11 19:10:28 +0000775 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000776 .Case("export", MMToken::ExportKeyword)
Douglas Gregor755b2052011-11-17 22:09:43 +0000777 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregor718292f2011-11-11 19:10:28 +0000778 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000779 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregor718292f2011-11-11 19:10:28 +0000780 .Case("umbrella", MMToken::UmbrellaKeyword)
781 .Default(MMToken::Identifier);
782 break;
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000783
784 case tok::comma:
785 Tok.Kind = MMToken::Comma;
786 break;
787
Douglas Gregor718292f2011-11-11 19:10:28 +0000788 case tok::eof:
789 Tok.Kind = MMToken::EndOfFile;
790 break;
791
792 case tok::l_brace:
793 Tok.Kind = MMToken::LBrace;
794 break;
795
Douglas Gregora686e1b2012-01-27 19:52:33 +0000796 case tok::l_square:
797 Tok.Kind = MMToken::LSquare;
798 break;
799
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000800 case tok::period:
801 Tok.Kind = MMToken::Period;
802 break;
803
Douglas Gregor718292f2011-11-11 19:10:28 +0000804 case tok::r_brace:
805 Tok.Kind = MMToken::RBrace;
806 break;
807
Douglas Gregora686e1b2012-01-27 19:52:33 +0000808 case tok::r_square:
809 Tok.Kind = MMToken::RSquare;
810 break;
811
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000812 case tok::star:
813 Tok.Kind = MMToken::Star;
814 break;
815
Douglas Gregor718292f2011-11-11 19:10:28 +0000816 case tok::string_literal: {
Richard Smithd67aea22012-03-06 03:21:47 +0000817 if (LToken.hasUDSuffix()) {
818 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
819 HadError = true;
820 goto retry;
821 }
822
Douglas Gregor718292f2011-11-11 19:10:28 +0000823 // Parse the string literal.
824 LangOptions LangOpts;
825 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
826 if (StringLiteral.hadError)
827 goto retry;
828
829 // Copy the string literal into our string data allocator.
830 unsigned Length = StringLiteral.GetStringLength();
831 char *Saved = StringData.Allocate<char>(Length + 1);
832 memcpy(Saved, StringLiteral.GetString().data(), Length);
833 Saved[Length] = 0;
834
835 // Form the token.
836 Tok.Kind = MMToken::StringLiteral;
837 Tok.StringData = Saved;
838 Tok.StringLength = Length;
839 break;
840 }
841
842 case tok::comment:
843 goto retry;
844
845 default:
846 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
847 HadError = true;
848 goto retry;
849 }
850
851 return Result;
852}
853
854void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
855 unsigned braceDepth = 0;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000856 unsigned squareDepth = 0;
Douglas Gregor718292f2011-11-11 19:10:28 +0000857 do {
858 switch (Tok.Kind) {
859 case MMToken::EndOfFile:
860 return;
861
862 case MMToken::LBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000863 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregor718292f2011-11-11 19:10:28 +0000864 return;
865
866 ++braceDepth;
867 break;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000868
869 case MMToken::LSquare:
870 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
871 return;
872
873 ++squareDepth;
874 break;
875
Douglas Gregor718292f2011-11-11 19:10:28 +0000876 case MMToken::RBrace:
877 if (braceDepth > 0)
878 --braceDepth;
879 else if (Tok.is(K))
880 return;
881 break;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000882
883 case MMToken::RSquare:
884 if (squareDepth > 0)
885 --squareDepth;
886 else if (Tok.is(K))
887 return;
888 break;
889
Douglas Gregor718292f2011-11-11 19:10:28 +0000890 default:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000891 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregor718292f2011-11-11 19:10:28 +0000892 return;
893 break;
894 }
895
896 consumeToken();
897 } while (true);
898}
899
Douglas Gregore7ab3662011-12-07 02:23:45 +0000900/// \brief Parse a module-id.
901///
902/// module-id:
903/// identifier
904/// identifier '.' module-id
905///
906/// \returns true if an error occurred, false otherwise.
907bool ModuleMapParser::parseModuleId(ModuleId &Id) {
908 Id.clear();
909 do {
910 if (Tok.is(MMToken::Identifier)) {
911 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
912 consumeToken();
913 } else {
914 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
915 return true;
916 }
917
918 if (!Tok.is(MMToken::Period))
919 break;
920
921 consumeToken();
922 } while (true);
923
924 return false;
925}
926
Douglas Gregora686e1b2012-01-27 19:52:33 +0000927namespace {
928 /// \brief Enumerates the known attributes.
929 enum AttributeKind {
930 /// \brief An unknown attribute.
931 AT_unknown,
932 /// \brief The 'system' attribute.
933 AT_system
934 };
935}
936
Douglas Gregor718292f2011-11-11 19:10:28 +0000937/// \brief Parse a module declaration.
938///
939/// module-declaration:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000940/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
941/// { module-member* }
942///
Douglas Gregor718292f2011-11-11 19:10:28 +0000943/// module-member:
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000944/// requires-declaration
Douglas Gregor718292f2011-11-11 19:10:28 +0000945/// header-declaration
Douglas Gregore7ab3662011-12-07 02:23:45 +0000946/// submodule-declaration
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000947/// export-declaration
Douglas Gregor73441092011-12-05 22:27:44 +0000948///
949/// submodule-declaration:
950/// module-declaration
951/// inferred-submodule-declaration
Douglas Gregor718292f2011-11-11 19:10:28 +0000952void ModuleMapParser::parseModuleDecl() {
Douglas Gregor755b2052011-11-17 22:09:43 +0000953 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
954 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregorf2161a72011-12-06 17:16:41 +0000955 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregore7ab3662011-12-07 02:23:45 +0000956 SourceLocation ExplicitLoc;
Douglas Gregor718292f2011-11-11 19:10:28 +0000957 bool Explicit = false;
Douglas Gregorf2161a72011-12-06 17:16:41 +0000958 bool Framework = false;
Douglas Gregor755b2052011-11-17 22:09:43 +0000959
Douglas Gregorf2161a72011-12-06 17:16:41 +0000960 // Parse 'explicit' keyword, if present.
961 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregore7ab3662011-12-07 02:23:45 +0000962 ExplicitLoc = consumeToken();
Douglas Gregorf2161a72011-12-06 17:16:41 +0000963 Explicit = true;
964 }
965
966 // Parse 'framework' keyword, if present.
Douglas Gregor755b2052011-11-17 22:09:43 +0000967 if (Tok.is(MMToken::FrameworkKeyword)) {
968 consumeToken();
969 Framework = true;
970 }
Douglas Gregor718292f2011-11-11 19:10:28 +0000971
972 // Parse 'module' keyword.
973 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregord6343c92011-12-06 19:57:48 +0000974 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregor718292f2011-11-11 19:10:28 +0000975 consumeToken();
976 HadError = true;
977 return;
978 }
979 consumeToken(); // 'module' keyword
Douglas Gregor73441092011-12-05 22:27:44 +0000980
981 // If we have a wildcard for the module name, this is an inferred submodule.
982 // Parse it.
983 if (Tok.is(MMToken::Star))
Douglas Gregor9194a912012-11-06 19:39:40 +0000984 return parseInferredModuleDecl(Framework, Explicit);
Douglas Gregor718292f2011-11-11 19:10:28 +0000985
986 // Parse the module name.
Douglas Gregore7ab3662011-12-07 02:23:45 +0000987 ModuleId Id;
988 if (parseModuleId(Id)) {
Douglas Gregor718292f2011-11-11 19:10:28 +0000989 HadError = true;
Douglas Gregore7ab3662011-12-07 02:23:45 +0000990 return;
Douglas Gregor718292f2011-11-11 19:10:28 +0000991 }
Douglas Gregor9194a912012-11-06 19:39:40 +0000992
Douglas Gregore7ab3662011-12-07 02:23:45 +0000993 if (ActiveModule) {
994 if (Id.size() > 1) {
995 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
996 << SourceRange(Id.front().second, Id.back().second);
997
998 HadError = true;
999 return;
1000 }
1001 } else if (Id.size() == 1 && Explicit) {
1002 // Top-level modules can't be explicit.
1003 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1004 Explicit = false;
1005 ExplicitLoc = SourceLocation();
1006 HadError = true;
1007 }
1008
1009 Module *PreviousActiveModule = ActiveModule;
1010 if (Id.size() > 1) {
1011 // This module map defines a submodule. Go find the module of which it
1012 // is a submodule.
1013 ActiveModule = 0;
1014 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1015 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1016 ActiveModule = Next;
1017 continue;
1018 }
1019
1020 if (ActiveModule) {
1021 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1022 << Id[I].first << ActiveModule->getTopLevelModule();
1023 } else {
1024 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1025 }
1026 HadError = true;
1027 return;
1028 }
1029 }
1030
1031 StringRef ModuleName = Id.back().first;
1032 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregor718292f2011-11-11 19:10:28 +00001033
Douglas Gregora686e1b2012-01-27 19:52:33 +00001034 // Parse the optional attribute list.
Bill Wendling44426052012-12-20 19:22:21 +00001035 Attributes Attrs;
Douglas Gregor9194a912012-11-06 19:39:40 +00001036 parseOptionalAttributes(Attrs);
Douglas Gregora686e1b2012-01-27 19:52:33 +00001037
Douglas Gregor718292f2011-11-11 19:10:28 +00001038 // Parse the opening brace.
1039 if (!Tok.is(MMToken::LBrace)) {
1040 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1041 << ModuleName;
1042 HadError = true;
1043 return;
1044 }
1045 SourceLocation LBraceLoc = consumeToken();
1046
1047 // Determine whether this (sub)module has already been defined.
Douglas Gregoreb90e832012-01-04 23:32:19 +00001048 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorfcc54a32012-01-05 00:12:00 +00001049 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1050 // Skip the module definition.
1051 skipUntil(MMToken::RBrace);
1052 if (Tok.is(MMToken::RBrace))
1053 consumeToken();
1054 else {
1055 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1056 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1057 HadError = true;
1058 }
1059 return;
1060 }
1061
Douglas Gregor718292f2011-11-11 19:10:28 +00001062 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1063 << ModuleName;
Douglas Gregoreb90e832012-01-04 23:32:19 +00001064 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregor718292f2011-11-11 19:10:28 +00001065
1066 // Skip the module definition.
1067 skipUntil(MMToken::RBrace);
1068 if (Tok.is(MMToken::RBrace))
1069 consumeToken();
1070
1071 HadError = true;
1072 return;
1073 }
1074
1075 // Start defining this module.
Douglas Gregoreb90e832012-01-04 23:32:19 +00001076 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1077 Explicit).first;
1078 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregor9194a912012-11-06 19:39:40 +00001079 if (Attrs.IsSystem)
Douglas Gregora686e1b2012-01-27 19:52:33 +00001080 ActiveModule->IsSystem = true;
Douglas Gregor718292f2011-11-11 19:10:28 +00001081
1082 bool Done = false;
1083 do {
1084 switch (Tok.Kind) {
1085 case MMToken::EndOfFile:
1086 case MMToken::RBrace:
1087 Done = true;
1088 break;
1089
1090 case MMToken::ExplicitKeyword:
Douglas Gregorf2161a72011-12-06 17:16:41 +00001091 case MMToken::FrameworkKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001092 case MMToken::ModuleKeyword:
1093 parseModuleDecl();
1094 break;
1095
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001096 case MMToken::ExportKeyword:
1097 parseExportDecl();
1098 break;
1099
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001100 case MMToken::RequiresKeyword:
1101 parseRequiresDecl();
1102 break;
1103
Douglas Gregor524e33e2011-12-08 19:11:24 +00001104 case MMToken::UmbrellaKeyword: {
1105 SourceLocation UmbrellaLoc = consumeToken();
1106 if (Tok.is(MMToken::HeaderKeyword))
Douglas Gregor59527662012-10-15 06:28:11 +00001107 parseHeaderDecl(UmbrellaLoc, SourceLocation());
Douglas Gregor524e33e2011-12-08 19:11:24 +00001108 else
1109 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregor718292f2011-11-11 19:10:28 +00001110 break;
Douglas Gregor524e33e2011-12-08 19:11:24 +00001111 }
Douglas Gregor718292f2011-11-11 19:10:28 +00001112
Douglas Gregor59527662012-10-15 06:28:11 +00001113 case MMToken::ExcludeKeyword: {
1114 SourceLocation ExcludeLoc = consumeToken();
1115 if (Tok.is(MMToken::HeaderKeyword)) {
1116 parseHeaderDecl(SourceLocation(), ExcludeLoc);
1117 } else {
1118 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1119 << "exclude";
1120 }
1121 break;
1122 }
1123
Douglas Gregor322f6332011-12-08 18:00:48 +00001124 case MMToken::HeaderKeyword:
Douglas Gregor59527662012-10-15 06:28:11 +00001125 parseHeaderDecl(SourceLocation(), SourceLocation());
Douglas Gregor718292f2011-11-11 19:10:28 +00001126 break;
Douglas Gregor322f6332011-12-08 18:00:48 +00001127
Douglas Gregor718292f2011-11-11 19:10:28 +00001128 default:
1129 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1130 consumeToken();
1131 break;
1132 }
1133 } while (!Done);
1134
1135 if (Tok.is(MMToken::RBrace))
1136 consumeToken();
1137 else {
1138 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1139 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1140 HadError = true;
1141 }
1142
Douglas Gregore7ab3662011-12-07 02:23:45 +00001143 // We're done parsing this module. Pop back to the previous module.
1144 ActiveModule = PreviousActiveModule;
Douglas Gregor718292f2011-11-11 19:10:28 +00001145}
Douglas Gregorf2161a72011-12-06 17:16:41 +00001146
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001147/// \brief Parse a requires declaration.
1148///
1149/// requires-declaration:
1150/// 'requires' feature-list
1151///
1152/// feature-list:
1153/// identifier ',' feature-list
1154/// identifier
1155void ModuleMapParser::parseRequiresDecl() {
1156 assert(Tok.is(MMToken::RequiresKeyword));
1157
1158 // Parse 'requires' keyword.
1159 consumeToken();
1160
1161 // Parse the feature-list.
1162 do {
1163 if (!Tok.is(MMToken::Identifier)) {
1164 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1165 HadError = true;
1166 return;
1167 }
1168
1169 // Consume the feature name.
1170 std::string Feature = Tok.getString();
1171 consumeToken();
1172
1173 // Add this feature.
Douglas Gregor89929282012-01-30 06:01:29 +00001174 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001175
1176 if (!Tok.is(MMToken::Comma))
1177 break;
1178
1179 // Consume the comma.
1180 consumeToken();
1181 } while (true);
1182}
1183
Douglas Gregorf2161a72011-12-06 17:16:41 +00001184/// \brief Append to \p Paths the set of paths needed to get to the
1185/// subframework in which the given module lives.
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001186static void appendSubframeworkPaths(Module *Mod,
1187 llvm::SmallVectorImpl<char> &Path) {
Douglas Gregorf2161a72011-12-06 17:16:41 +00001188 // Collect the framework names from the given module to the top-level module.
1189 llvm::SmallVector<StringRef, 2> Paths;
1190 for (; Mod; Mod = Mod->Parent) {
1191 if (Mod->IsFramework)
1192 Paths.push_back(Mod->Name);
1193 }
1194
1195 if (Paths.empty())
1196 return;
1197
1198 // Add Frameworks/Name.framework for each subframework.
1199 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1200 llvm::sys::path::append(Path, "Frameworks");
1201 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1202 }
1203}
1204
Douglas Gregor3ec66632012-02-02 18:42:48 +00001205/// \brief Determine whether the given file name is the name of a builtin
1206/// header, supplied by Clang to replace, override, or augment existing system
1207/// headers.
1208static bool isBuiltinHeader(StringRef FileName) {
1209 return llvm::StringSwitch<bool>(FileName)
1210 .Case("float.h", true)
1211 .Case("iso646.h", true)
1212 .Case("limits.h", true)
1213 .Case("stdalign.h", true)
1214 .Case("stdarg.h", true)
1215 .Case("stdbool.h", true)
1216 .Case("stddef.h", true)
1217 .Case("stdint.h", true)
1218 .Case("tgmath.h", true)
1219 .Case("unwind.h", true)
1220 .Default(false);
1221}
1222
Douglas Gregor718292f2011-11-11 19:10:28 +00001223/// \brief Parse a header declaration.
1224///
1225/// header-declaration:
Douglas Gregor322f6332011-12-08 18:00:48 +00001226/// 'umbrella'[opt] 'header' string-literal
Douglas Gregor59527662012-10-15 06:28:11 +00001227/// 'exclude'[opt] 'header' string-literal
1228void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
1229 SourceLocation ExcludeLoc) {
Douglas Gregor718292f2011-11-11 19:10:28 +00001230 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramer1871ed32011-11-13 16:52:09 +00001231 consumeToken();
1232
Douglas Gregor322f6332011-12-08 18:00:48 +00001233 bool Umbrella = UmbrellaLoc.isValid();
Douglas Gregor59527662012-10-15 06:28:11 +00001234 bool Exclude = ExcludeLoc.isValid();
1235 assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
Douglas Gregor718292f2011-11-11 19:10:28 +00001236 // Parse the header name.
1237 if (!Tok.is(MMToken::StringLiteral)) {
1238 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1239 << "header";
1240 HadError = true;
1241 return;
1242 }
Douglas Gregore7ab3662011-12-07 02:23:45 +00001243 std::string FileName = Tok.getString();
Douglas Gregor718292f2011-11-11 19:10:28 +00001244 SourceLocation FileNameLoc = consumeToken();
1245
Douglas Gregor524e33e2011-12-08 19:11:24 +00001246 // Check whether we already have an umbrella.
1247 if (Umbrella && ActiveModule->Umbrella) {
1248 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1249 << ActiveModule->getFullModuleName();
Douglas Gregor322f6332011-12-08 18:00:48 +00001250 HadError = true;
1251 return;
1252 }
1253
Douglas Gregor5257fc62011-11-11 21:55:48 +00001254 // Look for this file.
Douglas Gregore7ab3662011-12-07 02:23:45 +00001255 const FileEntry *File = 0;
Douglas Gregor3ec66632012-02-02 18:42:48 +00001256 const FileEntry *BuiltinFile = 0;
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00001257 SmallString<128> PathName;
Douglas Gregore7ab3662011-12-07 02:23:45 +00001258 if (llvm::sys::path::is_absolute(FileName)) {
1259 PathName = FileName;
1260 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor70331272011-12-09 02:04:43 +00001261 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1262 PathName = Dir->getName();
1263 llvm::sys::path::append(PathName, FileName);
1264 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregore7ab3662011-12-07 02:23:45 +00001265 } else {
1266 // Search for the header file within the search directory.
Douglas Gregor70331272011-12-09 02:04:43 +00001267 PathName = Directory->getName();
Douglas Gregore7ab3662011-12-07 02:23:45 +00001268 unsigned PathLength = PathName.size();
Douglas Gregorf545f672011-11-29 21:59:16 +00001269
Douglas Gregorf2161a72011-12-06 17:16:41 +00001270 if (ActiveModule->isPartOfFramework()) {
1271 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregore7ab3662011-12-07 02:23:45 +00001272
1273 // Check whether this file is in the public headers.
Douglas Gregorf545f672011-11-29 21:59:16 +00001274 llvm::sys::path::append(PathName, "Headers");
Douglas Gregore7ab3662011-12-07 02:23:45 +00001275 llvm::sys::path::append(PathName, FileName);
1276 File = SourceMgr.getFileManager().getFile(PathName);
1277
1278 if (!File) {
1279 // Check whether this file is in the private headers.
1280 PathName.resize(PathLength);
1281 llvm::sys::path::append(PathName, "PrivateHeaders");
1282 llvm::sys::path::append(PathName, FileName);
1283 File = SourceMgr.getFileManager().getFile(PathName);
1284 }
1285 } else {
1286 // Lookup for normal headers.
1287 llvm::sys::path::append(PathName, FileName);
1288 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor3ec66632012-02-02 18:42:48 +00001289
1290 // If this is a system module with a top-level header, this header
1291 // may have a counterpart (or replacement) in the set of headers
1292 // supplied by Clang. Find that builtin header.
1293 if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
1294 BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00001295 SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
Douglas Gregor3ec66632012-02-02 18:42:48 +00001296 llvm::sys::path::append(BuiltinPathName, FileName);
1297 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1298
1299 // If Clang supplies this header but the underlying system does not,
1300 // just silently swap in our builtin version. Otherwise, we'll end
1301 // up adding both (later).
1302 if (!File && BuiltinFile) {
1303 File = BuiltinFile;
1304 BuiltinFile = 0;
1305 }
1306 }
Douglas Gregorf2161a72011-12-06 17:16:41 +00001307 }
Douglas Gregorf545f672011-11-29 21:59:16 +00001308 }
Douglas Gregor755b2052011-11-17 22:09:43 +00001309
Douglas Gregor5257fc62011-11-11 21:55:48 +00001310 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1311 // Come up with a lazy way to do this.
Douglas Gregore7ab3662011-12-07 02:23:45 +00001312 if (File) {
Douglas Gregor59527662012-10-15 06:28:11 +00001313 if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
Douglas Gregor5257fc62011-11-11 21:55:48 +00001314 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
Douglas Gregor59527662012-10-15 06:28:11 +00001315 << FileName << OwningModule.getModule()->getFullModuleName();
Douglas Gregor5257fc62011-11-11 21:55:48 +00001316 HadError = true;
Douglas Gregor322f6332011-12-08 18:00:48 +00001317 } else if (Umbrella) {
1318 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor59527662012-10-15 06:28:11 +00001319 if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Douglas Gregor322f6332011-12-08 18:00:48 +00001320 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
Douglas Gregor59527662012-10-15 06:28:11 +00001321 << UmbrellaModule->getFullModuleName();
Douglas Gregor322f6332011-12-08 18:00:48 +00001322 HadError = true;
1323 } else {
1324 // Record this umbrella header.
1325 Map.setUmbrellaHeader(ActiveModule, File);
1326 }
Douglas Gregor5257fc62011-11-11 21:55:48 +00001327 } else {
Douglas Gregor322f6332011-12-08 18:00:48 +00001328 // Record this header.
Douglas Gregor59527662012-10-15 06:28:11 +00001329 Map.addHeader(ActiveModule, File, Exclude);
Douglas Gregor3ec66632012-02-02 18:42:48 +00001330
1331 // If there is a builtin counterpart to this file, add it now.
1332 if (BuiltinFile)
Douglas Gregor59527662012-10-15 06:28:11 +00001333 Map.addHeader(ActiveModule, BuiltinFile, Exclude);
Douglas Gregor5257fc62011-11-11 21:55:48 +00001334 }
Douglas Gregor4b27a642012-11-15 19:47:16 +00001335 } else if (!Exclude) {
1336 // Ignore excluded header files. They're optional anyway.
1337
Douglas Gregor5257fc62011-11-11 21:55:48 +00001338 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor524e33e2011-12-08 19:11:24 +00001339 << Umbrella << FileName;
Douglas Gregor5257fc62011-11-11 21:55:48 +00001340 HadError = true;
1341 }
Douglas Gregor718292f2011-11-11 19:10:28 +00001342}
1343
Douglas Gregor524e33e2011-12-08 19:11:24 +00001344/// \brief Parse an umbrella directory declaration.
1345///
1346/// umbrella-dir-declaration:
1347/// umbrella string-literal
1348void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1349 // Parse the directory name.
1350 if (!Tok.is(MMToken::StringLiteral)) {
1351 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1352 << "umbrella";
1353 HadError = true;
1354 return;
1355 }
1356
1357 std::string DirName = Tok.getString();
1358 SourceLocation DirNameLoc = consumeToken();
1359
1360 // Check whether we already have an umbrella.
1361 if (ActiveModule->Umbrella) {
1362 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1363 << ActiveModule->getFullModuleName();
1364 HadError = true;
1365 return;
1366 }
1367
1368 // Look for this file.
1369 const DirectoryEntry *Dir = 0;
1370 if (llvm::sys::path::is_absolute(DirName))
1371 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1372 else {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00001373 SmallString<128> PathName;
Douglas Gregor524e33e2011-12-08 19:11:24 +00001374 PathName = Directory->getName();
1375 llvm::sys::path::append(PathName, DirName);
1376 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1377 }
1378
1379 if (!Dir) {
1380 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1381 << DirName;
1382 HadError = true;
1383 return;
1384 }
1385
1386 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1387 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1388 << OwningModule->getFullModuleName();
1389 HadError = true;
1390 return;
1391 }
1392
1393 // Record this umbrella directory.
1394 Map.setUmbrellaDir(ActiveModule, Dir);
1395}
1396
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001397/// \brief Parse a module export declaration.
1398///
1399/// export-declaration:
1400/// 'export' wildcard-module-id
1401///
1402/// wildcard-module-id:
1403/// identifier
1404/// '*'
1405/// identifier '.' wildcard-module-id
1406void ModuleMapParser::parseExportDecl() {
1407 assert(Tok.is(MMToken::ExportKeyword));
1408 SourceLocation ExportLoc = consumeToken();
1409
1410 // Parse the module-id with an optional wildcard at the end.
1411 ModuleId ParsedModuleId;
1412 bool Wildcard = false;
1413 do {
1414 if (Tok.is(MMToken::Identifier)) {
1415 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1416 Tok.getLocation()));
1417 consumeToken();
1418
1419 if (Tok.is(MMToken::Period)) {
1420 consumeToken();
1421 continue;
1422 }
1423
1424 break;
1425 }
1426
1427 if(Tok.is(MMToken::Star)) {
1428 Wildcard = true;
Douglas Gregorf5eedd02011-12-05 17:28:06 +00001429 consumeToken();
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001430 break;
1431 }
1432
1433 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1434 HadError = true;
1435 return;
1436 } while (true);
1437
1438 Module::UnresolvedExportDecl Unresolved = {
1439 ExportLoc, ParsedModuleId, Wildcard
1440 };
1441 ActiveModule->UnresolvedExports.push_back(Unresolved);
1442}
1443
Douglas Gregor9194a912012-11-06 19:39:40 +00001444/// \brief Parse an inferried module declaration (wildcard modules).
1445///
1446/// module-declaration:
1447/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
1448/// { inferred-module-member* }
1449///
1450/// inferred-module-member:
1451/// 'export' '*'
1452/// 'exclude' identifier
1453void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Douglas Gregor73441092011-12-05 22:27:44 +00001454 assert(Tok.is(MMToken::Star));
1455 SourceLocation StarLoc = consumeToken();
1456 bool Failed = false;
Douglas Gregor9194a912012-11-06 19:39:40 +00001457
Douglas Gregor73441092011-12-05 22:27:44 +00001458 // Inferred modules must be submodules.
Douglas Gregor9194a912012-11-06 19:39:40 +00001459 if (!ActiveModule && !Framework) {
Douglas Gregor73441092011-12-05 22:27:44 +00001460 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1461 Failed = true;
1462 }
Douglas Gregor9194a912012-11-06 19:39:40 +00001463
1464 if (ActiveModule) {
1465 // Inferred modules must have umbrella directories.
1466 if (!Failed && !ActiveModule->getUmbrellaDir()) {
1467 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1468 Failed = true;
1469 }
1470
1471 // Check for redefinition of an inferred module.
1472 if (!Failed && ActiveModule->InferSubmodules) {
1473 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1474 if (ActiveModule->InferredSubmoduleLoc.isValid())
1475 Diags.Report(ActiveModule->InferredSubmoduleLoc,
1476 diag::note_mmap_prev_definition);
1477 Failed = true;
1478 }
1479
1480 // Check for the 'framework' keyword, which is not permitted here.
1481 if (Framework) {
1482 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
1483 Framework = false;
1484 }
1485 } else if (Explicit) {
1486 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
1487 Explicit = false;
Douglas Gregor73441092011-12-05 22:27:44 +00001488 }
Douglas Gregor9194a912012-11-06 19:39:40 +00001489
Douglas Gregor73441092011-12-05 22:27:44 +00001490 // If there were any problems with this inferred submodule, skip its body.
1491 if (Failed) {
1492 if (Tok.is(MMToken::LBrace)) {
1493 consumeToken();
1494 skipUntil(MMToken::RBrace);
1495 if (Tok.is(MMToken::RBrace))
1496 consumeToken();
1497 }
1498 HadError = true;
1499 return;
1500 }
Douglas Gregor9194a912012-11-06 19:39:40 +00001501
1502 // Parse optional attributes.
Bill Wendling44426052012-12-20 19:22:21 +00001503 Attributes Attrs;
Douglas Gregor9194a912012-11-06 19:39:40 +00001504 parseOptionalAttributes(Attrs);
1505
1506 if (ActiveModule) {
1507 // Note that we have an inferred submodule.
1508 ActiveModule->InferSubmodules = true;
1509 ActiveModule->InferredSubmoduleLoc = StarLoc;
1510 ActiveModule->InferExplicitSubmodules = Explicit;
1511 } else {
1512 // We'll be inferring framework modules for this directory.
1513 Map.InferredDirectories[Directory].InferModules = true;
1514 Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
1515 }
1516
Douglas Gregor73441092011-12-05 22:27:44 +00001517 // Parse the opening brace.
1518 if (!Tok.is(MMToken::LBrace)) {
1519 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1520 HadError = true;
1521 return;
1522 }
1523 SourceLocation LBraceLoc = consumeToken();
1524
1525 // Parse the body of the inferred submodule.
1526 bool Done = false;
1527 do {
1528 switch (Tok.Kind) {
1529 case MMToken::EndOfFile:
1530 case MMToken::RBrace:
1531 Done = true;
1532 break;
Douglas Gregor9194a912012-11-06 19:39:40 +00001533
1534 case MMToken::ExcludeKeyword: {
1535 if (ActiveModule) {
1536 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregor162405d2012-11-06 19:41:11 +00001537 << (ActiveModule != 0);
Douglas Gregor9194a912012-11-06 19:39:40 +00001538 consumeToken();
1539 break;
1540 }
1541
1542 consumeToken();
1543 if (!Tok.is(MMToken::Identifier)) {
1544 Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
1545 break;
1546 }
1547
1548 Map.InferredDirectories[Directory].ExcludedModules
1549 .push_back(Tok.getString());
1550 consumeToken();
1551 break;
1552 }
1553
1554 case MMToken::ExportKeyword:
1555 if (!ActiveModule) {
1556 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregor162405d2012-11-06 19:41:11 +00001557 << (ActiveModule != 0);
Douglas Gregor9194a912012-11-06 19:39:40 +00001558 consumeToken();
1559 break;
1560 }
1561
Douglas Gregor73441092011-12-05 22:27:44 +00001562 consumeToken();
1563 if (Tok.is(MMToken::Star))
Douglas Gregordd005f62011-12-06 17:34:58 +00001564 ActiveModule->InferExportWildcard = true;
Douglas Gregor73441092011-12-05 22:27:44 +00001565 else
1566 Diags.Report(Tok.getLocation(),
1567 diag::err_mmap_expected_export_wildcard);
1568 consumeToken();
1569 break;
Douglas Gregor9194a912012-11-06 19:39:40 +00001570
Douglas Gregor73441092011-12-05 22:27:44 +00001571 case MMToken::ExplicitKeyword:
1572 case MMToken::ModuleKeyword:
1573 case MMToken::HeaderKeyword:
1574 case MMToken::UmbrellaKeyword:
1575 default:
Douglas Gregor9194a912012-11-06 19:39:40 +00001576 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregor162405d2012-11-06 19:41:11 +00001577 << (ActiveModule != 0);
Douglas Gregor73441092011-12-05 22:27:44 +00001578 consumeToken();
1579 break;
1580 }
1581 } while (!Done);
1582
1583 if (Tok.is(MMToken::RBrace))
1584 consumeToken();
1585 else {
1586 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1587 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1588 HadError = true;
1589 }
1590}
1591
Douglas Gregor9194a912012-11-06 19:39:40 +00001592/// \brief Parse optional attributes.
1593///
1594/// attributes:
1595/// attribute attributes
1596/// attribute
1597///
1598/// attribute:
1599/// [ identifier ]
1600///
1601/// \param Attrs Will be filled in with the parsed attributes.
1602///
1603/// \returns true if an error occurred, false otherwise.
Bill Wendling44426052012-12-20 19:22:21 +00001604bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
Douglas Gregor9194a912012-11-06 19:39:40 +00001605 bool HadError = false;
1606
1607 while (Tok.is(MMToken::LSquare)) {
1608 // Consume the '['.
1609 SourceLocation LSquareLoc = consumeToken();
1610
1611 // Check whether we have an attribute name here.
1612 if (!Tok.is(MMToken::Identifier)) {
1613 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
1614 skipUntil(MMToken::RSquare);
1615 if (Tok.is(MMToken::RSquare))
1616 consumeToken();
1617 HadError = true;
1618 }
1619
1620 // Decode the attribute name.
1621 AttributeKind Attribute
1622 = llvm::StringSwitch<AttributeKind>(Tok.getString())
1623 .Case("system", AT_system)
1624 .Default(AT_unknown);
1625 switch (Attribute) {
1626 case AT_unknown:
1627 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
1628 << Tok.getString();
1629 break;
1630
1631 case AT_system:
1632 Attrs.IsSystem = true;
1633 break;
1634 }
1635 consumeToken();
1636
1637 // Consume the ']'.
1638 if (!Tok.is(MMToken::RSquare)) {
1639 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
1640 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
1641 skipUntil(MMToken::RSquare);
1642 HadError = true;
1643 }
1644
1645 if (Tok.is(MMToken::RSquare))
1646 consumeToken();
1647 }
1648
1649 return HadError;
1650}
1651
Douglas Gregor70331272011-12-09 02:04:43 +00001652/// \brief If there is a specific header search directory due the presence
1653/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1654const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1655 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1656 // If we have an umbrella directory, use that.
1657 if (Mod->hasUmbrellaDir())
1658 return Mod->getUmbrellaDir();
1659
1660 // If we have a framework directory, stop looking.
1661 if (Mod->IsFramework)
1662 return 0;
1663 }
1664
1665 return 0;
1666}
1667
Douglas Gregor718292f2011-11-11 19:10:28 +00001668/// \brief Parse a module map file.
1669///
1670/// module-map-file:
1671/// module-declaration*
1672bool ModuleMapParser::parseModuleMapFile() {
1673 do {
1674 switch (Tok.Kind) {
1675 case MMToken::EndOfFile:
1676 return HadError;
1677
Douglas Gregore7ab3662011-12-07 02:23:45 +00001678 case MMToken::ExplicitKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001679 case MMToken::ModuleKeyword:
Douglas Gregor755b2052011-11-17 22:09:43 +00001680 case MMToken::FrameworkKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001681 parseModuleDecl();
1682 break;
1683
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001684 case MMToken::Comma:
Douglas Gregor59527662012-10-15 06:28:11 +00001685 case MMToken::ExcludeKeyword:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001686 case MMToken::ExportKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001687 case MMToken::HeaderKeyword:
1688 case MMToken::Identifier:
1689 case MMToken::LBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +00001690 case MMToken::LSquare:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001691 case MMToken::Period:
Douglas Gregor718292f2011-11-11 19:10:28 +00001692 case MMToken::RBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +00001693 case MMToken::RSquare:
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001694 case MMToken::RequiresKeyword:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001695 case MMToken::Star:
Douglas Gregor718292f2011-11-11 19:10:28 +00001696 case MMToken::StringLiteral:
1697 case MMToken::UmbrellaKeyword:
1698 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1699 HadError = true;
1700 consumeToken();
1701 break;
1702 }
1703 } while (true);
Douglas Gregor718292f2011-11-11 19:10:28 +00001704}
1705
1706bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregor4ddf2222013-01-10 01:43:00 +00001707 llvm::DenseMap<const FileEntry *, bool>::iterator Known
1708 = ParsedModuleMap.find(File);
1709 if (Known != ParsedModuleMap.end())
1710 return Known->second;
1711
Douglas Gregor89929282012-01-30 06:01:29 +00001712 assert(Target != 0 && "Missing target information");
Douglas Gregor718292f2011-11-11 19:10:28 +00001713 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1714 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1715 if (!Buffer)
Douglas Gregor4ddf2222013-01-10 01:43:00 +00001716 return ParsedModuleMap[File] = true;
Douglas Gregor718292f2011-11-11 19:10:28 +00001717
1718 // Parse this module map file.
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001719 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1720 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregorbc10b9f2012-10-15 16:45:32 +00001721 ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
Douglas Gregor3ec66632012-02-02 18:42:48 +00001722 BuiltinIncludeDir);
Douglas Gregor718292f2011-11-11 19:10:28 +00001723 bool Result = Parser.parseModuleMapFile();
1724 Diags->getClient()->EndSourceFile();
Douglas Gregor4ddf2222013-01-10 01:43:00 +00001725 ParsedModuleMap[File] = Result;
Douglas Gregor718292f2011-11-11 19:10:28 +00001726 return Result;
1727}