blob: 8457b1cea93bb2870ba5db60e2d9c89151e515f4 [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"
15#include "clang/Lex/Lexer.h"
16#include "clang/Lex/LiteralSupport.h"
17#include "clang/Lex/LexDiagnostic.h"
18#include "clang/Basic/Diagnostic.h"
19#include "clang/Basic/FileManager.h"
20#include "clang/Basic/TargetInfo.h"
21#include "clang/Basic/TargetOptions.h"
22#include "llvm/Support/Allocator.h"
Douglas Gregorac252a32011-12-06 19:39:29 +000023#include "llvm/Support/FileSystem.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000024#include "llvm/Support/Host.h"
Douglas Gregor8b6d3de2011-11-11 21:55:48 +000025#include "llvm/Support/PathV2.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000026#include "llvm/Support/raw_ostream.h"
27#include "llvm/ADT/StringRef.h"
28#include "llvm/ADT/StringSwitch.h"
29using namespace clang;
30
Douglas Gregor90db2602011-12-02 01:47:07 +000031Module::ExportDecl
32ModuleMap::resolveExport(Module *Mod,
33 const Module::UnresolvedExportDecl &Unresolved,
34 bool Complain) {
Douglas Gregor0adaa882011-12-05 17:28:06 +000035 // We may have just a wildcard.
36 if (Unresolved.Id.empty()) {
37 assert(Unresolved.Wildcard && "Invalid unresolved export");
38 return Module::ExportDecl(0, true);
39 }
40
Douglas Gregor90db2602011-12-02 01:47:07 +000041 // Find the starting module.
42 Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
43 if (!Context) {
44 if (Complain)
45 Diags->Report(Unresolved.Id[0].second,
46 diag::err_mmap_missing_module_unqualified)
47 << Unresolved.Id[0].first << Mod->getFullModuleName();
48
49 return Module::ExportDecl();
50 }
51
52 // Dig into the module path.
53 for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
54 Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
55 Context);
56 if (!Sub) {
57 if (Complain)
58 Diags->Report(Unresolved.Id[I].second,
59 diag::err_mmap_missing_module_qualified)
60 << Unresolved.Id[I].first << Context->getFullModuleName()
61 << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
62
63 return Module::ExportDecl();
64 }
65
66 Context = Sub;
67 }
68
69 return Module::ExportDecl(Context, Unresolved.Wildcard);
70}
71
Douglas Gregora30cfe52011-11-11 19:10:28 +000072ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
73 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
74 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
75 new DiagnosticsEngine(DiagIDs));
76 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
77 SourceMgr = new SourceManager(*Diags, FileMgr);
78}
79
80ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +000081 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
82 IEnd = Modules.end();
83 I != IEnd; ++I) {
84 delete I->getValue();
85 }
86
Douglas Gregora30cfe52011-11-11 19:10:28 +000087 delete SourceMgr;
88}
89
Douglas Gregor1a4761e2011-11-30 23:21:26 +000090Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor65f3b5e2011-11-11 22:18:48 +000091 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
92 = Headers.find(File);
93 if (Known != Headers.end())
94 return Known->second;
95
Douglas Gregoradb97992011-11-16 23:02:25 +000096 const DirectoryEntry *Dir = File->getDir();
Douglas Gregoradb97992011-11-16 23:02:25 +000097 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
98 StringRef DirName = Dir->getName();
Douglas Gregore209e502011-12-06 01:10:29 +000099
100 // Keep walking up the directory hierarchy, looking for a directory with
101 // an umbrella header.
102 do {
103 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
104 = UmbrellaDirs.find(Dir);
105 if (KnownDir != UmbrellaDirs.end()) {
106 Module *Result = KnownDir->second;
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000107
108 // Search up the module stack until we find a module with an umbrella
Douglas Gregor10694ce2011-12-08 17:39:04 +0000109 // directory.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000110 Module *UmbrellaModule = Result;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000111 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000112 UmbrellaModule = UmbrellaModule->Parent;
113
114 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-12-06 01:10:29 +0000115 // Infer submodules for each of the directories we found between
116 // the directory of the umbrella header and the directory where
117 // the actual header is located.
118
119 // For a framework module, the umbrella directory is the framework
120 // directory, so strip off the "Headers" or "PrivateHeaders".
Douglas Gregor23af6d52011-12-07 22:05:21 +0000121 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregore209e502011-12-06 01:10:29 +0000122 unsigned LastSkippedDir = SkippedDirs.size();
Douglas Gregor23af6d52011-12-07 22:05:21 +0000123 if (LastSkippedDir && UmbrellaModule->IsFramework) {
124 if (llvm::sys::path::filename(SkippedDirs.back()->getName())
125 == "PrivateHeaders") {
126 // For private headers, add an explicit "Private" module.
127 // FIXME: This feels somewhat hackish. Do we want to introduce
128 // some kind of "umbrella directory" here?
129 Result = findOrCreateModule("Private", Result,
130 /*IsFramework=*/false,
131 /*IsExplicit=*/true).first;
132 Explicit = true;
133 }
134
Douglas Gregore209e502011-12-06 01:10:29 +0000135 --LastSkippedDir;
Douglas Gregor23af6d52011-12-07 22:05:21 +0000136 }
Douglas Gregore209e502011-12-06 01:10:29 +0000137
138 for (unsigned I = LastSkippedDir; I != 0; --I) {
139 // Find or create the module that corresponds to this directory name.
140 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
141 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000142 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000143
144 // Associate the module and the directory.
145 UmbrellaDirs[SkippedDirs[I-1]] = Result;
146
147 // If inferred submodules export everything they import, add a
148 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000149 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000150 Result->Exports.push_back(Module::ExportDecl(0, true));
151 }
152
153 // Infer a submodule with the same name as this header file.
154 StringRef Name = llvm::sys::path::stem(File->getName());
155 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000156 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000157
158 // If inferred submodules export everything they import, add a
159 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000160 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000161 Result->Exports.push_back(Module::ExportDecl(0, true));
162 } else {
163 // Record each of the directories we stepped through as being part of
164 // the module we found, since the umbrella header covers them all.
165 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
166 UmbrellaDirs[SkippedDirs[I]] = Result;
167 }
168
169 Headers[File] = Result;
170 return Result;
171 }
172
173 SkippedDirs.push_back(Dir);
174
Douglas Gregoradb97992011-11-16 23:02:25 +0000175 // Retrieve our parent path.
176 DirName = llvm::sys::path::parent_path(DirName);
177 if (DirName.empty())
178 break;
179
180 // Resolve the parent path to a directory entry.
181 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000182 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000183
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000184 return 0;
185}
186
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000187Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000188 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
189 if (Known != Modules.end())
190 return Known->getValue();
191
192 return 0;
193}
194
Douglas Gregor90db2602011-12-02 01:47:07 +0000195Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
196 for(; Context; Context = Context->Parent) {
197 if (Module *Sub = lookupModuleQualified(Name, Context))
198 return Sub;
199 }
200
201 return findModule(Name);
202}
203
204Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
205 if (!Context)
206 return findModule(Name);
207
208 llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
209 if (Sub != Context->SubModules.end())
210 return Sub->getValue();
211
212 return 0;
213}
214
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000215std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000216ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
217 bool IsExplicit) {
218 // Try to find an existing module with this name.
219 if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
220 return std::make_pair(Found, false);
221
222 // Create a new module with this name.
223 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
224 IsExplicit);
225 if (Parent)
226 Parent->SubModules[Name] = Result;
227 else
228 Modules[Name] = Result;
229 return std::make_pair(Result, true);
230}
231
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000232Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000233ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000234 const DirectoryEntry *FrameworkDir,
235 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000236 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000237 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
238 return Mod;
239
240 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000241
242 // Look for an umbrella header.
243 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
244 llvm::sys::path::append(UmbrellaName, "Headers");
245 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000246 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000247
248 // FIXME: If there's no umbrella header, we could probably scan the
249 // framework to load *everything*. But, it's not clear that this is a good
250 // idea.
251 if (!UmbrellaHeader)
252 return 0;
253
Douglas Gregorac252a32011-12-06 19:39:29 +0000254 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
255 /*IsFramework=*/true, /*IsExplicit=*/false);
256
257 if (Parent)
258 Parent->SubModules[ModuleName] = Result;
259 else
260 Modules[ModuleName] = Result;
261
Douglas Gregor209977c2011-12-05 17:40:25 +0000262 // umbrella "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000263 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000264 Headers[UmbrellaHeader] = Result;
265 UmbrellaDirs[FrameworkDir] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000266
267 // export *
268 Result->Exports.push_back(Module::ExportDecl(0, true));
269
Douglas Gregore209e502011-12-06 01:10:29 +0000270 // module * { export * }
271 Result->InferSubmodules = true;
272 Result->InferExportWildcard = true;
273
Douglas Gregorac252a32011-12-06 19:39:29 +0000274 // Look for subframeworks.
275 llvm::error_code EC;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000276 llvm::SmallString<128> SubframeworksDirName
277 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000278 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000279 llvm::SmallString<128> SubframeworksDirNameNative;
280 llvm::sys::path::native(SubframeworksDirName.str(),
281 SubframeworksDirNameNative);
282 for (llvm::sys::fs::directory_iterator
283 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregorac252a32011-12-06 19:39:29 +0000284 Dir != DirEnd && !EC; Dir.increment(EC)) {
285 if (!StringRef(Dir->path()).endswith(".framework"))
286 continue;
287
288 if (const DirectoryEntry *SubframeworkDir
289 = FileMgr.getDirectory(Dir->path())) {
290 // FIXME: Do we want to warn about subframeworks without umbrella headers?
291 inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
292 Result);
293 }
294 }
Douglas Gregord620a842011-12-06 17:16:41 +0000295
Douglas Gregor23af6d52011-12-07 22:05:21 +0000296 // Look for private headers.
297 Module *ModulePrivate = 0;
298 llvm::SmallString<128> PrivateHeadersDirName(FrameworkDir->getName());
299 llvm::sys::path::append(PrivateHeadersDirName, "PrivateHeaders");
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000300 llvm::SmallString<128> PrivateHeadersDirNameNative;
301 llvm::sys::path::native(PrivateHeadersDirName.str(),
302 PrivateHeadersDirNameNative);
303 for (llvm::sys::fs::directory_iterator
304 Dir(PrivateHeadersDirNameNative.str(), EC), DirEnd;
Douglas Gregor23af6d52011-12-07 22:05:21 +0000305 Dir != DirEnd && !EC; Dir.increment(EC)) {
306 // Check whether this entry has an extension typically associated with
307 // headers.
308 if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
309 .Cases(".h", ".H", ".hh", ".hpp", true)
310 .Default(false))
311 continue;
312
313 if (const FileEntry *PrivateHeader = FileMgr.getFile(Dir->path())) {
314 // Create the "private" submodule, if we haven't done so already.
315 if (!ModulePrivate) {
316 ModulePrivate = findOrCreateModule("Private", Result,
317 /*IsFramework=*/false,
318 /*IsExplicit=*/true).first;
319 }
320
321 Module *Sub = findOrCreateModule(llvm::sys::path::stem(Dir->path()),
322 ModulePrivate, /*IsFramework=*/false,
323 /*IsExplicit=*/true).first;
324 // header "the private header"
325 Sub->Headers.push_back(PrivateHeader);
326
327 // export *
328 Sub->Exports.push_back(Module::ExportDecl(0, true));
329
330 Headers[PrivateHeader] = Sub;
331 }
332 }
333
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000334 return Result;
335}
336
Douglas Gregore209e502011-12-06 01:10:29 +0000337void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
338 Headers[UmbrellaHeader] = Mod;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000339 Mod->Umbrella = UmbrellaHeader;
Douglas Gregore209e502011-12-06 01:10:29 +0000340
341 const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir();
342 if (Mod->IsFramework)
343 UmbrellaDir = SourceMgr->getFileManager().getDirectory(
344 llvm::sys::path::parent_path(UmbrellaDir->getName()));
345
346 UmbrellaDirs[UmbrellaDir] = Mod;
347}
348
349void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
350 Mod->Headers.push_back(Header);
351 Headers[Header] = Mod;
352}
353
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000354const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000355ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000356 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
357 return 0;
358
359 return SourceMgr->getFileEntryForID(
360 SourceMgr->getFileID(Module->DefinitionLoc));
361}
362
Douglas Gregora30cfe52011-11-11 19:10:28 +0000363void ModuleMap::dump() {
364 llvm::errs() << "Modules:";
365 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
366 MEnd = Modules.end();
367 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000368 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000369
370 llvm::errs() << "Headers:";
371 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
372 H = Headers.begin(),
373 HEnd = Headers.end();
374 H != HEnd; ++H) {
375 llvm::errs() << " \"" << H->first->getName() << "\" -> "
376 << H->second->getFullModuleName() << "\n";
377 }
378}
379
Douglas Gregor90db2602011-12-02 01:47:07 +0000380bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
381 bool HadError = false;
382 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
383 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
384 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000385 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000386 Mod->Exports.push_back(Export);
387 else
388 HadError = true;
389 }
390 Mod->UnresolvedExports.clear();
391 return HadError;
392}
393
Douglas Gregor55988682011-12-05 16:33:54 +0000394Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
395 if (Loc.isInvalid())
396 return 0;
397
398 // Use the expansion location to determine which module we're in.
399 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
400 if (!ExpansionLoc.isFileID())
401 return 0;
402
403
404 const SourceManager &SrcMgr = Loc.getManager();
405 FileID ExpansionFileID = ExpansionLoc.getFileID();
406 const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
407 if (!ExpansionFile)
408 return 0;
409
410 // Find the module that owns this header.
411 return findModuleForHeader(ExpansionFile);
412}
413
Douglas Gregora30cfe52011-11-11 19:10:28 +0000414//----------------------------------------------------------------------------//
415// Module map file parser
416//----------------------------------------------------------------------------//
417
418namespace clang {
419 /// \brief A token in a module map file.
420 struct MMToken {
421 enum TokenKind {
422 EndOfFile,
423 HeaderKeyword,
424 Identifier,
425 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000426 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000427 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000428 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000429 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000430 UmbrellaKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000431 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000432 StringLiteral,
433 LBrace,
434 RBrace
435 } Kind;
436
437 unsigned Location;
438 unsigned StringLength;
439 const char *StringData;
440
441 void clear() {
442 Kind = EndOfFile;
443 Location = 0;
444 StringLength = 0;
445 StringData = 0;
446 }
447
448 bool is(TokenKind K) const { return Kind == K; }
449
450 SourceLocation getLocation() const {
451 return SourceLocation::getFromRawEncoding(Location);
452 }
453
454 StringRef getString() const {
455 return StringRef(StringData, StringLength);
456 }
457 };
458
459 class ModuleMapParser {
460 Lexer &L;
461 SourceManager &SourceMgr;
462 DiagnosticsEngine &Diags;
463 ModuleMap &Map;
464
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000465 /// \brief The directory that this module map resides in.
466 const DirectoryEntry *Directory;
467
Douglas Gregora30cfe52011-11-11 19:10:28 +0000468 /// \brief Whether an error occurred.
469 bool HadError;
470
471 /// \brief Default target information, used only for string literal
472 /// parsing.
473 TargetInfo *Target;
474
475 /// \brief Stores string data for the various string literals referenced
476 /// during parsing.
477 llvm::BumpPtrAllocator StringData;
478
479 /// \brief The current token.
480 MMToken Tok;
481
482 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000483 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000484
485 /// \brief Consume the current token and return its location.
486 SourceLocation consumeToken();
487
488 /// \brief Skip tokens until we reach the a token with the given kind
489 /// (or the end of the file).
490 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000491
492 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
493 ModuleId;
494 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000495 void parseModuleDecl();
496 void parseUmbrellaDecl();
497 void parseHeaderDecl();
Douglas Gregor90db2602011-12-02 01:47:07 +0000498 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000499 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000500
501 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000502 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
503 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000504 ModuleMap &Map,
505 const DirectoryEntry *Directory)
506 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
507 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000508 {
509 TargetOptions TargetOpts;
510 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
511 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
512
513 Tok.clear();
514 consumeToken();
515 }
516
517 bool parseModuleMapFile();
518 };
519}
520
521SourceLocation ModuleMapParser::consumeToken() {
522retry:
523 SourceLocation Result = Tok.getLocation();
524 Tok.clear();
525
526 Token LToken;
527 L.LexFromRawLexer(LToken);
528 Tok.Location = LToken.getLocation().getRawEncoding();
529 switch (LToken.getKind()) {
530 case tok::raw_identifier:
531 Tok.StringData = LToken.getRawIdentifierData();
532 Tok.StringLength = LToken.getLength();
533 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
534 .Case("header", MMToken::HeaderKeyword)
535 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000536 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000537 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000538 .Case("module", MMToken::ModuleKeyword)
539 .Case("umbrella", MMToken::UmbrellaKeyword)
540 .Default(MMToken::Identifier);
541 break;
542
543 case tok::eof:
544 Tok.Kind = MMToken::EndOfFile;
545 break;
546
547 case tok::l_brace:
548 Tok.Kind = MMToken::LBrace;
549 break;
550
Douglas Gregor90db2602011-12-02 01:47:07 +0000551 case tok::period:
552 Tok.Kind = MMToken::Period;
553 break;
554
Douglas Gregora30cfe52011-11-11 19:10:28 +0000555 case tok::r_brace:
556 Tok.Kind = MMToken::RBrace;
557 break;
558
Douglas Gregor90db2602011-12-02 01:47:07 +0000559 case tok::star:
560 Tok.Kind = MMToken::Star;
561 break;
562
Douglas Gregora30cfe52011-11-11 19:10:28 +0000563 case tok::string_literal: {
564 // Parse the string literal.
565 LangOptions LangOpts;
566 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
567 if (StringLiteral.hadError)
568 goto retry;
569
570 // Copy the string literal into our string data allocator.
571 unsigned Length = StringLiteral.GetStringLength();
572 char *Saved = StringData.Allocate<char>(Length + 1);
573 memcpy(Saved, StringLiteral.GetString().data(), Length);
574 Saved[Length] = 0;
575
576 // Form the token.
577 Tok.Kind = MMToken::StringLiteral;
578 Tok.StringData = Saved;
579 Tok.StringLength = Length;
580 break;
581 }
582
583 case tok::comment:
584 goto retry;
585
586 default:
587 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
588 HadError = true;
589 goto retry;
590 }
591
592 return Result;
593}
594
595void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
596 unsigned braceDepth = 0;
597 do {
598 switch (Tok.Kind) {
599 case MMToken::EndOfFile:
600 return;
601
602 case MMToken::LBrace:
603 if (Tok.is(K) && braceDepth == 0)
604 return;
605
606 ++braceDepth;
607 break;
608
609 case MMToken::RBrace:
610 if (braceDepth > 0)
611 --braceDepth;
612 else if (Tok.is(K))
613 return;
614 break;
615
616 default:
617 if (braceDepth == 0 && Tok.is(K))
618 return;
619 break;
620 }
621
622 consumeToken();
623 } while (true);
624}
625
Douglas Gregor587986e2011-12-07 02:23:45 +0000626/// \brief Parse a module-id.
627///
628/// module-id:
629/// identifier
630/// identifier '.' module-id
631///
632/// \returns true if an error occurred, false otherwise.
633bool ModuleMapParser::parseModuleId(ModuleId &Id) {
634 Id.clear();
635 do {
636 if (Tok.is(MMToken::Identifier)) {
637 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
638 consumeToken();
639 } else {
640 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
641 return true;
642 }
643
644 if (!Tok.is(MMToken::Period))
645 break;
646
647 consumeToken();
648 } while (true);
649
650 return false;
651}
652
Douglas Gregora30cfe52011-11-11 19:10:28 +0000653/// \brief Parse a module declaration.
654///
655/// module-declaration:
Douglas Gregor587986e2011-12-07 02:23:45 +0000656/// 'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000657///
658/// module-member:
659/// umbrella-declaration
660/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000661/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000662/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000663///
664/// submodule-declaration:
665/// module-declaration
666/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000667void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000668 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
669 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000670 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000671 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000672 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000673 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000674
Douglas Gregord620a842011-12-06 17:16:41 +0000675 // Parse 'explicit' keyword, if present.
676 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000677 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000678 Explicit = true;
679 }
680
681 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000682 if (Tok.is(MMToken::FrameworkKeyword)) {
683 consumeToken();
684 Framework = true;
685 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000686
687 // Parse 'module' keyword.
688 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000689 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000690 consumeToken();
691 HadError = true;
692 return;
693 }
694 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000695
696 // If we have a wildcard for the module name, this is an inferred submodule.
697 // Parse it.
698 if (Tok.is(MMToken::Star))
699 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000700
701 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000702 ModuleId Id;
703 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000704 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000705 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000706 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000707
708 if (ActiveModule) {
709 if (Id.size() > 1) {
710 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
711 << SourceRange(Id.front().second, Id.back().second);
712
713 HadError = true;
714 return;
715 }
716 } else if (Id.size() == 1 && Explicit) {
717 // Top-level modules can't be explicit.
718 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
719 Explicit = false;
720 ExplicitLoc = SourceLocation();
721 HadError = true;
722 }
723
724 Module *PreviousActiveModule = ActiveModule;
725 if (Id.size() > 1) {
726 // This module map defines a submodule. Go find the module of which it
727 // is a submodule.
728 ActiveModule = 0;
729 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
730 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
731 ActiveModule = Next;
732 continue;
733 }
734
735 if (ActiveModule) {
736 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
737 << Id[I].first << ActiveModule->getTopLevelModule();
738 } else {
739 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
740 }
741 HadError = true;
742 return;
743 }
744 }
745
746 StringRef ModuleName = Id.back().first;
747 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000748
749 // Parse the opening brace.
750 if (!Tok.is(MMToken::LBrace)) {
751 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
752 << ModuleName;
753 HadError = true;
754 return;
755 }
756 SourceLocation LBraceLoc = consumeToken();
757
758 // Determine whether this (sub)module has already been defined.
759 llvm::StringMap<Module *> &ModuleSpace
760 = ActiveModule? ActiveModule->SubModules : Map.Modules;
761 llvm::StringMap<Module *>::iterator ExistingModule
762 = ModuleSpace.find(ModuleName);
763 if (ExistingModule != ModuleSpace.end()) {
764 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
765 << ModuleName;
766 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
767 diag::note_mmap_prev_definition);
768
769 // Skip the module definition.
770 skipUntil(MMToken::RBrace);
771 if (Tok.is(MMToken::RBrace))
772 consumeToken();
773
774 HadError = true;
775 return;
776 }
777
778 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000779 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
780 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000781 ModuleSpace[ModuleName] = ActiveModule;
782
783 bool Done = false;
784 do {
785 switch (Tok.Kind) {
786 case MMToken::EndOfFile:
787 case MMToken::RBrace:
788 Done = true;
789 break;
790
791 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000792 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000793 case MMToken::ModuleKeyword:
794 parseModuleDecl();
795 break;
796
Douglas Gregor90db2602011-12-02 01:47:07 +0000797 case MMToken::ExportKeyword:
798 parseExportDecl();
799 break;
800
Douglas Gregora30cfe52011-11-11 19:10:28 +0000801 case MMToken::HeaderKeyword:
802 parseHeaderDecl();
803 break;
804
805 case MMToken::UmbrellaKeyword:
806 parseUmbrellaDecl();
807 break;
Douglas Gregor90db2602011-12-02 01:47:07 +0000808
Douglas Gregora30cfe52011-11-11 19:10:28 +0000809 default:
810 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
811 consumeToken();
812 break;
813 }
814 } while (!Done);
815
816 if (Tok.is(MMToken::RBrace))
817 consumeToken();
818 else {
819 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
820 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
821 HadError = true;
822 }
823
Douglas Gregor587986e2011-12-07 02:23:45 +0000824 // We're done parsing this module. Pop back to the previous module.
825 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000826}
Douglas Gregord620a842011-12-06 17:16:41 +0000827
828/// \brief Append to \p Paths the set of paths needed to get to the
829/// subframework in which the given module lives.
830void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
831 // Collect the framework names from the given module to the top-level module.
832 llvm::SmallVector<StringRef, 2> Paths;
833 for (; Mod; Mod = Mod->Parent) {
834 if (Mod->IsFramework)
835 Paths.push_back(Mod->Name);
836 }
837
838 if (Paths.empty())
839 return;
840
841 // Add Frameworks/Name.framework for each subframework.
842 for (unsigned I = Paths.size() - 1; I != 0; --I) {
843 llvm::sys::path::append(Path, "Frameworks");
844 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
845 }
846}
847
Douglas Gregora30cfe52011-11-11 19:10:28 +0000848/// \brief Parse an umbrella header declaration.
849///
850/// umbrella-declaration:
851/// 'umbrella' string-literal
852void ModuleMapParser::parseUmbrellaDecl() {
853 assert(Tok.is(MMToken::UmbrellaKeyword));
854 SourceLocation UmbrellaLoc = consumeToken();
855
856 // Parse the header name.
857 if (!Tok.is(MMToken::StringLiteral)) {
858 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
859 << "umbrella";
860 HadError = true;
861 return;
862 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000863 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000864 SourceLocation FileNameLoc = consumeToken();
865
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000866 // Check whether we already have an umbrella header.
Douglas Gregor10694ce2011-12-08 17:39:04 +0000867 if (ActiveModule->getUmbrellaHeader()) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000868 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
869 << ActiveModule->getFullModuleName()
Douglas Gregor10694ce2011-12-08 17:39:04 +0000870 << ActiveModule->getUmbrellaHeader()->getName();
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000871 HadError = true;
872 return;
873 }
874
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000875 // Look for this file.
876 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000877 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000878
879 if (llvm::sys::path::is_absolute(FileName)) {
880 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000881 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000882 } else {
883 // Search for the header file within the search directory.
884 PathName += Directory->getName();
885 unsigned PathLength = PathName.size();
Douglas Gregord620a842011-12-06 17:16:41 +0000886
Douglas Gregor18ee5472011-11-29 21:59:16 +0000887 if (ActiveModule->isPartOfFramework()) {
Douglas Gregord620a842011-12-06 17:16:41 +0000888 appendSubframeworkPaths(ActiveModule, PathName);
889
Douglas Gregor18ee5472011-11-29 21:59:16 +0000890 // Check whether this file is in the public headers.
891 llvm::sys::path::append(PathName, "Headers");
892 llvm::sys::path::append(PathName, FileName);
893 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000894
Douglas Gregor18ee5472011-11-29 21:59:16 +0000895 if (!File) {
896 // Check whether this file is in the private headers.
897 PathName.resize(PathLength);
898 llvm::sys::path::append(PathName, "PrivateHeaders");
899 llvm::sys::path::append(PathName, FileName);
900 File = SourceMgr.getFileManager().getFile(PathName);
901 }
Douglas Gregor18ee5472011-11-29 21:59:16 +0000902 } else {
903 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000904 llvm::sys::path::append(PathName, FileName);
905 File = SourceMgr.getFileManager().getFile(PathName);
906 }
Douglas Gregora8654052011-11-17 22:09:43 +0000907 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000908
909 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
910 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000911 if (File) {
Douglas Gregore209e502011-12-06 01:10:29 +0000912 const DirectoryEntry *UmbrellaDir = File->getDir();
913 if (ActiveModule->IsFramework) {
914 // For framework modules, use the framework directory as the umbrella
915 // directory.
916 UmbrellaDir = SourceMgr.getFileManager().getDirectory(
917 llvm::sys::path::parent_path(UmbrellaDir->getName()));
918 }
919
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000920 if (const Module *OwningModule = Map.Headers[File]) {
921 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
922 << FileName << OwningModule->getFullModuleName();
923 HadError = true;
Douglas Gregore209e502011-12-06 01:10:29 +0000924 } else if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
Douglas Gregoradb97992011-11-16 23:02:25 +0000925 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
926 << OwningModule->getFullModuleName();
927 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000928 } else {
929 // Record this umbrella header.
Douglas Gregore209e502011-12-06 01:10:29 +0000930 Map.setUmbrellaHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000931 }
932 } else {
933 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
934 << true << FileName;
935 HadError = true;
936 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000937}
938
939/// \brief Parse a header declaration.
940///
941/// header-declaration:
942/// 'header' string-literal
943void ModuleMapParser::parseHeaderDecl() {
944 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000945 consumeToken();
946
Douglas Gregora30cfe52011-11-11 19:10:28 +0000947 // Parse the header name.
948 if (!Tok.is(MMToken::StringLiteral)) {
949 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
950 << "header";
951 HadError = true;
952 return;
953 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000954 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000955 SourceLocation FileNameLoc = consumeToken();
956
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000957 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +0000958 const FileEntry *File = 0;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000959 llvm::SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +0000960 if (llvm::sys::path::is_absolute(FileName)) {
961 PathName = FileName;
962 File = SourceMgr.getFileManager().getFile(PathName);
963 } else {
964 // Search for the header file within the search directory.
Douglas Gregor18ee5472011-11-29 21:59:16 +0000965 PathName += Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +0000966 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +0000967
Douglas Gregord620a842011-12-06 17:16:41 +0000968 if (ActiveModule->isPartOfFramework()) {
969 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +0000970
971 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +0000972 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +0000973 llvm::sys::path::append(PathName, FileName);
974 File = SourceMgr.getFileManager().getFile(PathName);
975
976 if (!File) {
977 // Check whether this file is in the private headers.
978 PathName.resize(PathLength);
979 llvm::sys::path::append(PathName, "PrivateHeaders");
980 llvm::sys::path::append(PathName, FileName);
981 File = SourceMgr.getFileManager().getFile(PathName);
982 }
983 } else {
984 // Lookup for normal headers.
985 llvm::sys::path::append(PathName, FileName);
986 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregord620a842011-12-06 17:16:41 +0000987 }
Douglas Gregor18ee5472011-11-29 21:59:16 +0000988 }
Douglas Gregora8654052011-11-17 22:09:43 +0000989
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000990 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
991 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +0000992 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000993 if (const Module *OwningModule = Map.Headers[File]) {
994 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
995 << FileName << OwningModule->getFullModuleName();
996 HadError = true;
997 } else {
998 // Record this file.
Douglas Gregore209e502011-12-06 01:10:29 +0000999 Map.addHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001000 }
1001 } else {
1002 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
1003 << false << FileName;
1004 HadError = true;
1005 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001006}
1007
Douglas Gregor90db2602011-12-02 01:47:07 +00001008/// \brief Parse a module export declaration.
1009///
1010/// export-declaration:
1011/// 'export' wildcard-module-id
1012///
1013/// wildcard-module-id:
1014/// identifier
1015/// '*'
1016/// identifier '.' wildcard-module-id
1017void ModuleMapParser::parseExportDecl() {
1018 assert(Tok.is(MMToken::ExportKeyword));
1019 SourceLocation ExportLoc = consumeToken();
1020
1021 // Parse the module-id with an optional wildcard at the end.
1022 ModuleId ParsedModuleId;
1023 bool Wildcard = false;
1024 do {
1025 if (Tok.is(MMToken::Identifier)) {
1026 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1027 Tok.getLocation()));
1028 consumeToken();
1029
1030 if (Tok.is(MMToken::Period)) {
1031 consumeToken();
1032 continue;
1033 }
1034
1035 break;
1036 }
1037
1038 if(Tok.is(MMToken::Star)) {
1039 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001040 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001041 break;
1042 }
1043
1044 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1045 HadError = true;
1046 return;
1047 } while (true);
1048
1049 Module::UnresolvedExportDecl Unresolved = {
1050 ExportLoc, ParsedModuleId, Wildcard
1051 };
1052 ActiveModule->UnresolvedExports.push_back(Unresolved);
1053}
1054
Douglas Gregor1e123682011-12-05 22:27:44 +00001055void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1056 assert(Tok.is(MMToken::Star));
1057 SourceLocation StarLoc = consumeToken();
1058 bool Failed = false;
1059
1060 // Inferred modules must be submodules.
1061 if (!ActiveModule) {
1062 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1063 Failed = true;
1064 }
1065
1066 // Inferred modules must have umbrella headers.
Douglas Gregor10694ce2011-12-08 17:39:04 +00001067 if (!Failed && !ActiveModule->getUmbrellaHeader()) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001068 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1069 Failed = true;
1070 }
1071
1072 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +00001073 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001074 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +00001075 if (ActiveModule->InferredSubmoduleLoc.isValid())
1076 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +00001077 diag::note_mmap_prev_definition);
1078 Failed = true;
1079 }
1080
1081 // If there were any problems with this inferred submodule, skip its body.
1082 if (Failed) {
1083 if (Tok.is(MMToken::LBrace)) {
1084 consumeToken();
1085 skipUntil(MMToken::RBrace);
1086 if (Tok.is(MMToken::RBrace))
1087 consumeToken();
1088 }
1089 HadError = true;
1090 return;
1091 }
1092
1093 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +00001094 ActiveModule->InferSubmodules = true;
1095 ActiveModule->InferredSubmoduleLoc = StarLoc;
1096 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +00001097
1098 // Parse the opening brace.
1099 if (!Tok.is(MMToken::LBrace)) {
1100 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1101 HadError = true;
1102 return;
1103 }
1104 SourceLocation LBraceLoc = consumeToken();
1105
1106 // Parse the body of the inferred submodule.
1107 bool Done = false;
1108 do {
1109 switch (Tok.Kind) {
1110 case MMToken::EndOfFile:
1111 case MMToken::RBrace:
1112 Done = true;
1113 break;
1114
1115 case MMToken::ExportKeyword: {
1116 consumeToken();
1117 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001118 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001119 else
1120 Diags.Report(Tok.getLocation(),
1121 diag::err_mmap_expected_export_wildcard);
1122 consumeToken();
1123 break;
1124 }
1125
1126 case MMToken::ExplicitKeyword:
1127 case MMToken::ModuleKeyword:
1128 case MMToken::HeaderKeyword:
1129 case MMToken::UmbrellaKeyword:
1130 default:
1131 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1132 consumeToken();
1133 break;
1134 }
1135 } while (!Done);
1136
1137 if (Tok.is(MMToken::RBrace))
1138 consumeToken();
1139 else {
1140 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1141 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1142 HadError = true;
1143 }
1144}
1145
Douglas Gregora30cfe52011-11-11 19:10:28 +00001146/// \brief Parse a module map file.
1147///
1148/// module-map-file:
1149/// module-declaration*
1150bool ModuleMapParser::parseModuleMapFile() {
1151 do {
1152 switch (Tok.Kind) {
1153 case MMToken::EndOfFile:
1154 return HadError;
1155
Douglas Gregor587986e2011-12-07 02:23:45 +00001156 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001157 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001158 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001159 parseModuleDecl();
1160 break;
1161
Douglas Gregor90db2602011-12-02 01:47:07 +00001162 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001163 case MMToken::HeaderKeyword:
1164 case MMToken::Identifier:
1165 case MMToken::LBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001166 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001167 case MMToken::RBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001168 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001169 case MMToken::StringLiteral:
1170 case MMToken::UmbrellaKeyword:
1171 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1172 HadError = true;
1173 consumeToken();
1174 break;
1175 }
1176 } while (true);
1177
1178 return HadError;
1179}
1180
1181bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
1182 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1183 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1184 if (!Buffer)
1185 return true;
1186
1187 // Parse this module map file.
1188 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
1189 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001190 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001191 bool Result = Parser.parseModuleMapFile();
1192 Diags->getClient()->EndSourceFile();
1193
1194 return Result;
1195}