blob: b815400754da5ae36092290968bc45186a21224b [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;
161 StringRef DirName = Dir->getName();
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000162
163 // Keep walking up the directory hierarchy, looking for a directory with
164 // an umbrella header.
165 do {
166 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
167 = UmbrellaDirs.find(Dir);
168 if (KnownDir != UmbrellaDirs.end()) {
169 Module *Result = KnownDir->second;
Douglas Gregor930a85c2011-12-06 16:17:15 +0000170
171 // Search up the module stack until we find a module with an umbrella
Douglas Gregor73141fa2011-12-08 17:39:04 +0000172 // directory.
Douglas Gregor930a85c2011-12-06 16:17:15 +0000173 Module *UmbrellaModule = Result;
Douglas Gregor73141fa2011-12-08 17:39:04 +0000174 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor930a85c2011-12-06 16:17:15 +0000175 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000176
Douglas Gregor930a85c2011-12-06 16:17:15 +0000177 if (UmbrellaModule->InferSubmodules) {
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000178 // Infer submodules for each of the directories we found between
179 // the directory of the umbrella header and the directory where
180 // the actual header is located.
Douglas Gregor9458f822011-12-07 22:05:21 +0000181 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000182
Douglas Gregor70331272011-12-09 02:04:43 +0000183 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000184 // Find or create the module that corresponds to this directory name.
Douglas Gregor056396a2012-10-12 21:15:50 +0000185 SmallString<32> NameBuf;
186 StringRef Name = sanitizeFilenameAsIdentifier(
187 llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
188 NameBuf);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000189 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9458f822011-12-07 22:05:21 +0000190 Explicit).first;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000191
192 // Associate the module and the directory.
193 UmbrellaDirs[SkippedDirs[I-1]] = Result;
194
195 // If inferred submodules export everything they import, add a
196 // wildcard to the set of exports.
Douglas Gregor930a85c2011-12-06 16:17:15 +0000197 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000198 Result->Exports.push_back(Module::ExportDecl(0, true));
199 }
200
201 // Infer a submodule with the same name as this header file.
Douglas Gregor056396a2012-10-12 21:15:50 +0000202 SmallString<32> NameBuf;
203 StringRef Name = sanitizeFilenameAsIdentifier(
204 llvm::sys::path::stem(File->getName()), NameBuf);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000205 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9458f822011-12-07 22:05:21 +0000206 Explicit).first;
Argyrios Kyrtzidisc597c8c2012-10-05 00:22:33 +0000207 Result->TopHeaders.insert(File);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000208
209 // If inferred submodules export everything they import, add a
210 // wildcard to the set of exports.
Douglas Gregor930a85c2011-12-06 16:17:15 +0000211 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000212 Result->Exports.push_back(Module::ExportDecl(0, true));
213 } else {
214 // Record each of the directories we stepped through as being part of
215 // the module we found, since the umbrella header covers them all.
216 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
217 UmbrellaDirs[SkippedDirs[I]] = Result;
218 }
219
Douglas Gregor59527662012-10-15 06:28:11 +0000220 Headers[File] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000221
222 // If a header corresponds to an unavailable module, don't report
223 // that it maps to anything.
224 if (!Result->isAvailable())
225 return 0;
226
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000227 return Result;
228 }
229
230 SkippedDirs.push_back(Dir);
231
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000232 // Retrieve our parent path.
233 DirName = llvm::sys::path::parent_path(DirName);
234 if (DirName.empty())
235 break;
236
237 // Resolve the parent path to a directory entry.
238 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000239 } while (Dir);
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000240
Douglas Gregorab0c8a82011-11-11 22:18:48 +0000241 return 0;
242}
243
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000244bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
Douglas Gregor59527662012-10-15 06:28:11 +0000245 HeadersMap::iterator Known = Headers.find(Header);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000246 if (Known != Headers.end())
Douglas Gregor59527662012-10-15 06:28:11 +0000247 return !Known->second.isAvailable();
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000248
249 const DirectoryEntry *Dir = Header->getDir();
250 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
251 StringRef DirName = Dir->getName();
252
253 // Keep walking up the directory hierarchy, looking for a directory with
254 // an umbrella header.
255 do {
256 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
257 = UmbrellaDirs.find(Dir);
258 if (KnownDir != UmbrellaDirs.end()) {
259 Module *Found = KnownDir->second;
260 if (!Found->isAvailable())
261 return true;
262
263 // Search up the module stack until we find a module with an umbrella
264 // directory.
265 Module *UmbrellaModule = Found;
266 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
267 UmbrellaModule = UmbrellaModule->Parent;
268
269 if (UmbrellaModule->InferSubmodules) {
270 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
271 // Find or create the module that corresponds to this directory name.
Douglas Gregor056396a2012-10-12 21:15:50 +0000272 SmallString<32> NameBuf;
273 StringRef Name = sanitizeFilenameAsIdentifier(
274 llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
275 NameBuf);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000276 Found = lookupModuleQualified(Name, Found);
277 if (!Found)
278 return false;
279 if (!Found->isAvailable())
280 return true;
281 }
282
283 // Infer a submodule with the same name as this header file.
Douglas Gregor056396a2012-10-12 21:15:50 +0000284 SmallString<32> NameBuf;
285 StringRef Name = sanitizeFilenameAsIdentifier(
286 llvm::sys::path::stem(Header->getName()),
287 NameBuf);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000288 Found = lookupModuleQualified(Name, Found);
289 if (!Found)
290 return false;
291 }
292
293 return !Found->isAvailable();
294 }
295
296 SkippedDirs.push_back(Dir);
297
298 // Retrieve our parent path.
299 DirName = llvm::sys::path::parent_path(DirName);
300 if (DirName.empty())
301 break;
302
303 // Resolve the parent path to a directory entry.
304 Dir = SourceMgr->getFileManager().getDirectory(DirName);
305 } while (Dir);
306
307 return false;
308}
309
Douglas Gregorde3ef502011-11-30 23:21:26 +0000310Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor88bdfb02011-11-11 23:20:24 +0000311 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
312 if (Known != Modules.end())
313 return Known->getValue();
314
315 return 0;
316}
317
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000318Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
319 for(; Context; Context = Context->Parent) {
320 if (Module *Sub = lookupModuleQualified(Name, Context))
321 return Sub;
322 }
323
324 return findModule(Name);
325}
326
327Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
328 if (!Context)
329 return findModule(Name);
330
Douglas Gregoreb90e832012-01-04 23:32:19 +0000331 return Context->findSubmodule(Name);
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000332}
333
Douglas Gregorde3ef502011-11-30 23:21:26 +0000334std::pair<Module *, bool>
Douglas Gregor69021972011-11-30 17:33:56 +0000335ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
336 bool IsExplicit) {
337 // Try to find an existing module with this name.
Douglas Gregoreb90e832012-01-04 23:32:19 +0000338 if (Module *Sub = lookupModuleQualified(Name, Parent))
339 return std::make_pair(Sub, false);
Douglas Gregor69021972011-11-30 17:33:56 +0000340
341 // Create a new module with this name.
342 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
343 IsExplicit);
Douglas Gregoreb90e832012-01-04 23:32:19 +0000344 if (!Parent)
Douglas Gregor69021972011-11-30 17:33:56 +0000345 Modules[Name] = Result;
346 return std::make_pair(Result, true);
347}
348
Douglas Gregor9194a912012-11-06 19:39:40 +0000349bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
350 StringRef Name, bool &IsSystem) {
351 // Check whether we have already looked into the parent directory
352 // for a module map.
353 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
354 inferred = InferredDirectories.find(ParentDir);
355 if (inferred == InferredDirectories.end())
356 return false;
357
358 if (!inferred->second.InferModules)
359 return false;
360
361 // We're allowed to infer for this directory, but make sure it's okay
362 // to infer this particular module.
363 bool canInfer = std::find(inferred->second.ExcludedModules.begin(),
364 inferred->second.ExcludedModules.end(),
365 Name) == inferred->second.ExcludedModules.end();
366
367 if (canInfer && inferred->second.InferSystemModules)
368 IsSystem = true;
369
370 return canInfer;
371}
372
Douglas Gregorde3ef502011-11-30 23:21:26 +0000373Module *
Douglas Gregor9194a912012-11-06 19:39:40 +0000374ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregore89dbc12011-12-06 19:39:29 +0000375 const DirectoryEntry *FrameworkDir,
Douglas Gregora686e1b2012-01-27 19:52:33 +0000376 bool IsSystem,
Douglas Gregore89dbc12011-12-06 19:39:29 +0000377 Module *Parent) {
Douglas Gregor56c64012011-11-17 01:41:17 +0000378 // Check whether we've already found this module.
Douglas Gregore89dbc12011-12-06 19:39:29 +0000379 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
380 return Mod;
381
382 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor9194a912012-11-06 19:39:40 +0000383
384 // If the framework has a parent path from which we're allowed to infer
385 // a framework module, do so.
386 if (!Parent) {
387 bool canInfer = false;
388 if (llvm::sys::path::has_parent_path(FrameworkDir->getName())) {
389 // Figure out the parent path.
390 StringRef Parent = llvm::sys::path::parent_path(FrameworkDir->getName());
391 if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
392 // Check whether we have already looked into the parent directory
393 // for a module map.
394 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator
395 inferred = InferredDirectories.find(ParentDir);
396 if (inferred == InferredDirectories.end()) {
397 // We haven't looked here before. Load a module map, if there is
398 // one.
399 SmallString<128> ModMapPath = Parent;
400 llvm::sys::path::append(ModMapPath, "module.map");
401 if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
402 parseModuleMapFile(ModMapFile);
403 inferred = InferredDirectories.find(ParentDir);
404 }
405
406 if (inferred == InferredDirectories.end())
407 inferred = InferredDirectories.insert(
408 std::make_pair(ParentDir, InferredDirectory())).first;
409 }
410
411 if (inferred->second.InferModules) {
412 // We're allowed to infer for this directory, but make sure it's okay
413 // to infer this particular module.
414 StringRef Name = llvm::sys::path::filename(FrameworkDir->getName());
415 canInfer = std::find(inferred->second.ExcludedModules.begin(),
416 inferred->second.ExcludedModules.end(),
417 Name) == inferred->second.ExcludedModules.end();
418
419 if (inferred->second.InferSystemModules)
420 IsSystem = true;
421 }
422 }
423 }
424
425 // If we're not allowed to infer a framework module, don't.
426 if (!canInfer)
427 return 0;
428 }
429
430
Douglas Gregor56c64012011-11-17 01:41:17 +0000431 // Look for an umbrella header.
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +0000432 SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Douglas Gregor56c64012011-11-17 01:41:17 +0000433 llvm::sys::path::append(UmbrellaName, "Headers");
434 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregore89dbc12011-12-06 19:39:29 +0000435 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor56c64012011-11-17 01:41:17 +0000436
437 // FIXME: If there's no umbrella header, we could probably scan the
438 // framework to load *everything*. But, it's not clear that this is a good
439 // idea.
440 if (!UmbrellaHeader)
441 return 0;
442
Douglas Gregore89dbc12011-12-06 19:39:29 +0000443 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
444 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora686e1b2012-01-27 19:52:33 +0000445 if (IsSystem)
446 Result->IsSystem = IsSystem;
447
Douglas Gregoreb90e832012-01-04 23:32:19 +0000448 if (!Parent)
Douglas Gregore89dbc12011-12-06 19:39:29 +0000449 Modules[ModuleName] = Result;
Douglas Gregoreb90e832012-01-04 23:32:19 +0000450
Douglas Gregor322f6332011-12-08 18:00:48 +0000451 // umbrella header "umbrella-header-name"
Douglas Gregor73141fa2011-12-08 17:39:04 +0000452 Result->Umbrella = UmbrellaHeader;
Douglas Gregor59527662012-10-15 06:28:11 +0000453 Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
Douglas Gregor4dc71832011-12-12 23:55:05 +0000454 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregord8bd7532011-12-05 17:40:25 +0000455
456 // export *
457 Result->Exports.push_back(Module::ExportDecl(0, true));
458
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000459 // module * { export * }
460 Result->InferSubmodules = true;
461 Result->InferExportWildcard = true;
462
Douglas Gregore89dbc12011-12-06 19:39:29 +0000463 // Look for subframeworks.
464 llvm::error_code EC;
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +0000465 SmallString<128> SubframeworksDirName
Douglas Gregorddaa69c2011-12-08 16:13:24 +0000466 = StringRef(FrameworkDir->getName());
Douglas Gregore89dbc12011-12-06 19:39:29 +0000467 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +0000468 SmallString<128> SubframeworksDirNameNative;
Douglas Gregorddaa69c2011-12-08 16:13:24 +0000469 llvm::sys::path::native(SubframeworksDirName.str(),
470 SubframeworksDirNameNative);
471 for (llvm::sys::fs::directory_iterator
472 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregore89dbc12011-12-06 19:39:29 +0000473 Dir != DirEnd && !EC; Dir.increment(EC)) {
474 if (!StringRef(Dir->path()).endswith(".framework"))
475 continue;
Douglas Gregor07c22b72012-09-27 14:50:15 +0000476
Douglas Gregore89dbc12011-12-06 19:39:29 +0000477 if (const DirectoryEntry *SubframeworkDir
478 = FileMgr.getDirectory(Dir->path())) {
Douglas Gregor07c22b72012-09-27 14:50:15 +0000479 // Note: as an egregious but useful hack, we use the real path here and
480 // check whether it is actually a subdirectory of the parent directory.
481 // This will not be the case if the 'subframework' is actually a symlink
482 // out to a top-level framework.
483#ifdef LLVM_ON_UNIX
484 char RealSubframeworkDirName[PATH_MAX];
485 if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) {
486 StringRef SubframeworkDirName = RealSubframeworkDirName;
487
488 bool FoundParent = false;
489 do {
490 // Get the parent directory name.
491 SubframeworkDirName
492 = llvm::sys::path::parent_path(SubframeworkDirName);
493 if (SubframeworkDirName.empty())
494 break;
495
496 if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
497 FoundParent = true;
498 break;
499 }
500 } while (true);
501
502 if (!FoundParent)
503 continue;
504 }
505#endif
506
Douglas Gregore89dbc12011-12-06 19:39:29 +0000507 // FIXME: Do we want to warn about subframeworks without umbrella headers?
Douglas Gregor056396a2012-10-12 21:15:50 +0000508 SmallString<32> NameBuf;
509 inferFrameworkModule(sanitizeFilenameAsIdentifier(
510 llvm::sys::path::stem(Dir->path()), NameBuf),
511 SubframeworkDir, IsSystem, Result);
Douglas Gregore89dbc12011-12-06 19:39:29 +0000512 }
513 }
Douglas Gregor09a22f02012-01-13 16:54:27 +0000514
Douglas Gregor56c64012011-11-17 01:41:17 +0000515 return Result;
516}
517
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000518void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
Douglas Gregor59527662012-10-15 06:28:11 +0000519 Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
Douglas Gregor73141fa2011-12-08 17:39:04 +0000520 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor70331272011-12-09 02:04:43 +0000521 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000522}
523
Douglas Gregor524e33e2011-12-08 19:11:24 +0000524void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
525 Mod->Umbrella = UmbrellaDir;
526 UmbrellaDirs[UmbrellaDir] = Mod;
527}
528
Douglas Gregor59527662012-10-15 06:28:11 +0000529void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
530 bool Excluded) {
531 if (Excluded)
532 Mod->ExcludedHeaders.push_back(Header);
533 else
534 Mod->Headers.push_back(Header);
535 Headers[Header] = KnownHeader(Mod, Excluded);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000536}
537
Douglas Gregor514b6362011-11-29 19:06:37 +0000538const FileEntry *
Douglas Gregorde3ef502011-11-30 23:21:26 +0000539ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregor514b6362011-11-29 19:06:37 +0000540 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
541 return 0;
542
543 return SourceMgr->getFileEntryForID(
544 SourceMgr->getFileID(Module->DefinitionLoc));
545}
546
Douglas Gregor718292f2011-11-11 19:10:28 +0000547void ModuleMap::dump() {
548 llvm::errs() << "Modules:";
549 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
550 MEnd = Modules.end();
551 M != MEnd; ++M)
Douglas Gregord28d1b82011-11-29 18:17:59 +0000552 M->getValue()->print(llvm::errs(), 2);
Douglas Gregor718292f2011-11-11 19:10:28 +0000553
554 llvm::errs() << "Headers:";
Douglas Gregor59527662012-10-15 06:28:11 +0000555 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
Douglas Gregor718292f2011-11-11 19:10:28 +0000556 H != HEnd; ++H) {
557 llvm::errs() << " \"" << H->first->getName() << "\" -> "
Douglas Gregor59527662012-10-15 06:28:11 +0000558 << H->second.getModule()->getFullModuleName() << "\n";
Douglas Gregor718292f2011-11-11 19:10:28 +0000559 }
560}
561
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000562bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
563 bool HadError = false;
564 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
565 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
566 Complain);
Douglas Gregorf5eedd02011-12-05 17:28:06 +0000567 if (Export.getPointer() || Export.getInt())
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000568 Mod->Exports.push_back(Export);
569 else
570 HadError = true;
571 }
572 Mod->UnresolvedExports.clear();
573 return HadError;
574}
575
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000576Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
577 if (Loc.isInvalid())
578 return 0;
579
580 // Use the expansion location to determine which module we're in.
581 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
582 if (!ExpansionLoc.isFileID())
583 return 0;
584
585
586 const SourceManager &SrcMgr = Loc.getManager();
587 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000588
Douglas Gregor224d8a72012-01-06 17:19:32 +0000589 while (const FileEntry *ExpansionFile
590 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
591 // Find the module that owns this header (if any).
592 if (Module *Mod = findModuleForHeader(ExpansionFile))
593 return Mod;
594
595 // No module owns this header, so look up the inclusion chain to see if
596 // any included header has an associated module.
597 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
598 if (IncludeLoc.isInvalid())
599 return 0;
600
601 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
602 }
603
604 return 0;
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000605}
606
Douglas Gregor718292f2011-11-11 19:10:28 +0000607//----------------------------------------------------------------------------//
608// Module map file parser
609//----------------------------------------------------------------------------//
610
611namespace clang {
612 /// \brief A token in a module map file.
613 struct MMToken {
614 enum TokenKind {
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000615 Comma,
Douglas Gregor718292f2011-11-11 19:10:28 +0000616 EndOfFile,
617 HeaderKeyword,
618 Identifier,
Douglas Gregor59527662012-10-15 06:28:11 +0000619 ExcludeKeyword,
Douglas Gregor718292f2011-11-11 19:10:28 +0000620 ExplicitKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000621 ExportKeyword,
Douglas Gregor755b2052011-11-17 22:09:43 +0000622 FrameworkKeyword,
Douglas Gregor718292f2011-11-11 19:10:28 +0000623 ModuleKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000624 Period,
Douglas Gregor718292f2011-11-11 19:10:28 +0000625 UmbrellaKeyword,
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000626 RequiresKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000627 Star,
Douglas Gregor718292f2011-11-11 19:10:28 +0000628 StringLiteral,
629 LBrace,
Douglas Gregora686e1b2012-01-27 19:52:33 +0000630 RBrace,
631 LSquare,
632 RSquare
Douglas Gregor718292f2011-11-11 19:10:28 +0000633 } Kind;
634
635 unsigned Location;
636 unsigned StringLength;
637 const char *StringData;
638
639 void clear() {
640 Kind = EndOfFile;
641 Location = 0;
642 StringLength = 0;
643 StringData = 0;
644 }
645
646 bool is(TokenKind K) const { return Kind == K; }
647
648 SourceLocation getLocation() const {
649 return SourceLocation::getFromRawEncoding(Location);
650 }
651
652 StringRef getString() const {
653 return StringRef(StringData, StringLength);
654 }
655 };
Douglas Gregor9194a912012-11-06 19:39:40 +0000656
657 /// \brief The set of attributes that can be attached to a module.
658 struct Attributes {
659 Attributes() : IsSystem() { }
660
661 /// \brief Whether this is a system module.
662 unsigned IsSystem : 1;
663 };
Douglas Gregor718292f2011-11-11 19:10:28 +0000664
Douglas Gregor9194a912012-11-06 19:39:40 +0000665
Douglas Gregor718292f2011-11-11 19:10:28 +0000666 class ModuleMapParser {
667 Lexer &L;
668 SourceManager &SourceMgr;
Douglas Gregorbc10b9f2012-10-15 16:45:32 +0000669
670 /// \brief Default target information, used only for string literal
671 /// parsing.
672 const TargetInfo *Target;
673
Douglas Gregor718292f2011-11-11 19:10:28 +0000674 DiagnosticsEngine &Diags;
675 ModuleMap &Map;
676
Douglas Gregor5257fc62011-11-11 21:55:48 +0000677 /// \brief The directory that this module map resides in.
678 const DirectoryEntry *Directory;
Douglas Gregor3ec66632012-02-02 18:42:48 +0000679
680 /// \brief The directory containing Clang-supplied headers.
681 const DirectoryEntry *BuiltinIncludeDir;
682
Douglas Gregor718292f2011-11-11 19:10:28 +0000683 /// \brief Whether an error occurred.
684 bool HadError;
Douglas Gregorbc10b9f2012-10-15 16:45:32 +0000685
Douglas Gregor718292f2011-11-11 19:10:28 +0000686 /// \brief Stores string data for the various string literals referenced
687 /// during parsing.
688 llvm::BumpPtrAllocator StringData;
689
690 /// \brief The current token.
691 MMToken Tok;
692
693 /// \brief The active module.
Douglas Gregorde3ef502011-11-30 23:21:26 +0000694 Module *ActiveModule;
Douglas Gregor718292f2011-11-11 19:10:28 +0000695
696 /// \brief Consume the current token and return its location.
697 SourceLocation consumeToken();
698
699 /// \brief Skip tokens until we reach the a token with the given kind
700 /// (or the end of the file).
701 void skipUntil(MMToken::TokenKind K);
Douglas Gregore7ab3662011-12-07 02:23:45 +0000702
703 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
704 ModuleId;
705 bool parseModuleId(ModuleId &Id);
Douglas Gregor718292f2011-11-11 19:10:28 +0000706 void parseModuleDecl();
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000707 void parseRequiresDecl();
Douglas Gregor59527662012-10-15 06:28:11 +0000708 void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
Douglas Gregor524e33e2011-12-08 19:11:24 +0000709 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000710 void parseExportDecl();
Douglas Gregor9194a912012-11-06 19:39:40 +0000711 void parseInferredModuleDecl(bool Framework, bool Explicit);
712 bool parseOptionalAttributes(Attributes &Attrs);
713
Douglas Gregor70331272011-12-09 02:04:43 +0000714 const DirectoryEntry *getOverriddenHeaderSearchDir();
715
Douglas Gregor718292f2011-11-11 19:10:28 +0000716 public:
Douglas Gregor718292f2011-11-11 19:10:28 +0000717 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
Douglas Gregorbc10b9f2012-10-15 16:45:32 +0000718 const TargetInfo *Target,
Douglas Gregor718292f2011-11-11 19:10:28 +0000719 DiagnosticsEngine &Diags,
Douglas Gregor5257fc62011-11-11 21:55:48 +0000720 ModuleMap &Map,
Douglas Gregor3ec66632012-02-02 18:42:48 +0000721 const DirectoryEntry *Directory,
722 const DirectoryEntry *BuiltinIncludeDir)
Douglas Gregorbc10b9f2012-10-15 16:45:32 +0000723 : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
Douglas Gregor3ec66632012-02-02 18:42:48 +0000724 Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
725 HadError(false), ActiveModule(0)
Douglas Gregor718292f2011-11-11 19:10:28 +0000726 {
Douglas Gregor718292f2011-11-11 19:10:28 +0000727 Tok.clear();
728 consumeToken();
729 }
730
731 bool parseModuleMapFile();
732 };
733}
734
735SourceLocation ModuleMapParser::consumeToken() {
736retry:
737 SourceLocation Result = Tok.getLocation();
738 Tok.clear();
739
740 Token LToken;
741 L.LexFromRawLexer(LToken);
742 Tok.Location = LToken.getLocation().getRawEncoding();
743 switch (LToken.getKind()) {
744 case tok::raw_identifier:
745 Tok.StringData = LToken.getRawIdentifierData();
746 Tok.StringLength = LToken.getLength();
747 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
748 .Case("header", MMToken::HeaderKeyword)
Douglas Gregor59527662012-10-15 06:28:11 +0000749 .Case("exclude", MMToken::ExcludeKeyword)
Douglas Gregor718292f2011-11-11 19:10:28 +0000750 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000751 .Case("export", MMToken::ExportKeyword)
Douglas Gregor755b2052011-11-17 22:09:43 +0000752 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregor718292f2011-11-11 19:10:28 +0000753 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000754 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregor718292f2011-11-11 19:10:28 +0000755 .Case("umbrella", MMToken::UmbrellaKeyword)
756 .Default(MMToken::Identifier);
757 break;
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000758
759 case tok::comma:
760 Tok.Kind = MMToken::Comma;
761 break;
762
Douglas Gregor718292f2011-11-11 19:10:28 +0000763 case tok::eof:
764 Tok.Kind = MMToken::EndOfFile;
765 break;
766
767 case tok::l_brace:
768 Tok.Kind = MMToken::LBrace;
769 break;
770
Douglas Gregora686e1b2012-01-27 19:52:33 +0000771 case tok::l_square:
772 Tok.Kind = MMToken::LSquare;
773 break;
774
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000775 case tok::period:
776 Tok.Kind = MMToken::Period;
777 break;
778
Douglas Gregor718292f2011-11-11 19:10:28 +0000779 case tok::r_brace:
780 Tok.Kind = MMToken::RBrace;
781 break;
782
Douglas Gregora686e1b2012-01-27 19:52:33 +0000783 case tok::r_square:
784 Tok.Kind = MMToken::RSquare;
785 break;
786
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000787 case tok::star:
788 Tok.Kind = MMToken::Star;
789 break;
790
Douglas Gregor718292f2011-11-11 19:10:28 +0000791 case tok::string_literal: {
Richard Smithd67aea22012-03-06 03:21:47 +0000792 if (LToken.hasUDSuffix()) {
793 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
794 HadError = true;
795 goto retry;
796 }
797
Douglas Gregor718292f2011-11-11 19:10:28 +0000798 // Parse the string literal.
799 LangOptions LangOpts;
800 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
801 if (StringLiteral.hadError)
802 goto retry;
803
804 // Copy the string literal into our string data allocator.
805 unsigned Length = StringLiteral.GetStringLength();
806 char *Saved = StringData.Allocate<char>(Length + 1);
807 memcpy(Saved, StringLiteral.GetString().data(), Length);
808 Saved[Length] = 0;
809
810 // Form the token.
811 Tok.Kind = MMToken::StringLiteral;
812 Tok.StringData = Saved;
813 Tok.StringLength = Length;
814 break;
815 }
816
817 case tok::comment:
818 goto retry;
819
820 default:
821 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
822 HadError = true;
823 goto retry;
824 }
825
826 return Result;
827}
828
829void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
830 unsigned braceDepth = 0;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000831 unsigned squareDepth = 0;
Douglas Gregor718292f2011-11-11 19:10:28 +0000832 do {
833 switch (Tok.Kind) {
834 case MMToken::EndOfFile:
835 return;
836
837 case MMToken::LBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000838 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregor718292f2011-11-11 19:10:28 +0000839 return;
840
841 ++braceDepth;
842 break;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000843
844 case MMToken::LSquare:
845 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
846 return;
847
848 ++squareDepth;
849 break;
850
Douglas Gregor718292f2011-11-11 19:10:28 +0000851 case MMToken::RBrace:
852 if (braceDepth > 0)
853 --braceDepth;
854 else if (Tok.is(K))
855 return;
856 break;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000857
858 case MMToken::RSquare:
859 if (squareDepth > 0)
860 --squareDepth;
861 else if (Tok.is(K))
862 return;
863 break;
864
Douglas Gregor718292f2011-11-11 19:10:28 +0000865 default:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000866 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregor718292f2011-11-11 19:10:28 +0000867 return;
868 break;
869 }
870
871 consumeToken();
872 } while (true);
873}
874
Douglas Gregore7ab3662011-12-07 02:23:45 +0000875/// \brief Parse a module-id.
876///
877/// module-id:
878/// identifier
879/// identifier '.' module-id
880///
881/// \returns true if an error occurred, false otherwise.
882bool ModuleMapParser::parseModuleId(ModuleId &Id) {
883 Id.clear();
884 do {
885 if (Tok.is(MMToken::Identifier)) {
886 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
887 consumeToken();
888 } else {
889 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
890 return true;
891 }
892
893 if (!Tok.is(MMToken::Period))
894 break;
895
896 consumeToken();
897 } while (true);
898
899 return false;
900}
901
Douglas Gregora686e1b2012-01-27 19:52:33 +0000902namespace {
903 /// \brief Enumerates the known attributes.
904 enum AttributeKind {
905 /// \brief An unknown attribute.
906 AT_unknown,
907 /// \brief The 'system' attribute.
908 AT_system
909 };
910}
911
Douglas Gregor718292f2011-11-11 19:10:28 +0000912/// \brief Parse a module declaration.
913///
914/// module-declaration:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000915/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
916/// { module-member* }
917///
Douglas Gregor718292f2011-11-11 19:10:28 +0000918/// module-member:
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000919/// requires-declaration
Douglas Gregor718292f2011-11-11 19:10:28 +0000920/// header-declaration
Douglas Gregore7ab3662011-12-07 02:23:45 +0000921/// submodule-declaration
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000922/// export-declaration
Douglas Gregor73441092011-12-05 22:27:44 +0000923///
924/// submodule-declaration:
925/// module-declaration
926/// inferred-submodule-declaration
Douglas Gregor718292f2011-11-11 19:10:28 +0000927void ModuleMapParser::parseModuleDecl() {
Douglas Gregor755b2052011-11-17 22:09:43 +0000928 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
929 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregorf2161a72011-12-06 17:16:41 +0000930 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregore7ab3662011-12-07 02:23:45 +0000931 SourceLocation ExplicitLoc;
Douglas Gregor718292f2011-11-11 19:10:28 +0000932 bool Explicit = false;
Douglas Gregorf2161a72011-12-06 17:16:41 +0000933 bool Framework = false;
Douglas Gregor755b2052011-11-17 22:09:43 +0000934
Douglas Gregorf2161a72011-12-06 17:16:41 +0000935 // Parse 'explicit' keyword, if present.
936 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregore7ab3662011-12-07 02:23:45 +0000937 ExplicitLoc = consumeToken();
Douglas Gregorf2161a72011-12-06 17:16:41 +0000938 Explicit = true;
939 }
940
941 // Parse 'framework' keyword, if present.
Douglas Gregor755b2052011-11-17 22:09:43 +0000942 if (Tok.is(MMToken::FrameworkKeyword)) {
943 consumeToken();
944 Framework = true;
945 }
Douglas Gregor718292f2011-11-11 19:10:28 +0000946
947 // Parse 'module' keyword.
948 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregord6343c92011-12-06 19:57:48 +0000949 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregor718292f2011-11-11 19:10:28 +0000950 consumeToken();
951 HadError = true;
952 return;
953 }
954 consumeToken(); // 'module' keyword
Douglas Gregor73441092011-12-05 22:27:44 +0000955
956 // If we have a wildcard for the module name, this is an inferred submodule.
957 // Parse it.
958 if (Tok.is(MMToken::Star))
Douglas Gregor9194a912012-11-06 19:39:40 +0000959 return parseInferredModuleDecl(Framework, Explicit);
Douglas Gregor718292f2011-11-11 19:10:28 +0000960
961 // Parse the module name.
Douglas Gregore7ab3662011-12-07 02:23:45 +0000962 ModuleId Id;
963 if (parseModuleId(Id)) {
Douglas Gregor718292f2011-11-11 19:10:28 +0000964 HadError = true;
Douglas Gregore7ab3662011-12-07 02:23:45 +0000965 return;
Douglas Gregor718292f2011-11-11 19:10:28 +0000966 }
Douglas Gregor9194a912012-11-06 19:39:40 +0000967
Douglas Gregore7ab3662011-12-07 02:23:45 +0000968 if (ActiveModule) {
969 if (Id.size() > 1) {
970 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
971 << SourceRange(Id.front().second, Id.back().second);
972
973 HadError = true;
974 return;
975 }
976 } else if (Id.size() == 1 && Explicit) {
977 // Top-level modules can't be explicit.
978 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
979 Explicit = false;
980 ExplicitLoc = SourceLocation();
981 HadError = true;
982 }
983
984 Module *PreviousActiveModule = ActiveModule;
985 if (Id.size() > 1) {
986 // This module map defines a submodule. Go find the module of which it
987 // is a submodule.
988 ActiveModule = 0;
989 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
990 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
991 ActiveModule = Next;
992 continue;
993 }
994
995 if (ActiveModule) {
996 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
997 << Id[I].first << ActiveModule->getTopLevelModule();
998 } else {
999 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1000 }
1001 HadError = true;
1002 return;
1003 }
1004 }
1005
1006 StringRef ModuleName = Id.back().first;
1007 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregor718292f2011-11-11 19:10:28 +00001008
Douglas Gregora686e1b2012-01-27 19:52:33 +00001009 // Parse the optional attribute list.
Douglas Gregor9194a912012-11-06 19:39:40 +00001010 Attributes Attrs;
1011 parseOptionalAttributes(Attrs);
Douglas Gregora686e1b2012-01-27 19:52:33 +00001012
Douglas Gregor718292f2011-11-11 19:10:28 +00001013 // Parse the opening brace.
1014 if (!Tok.is(MMToken::LBrace)) {
1015 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1016 << ModuleName;
1017 HadError = true;
1018 return;
1019 }
1020 SourceLocation LBraceLoc = consumeToken();
1021
1022 // Determine whether this (sub)module has already been defined.
Douglas Gregoreb90e832012-01-04 23:32:19 +00001023 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorfcc54a32012-01-05 00:12:00 +00001024 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1025 // Skip the module definition.
1026 skipUntil(MMToken::RBrace);
1027 if (Tok.is(MMToken::RBrace))
1028 consumeToken();
1029 else {
1030 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1031 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1032 HadError = true;
1033 }
1034 return;
1035 }
1036
Douglas Gregor718292f2011-11-11 19:10:28 +00001037 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1038 << ModuleName;
Douglas Gregoreb90e832012-01-04 23:32:19 +00001039 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregor718292f2011-11-11 19:10:28 +00001040
1041 // Skip the module definition.
1042 skipUntil(MMToken::RBrace);
1043 if (Tok.is(MMToken::RBrace))
1044 consumeToken();
1045
1046 HadError = true;
1047 return;
1048 }
1049
1050 // Start defining this module.
Douglas Gregoreb90e832012-01-04 23:32:19 +00001051 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1052 Explicit).first;
1053 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregor9194a912012-11-06 19:39:40 +00001054 if (Attrs.IsSystem)
Douglas Gregora686e1b2012-01-27 19:52:33 +00001055 ActiveModule->IsSystem = true;
Douglas Gregor718292f2011-11-11 19:10:28 +00001056
1057 bool Done = false;
1058 do {
1059 switch (Tok.Kind) {
1060 case MMToken::EndOfFile:
1061 case MMToken::RBrace:
1062 Done = true;
1063 break;
1064
1065 case MMToken::ExplicitKeyword:
Douglas Gregorf2161a72011-12-06 17:16:41 +00001066 case MMToken::FrameworkKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001067 case MMToken::ModuleKeyword:
1068 parseModuleDecl();
1069 break;
1070
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001071 case MMToken::ExportKeyword:
1072 parseExportDecl();
1073 break;
1074
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001075 case MMToken::RequiresKeyword:
1076 parseRequiresDecl();
1077 break;
1078
Douglas Gregor524e33e2011-12-08 19:11:24 +00001079 case MMToken::UmbrellaKeyword: {
1080 SourceLocation UmbrellaLoc = consumeToken();
1081 if (Tok.is(MMToken::HeaderKeyword))
Douglas Gregor59527662012-10-15 06:28:11 +00001082 parseHeaderDecl(UmbrellaLoc, SourceLocation());
Douglas Gregor524e33e2011-12-08 19:11:24 +00001083 else
1084 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregor718292f2011-11-11 19:10:28 +00001085 break;
Douglas Gregor524e33e2011-12-08 19:11:24 +00001086 }
Douglas Gregor718292f2011-11-11 19:10:28 +00001087
Douglas Gregor59527662012-10-15 06:28:11 +00001088 case MMToken::ExcludeKeyword: {
1089 SourceLocation ExcludeLoc = consumeToken();
1090 if (Tok.is(MMToken::HeaderKeyword)) {
1091 parseHeaderDecl(SourceLocation(), ExcludeLoc);
1092 } else {
1093 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1094 << "exclude";
1095 }
1096 break;
1097 }
1098
Douglas Gregor322f6332011-12-08 18:00:48 +00001099 case MMToken::HeaderKeyword:
Douglas Gregor59527662012-10-15 06:28:11 +00001100 parseHeaderDecl(SourceLocation(), SourceLocation());
Douglas Gregor718292f2011-11-11 19:10:28 +00001101 break;
Douglas Gregor322f6332011-12-08 18:00:48 +00001102
Douglas Gregor718292f2011-11-11 19:10:28 +00001103 default:
1104 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1105 consumeToken();
1106 break;
1107 }
1108 } while (!Done);
1109
1110 if (Tok.is(MMToken::RBrace))
1111 consumeToken();
1112 else {
1113 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1114 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1115 HadError = true;
1116 }
1117
Douglas Gregore7ab3662011-12-07 02:23:45 +00001118 // We're done parsing this module. Pop back to the previous module.
1119 ActiveModule = PreviousActiveModule;
Douglas Gregor718292f2011-11-11 19:10:28 +00001120}
Douglas Gregorf2161a72011-12-06 17:16:41 +00001121
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001122/// \brief Parse a requires declaration.
1123///
1124/// requires-declaration:
1125/// 'requires' feature-list
1126///
1127/// feature-list:
1128/// identifier ',' feature-list
1129/// identifier
1130void ModuleMapParser::parseRequiresDecl() {
1131 assert(Tok.is(MMToken::RequiresKeyword));
1132
1133 // Parse 'requires' keyword.
1134 consumeToken();
1135
1136 // Parse the feature-list.
1137 do {
1138 if (!Tok.is(MMToken::Identifier)) {
1139 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1140 HadError = true;
1141 return;
1142 }
1143
1144 // Consume the feature name.
1145 std::string Feature = Tok.getString();
1146 consumeToken();
1147
1148 // Add this feature.
Douglas Gregor89929282012-01-30 06:01:29 +00001149 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001150
1151 if (!Tok.is(MMToken::Comma))
1152 break;
1153
1154 // Consume the comma.
1155 consumeToken();
1156 } while (true);
1157}
1158
Douglas Gregorf2161a72011-12-06 17:16:41 +00001159/// \brief Append to \p Paths the set of paths needed to get to the
1160/// subframework in which the given module lives.
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001161static void appendSubframeworkPaths(Module *Mod,
1162 llvm::SmallVectorImpl<char> &Path) {
Douglas Gregorf2161a72011-12-06 17:16:41 +00001163 // Collect the framework names from the given module to the top-level module.
1164 llvm::SmallVector<StringRef, 2> Paths;
1165 for (; Mod; Mod = Mod->Parent) {
1166 if (Mod->IsFramework)
1167 Paths.push_back(Mod->Name);
1168 }
1169
1170 if (Paths.empty())
1171 return;
1172
1173 // Add Frameworks/Name.framework for each subframework.
1174 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1175 llvm::sys::path::append(Path, "Frameworks");
1176 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1177 }
1178}
1179
Douglas Gregor3ec66632012-02-02 18:42:48 +00001180/// \brief Determine whether the given file name is the name of a builtin
1181/// header, supplied by Clang to replace, override, or augment existing system
1182/// headers.
1183static bool isBuiltinHeader(StringRef FileName) {
1184 return llvm::StringSwitch<bool>(FileName)
1185 .Case("float.h", true)
1186 .Case("iso646.h", true)
1187 .Case("limits.h", true)
1188 .Case("stdalign.h", true)
1189 .Case("stdarg.h", true)
1190 .Case("stdbool.h", true)
1191 .Case("stddef.h", true)
1192 .Case("stdint.h", true)
1193 .Case("tgmath.h", true)
1194 .Case("unwind.h", true)
1195 .Default(false);
1196}
1197
Douglas Gregor718292f2011-11-11 19:10:28 +00001198/// \brief Parse a header declaration.
1199///
1200/// header-declaration:
Douglas Gregor322f6332011-12-08 18:00:48 +00001201/// 'umbrella'[opt] 'header' string-literal
Douglas Gregor59527662012-10-15 06:28:11 +00001202/// 'exclude'[opt] 'header' string-literal
1203void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
1204 SourceLocation ExcludeLoc) {
Douglas Gregor718292f2011-11-11 19:10:28 +00001205 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramer1871ed32011-11-13 16:52:09 +00001206 consumeToken();
1207
Douglas Gregor322f6332011-12-08 18:00:48 +00001208 bool Umbrella = UmbrellaLoc.isValid();
Douglas Gregor59527662012-10-15 06:28:11 +00001209 bool Exclude = ExcludeLoc.isValid();
1210 assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
Douglas Gregor718292f2011-11-11 19:10:28 +00001211 // Parse the header name.
1212 if (!Tok.is(MMToken::StringLiteral)) {
1213 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1214 << "header";
1215 HadError = true;
1216 return;
1217 }
Douglas Gregore7ab3662011-12-07 02:23:45 +00001218 std::string FileName = Tok.getString();
Douglas Gregor718292f2011-11-11 19:10:28 +00001219 SourceLocation FileNameLoc = consumeToken();
1220
Douglas Gregor524e33e2011-12-08 19:11:24 +00001221 // Check whether we already have an umbrella.
1222 if (Umbrella && ActiveModule->Umbrella) {
1223 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1224 << ActiveModule->getFullModuleName();
Douglas Gregor322f6332011-12-08 18:00:48 +00001225 HadError = true;
1226 return;
1227 }
1228
Douglas Gregor5257fc62011-11-11 21:55:48 +00001229 // Look for this file.
Douglas Gregore7ab3662011-12-07 02:23:45 +00001230 const FileEntry *File = 0;
Douglas Gregor3ec66632012-02-02 18:42:48 +00001231 const FileEntry *BuiltinFile = 0;
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00001232 SmallString<128> PathName;
Douglas Gregore7ab3662011-12-07 02:23:45 +00001233 if (llvm::sys::path::is_absolute(FileName)) {
1234 PathName = FileName;
1235 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor70331272011-12-09 02:04:43 +00001236 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1237 PathName = Dir->getName();
1238 llvm::sys::path::append(PathName, FileName);
1239 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregore7ab3662011-12-07 02:23:45 +00001240 } else {
1241 // Search for the header file within the search directory.
Douglas Gregor70331272011-12-09 02:04:43 +00001242 PathName = Directory->getName();
Douglas Gregore7ab3662011-12-07 02:23:45 +00001243 unsigned PathLength = PathName.size();
Douglas Gregorf545f672011-11-29 21:59:16 +00001244
Douglas Gregorf2161a72011-12-06 17:16:41 +00001245 if (ActiveModule->isPartOfFramework()) {
1246 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregore7ab3662011-12-07 02:23:45 +00001247
1248 // Check whether this file is in the public headers.
Douglas Gregorf545f672011-11-29 21:59:16 +00001249 llvm::sys::path::append(PathName, "Headers");
Douglas Gregore7ab3662011-12-07 02:23:45 +00001250 llvm::sys::path::append(PathName, FileName);
1251 File = SourceMgr.getFileManager().getFile(PathName);
1252
1253 if (!File) {
1254 // Check whether this file is in the private headers.
1255 PathName.resize(PathLength);
1256 llvm::sys::path::append(PathName, "PrivateHeaders");
1257 llvm::sys::path::append(PathName, FileName);
1258 File = SourceMgr.getFileManager().getFile(PathName);
1259 }
1260 } else {
1261 // Lookup for normal headers.
1262 llvm::sys::path::append(PathName, FileName);
1263 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor3ec66632012-02-02 18:42:48 +00001264
1265 // If this is a system module with a top-level header, this header
1266 // may have a counterpart (or replacement) in the set of headers
1267 // supplied by Clang. Find that builtin header.
1268 if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
1269 BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00001270 SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
Douglas Gregor3ec66632012-02-02 18:42:48 +00001271 llvm::sys::path::append(BuiltinPathName, FileName);
1272 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1273
1274 // If Clang supplies this header but the underlying system does not,
1275 // just silently swap in our builtin version. Otherwise, we'll end
1276 // up adding both (later).
1277 if (!File && BuiltinFile) {
1278 File = BuiltinFile;
1279 BuiltinFile = 0;
1280 }
1281 }
Douglas Gregorf2161a72011-12-06 17:16:41 +00001282 }
Douglas Gregorf545f672011-11-29 21:59:16 +00001283 }
Douglas Gregor755b2052011-11-17 22:09:43 +00001284
Douglas Gregor5257fc62011-11-11 21:55:48 +00001285 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1286 // Come up with a lazy way to do this.
Douglas Gregore7ab3662011-12-07 02:23:45 +00001287 if (File) {
Douglas Gregor59527662012-10-15 06:28:11 +00001288 if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
Douglas Gregor5257fc62011-11-11 21:55:48 +00001289 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
Douglas Gregor59527662012-10-15 06:28:11 +00001290 << FileName << OwningModule.getModule()->getFullModuleName();
Douglas Gregor5257fc62011-11-11 21:55:48 +00001291 HadError = true;
Douglas Gregor322f6332011-12-08 18:00:48 +00001292 } else if (Umbrella) {
1293 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor59527662012-10-15 06:28:11 +00001294 if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Douglas Gregor322f6332011-12-08 18:00:48 +00001295 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
Douglas Gregor59527662012-10-15 06:28:11 +00001296 << UmbrellaModule->getFullModuleName();
Douglas Gregor322f6332011-12-08 18:00:48 +00001297 HadError = true;
1298 } else {
1299 // Record this umbrella header.
1300 Map.setUmbrellaHeader(ActiveModule, File);
1301 }
Douglas Gregor5257fc62011-11-11 21:55:48 +00001302 } else {
Douglas Gregor322f6332011-12-08 18:00:48 +00001303 // Record this header.
Douglas Gregor59527662012-10-15 06:28:11 +00001304 Map.addHeader(ActiveModule, File, Exclude);
Douglas Gregor3ec66632012-02-02 18:42:48 +00001305
1306 // If there is a builtin counterpart to this file, add it now.
1307 if (BuiltinFile)
Douglas Gregor59527662012-10-15 06:28:11 +00001308 Map.addHeader(ActiveModule, BuiltinFile, Exclude);
Douglas Gregor5257fc62011-11-11 21:55:48 +00001309 }
Douglas Gregor4b27a642012-11-15 19:47:16 +00001310 } else if (!Exclude) {
1311 // Ignore excluded header files. They're optional anyway.
1312
Douglas Gregor5257fc62011-11-11 21:55:48 +00001313 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor524e33e2011-12-08 19:11:24 +00001314 << Umbrella << FileName;
Douglas Gregor5257fc62011-11-11 21:55:48 +00001315 HadError = true;
1316 }
Douglas Gregor718292f2011-11-11 19:10:28 +00001317}
1318
Douglas Gregor524e33e2011-12-08 19:11:24 +00001319/// \brief Parse an umbrella directory declaration.
1320///
1321/// umbrella-dir-declaration:
1322/// umbrella string-literal
1323void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1324 // Parse the directory name.
1325 if (!Tok.is(MMToken::StringLiteral)) {
1326 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1327 << "umbrella";
1328 HadError = true;
1329 return;
1330 }
1331
1332 std::string DirName = Tok.getString();
1333 SourceLocation DirNameLoc = consumeToken();
1334
1335 // Check whether we already have an umbrella.
1336 if (ActiveModule->Umbrella) {
1337 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1338 << ActiveModule->getFullModuleName();
1339 HadError = true;
1340 return;
1341 }
1342
1343 // Look for this file.
1344 const DirectoryEntry *Dir = 0;
1345 if (llvm::sys::path::is_absolute(DirName))
1346 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1347 else {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00001348 SmallString<128> PathName;
Douglas Gregor524e33e2011-12-08 19:11:24 +00001349 PathName = Directory->getName();
1350 llvm::sys::path::append(PathName, DirName);
1351 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1352 }
1353
1354 if (!Dir) {
1355 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1356 << DirName;
1357 HadError = true;
1358 return;
1359 }
1360
1361 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1362 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1363 << OwningModule->getFullModuleName();
1364 HadError = true;
1365 return;
1366 }
1367
1368 // Record this umbrella directory.
1369 Map.setUmbrellaDir(ActiveModule, Dir);
1370}
1371
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001372/// \brief Parse a module export declaration.
1373///
1374/// export-declaration:
1375/// 'export' wildcard-module-id
1376///
1377/// wildcard-module-id:
1378/// identifier
1379/// '*'
1380/// identifier '.' wildcard-module-id
1381void ModuleMapParser::parseExportDecl() {
1382 assert(Tok.is(MMToken::ExportKeyword));
1383 SourceLocation ExportLoc = consumeToken();
1384
1385 // Parse the module-id with an optional wildcard at the end.
1386 ModuleId ParsedModuleId;
1387 bool Wildcard = false;
1388 do {
1389 if (Tok.is(MMToken::Identifier)) {
1390 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1391 Tok.getLocation()));
1392 consumeToken();
1393
1394 if (Tok.is(MMToken::Period)) {
1395 consumeToken();
1396 continue;
1397 }
1398
1399 break;
1400 }
1401
1402 if(Tok.is(MMToken::Star)) {
1403 Wildcard = true;
Douglas Gregorf5eedd02011-12-05 17:28:06 +00001404 consumeToken();
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001405 break;
1406 }
1407
1408 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1409 HadError = true;
1410 return;
1411 } while (true);
1412
1413 Module::UnresolvedExportDecl Unresolved = {
1414 ExportLoc, ParsedModuleId, Wildcard
1415 };
1416 ActiveModule->UnresolvedExports.push_back(Unresolved);
1417}
1418
Douglas Gregor9194a912012-11-06 19:39:40 +00001419/// \brief Parse an inferried module declaration (wildcard modules).
1420///
1421/// module-declaration:
1422/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
1423/// { inferred-module-member* }
1424///
1425/// inferred-module-member:
1426/// 'export' '*'
1427/// 'exclude' identifier
1428void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Douglas Gregor73441092011-12-05 22:27:44 +00001429 assert(Tok.is(MMToken::Star));
1430 SourceLocation StarLoc = consumeToken();
1431 bool Failed = false;
Douglas Gregor9194a912012-11-06 19:39:40 +00001432
Douglas Gregor73441092011-12-05 22:27:44 +00001433 // Inferred modules must be submodules.
Douglas Gregor9194a912012-11-06 19:39:40 +00001434 if (!ActiveModule && !Framework) {
Douglas Gregor73441092011-12-05 22:27:44 +00001435 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1436 Failed = true;
1437 }
Douglas Gregor9194a912012-11-06 19:39:40 +00001438
1439 if (ActiveModule) {
1440 // Inferred modules must have umbrella directories.
1441 if (!Failed && !ActiveModule->getUmbrellaDir()) {
1442 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1443 Failed = true;
1444 }
1445
1446 // Check for redefinition of an inferred module.
1447 if (!Failed && ActiveModule->InferSubmodules) {
1448 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1449 if (ActiveModule->InferredSubmoduleLoc.isValid())
1450 Diags.Report(ActiveModule->InferredSubmoduleLoc,
1451 diag::note_mmap_prev_definition);
1452 Failed = true;
1453 }
1454
1455 // Check for the 'framework' keyword, which is not permitted here.
1456 if (Framework) {
1457 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
1458 Framework = false;
1459 }
1460 } else if (Explicit) {
1461 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
1462 Explicit = false;
Douglas Gregor73441092011-12-05 22:27:44 +00001463 }
Douglas Gregor9194a912012-11-06 19:39:40 +00001464
Douglas Gregor73441092011-12-05 22:27:44 +00001465 // If there were any problems with this inferred submodule, skip its body.
1466 if (Failed) {
1467 if (Tok.is(MMToken::LBrace)) {
1468 consumeToken();
1469 skipUntil(MMToken::RBrace);
1470 if (Tok.is(MMToken::RBrace))
1471 consumeToken();
1472 }
1473 HadError = true;
1474 return;
1475 }
Douglas Gregor9194a912012-11-06 19:39:40 +00001476
1477 // Parse optional attributes.
1478 Attributes Attrs;
1479 parseOptionalAttributes(Attrs);
1480
1481 if (ActiveModule) {
1482 // Note that we have an inferred submodule.
1483 ActiveModule->InferSubmodules = true;
1484 ActiveModule->InferredSubmoduleLoc = StarLoc;
1485 ActiveModule->InferExplicitSubmodules = Explicit;
1486 } else {
1487 // We'll be inferring framework modules for this directory.
1488 Map.InferredDirectories[Directory].InferModules = true;
1489 Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
1490 }
1491
Douglas Gregor73441092011-12-05 22:27:44 +00001492 // Parse the opening brace.
1493 if (!Tok.is(MMToken::LBrace)) {
1494 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1495 HadError = true;
1496 return;
1497 }
1498 SourceLocation LBraceLoc = consumeToken();
1499
1500 // Parse the body of the inferred submodule.
1501 bool Done = false;
1502 do {
1503 switch (Tok.Kind) {
1504 case MMToken::EndOfFile:
1505 case MMToken::RBrace:
1506 Done = true;
1507 break;
Douglas Gregor9194a912012-11-06 19:39:40 +00001508
1509 case MMToken::ExcludeKeyword: {
1510 if (ActiveModule) {
1511 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregor162405d2012-11-06 19:41:11 +00001512 << (ActiveModule != 0);
Douglas Gregor9194a912012-11-06 19:39:40 +00001513 consumeToken();
1514 break;
1515 }
1516
1517 consumeToken();
1518 if (!Tok.is(MMToken::Identifier)) {
1519 Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
1520 break;
1521 }
1522
1523 Map.InferredDirectories[Directory].ExcludedModules
1524 .push_back(Tok.getString());
1525 consumeToken();
1526 break;
1527 }
1528
1529 case MMToken::ExportKeyword:
1530 if (!ActiveModule) {
1531 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregor162405d2012-11-06 19:41:11 +00001532 << (ActiveModule != 0);
Douglas Gregor9194a912012-11-06 19:39:40 +00001533 consumeToken();
1534 break;
1535 }
1536
Douglas Gregor73441092011-12-05 22:27:44 +00001537 consumeToken();
1538 if (Tok.is(MMToken::Star))
Douglas Gregordd005f62011-12-06 17:34:58 +00001539 ActiveModule->InferExportWildcard = true;
Douglas Gregor73441092011-12-05 22:27:44 +00001540 else
1541 Diags.Report(Tok.getLocation(),
1542 diag::err_mmap_expected_export_wildcard);
1543 consumeToken();
1544 break;
Douglas Gregor9194a912012-11-06 19:39:40 +00001545
Douglas Gregor73441092011-12-05 22:27:44 +00001546 case MMToken::ExplicitKeyword:
1547 case MMToken::ModuleKeyword:
1548 case MMToken::HeaderKeyword:
1549 case MMToken::UmbrellaKeyword:
1550 default:
Douglas Gregor9194a912012-11-06 19:39:40 +00001551 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregor162405d2012-11-06 19:41:11 +00001552 << (ActiveModule != 0);
Douglas Gregor73441092011-12-05 22:27:44 +00001553 consumeToken();
1554 break;
1555 }
1556 } while (!Done);
1557
1558 if (Tok.is(MMToken::RBrace))
1559 consumeToken();
1560 else {
1561 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1562 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1563 HadError = true;
1564 }
1565}
1566
Douglas Gregor9194a912012-11-06 19:39:40 +00001567/// \brief Parse optional attributes.
1568///
1569/// attributes:
1570/// attribute attributes
1571/// attribute
1572///
1573/// attribute:
1574/// [ identifier ]
1575///
1576/// \param Attrs Will be filled in with the parsed attributes.
1577///
1578/// \returns true if an error occurred, false otherwise.
1579bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
1580 bool HadError = false;
1581
1582 while (Tok.is(MMToken::LSquare)) {
1583 // Consume the '['.
1584 SourceLocation LSquareLoc = consumeToken();
1585
1586 // Check whether we have an attribute name here.
1587 if (!Tok.is(MMToken::Identifier)) {
1588 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
1589 skipUntil(MMToken::RSquare);
1590 if (Tok.is(MMToken::RSquare))
1591 consumeToken();
1592 HadError = true;
1593 }
1594
1595 // Decode the attribute name.
1596 AttributeKind Attribute
1597 = llvm::StringSwitch<AttributeKind>(Tok.getString())
1598 .Case("system", AT_system)
1599 .Default(AT_unknown);
1600 switch (Attribute) {
1601 case AT_unknown:
1602 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
1603 << Tok.getString();
1604 break;
1605
1606 case AT_system:
1607 Attrs.IsSystem = true;
1608 break;
1609 }
1610 consumeToken();
1611
1612 // Consume the ']'.
1613 if (!Tok.is(MMToken::RSquare)) {
1614 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
1615 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
1616 skipUntil(MMToken::RSquare);
1617 HadError = true;
1618 }
1619
1620 if (Tok.is(MMToken::RSquare))
1621 consumeToken();
1622 }
1623
1624 return HadError;
1625}
1626
Douglas Gregor70331272011-12-09 02:04:43 +00001627/// \brief If there is a specific header search directory due the presence
1628/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1629const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1630 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1631 // If we have an umbrella directory, use that.
1632 if (Mod->hasUmbrellaDir())
1633 return Mod->getUmbrellaDir();
1634
1635 // If we have a framework directory, stop looking.
1636 if (Mod->IsFramework)
1637 return 0;
1638 }
1639
1640 return 0;
1641}
1642
Douglas Gregor718292f2011-11-11 19:10:28 +00001643/// \brief Parse a module map file.
1644///
1645/// module-map-file:
1646/// module-declaration*
1647bool ModuleMapParser::parseModuleMapFile() {
1648 do {
1649 switch (Tok.Kind) {
1650 case MMToken::EndOfFile:
1651 return HadError;
1652
Douglas Gregore7ab3662011-12-07 02:23:45 +00001653 case MMToken::ExplicitKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001654 case MMToken::ModuleKeyword:
Douglas Gregor755b2052011-11-17 22:09:43 +00001655 case MMToken::FrameworkKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001656 parseModuleDecl();
1657 break;
1658
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001659 case MMToken::Comma:
Douglas Gregor59527662012-10-15 06:28:11 +00001660 case MMToken::ExcludeKeyword:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001661 case MMToken::ExportKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001662 case MMToken::HeaderKeyword:
1663 case MMToken::Identifier:
1664 case MMToken::LBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +00001665 case MMToken::LSquare:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001666 case MMToken::Period:
Douglas Gregor718292f2011-11-11 19:10:28 +00001667 case MMToken::RBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +00001668 case MMToken::RSquare:
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001669 case MMToken::RequiresKeyword:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001670 case MMToken::Star:
Douglas Gregor718292f2011-11-11 19:10:28 +00001671 case MMToken::StringLiteral:
1672 case MMToken::UmbrellaKeyword:
1673 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1674 HadError = true;
1675 consumeToken();
1676 break;
1677 }
1678 } while (true);
Douglas Gregor718292f2011-11-11 19:10:28 +00001679}
1680
1681bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregor89929282012-01-30 06:01:29 +00001682 assert(Target != 0 && "Missing target information");
Douglas Gregor718292f2011-11-11 19:10:28 +00001683 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1684 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1685 if (!Buffer)
1686 return true;
1687
1688 // Parse this module map file.
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001689 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1690 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregorbc10b9f2012-10-15 16:45:32 +00001691 ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
Douglas Gregor3ec66632012-02-02 18:42:48 +00001692 BuiltinIncludeDir);
Douglas Gregor718292f2011-11-11 19:10:28 +00001693 bool Result = Parser.parseModuleMapFile();
1694 Diags->getClient()->EndSourceFile();
1695
1696 return Result;
1697}