blob: f6df30200733e341af6a843a2199809685441bd2 [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
109 // header.
110 Module *UmbrellaModule = Result;
111 while (!UmbrellaModule->UmbrellaHeader && UmbrellaModule->Parent)
112 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".
121 // FIXME: Should we tack on an "explicit" for PrivateHeaders? That
122 // might be what we want, but it feels like a hack.
123 unsigned LastSkippedDir = SkippedDirs.size();
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000124 if (LastSkippedDir && UmbrellaModule->IsFramework)
Douglas Gregore209e502011-12-06 01:10:29 +0000125 --LastSkippedDir;
126
127 for (unsigned I = LastSkippedDir; I != 0; --I) {
128 // Find or create the module that corresponds to this directory name.
129 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
130 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000131 UmbrellaModule->InferExplicitSubmodules).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000132
133 // Associate the module and the directory.
134 UmbrellaDirs[SkippedDirs[I-1]] = Result;
135
136 // If inferred submodules export everything they import, add a
137 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000138 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000139 Result->Exports.push_back(Module::ExportDecl(0, true));
140 }
141
142 // Infer a submodule with the same name as this header file.
143 StringRef Name = llvm::sys::path::stem(File->getName());
144 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000145 UmbrellaModule->InferExplicitSubmodules).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000146
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 } else {
152 // Record each of the directories we stepped through as being part of
153 // the module we found, since the umbrella header covers them all.
154 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
155 UmbrellaDirs[SkippedDirs[I]] = Result;
156 }
157
158 Headers[File] = Result;
159 return Result;
160 }
161
162 SkippedDirs.push_back(Dir);
163
Douglas Gregoradb97992011-11-16 23:02:25 +0000164 // Retrieve our parent path.
165 DirName = llvm::sys::path::parent_path(DirName);
166 if (DirName.empty())
167 break;
168
169 // Resolve the parent path to a directory entry.
170 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000171 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000172
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000173 return 0;
174}
175
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000176Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000177 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
178 if (Known != Modules.end())
179 return Known->getValue();
180
181 return 0;
182}
183
Douglas Gregor90db2602011-12-02 01:47:07 +0000184Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
185 for(; Context; Context = Context->Parent) {
186 if (Module *Sub = lookupModuleQualified(Name, Context))
187 return Sub;
188 }
189
190 return findModule(Name);
191}
192
193Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
194 if (!Context)
195 return findModule(Name);
196
197 llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
198 if (Sub != Context->SubModules.end())
199 return Sub->getValue();
200
201 return 0;
202}
203
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000204std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000205ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
206 bool IsExplicit) {
207 // Try to find an existing module with this name.
208 if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
209 return std::make_pair(Found, false);
210
211 // Create a new module with this name.
212 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
213 IsExplicit);
214 if (Parent)
215 Parent->SubModules[Name] = Result;
216 else
217 Modules[Name] = Result;
218 return std::make_pair(Result, true);
219}
220
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000221Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000222ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000223 const DirectoryEntry *FrameworkDir,
224 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000225 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000226 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
227 return Mod;
228
229 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000230
231 // Look for an umbrella header.
232 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
233 llvm::sys::path::append(UmbrellaName, "Headers");
234 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000235 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000236
237 // FIXME: If there's no umbrella header, we could probably scan the
238 // framework to load *everything*. But, it's not clear that this is a good
239 // idea.
240 if (!UmbrellaHeader)
241 return 0;
242
Douglas Gregorac252a32011-12-06 19:39:29 +0000243 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
244 /*IsFramework=*/true, /*IsExplicit=*/false);
245
246 if (Parent)
247 Parent->SubModules[ModuleName] = Result;
248 else
249 Modules[ModuleName] = Result;
250
Douglas Gregor209977c2011-12-05 17:40:25 +0000251 // umbrella "umbrella-header-name"
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000252 Result->UmbrellaHeader = UmbrellaHeader;
253 Headers[UmbrellaHeader] = Result;
254 UmbrellaDirs[FrameworkDir] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000255
256 // export *
257 Result->Exports.push_back(Module::ExportDecl(0, true));
258
Douglas Gregore209e502011-12-06 01:10:29 +0000259 // module * { export * }
260 Result->InferSubmodules = true;
261 Result->InferExportWildcard = true;
262
Douglas Gregorac252a32011-12-06 19:39:29 +0000263 // Look for subframeworks.
264 llvm::error_code EC;
265 llvm::SmallString<128> SubframeworksDirName = StringRef(FrameworkDir->getName());
266 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
267 for (llvm::sys::fs::directory_iterator Dir(SubframeworksDirName.str(), EC),
268 DirEnd;
269 Dir != DirEnd && !EC; Dir.increment(EC)) {
270 if (!StringRef(Dir->path()).endswith(".framework"))
271 continue;
272
273 if (const DirectoryEntry *SubframeworkDir
274 = FileMgr.getDirectory(Dir->path())) {
275 // FIXME: Do we want to warn about subframeworks without umbrella headers?
276 inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
277 Result);
278 }
279 }
Douglas Gregord620a842011-12-06 17:16:41 +0000280
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000281 return Result;
282}
283
Douglas Gregore209e502011-12-06 01:10:29 +0000284void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
285 Headers[UmbrellaHeader] = Mod;
286 Mod->UmbrellaHeader = UmbrellaHeader;
287
288 const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir();
289 if (Mod->IsFramework)
290 UmbrellaDir = SourceMgr->getFileManager().getDirectory(
291 llvm::sys::path::parent_path(UmbrellaDir->getName()));
292
293 UmbrellaDirs[UmbrellaDir] = Mod;
294}
295
296void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
297 Mod->Headers.push_back(Header);
298 Headers[Header] = Mod;
299}
300
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000301const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000302ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000303 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
304 return 0;
305
306 return SourceMgr->getFileEntryForID(
307 SourceMgr->getFileID(Module->DefinitionLoc));
308}
309
Douglas Gregora30cfe52011-11-11 19:10:28 +0000310void ModuleMap::dump() {
311 llvm::errs() << "Modules:";
312 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
313 MEnd = Modules.end();
314 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000315 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000316
317 llvm::errs() << "Headers:";
318 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
319 H = Headers.begin(),
320 HEnd = Headers.end();
321 H != HEnd; ++H) {
322 llvm::errs() << " \"" << H->first->getName() << "\" -> "
323 << H->second->getFullModuleName() << "\n";
324 }
325}
326
Douglas Gregor90db2602011-12-02 01:47:07 +0000327bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
328 bool HadError = false;
329 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
330 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
331 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000332 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000333 Mod->Exports.push_back(Export);
334 else
335 HadError = true;
336 }
337 Mod->UnresolvedExports.clear();
338 return HadError;
339}
340
Douglas Gregor55988682011-12-05 16:33:54 +0000341Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
342 if (Loc.isInvalid())
343 return 0;
344
345 // Use the expansion location to determine which module we're in.
346 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
347 if (!ExpansionLoc.isFileID())
348 return 0;
349
350
351 const SourceManager &SrcMgr = Loc.getManager();
352 FileID ExpansionFileID = ExpansionLoc.getFileID();
353 const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
354 if (!ExpansionFile)
355 return 0;
356
357 // Find the module that owns this header.
358 return findModuleForHeader(ExpansionFile);
359}
360
Douglas Gregora30cfe52011-11-11 19:10:28 +0000361//----------------------------------------------------------------------------//
362// Module map file parser
363//----------------------------------------------------------------------------//
364
365namespace clang {
366 /// \brief A token in a module map file.
367 struct MMToken {
368 enum TokenKind {
369 EndOfFile,
370 HeaderKeyword,
371 Identifier,
372 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000373 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000374 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000375 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000376 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000377 UmbrellaKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000378 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000379 StringLiteral,
380 LBrace,
381 RBrace
382 } Kind;
383
384 unsigned Location;
385 unsigned StringLength;
386 const char *StringData;
387
388 void clear() {
389 Kind = EndOfFile;
390 Location = 0;
391 StringLength = 0;
392 StringData = 0;
393 }
394
395 bool is(TokenKind K) const { return Kind == K; }
396
397 SourceLocation getLocation() const {
398 return SourceLocation::getFromRawEncoding(Location);
399 }
400
401 StringRef getString() const {
402 return StringRef(StringData, StringLength);
403 }
404 };
405
406 class ModuleMapParser {
407 Lexer &L;
408 SourceManager &SourceMgr;
409 DiagnosticsEngine &Diags;
410 ModuleMap &Map;
411
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000412 /// \brief The directory that this module map resides in.
413 const DirectoryEntry *Directory;
414
Douglas Gregora30cfe52011-11-11 19:10:28 +0000415 /// \brief Whether an error occurred.
416 bool HadError;
417
418 /// \brief Default target information, used only for string literal
419 /// parsing.
420 TargetInfo *Target;
421
422 /// \brief Stores string data for the various string literals referenced
423 /// during parsing.
424 llvm::BumpPtrAllocator StringData;
425
426 /// \brief The current token.
427 MMToken Tok;
428
429 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000430 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000431
432 /// \brief Consume the current token and return its location.
433 SourceLocation consumeToken();
434
435 /// \brief Skip tokens until we reach the a token with the given kind
436 /// (or the end of the file).
437 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000438
439 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
440 ModuleId;
441 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000442 void parseModuleDecl();
443 void parseUmbrellaDecl();
444 void parseHeaderDecl();
Douglas Gregor90db2602011-12-02 01:47:07 +0000445 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000446 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000447
448 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000449 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
450 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000451 ModuleMap &Map,
452 const DirectoryEntry *Directory)
453 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
454 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000455 {
456 TargetOptions TargetOpts;
457 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
458 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
459
460 Tok.clear();
461 consumeToken();
462 }
463
464 bool parseModuleMapFile();
465 };
466}
467
468SourceLocation ModuleMapParser::consumeToken() {
469retry:
470 SourceLocation Result = Tok.getLocation();
471 Tok.clear();
472
473 Token LToken;
474 L.LexFromRawLexer(LToken);
475 Tok.Location = LToken.getLocation().getRawEncoding();
476 switch (LToken.getKind()) {
477 case tok::raw_identifier:
478 Tok.StringData = LToken.getRawIdentifierData();
479 Tok.StringLength = LToken.getLength();
480 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
481 .Case("header", MMToken::HeaderKeyword)
482 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000483 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000484 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000485 .Case("module", MMToken::ModuleKeyword)
486 .Case("umbrella", MMToken::UmbrellaKeyword)
487 .Default(MMToken::Identifier);
488 break;
489
490 case tok::eof:
491 Tok.Kind = MMToken::EndOfFile;
492 break;
493
494 case tok::l_brace:
495 Tok.Kind = MMToken::LBrace;
496 break;
497
Douglas Gregor90db2602011-12-02 01:47:07 +0000498 case tok::period:
499 Tok.Kind = MMToken::Period;
500 break;
501
Douglas Gregora30cfe52011-11-11 19:10:28 +0000502 case tok::r_brace:
503 Tok.Kind = MMToken::RBrace;
504 break;
505
Douglas Gregor90db2602011-12-02 01:47:07 +0000506 case tok::star:
507 Tok.Kind = MMToken::Star;
508 break;
509
Douglas Gregora30cfe52011-11-11 19:10:28 +0000510 case tok::string_literal: {
511 // Parse the string literal.
512 LangOptions LangOpts;
513 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
514 if (StringLiteral.hadError)
515 goto retry;
516
517 // Copy the string literal into our string data allocator.
518 unsigned Length = StringLiteral.GetStringLength();
519 char *Saved = StringData.Allocate<char>(Length + 1);
520 memcpy(Saved, StringLiteral.GetString().data(), Length);
521 Saved[Length] = 0;
522
523 // Form the token.
524 Tok.Kind = MMToken::StringLiteral;
525 Tok.StringData = Saved;
526 Tok.StringLength = Length;
527 break;
528 }
529
530 case tok::comment:
531 goto retry;
532
533 default:
534 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
535 HadError = true;
536 goto retry;
537 }
538
539 return Result;
540}
541
542void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
543 unsigned braceDepth = 0;
544 do {
545 switch (Tok.Kind) {
546 case MMToken::EndOfFile:
547 return;
548
549 case MMToken::LBrace:
550 if (Tok.is(K) && braceDepth == 0)
551 return;
552
553 ++braceDepth;
554 break;
555
556 case MMToken::RBrace:
557 if (braceDepth > 0)
558 --braceDepth;
559 else if (Tok.is(K))
560 return;
561 break;
562
563 default:
564 if (braceDepth == 0 && Tok.is(K))
565 return;
566 break;
567 }
568
569 consumeToken();
570 } while (true);
571}
572
Douglas Gregor587986e2011-12-07 02:23:45 +0000573/// \brief Parse a module-id.
574///
575/// module-id:
576/// identifier
577/// identifier '.' module-id
578///
579/// \returns true if an error occurred, false otherwise.
580bool ModuleMapParser::parseModuleId(ModuleId &Id) {
581 Id.clear();
582 do {
583 if (Tok.is(MMToken::Identifier)) {
584 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
585 consumeToken();
586 } else {
587 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
588 return true;
589 }
590
591 if (!Tok.is(MMToken::Period))
592 break;
593
594 consumeToken();
595 } while (true);
596
597 return false;
598}
599
Douglas Gregora30cfe52011-11-11 19:10:28 +0000600/// \brief Parse a module declaration.
601///
602/// module-declaration:
Douglas Gregor587986e2011-12-07 02:23:45 +0000603/// 'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000604///
605/// module-member:
606/// umbrella-declaration
607/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000608/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000609/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000610///
611/// submodule-declaration:
612/// module-declaration
613/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000614void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000615 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
616 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000617 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000618 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000619 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000620 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000621
Douglas Gregord620a842011-12-06 17:16:41 +0000622 // Parse 'explicit' keyword, if present.
623 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000624 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000625 Explicit = true;
626 }
627
628 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000629 if (Tok.is(MMToken::FrameworkKeyword)) {
630 consumeToken();
631 Framework = true;
632 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000633
634 // Parse 'module' keyword.
635 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000636 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000637 consumeToken();
638 HadError = true;
639 return;
640 }
641 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000642
643 // If we have a wildcard for the module name, this is an inferred submodule.
644 // Parse it.
645 if (Tok.is(MMToken::Star))
646 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000647
648 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000649 ModuleId Id;
650 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000651 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000652 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000653 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000654
655 if (ActiveModule) {
656 if (Id.size() > 1) {
657 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
658 << SourceRange(Id.front().second, Id.back().second);
659
660 HadError = true;
661 return;
662 }
663 } else if (Id.size() == 1 && Explicit) {
664 // Top-level modules can't be explicit.
665 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
666 Explicit = false;
667 ExplicitLoc = SourceLocation();
668 HadError = true;
669 }
670
671 Module *PreviousActiveModule = ActiveModule;
672 if (Id.size() > 1) {
673 // This module map defines a submodule. Go find the module of which it
674 // is a submodule.
675 ActiveModule = 0;
676 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
677 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
678 ActiveModule = Next;
679 continue;
680 }
681
682 if (ActiveModule) {
683 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
684 << Id[I].first << ActiveModule->getTopLevelModule();
685 } else {
686 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
687 }
688 HadError = true;
689 return;
690 }
691 }
692
693 StringRef ModuleName = Id.back().first;
694 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000695
696 // Parse the opening brace.
697 if (!Tok.is(MMToken::LBrace)) {
698 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
699 << ModuleName;
700 HadError = true;
701 return;
702 }
703 SourceLocation LBraceLoc = consumeToken();
704
705 // Determine whether this (sub)module has already been defined.
706 llvm::StringMap<Module *> &ModuleSpace
707 = ActiveModule? ActiveModule->SubModules : Map.Modules;
708 llvm::StringMap<Module *>::iterator ExistingModule
709 = ModuleSpace.find(ModuleName);
710 if (ExistingModule != ModuleSpace.end()) {
711 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
712 << ModuleName;
713 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
714 diag::note_mmap_prev_definition);
715
716 // Skip the module definition.
717 skipUntil(MMToken::RBrace);
718 if (Tok.is(MMToken::RBrace))
719 consumeToken();
720
721 HadError = true;
722 return;
723 }
724
725 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000726 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
727 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000728 ModuleSpace[ModuleName] = ActiveModule;
729
730 bool Done = false;
731 do {
732 switch (Tok.Kind) {
733 case MMToken::EndOfFile:
734 case MMToken::RBrace:
735 Done = true;
736 break;
737
738 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000739 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000740 case MMToken::ModuleKeyword:
741 parseModuleDecl();
742 break;
743
Douglas Gregor90db2602011-12-02 01:47:07 +0000744 case MMToken::ExportKeyword:
745 parseExportDecl();
746 break;
747
Douglas Gregora30cfe52011-11-11 19:10:28 +0000748 case MMToken::HeaderKeyword:
749 parseHeaderDecl();
750 break;
751
752 case MMToken::UmbrellaKeyword:
753 parseUmbrellaDecl();
754 break;
Douglas Gregor90db2602011-12-02 01:47:07 +0000755
Douglas Gregora30cfe52011-11-11 19:10:28 +0000756 default:
757 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
758 consumeToken();
759 break;
760 }
761 } while (!Done);
762
763 if (Tok.is(MMToken::RBrace))
764 consumeToken();
765 else {
766 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
767 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
768 HadError = true;
769 }
770
Douglas Gregor587986e2011-12-07 02:23:45 +0000771 // We're done parsing this module. Pop back to the previous module.
772 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000773}
Douglas Gregord620a842011-12-06 17:16:41 +0000774
775/// \brief Append to \p Paths the set of paths needed to get to the
776/// subframework in which the given module lives.
777void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
778 // Collect the framework names from the given module to the top-level module.
779 llvm::SmallVector<StringRef, 2> Paths;
780 for (; Mod; Mod = Mod->Parent) {
781 if (Mod->IsFramework)
782 Paths.push_back(Mod->Name);
783 }
784
785 if (Paths.empty())
786 return;
787
788 // Add Frameworks/Name.framework for each subframework.
789 for (unsigned I = Paths.size() - 1; I != 0; --I) {
790 llvm::sys::path::append(Path, "Frameworks");
791 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
792 }
793}
794
Douglas Gregora30cfe52011-11-11 19:10:28 +0000795/// \brief Parse an umbrella header declaration.
796///
797/// umbrella-declaration:
798/// 'umbrella' string-literal
799void ModuleMapParser::parseUmbrellaDecl() {
800 assert(Tok.is(MMToken::UmbrellaKeyword));
801 SourceLocation UmbrellaLoc = consumeToken();
802
803 // Parse the header name.
804 if (!Tok.is(MMToken::StringLiteral)) {
805 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
806 << "umbrella";
807 HadError = true;
808 return;
809 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000810 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000811 SourceLocation FileNameLoc = consumeToken();
812
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000813 // Check whether we already have an umbrella header.
814 if (ActiveModule->UmbrellaHeader) {
815 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
816 << ActiveModule->getFullModuleName()
817 << ActiveModule->UmbrellaHeader->getName();
818 HadError = true;
819 return;
820 }
821
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000822 // Look for this file.
823 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000824 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000825
826 if (llvm::sys::path::is_absolute(FileName)) {
827 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000828 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000829 } else {
830 // Search for the header file within the search directory.
831 PathName += Directory->getName();
832 unsigned PathLength = PathName.size();
Douglas Gregord620a842011-12-06 17:16:41 +0000833
Douglas Gregor18ee5472011-11-29 21:59:16 +0000834 if (ActiveModule->isPartOfFramework()) {
Douglas Gregord620a842011-12-06 17:16:41 +0000835 appendSubframeworkPaths(ActiveModule, PathName);
836
Douglas Gregor18ee5472011-11-29 21:59:16 +0000837 // Check whether this file is in the public headers.
838 llvm::sys::path::append(PathName, "Headers");
839 llvm::sys::path::append(PathName, FileName);
840 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000841
Douglas Gregor18ee5472011-11-29 21:59:16 +0000842 if (!File) {
843 // Check whether this file is in the private headers.
844 PathName.resize(PathLength);
845 llvm::sys::path::append(PathName, "PrivateHeaders");
846 llvm::sys::path::append(PathName, FileName);
847 File = SourceMgr.getFileManager().getFile(PathName);
848 }
Douglas Gregor18ee5472011-11-29 21:59:16 +0000849 } else {
850 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000851 llvm::sys::path::append(PathName, FileName);
852 File = SourceMgr.getFileManager().getFile(PathName);
853 }
Douglas Gregora8654052011-11-17 22:09:43 +0000854 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000855
856 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
857 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000858 if (File) {
Douglas Gregore209e502011-12-06 01:10:29 +0000859 const DirectoryEntry *UmbrellaDir = File->getDir();
860 if (ActiveModule->IsFramework) {
861 // For framework modules, use the framework directory as the umbrella
862 // directory.
863 UmbrellaDir = SourceMgr.getFileManager().getDirectory(
864 llvm::sys::path::parent_path(UmbrellaDir->getName()));
865 }
866
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000867 if (const Module *OwningModule = Map.Headers[File]) {
868 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
869 << FileName << OwningModule->getFullModuleName();
870 HadError = true;
Douglas Gregore209e502011-12-06 01:10:29 +0000871 } else if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
Douglas Gregoradb97992011-11-16 23:02:25 +0000872 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
873 << OwningModule->getFullModuleName();
874 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000875 } else {
876 // Record this umbrella header.
Douglas Gregore209e502011-12-06 01:10:29 +0000877 Map.setUmbrellaHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000878 }
879 } else {
880 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
881 << true << FileName;
882 HadError = true;
883 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000884}
885
886/// \brief Parse a header declaration.
887///
888/// header-declaration:
889/// 'header' string-literal
890void ModuleMapParser::parseHeaderDecl() {
891 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000892 consumeToken();
893
Douglas Gregora30cfe52011-11-11 19:10:28 +0000894 // Parse the header name.
895 if (!Tok.is(MMToken::StringLiteral)) {
896 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
897 << "header";
898 HadError = true;
899 return;
900 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000901 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000902 SourceLocation FileNameLoc = consumeToken();
903
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000904 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +0000905 const FileEntry *File = 0;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000906 llvm::SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +0000907 if (llvm::sys::path::is_absolute(FileName)) {
908 PathName = FileName;
909 File = SourceMgr.getFileManager().getFile(PathName);
910 } else {
911 // Search for the header file within the search directory.
Douglas Gregor18ee5472011-11-29 21:59:16 +0000912 PathName += Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +0000913 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +0000914
Douglas Gregord620a842011-12-06 17:16:41 +0000915 if (ActiveModule->isPartOfFramework()) {
916 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +0000917
918 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +0000919 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +0000920 llvm::sys::path::append(PathName, FileName);
921 File = SourceMgr.getFileManager().getFile(PathName);
922
923 if (!File) {
924 // Check whether this file is in the private headers.
925 PathName.resize(PathLength);
926 llvm::sys::path::append(PathName, "PrivateHeaders");
927 llvm::sys::path::append(PathName, FileName);
928 File = SourceMgr.getFileManager().getFile(PathName);
929 }
930 } else {
931 // Lookup for normal headers.
932 llvm::sys::path::append(PathName, FileName);
933 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregord620a842011-12-06 17:16:41 +0000934 }
Douglas Gregor18ee5472011-11-29 21:59:16 +0000935 }
Douglas Gregora8654052011-11-17 22:09:43 +0000936
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000937 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
938 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +0000939 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000940 if (const Module *OwningModule = Map.Headers[File]) {
941 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
942 << FileName << OwningModule->getFullModuleName();
943 HadError = true;
944 } else {
945 // Record this file.
Douglas Gregore209e502011-12-06 01:10:29 +0000946 Map.addHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000947 }
948 } else {
949 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
950 << false << FileName;
951 HadError = true;
952 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000953}
954
Douglas Gregor90db2602011-12-02 01:47:07 +0000955/// \brief Parse a module export declaration.
956///
957/// export-declaration:
958/// 'export' wildcard-module-id
959///
960/// wildcard-module-id:
961/// identifier
962/// '*'
963/// identifier '.' wildcard-module-id
964void ModuleMapParser::parseExportDecl() {
965 assert(Tok.is(MMToken::ExportKeyword));
966 SourceLocation ExportLoc = consumeToken();
967
968 // Parse the module-id with an optional wildcard at the end.
969 ModuleId ParsedModuleId;
970 bool Wildcard = false;
971 do {
972 if (Tok.is(MMToken::Identifier)) {
973 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
974 Tok.getLocation()));
975 consumeToken();
976
977 if (Tok.is(MMToken::Period)) {
978 consumeToken();
979 continue;
980 }
981
982 break;
983 }
984
985 if(Tok.is(MMToken::Star)) {
986 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +0000987 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +0000988 break;
989 }
990
991 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
992 HadError = true;
993 return;
994 } while (true);
995
996 Module::UnresolvedExportDecl Unresolved = {
997 ExportLoc, ParsedModuleId, Wildcard
998 };
999 ActiveModule->UnresolvedExports.push_back(Unresolved);
1000}
1001
Douglas Gregor1e123682011-12-05 22:27:44 +00001002void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1003 assert(Tok.is(MMToken::Star));
1004 SourceLocation StarLoc = consumeToken();
1005 bool Failed = false;
1006
1007 // Inferred modules must be submodules.
1008 if (!ActiveModule) {
1009 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1010 Failed = true;
1011 }
1012
1013 // Inferred modules must have umbrella headers.
Douglas Gregoref85b562011-12-06 17:34:58 +00001014 if (!Failed && !ActiveModule->UmbrellaHeader) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001015 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1016 Failed = true;
1017 }
1018
1019 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +00001020 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001021 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +00001022 if (ActiveModule->InferredSubmoduleLoc.isValid())
1023 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +00001024 diag::note_mmap_prev_definition);
1025 Failed = true;
1026 }
1027
1028 // If there were any problems with this inferred submodule, skip its body.
1029 if (Failed) {
1030 if (Tok.is(MMToken::LBrace)) {
1031 consumeToken();
1032 skipUntil(MMToken::RBrace);
1033 if (Tok.is(MMToken::RBrace))
1034 consumeToken();
1035 }
1036 HadError = true;
1037 return;
1038 }
1039
1040 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +00001041 ActiveModule->InferSubmodules = true;
1042 ActiveModule->InferredSubmoduleLoc = StarLoc;
1043 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +00001044
1045 // Parse the opening brace.
1046 if (!Tok.is(MMToken::LBrace)) {
1047 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1048 HadError = true;
1049 return;
1050 }
1051 SourceLocation LBraceLoc = consumeToken();
1052
1053 // Parse the body of the inferred submodule.
1054 bool Done = false;
1055 do {
1056 switch (Tok.Kind) {
1057 case MMToken::EndOfFile:
1058 case MMToken::RBrace:
1059 Done = true;
1060 break;
1061
1062 case MMToken::ExportKeyword: {
1063 consumeToken();
1064 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001065 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001066 else
1067 Diags.Report(Tok.getLocation(),
1068 diag::err_mmap_expected_export_wildcard);
1069 consumeToken();
1070 break;
1071 }
1072
1073 case MMToken::ExplicitKeyword:
1074 case MMToken::ModuleKeyword:
1075 case MMToken::HeaderKeyword:
1076 case MMToken::UmbrellaKeyword:
1077 default:
1078 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1079 consumeToken();
1080 break;
1081 }
1082 } while (!Done);
1083
1084 if (Tok.is(MMToken::RBrace))
1085 consumeToken();
1086 else {
1087 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1088 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1089 HadError = true;
1090 }
1091}
1092
Douglas Gregora30cfe52011-11-11 19:10:28 +00001093/// \brief Parse a module map file.
1094///
1095/// module-map-file:
1096/// module-declaration*
1097bool ModuleMapParser::parseModuleMapFile() {
1098 do {
1099 switch (Tok.Kind) {
1100 case MMToken::EndOfFile:
1101 return HadError;
1102
Douglas Gregor587986e2011-12-07 02:23:45 +00001103 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001104 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001105 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001106 parseModuleDecl();
1107 break;
1108
Douglas Gregor90db2602011-12-02 01:47:07 +00001109 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001110 case MMToken::HeaderKeyword:
1111 case MMToken::Identifier:
1112 case MMToken::LBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001113 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001114 case MMToken::RBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001115 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001116 case MMToken::StringLiteral:
1117 case MMToken::UmbrellaKeyword:
1118 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1119 HadError = true;
1120 consumeToken();
1121 break;
1122 }
1123 } while (true);
1124
1125 return HadError;
1126}
1127
1128bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
1129 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1130 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1131 if (!Buffer)
1132 return true;
1133
1134 // Parse this module map file.
1135 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
1136 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001137 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001138 bool Result = Parser.parseModuleMapFile();
1139 Diags->getClient()->EndSourceFile();
1140
1141 return Result;
1142}