blob: d954bc9fc2757d60a711189e6942091a4f0a3f1b [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();
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000160 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();
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000263 SmallVector<const DirectoryEntry *, 2> SkippedDirs;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000264 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) {
Douglas Gregor7005b902013-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 Gregor82e52372012-11-06 19:39:40 +0000412 bool canInfer = false;
Douglas Gregor7005b902013-01-10 01:43:00 +0000413 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
Douglas Gregor82e52372012-11-06 19:39:40 +0000414 // Figure out the parent path.
Douglas Gregor7005b902013-01-10 01:43:00 +0000415 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
Douglas Gregor82e52372012-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 Gregor7005b902013-01-10 01:43:00 +0000439 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
Douglas Gregor82e52372012-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 Gregor2821c7f2011-11-17 01:41:17 +0000456 // Look for an umbrella header.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000457 SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000458 llvm::sys::path::append(UmbrellaName, "Headers");
459 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000460 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-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 Gregorac252a32011-12-06 19:39:29 +0000468 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
469 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000470 if (IsSystem)
471 Result->IsSystem = IsSystem;
472
Douglas Gregorb7a78192012-01-04 23:32:19 +0000473 if (!Parent)
Douglas Gregorac252a32011-12-06 19:39:29 +0000474 Modules[ModuleName] = Result;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000475
Douglas Gregor489ad432011-12-08 18:00:48 +0000476 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000477 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000478 Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor3cee31e2011-12-12 23:55:05 +0000479 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000480
481 // export *
482 Result->Exports.push_back(Module::ExportDecl(0, true));
483
Douglas Gregore209e502011-12-06 01:10:29 +0000484 // module * { export * }
485 Result->InferSubmodules = true;
486 Result->InferExportWildcard = true;
487
Douglas Gregorac252a32011-12-06 19:39:29 +0000488 // Look for subframeworks.
489 llvm::error_code EC;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000490 SmallString<128> SubframeworksDirName
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000491 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000492 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000493 SmallString<128> SubframeworksDirNameNative;
Douglas Gregor52b1ed32011-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 Gregorac252a32011-12-06 19:39:29 +0000498 Dir != DirEnd && !EC; Dir.increment(EC)) {
499 if (!StringRef(Dir->path()).endswith(".framework"))
500 continue;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000501
Douglas Gregorac252a32011-12-06 19:39:29 +0000502 if (const DirectoryEntry *SubframeworkDir
503 = FileMgr.getDirectory(Dir->path())) {
Douglas Gregor98cfcbf2012-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 Gregorac252a32011-12-06 19:39:29 +0000532 // FIXME: Do we want to warn about subframeworks without umbrella headers?
Douglas Gregor8b48e082012-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 Gregorac252a32011-12-06 19:39:29 +0000537 }
538 }
Douglas Gregor3a110f72012-01-13 16:54:27 +0000539
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000540 return Result;
541}
542
Douglas Gregore209e502011-12-06 01:10:29 +0000543void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000544 Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
Douglas Gregor10694ce2011-12-08 17:39:04 +0000545 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000546 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000547}
548
Douglas Gregor77d029f2011-12-08 19:11:24 +0000549void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
550 Mod->Umbrella = UmbrellaDir;
551 UmbrellaDirs[UmbrellaDir] = Mod;
552}
553
Douglas Gregor2b49d1f2012-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 Gregore209e502011-12-06 01:10:29 +0000561}
562
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000563const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000564ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-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 Gregora30cfe52011-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 Gregor804c3bf2011-11-29 18:17:59 +0000577 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000578
579 llvm::errs() << "Headers:";
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000580 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000581 H != HEnd; ++H) {
582 llvm::errs() << " \"" << H->first->getName() << "\" -> "
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000583 << H->second.getModule()->getFullModuleName() << "\n";
Douglas Gregora30cfe52011-11-11 19:10:28 +0000584 }
585}
586
Douglas Gregor90db2602011-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 Gregor0adaa882011-12-05 17:28:06 +0000592 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-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 Gregor55988682011-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 Gregor55988682011-12-05 16:33:54 +0000613
Douglas Gregor303aae92012-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 Gregor55988682011-12-05 16:33:54 +0000630}
631
Douglas Gregora30cfe52011-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 Gregor51f564f2011-12-31 04:05:44 +0000640 Comma,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000641 EndOfFile,
642 HeaderKeyword,
643 Identifier,
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000644 ExcludeKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000645 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000646 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000647 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000648 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000649 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000650 UmbrellaKeyword,
Douglas Gregor51f564f2011-12-31 04:05:44 +0000651 RequiresKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000652 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000653 StringLiteral,
654 LBrace,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000655 RBrace,
656 LSquare,
657 RSquare
Douglas Gregora30cfe52011-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 Gregor82e52372012-11-06 19:39:40 +0000681
682 /// \brief The set of attributes that can be attached to a module.
Bill Wendlingad017fa2012-12-20 19:22:21 +0000683 struct Attributes {
684 Attributes() : IsSystem() { }
Douglas Gregor82e52372012-11-06 19:39:40 +0000685
686 /// \brief Whether this is a system module.
687 unsigned IsSystem : 1;
688 };
Douglas Gregora30cfe52011-11-11 19:10:28 +0000689
Douglas Gregor82e52372012-11-06 19:39:40 +0000690
Douglas Gregora30cfe52011-11-11 19:10:28 +0000691 class ModuleMapParser {
692 Lexer &L;
693 SourceManager &SourceMgr;
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000694
695 /// \brief Default target information, used only for string literal
696 /// parsing.
697 const TargetInfo *Target;
698
Douglas Gregora30cfe52011-11-11 19:10:28 +0000699 DiagnosticsEngine &Diags;
700 ModuleMap &Map;
701
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000702 /// \brief The directory that this module map resides in.
703 const DirectoryEntry *Directory;
Douglas Gregor2f04f182012-02-02 18:42:48 +0000704
705 /// \brief The directory containing Clang-supplied headers.
706 const DirectoryEntry *BuiltinIncludeDir;
707
Douglas Gregora30cfe52011-11-11 19:10:28 +0000708 /// \brief Whether an error occurred.
709 bool HadError;
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000710
Douglas Gregora30cfe52011-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 Gregor1a4761e2011-11-30 23:21:26 +0000719 Module *ActiveModule;
Douglas Gregora30cfe52011-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 Gregor587986e2011-12-07 02:23:45 +0000727
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000728 typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
Douglas Gregor587986e2011-12-07 02:23:45 +0000729 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000730 void parseModuleDecl();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000731 void parseRequiresDecl();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000732 void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000733 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000734 void parseExportDecl();
Douglas Gregor82e52372012-11-06 19:39:40 +0000735 void parseInferredModuleDecl(bool Framework, bool Explicit);
Bill Wendlingad017fa2012-12-20 19:22:21 +0000736 bool parseOptionalAttributes(Attributes &Attrs);
Douglas Gregor82e52372012-11-06 19:39:40 +0000737
Douglas Gregor6a1db482011-12-09 02:04:43 +0000738 const DirectoryEntry *getOverriddenHeaderSearchDir();
739
Douglas Gregora30cfe52011-11-11 19:10:28 +0000740 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000741 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000742 const TargetInfo *Target,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000743 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000744 ModuleMap &Map,
Douglas Gregor2f04f182012-02-02 18:42:48 +0000745 const DirectoryEntry *Directory,
746 const DirectoryEntry *BuiltinIncludeDir)
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000747 : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
Douglas Gregor2f04f182012-02-02 18:42:48 +0000748 Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
749 HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000750 {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000751 Tok.clear();
752 consumeToken();
753 }
754
755 bool parseModuleMapFile();
756 };
757}
758
759SourceLocation ModuleMapParser::consumeToken() {
760retry:
761 SourceLocation Result = Tok.getLocation();
762 Tok.clear();
763
764 Token LToken;
765 L.LexFromRawLexer(LToken);
766 Tok.Location = LToken.getLocation().getRawEncoding();
767 switch (LToken.getKind()) {
768 case tok::raw_identifier:
769 Tok.StringData = LToken.getRawIdentifierData();
770 Tok.StringLength = LToken.getLength();
771 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
772 .Case("header", MMToken::HeaderKeyword)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000773 .Case("exclude", MMToken::ExcludeKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000774 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000775 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000776 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000777 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor51f564f2011-12-31 04:05:44 +0000778 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000779 .Case("umbrella", MMToken::UmbrellaKeyword)
780 .Default(MMToken::Identifier);
781 break;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000782
783 case tok::comma:
784 Tok.Kind = MMToken::Comma;
785 break;
786
Douglas Gregora30cfe52011-11-11 19:10:28 +0000787 case tok::eof:
788 Tok.Kind = MMToken::EndOfFile;
789 break;
790
791 case tok::l_brace:
792 Tok.Kind = MMToken::LBrace;
793 break;
794
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000795 case tok::l_square:
796 Tok.Kind = MMToken::LSquare;
797 break;
798
Douglas Gregor90db2602011-12-02 01:47:07 +0000799 case tok::period:
800 Tok.Kind = MMToken::Period;
801 break;
802
Douglas Gregora30cfe52011-11-11 19:10:28 +0000803 case tok::r_brace:
804 Tok.Kind = MMToken::RBrace;
805 break;
806
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000807 case tok::r_square:
808 Tok.Kind = MMToken::RSquare;
809 break;
810
Douglas Gregor90db2602011-12-02 01:47:07 +0000811 case tok::star:
812 Tok.Kind = MMToken::Star;
813 break;
814
Douglas Gregora30cfe52011-11-11 19:10:28 +0000815 case tok::string_literal: {
Richard Smith99831e42012-03-06 03:21:47 +0000816 if (LToken.hasUDSuffix()) {
817 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
818 HadError = true;
819 goto retry;
820 }
821
Douglas Gregora30cfe52011-11-11 19:10:28 +0000822 // Parse the string literal.
823 LangOptions LangOpts;
824 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
825 if (StringLiteral.hadError)
826 goto retry;
827
828 // Copy the string literal into our string data allocator.
829 unsigned Length = StringLiteral.GetStringLength();
830 char *Saved = StringData.Allocate<char>(Length + 1);
831 memcpy(Saved, StringLiteral.GetString().data(), Length);
832 Saved[Length] = 0;
833
834 // Form the token.
835 Tok.Kind = MMToken::StringLiteral;
836 Tok.StringData = Saved;
837 Tok.StringLength = Length;
838 break;
839 }
840
841 case tok::comment:
842 goto retry;
843
844 default:
845 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
846 HadError = true;
847 goto retry;
848 }
849
850 return Result;
851}
852
853void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
854 unsigned braceDepth = 0;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000855 unsigned squareDepth = 0;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000856 do {
857 switch (Tok.Kind) {
858 case MMToken::EndOfFile:
859 return;
860
861 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000862 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000863 return;
864
865 ++braceDepth;
866 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000867
868 case MMToken::LSquare:
869 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
870 return;
871
872 ++squareDepth;
873 break;
874
Douglas Gregora30cfe52011-11-11 19:10:28 +0000875 case MMToken::RBrace:
876 if (braceDepth > 0)
877 --braceDepth;
878 else if (Tok.is(K))
879 return;
880 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000881
882 case MMToken::RSquare:
883 if (squareDepth > 0)
884 --squareDepth;
885 else if (Tok.is(K))
886 return;
887 break;
888
Douglas Gregora30cfe52011-11-11 19:10:28 +0000889 default:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000890 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregora30cfe52011-11-11 19:10:28 +0000891 return;
892 break;
893 }
894
895 consumeToken();
896 } while (true);
897}
898
Douglas Gregor587986e2011-12-07 02:23:45 +0000899/// \brief Parse a module-id.
900///
901/// module-id:
902/// identifier
903/// identifier '.' module-id
904///
905/// \returns true if an error occurred, false otherwise.
906bool ModuleMapParser::parseModuleId(ModuleId &Id) {
907 Id.clear();
908 do {
909 if (Tok.is(MMToken::Identifier)) {
910 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
911 consumeToken();
912 } else {
913 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
914 return true;
915 }
916
917 if (!Tok.is(MMToken::Period))
918 break;
919
920 consumeToken();
921 } while (true);
922
923 return false;
924}
925
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000926namespace {
927 /// \brief Enumerates the known attributes.
928 enum AttributeKind {
929 /// \brief An unknown attribute.
930 AT_unknown,
931 /// \brief The 'system' attribute.
932 AT_system
933 };
934}
935
Douglas Gregora30cfe52011-11-11 19:10:28 +0000936/// \brief Parse a module declaration.
937///
938/// module-declaration:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000939/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
940/// { module-member* }
941///
Douglas Gregora30cfe52011-11-11 19:10:28 +0000942/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +0000943/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000944/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000945/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000946/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000947///
948/// submodule-declaration:
949/// module-declaration
950/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000951void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000952 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
953 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000954 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000955 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000956 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000957 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000958
Douglas Gregord620a842011-12-06 17:16:41 +0000959 // Parse 'explicit' keyword, if present.
960 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000961 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000962 Explicit = true;
963 }
964
965 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000966 if (Tok.is(MMToken::FrameworkKeyword)) {
967 consumeToken();
968 Framework = true;
969 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000970
971 // Parse 'module' keyword.
972 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000973 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000974 consumeToken();
975 HadError = true;
976 return;
977 }
978 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000979
980 // If we have a wildcard for the module name, this is an inferred submodule.
981 // Parse it.
982 if (Tok.is(MMToken::Star))
Douglas Gregor82e52372012-11-06 19:39:40 +0000983 return parseInferredModuleDecl(Framework, Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000984
985 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000986 ModuleId Id;
987 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000988 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000989 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000990 }
Douglas Gregor82e52372012-11-06 19:39:40 +0000991
Douglas Gregor587986e2011-12-07 02:23:45 +0000992 if (ActiveModule) {
993 if (Id.size() > 1) {
994 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
995 << SourceRange(Id.front().second, Id.back().second);
996
997 HadError = true;
998 return;
999 }
1000 } else if (Id.size() == 1 && Explicit) {
1001 // Top-level modules can't be explicit.
1002 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1003 Explicit = false;
1004 ExplicitLoc = SourceLocation();
1005 HadError = true;
1006 }
1007
1008 Module *PreviousActiveModule = ActiveModule;
1009 if (Id.size() > 1) {
1010 // This module map defines a submodule. Go find the module of which it
1011 // is a submodule.
1012 ActiveModule = 0;
1013 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1014 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1015 ActiveModule = Next;
1016 continue;
1017 }
1018
1019 if (ActiveModule) {
1020 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1021 << Id[I].first << ActiveModule->getTopLevelModule();
1022 } else {
1023 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1024 }
1025 HadError = true;
1026 return;
1027 }
1028 }
1029
1030 StringRef ModuleName = Id.back().first;
1031 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001032
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001033 // Parse the optional attribute list.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001034 Attributes Attrs;
Douglas Gregor82e52372012-11-06 19:39:40 +00001035 parseOptionalAttributes(Attrs);
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001036
Douglas Gregora30cfe52011-11-11 19:10:28 +00001037 // Parse the opening brace.
1038 if (!Tok.is(MMToken::LBrace)) {
1039 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1040 << ModuleName;
1041 HadError = true;
1042 return;
1043 }
1044 SourceLocation LBraceLoc = consumeToken();
1045
1046 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +00001047 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +00001048 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1049 // Skip the module definition.
1050 skipUntil(MMToken::RBrace);
1051 if (Tok.is(MMToken::RBrace))
1052 consumeToken();
1053 else {
1054 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1055 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1056 HadError = true;
1057 }
1058 return;
1059 }
1060
Douglas Gregora30cfe52011-11-11 19:10:28 +00001061 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1062 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +00001063 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001064
1065 // Skip the module definition.
1066 skipUntil(MMToken::RBrace);
1067 if (Tok.is(MMToken::RBrace))
1068 consumeToken();
1069
1070 HadError = true;
1071 return;
1072 }
1073
1074 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +00001075 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1076 Explicit).first;
1077 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregor82e52372012-11-06 19:39:40 +00001078 if (Attrs.IsSystem)
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001079 ActiveModule->IsSystem = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001080
1081 bool Done = false;
1082 do {
1083 switch (Tok.Kind) {
1084 case MMToken::EndOfFile:
1085 case MMToken::RBrace:
1086 Done = true;
1087 break;
1088
1089 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +00001090 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001091 case MMToken::ModuleKeyword:
1092 parseModuleDecl();
1093 break;
1094
Douglas Gregor90db2602011-12-02 01:47:07 +00001095 case MMToken::ExportKeyword:
1096 parseExportDecl();
1097 break;
1098
Douglas Gregor51f564f2011-12-31 04:05:44 +00001099 case MMToken::RequiresKeyword:
1100 parseRequiresDecl();
1101 break;
1102
Douglas Gregor77d029f2011-12-08 19:11:24 +00001103 case MMToken::UmbrellaKeyword: {
1104 SourceLocation UmbrellaLoc = consumeToken();
1105 if (Tok.is(MMToken::HeaderKeyword))
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001106 parseHeaderDecl(UmbrellaLoc, SourceLocation());
Douglas Gregor77d029f2011-12-08 19:11:24 +00001107 else
1108 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001109 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001110 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001111
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001112 case MMToken::ExcludeKeyword: {
1113 SourceLocation ExcludeLoc = consumeToken();
1114 if (Tok.is(MMToken::HeaderKeyword)) {
1115 parseHeaderDecl(SourceLocation(), ExcludeLoc);
1116 } else {
1117 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1118 << "exclude";
1119 }
1120 break;
1121 }
1122
Douglas Gregor489ad432011-12-08 18:00:48 +00001123 case MMToken::HeaderKeyword:
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001124 parseHeaderDecl(SourceLocation(), SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001125 break;
Douglas Gregor489ad432011-12-08 18:00:48 +00001126
Douglas Gregora30cfe52011-11-11 19:10:28 +00001127 default:
1128 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1129 consumeToken();
1130 break;
1131 }
1132 } while (!Done);
1133
1134 if (Tok.is(MMToken::RBrace))
1135 consumeToken();
1136 else {
1137 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1138 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1139 HadError = true;
1140 }
1141
Douglas Gregor587986e2011-12-07 02:23:45 +00001142 // We're done parsing this module. Pop back to the previous module.
1143 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001144}
Douglas Gregord620a842011-12-06 17:16:41 +00001145
Douglas Gregor51f564f2011-12-31 04:05:44 +00001146/// \brief Parse a requires declaration.
1147///
1148/// requires-declaration:
1149/// 'requires' feature-list
1150///
1151/// feature-list:
1152/// identifier ',' feature-list
1153/// identifier
1154void ModuleMapParser::parseRequiresDecl() {
1155 assert(Tok.is(MMToken::RequiresKeyword));
1156
1157 // Parse 'requires' keyword.
1158 consumeToken();
1159
1160 // Parse the feature-list.
1161 do {
1162 if (!Tok.is(MMToken::Identifier)) {
1163 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1164 HadError = true;
1165 return;
1166 }
1167
1168 // Consume the feature name.
1169 std::string Feature = Tok.getString();
1170 consumeToken();
1171
1172 // Add this feature.
Douglas Gregordc58aa72012-01-30 06:01:29 +00001173 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor51f564f2011-12-31 04:05:44 +00001174
1175 if (!Tok.is(MMToken::Comma))
1176 break;
1177
1178 // Consume the comma.
1179 consumeToken();
1180 } while (true);
1181}
1182
Douglas Gregord620a842011-12-06 17:16:41 +00001183/// \brief Append to \p Paths the set of paths needed to get to the
1184/// subframework in which the given module lives.
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001185static void appendSubframeworkPaths(Module *Mod,
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00001186 SmallVectorImpl<char> &Path) {
Douglas Gregord620a842011-12-06 17:16:41 +00001187 // Collect the framework names from the given module to the top-level module.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00001188 SmallVector<StringRef, 2> Paths;
Douglas Gregord620a842011-12-06 17:16:41 +00001189 for (; Mod; Mod = Mod->Parent) {
1190 if (Mod->IsFramework)
1191 Paths.push_back(Mod->Name);
1192 }
1193
1194 if (Paths.empty())
1195 return;
1196
1197 // Add Frameworks/Name.framework for each subframework.
1198 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1199 llvm::sys::path::append(Path, "Frameworks");
1200 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1201 }
1202}
1203
Douglas Gregor2f04f182012-02-02 18:42:48 +00001204/// \brief Determine whether the given file name is the name of a builtin
1205/// header, supplied by Clang to replace, override, or augment existing system
1206/// headers.
1207static bool isBuiltinHeader(StringRef FileName) {
1208 return llvm::StringSwitch<bool>(FileName)
1209 .Case("float.h", true)
1210 .Case("iso646.h", true)
1211 .Case("limits.h", true)
1212 .Case("stdalign.h", true)
1213 .Case("stdarg.h", true)
1214 .Case("stdbool.h", true)
1215 .Case("stddef.h", true)
1216 .Case("stdint.h", true)
1217 .Case("tgmath.h", true)
1218 .Case("unwind.h", true)
1219 .Default(false);
1220}
1221
Douglas Gregora30cfe52011-11-11 19:10:28 +00001222/// \brief Parse a header declaration.
1223///
1224/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +00001225/// 'umbrella'[opt] 'header' string-literal
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001226/// 'exclude'[opt] 'header' string-literal
1227void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
1228 SourceLocation ExcludeLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001229 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +00001230 consumeToken();
1231
Douglas Gregor489ad432011-12-08 18:00:48 +00001232 bool Umbrella = UmbrellaLoc.isValid();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001233 bool Exclude = ExcludeLoc.isValid();
1234 assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001235 // Parse the header name.
1236 if (!Tok.is(MMToken::StringLiteral)) {
1237 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1238 << "header";
1239 HadError = true;
1240 return;
1241 }
Douglas Gregor587986e2011-12-07 02:23:45 +00001242 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +00001243 SourceLocation FileNameLoc = consumeToken();
1244
Douglas Gregor77d029f2011-12-08 19:11:24 +00001245 // Check whether we already have an umbrella.
1246 if (Umbrella && ActiveModule->Umbrella) {
1247 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1248 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001249 HadError = true;
1250 return;
1251 }
1252
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001253 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +00001254 const FileEntry *File = 0;
Douglas Gregor2f04f182012-02-02 18:42:48 +00001255 const FileEntry *BuiltinFile = 0;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001256 SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +00001257 if (llvm::sys::path::is_absolute(FileName)) {
1258 PathName = FileName;
1259 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +00001260 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1261 PathName = Dir->getName();
1262 llvm::sys::path::append(PathName, FileName);
1263 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001264 } else {
1265 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +00001266 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +00001267 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +00001268
Douglas Gregord620a842011-12-06 17:16:41 +00001269 if (ActiveModule->isPartOfFramework()) {
1270 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001271
1272 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +00001273 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +00001274 llvm::sys::path::append(PathName, FileName);
1275 File = SourceMgr.getFileManager().getFile(PathName);
1276
1277 if (!File) {
1278 // Check whether this file is in the private headers.
1279 PathName.resize(PathLength);
1280 llvm::sys::path::append(PathName, "PrivateHeaders");
1281 llvm::sys::path::append(PathName, FileName);
1282 File = SourceMgr.getFileManager().getFile(PathName);
1283 }
1284 } else {
1285 // Lookup for normal headers.
1286 llvm::sys::path::append(PathName, FileName);
1287 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001288
1289 // If this is a system module with a top-level header, this header
1290 // may have a counterpart (or replacement) in the set of headers
1291 // supplied by Clang. Find that builtin header.
1292 if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
1293 BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001294 SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
Douglas Gregor2f04f182012-02-02 18:42:48 +00001295 llvm::sys::path::append(BuiltinPathName, FileName);
1296 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1297
1298 // If Clang supplies this header but the underlying system does not,
1299 // just silently swap in our builtin version. Otherwise, we'll end
1300 // up adding both (later).
1301 if (!File && BuiltinFile) {
1302 File = BuiltinFile;
1303 BuiltinFile = 0;
1304 }
1305 }
Douglas Gregord620a842011-12-06 17:16:41 +00001306 }
Douglas Gregor18ee5472011-11-29 21:59:16 +00001307 }
Douglas Gregora8654052011-11-17 22:09:43 +00001308
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001309 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1310 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001311 if (File) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001312 if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001313 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001314 << FileName << OwningModule.getModule()->getFullModuleName();
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001315 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +00001316 } else if (Umbrella) {
1317 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001318 if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Douglas Gregor489ad432011-12-08 18:00:48 +00001319 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001320 << UmbrellaModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001321 HadError = true;
1322 } else {
1323 // Record this umbrella header.
1324 Map.setUmbrellaHeader(ActiveModule, File);
1325 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001326 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001327 // Record this header.
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001328 Map.addHeader(ActiveModule, File, Exclude);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001329
1330 // If there is a builtin counterpart to this file, add it now.
1331 if (BuiltinFile)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001332 Map.addHeader(ActiveModule, BuiltinFile, Exclude);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001333 }
Douglas Gregor71f49f52012-11-15 19:47:16 +00001334 } else if (!Exclude) {
1335 // Ignore excluded header files. They're optional anyway.
1336
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001337 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +00001338 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001339 HadError = true;
1340 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001341}
1342
Douglas Gregor77d029f2011-12-08 19:11:24 +00001343/// \brief Parse an umbrella directory declaration.
1344///
1345/// umbrella-dir-declaration:
1346/// umbrella string-literal
1347void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1348 // Parse the directory name.
1349 if (!Tok.is(MMToken::StringLiteral)) {
1350 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1351 << "umbrella";
1352 HadError = true;
1353 return;
1354 }
1355
1356 std::string DirName = Tok.getString();
1357 SourceLocation DirNameLoc = consumeToken();
1358
1359 // Check whether we already have an umbrella.
1360 if (ActiveModule->Umbrella) {
1361 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1362 << ActiveModule->getFullModuleName();
1363 HadError = true;
1364 return;
1365 }
1366
1367 // Look for this file.
1368 const DirectoryEntry *Dir = 0;
1369 if (llvm::sys::path::is_absolute(DirName))
1370 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1371 else {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001372 SmallString<128> PathName;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001373 PathName = Directory->getName();
1374 llvm::sys::path::append(PathName, DirName);
1375 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1376 }
1377
1378 if (!Dir) {
1379 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1380 << DirName;
1381 HadError = true;
1382 return;
1383 }
1384
1385 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1386 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1387 << OwningModule->getFullModuleName();
1388 HadError = true;
1389 return;
1390 }
1391
1392 // Record this umbrella directory.
1393 Map.setUmbrellaDir(ActiveModule, Dir);
1394}
1395
Douglas Gregor90db2602011-12-02 01:47:07 +00001396/// \brief Parse a module export declaration.
1397///
1398/// export-declaration:
1399/// 'export' wildcard-module-id
1400///
1401/// wildcard-module-id:
1402/// identifier
1403/// '*'
1404/// identifier '.' wildcard-module-id
1405void ModuleMapParser::parseExportDecl() {
1406 assert(Tok.is(MMToken::ExportKeyword));
1407 SourceLocation ExportLoc = consumeToken();
1408
1409 // Parse the module-id with an optional wildcard at the end.
1410 ModuleId ParsedModuleId;
1411 bool Wildcard = false;
1412 do {
1413 if (Tok.is(MMToken::Identifier)) {
1414 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1415 Tok.getLocation()));
1416 consumeToken();
1417
1418 if (Tok.is(MMToken::Period)) {
1419 consumeToken();
1420 continue;
1421 }
1422
1423 break;
1424 }
1425
1426 if(Tok.is(MMToken::Star)) {
1427 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001428 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001429 break;
1430 }
1431
1432 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1433 HadError = true;
1434 return;
1435 } while (true);
1436
1437 Module::UnresolvedExportDecl Unresolved = {
1438 ExportLoc, ParsedModuleId, Wildcard
1439 };
1440 ActiveModule->UnresolvedExports.push_back(Unresolved);
1441}
1442
Douglas Gregor82e52372012-11-06 19:39:40 +00001443/// \brief Parse an inferried module declaration (wildcard modules).
1444///
1445/// module-declaration:
1446/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
1447/// { inferred-module-member* }
1448///
1449/// inferred-module-member:
1450/// 'export' '*'
1451/// 'exclude' identifier
1452void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001453 assert(Tok.is(MMToken::Star));
1454 SourceLocation StarLoc = consumeToken();
1455 bool Failed = false;
Douglas Gregor82e52372012-11-06 19:39:40 +00001456
Douglas Gregor1e123682011-12-05 22:27:44 +00001457 // Inferred modules must be submodules.
Douglas Gregor82e52372012-11-06 19:39:40 +00001458 if (!ActiveModule && !Framework) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001459 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1460 Failed = true;
1461 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001462
1463 if (ActiveModule) {
1464 // Inferred modules must have umbrella directories.
1465 if (!Failed && !ActiveModule->getUmbrellaDir()) {
1466 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1467 Failed = true;
1468 }
1469
1470 // Check for redefinition of an inferred module.
1471 if (!Failed && ActiveModule->InferSubmodules) {
1472 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1473 if (ActiveModule->InferredSubmoduleLoc.isValid())
1474 Diags.Report(ActiveModule->InferredSubmoduleLoc,
1475 diag::note_mmap_prev_definition);
1476 Failed = true;
1477 }
1478
1479 // Check for the 'framework' keyword, which is not permitted here.
1480 if (Framework) {
1481 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
1482 Framework = false;
1483 }
1484 } else if (Explicit) {
1485 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
1486 Explicit = false;
Douglas Gregor1e123682011-12-05 22:27:44 +00001487 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001488
Douglas Gregor1e123682011-12-05 22:27:44 +00001489 // If there were any problems with this inferred submodule, skip its body.
1490 if (Failed) {
1491 if (Tok.is(MMToken::LBrace)) {
1492 consumeToken();
1493 skipUntil(MMToken::RBrace);
1494 if (Tok.is(MMToken::RBrace))
1495 consumeToken();
1496 }
1497 HadError = true;
1498 return;
1499 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001500
1501 // Parse optional attributes.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001502 Attributes Attrs;
Douglas Gregor82e52372012-11-06 19:39:40 +00001503 parseOptionalAttributes(Attrs);
1504
1505 if (ActiveModule) {
1506 // Note that we have an inferred submodule.
1507 ActiveModule->InferSubmodules = true;
1508 ActiveModule->InferredSubmoduleLoc = StarLoc;
1509 ActiveModule->InferExplicitSubmodules = Explicit;
1510 } else {
1511 // We'll be inferring framework modules for this directory.
1512 Map.InferredDirectories[Directory].InferModules = true;
1513 Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
1514 }
1515
Douglas Gregor1e123682011-12-05 22:27:44 +00001516 // Parse the opening brace.
1517 if (!Tok.is(MMToken::LBrace)) {
1518 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1519 HadError = true;
1520 return;
1521 }
1522 SourceLocation LBraceLoc = consumeToken();
1523
1524 // Parse the body of the inferred submodule.
1525 bool Done = false;
1526 do {
1527 switch (Tok.Kind) {
1528 case MMToken::EndOfFile:
1529 case MMToken::RBrace:
1530 Done = true;
1531 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001532
1533 case MMToken::ExcludeKeyword: {
1534 if (ActiveModule) {
1535 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001536 << (ActiveModule != 0);
Douglas Gregor82e52372012-11-06 19:39:40 +00001537 consumeToken();
1538 break;
1539 }
1540
1541 consumeToken();
1542 if (!Tok.is(MMToken::Identifier)) {
1543 Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
1544 break;
1545 }
1546
1547 Map.InferredDirectories[Directory].ExcludedModules
1548 .push_back(Tok.getString());
1549 consumeToken();
1550 break;
1551 }
1552
1553 case MMToken::ExportKeyword:
1554 if (!ActiveModule) {
1555 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001556 << (ActiveModule != 0);
Douglas Gregor82e52372012-11-06 19:39:40 +00001557 consumeToken();
1558 break;
1559 }
1560
Douglas Gregor1e123682011-12-05 22:27:44 +00001561 consumeToken();
1562 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001563 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001564 else
1565 Diags.Report(Tok.getLocation(),
1566 diag::err_mmap_expected_export_wildcard);
1567 consumeToken();
1568 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001569
Douglas Gregor1e123682011-12-05 22:27:44 +00001570 case MMToken::ExplicitKeyword:
1571 case MMToken::ModuleKeyword:
1572 case MMToken::HeaderKeyword:
1573 case MMToken::UmbrellaKeyword:
1574 default:
Douglas Gregor82e52372012-11-06 19:39:40 +00001575 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001576 << (ActiveModule != 0);
Douglas Gregor1e123682011-12-05 22:27:44 +00001577 consumeToken();
1578 break;
1579 }
1580 } while (!Done);
1581
1582 if (Tok.is(MMToken::RBrace))
1583 consumeToken();
1584 else {
1585 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1586 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1587 HadError = true;
1588 }
1589}
1590
Douglas Gregor82e52372012-11-06 19:39:40 +00001591/// \brief Parse optional attributes.
1592///
1593/// attributes:
1594/// attribute attributes
1595/// attribute
1596///
1597/// attribute:
1598/// [ identifier ]
1599///
1600/// \param Attrs Will be filled in with the parsed attributes.
1601///
1602/// \returns true if an error occurred, false otherwise.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001603bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
Douglas Gregor82e52372012-11-06 19:39:40 +00001604 bool HadError = false;
1605
1606 while (Tok.is(MMToken::LSquare)) {
1607 // Consume the '['.
1608 SourceLocation LSquareLoc = consumeToken();
1609
1610 // Check whether we have an attribute name here.
1611 if (!Tok.is(MMToken::Identifier)) {
1612 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
1613 skipUntil(MMToken::RSquare);
1614 if (Tok.is(MMToken::RSquare))
1615 consumeToken();
1616 HadError = true;
1617 }
1618
1619 // Decode the attribute name.
1620 AttributeKind Attribute
1621 = llvm::StringSwitch<AttributeKind>(Tok.getString())
1622 .Case("system", AT_system)
1623 .Default(AT_unknown);
1624 switch (Attribute) {
1625 case AT_unknown:
1626 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
1627 << Tok.getString();
1628 break;
1629
1630 case AT_system:
1631 Attrs.IsSystem = true;
1632 break;
1633 }
1634 consumeToken();
1635
1636 // Consume the ']'.
1637 if (!Tok.is(MMToken::RSquare)) {
1638 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
1639 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
1640 skipUntil(MMToken::RSquare);
1641 HadError = true;
1642 }
1643
1644 if (Tok.is(MMToken::RSquare))
1645 consumeToken();
1646 }
1647
1648 return HadError;
1649}
1650
Douglas Gregor6a1db482011-12-09 02:04:43 +00001651/// \brief If there is a specific header search directory due the presence
1652/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1653const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1654 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1655 // If we have an umbrella directory, use that.
1656 if (Mod->hasUmbrellaDir())
1657 return Mod->getUmbrellaDir();
1658
1659 // If we have a framework directory, stop looking.
1660 if (Mod->IsFramework)
1661 return 0;
1662 }
1663
1664 return 0;
1665}
1666
Douglas Gregora30cfe52011-11-11 19:10:28 +00001667/// \brief Parse a module map file.
1668///
1669/// module-map-file:
1670/// module-declaration*
1671bool ModuleMapParser::parseModuleMapFile() {
1672 do {
1673 switch (Tok.Kind) {
1674 case MMToken::EndOfFile:
1675 return HadError;
1676
Douglas Gregor587986e2011-12-07 02:23:45 +00001677 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001678 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001679 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001680 parseModuleDecl();
1681 break;
1682
Douglas Gregor51f564f2011-12-31 04:05:44 +00001683 case MMToken::Comma:
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001684 case MMToken::ExcludeKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001685 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001686 case MMToken::HeaderKeyword:
1687 case MMToken::Identifier:
1688 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001689 case MMToken::LSquare:
Douglas Gregor90db2602011-12-02 01:47:07 +00001690 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001691 case MMToken::RBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001692 case MMToken::RSquare:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001693 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001694 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001695 case MMToken::StringLiteral:
1696 case MMToken::UmbrellaKeyword:
1697 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1698 HadError = true;
1699 consumeToken();
1700 break;
1701 }
1702 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001703}
1704
1705bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregor7005b902013-01-10 01:43:00 +00001706 llvm::DenseMap<const FileEntry *, bool>::iterator Known
1707 = ParsedModuleMap.find(File);
1708 if (Known != ParsedModuleMap.end())
1709 return Known->second;
1710
Douglas Gregordc58aa72012-01-30 06:01:29 +00001711 assert(Target != 0 && "Missing target information");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001712 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1713 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1714 if (!Buffer)
Douglas Gregor7005b902013-01-10 01:43:00 +00001715 return ParsedModuleMap[File] = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001716
1717 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00001718 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1719 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor9a022bb2012-10-15 16:45:32 +00001720 ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
Douglas Gregor2f04f182012-02-02 18:42:48 +00001721 BuiltinIncludeDir);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001722 bool Result = Parser.parseModuleMapFile();
1723 Diags->getClient()->EndSourceFile();
Douglas Gregor7005b902013-01-10 01:43:00 +00001724 ParsedModuleMap[File] = Result;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001725 return Result;
1726}