blob: 12e636c1beb836a6bc4aabdf95a81c51765f0361 [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.
Douglas Gregor23af6d52011-12-07 22:05:21 +0000118 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregore209e502011-12-06 01:10:29 +0000119
Douglas Gregor6a1db482011-12-09 02:04:43 +0000120 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregore209e502011-12-06 01:10:29 +0000121 // Find or create the module that corresponds to this directory name.
122 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
123 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000124 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000125
126 // Associate the module and the directory.
127 UmbrellaDirs[SkippedDirs[I-1]] = Result;
128
129 // If inferred submodules export everything they import, add a
130 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000131 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000132 Result->Exports.push_back(Module::ExportDecl(0, true));
133 }
134
135 // Infer a submodule with the same name as this header file.
136 StringRef Name = llvm::sys::path::stem(File->getName());
137 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000138 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000139
140 // If inferred submodules export everything they import, add a
141 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000142 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000143 Result->Exports.push_back(Module::ExportDecl(0, true));
144 } else {
145 // Record each of the directories we stepped through as being part of
146 // the module we found, since the umbrella header covers them all.
147 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
148 UmbrellaDirs[SkippedDirs[I]] = Result;
149 }
150
151 Headers[File] = Result;
152 return Result;
153 }
154
155 SkippedDirs.push_back(Dir);
156
Douglas Gregoradb97992011-11-16 23:02:25 +0000157 // Retrieve our parent path.
158 DirName = llvm::sys::path::parent_path(DirName);
159 if (DirName.empty())
160 break;
161
162 // Resolve the parent path to a directory entry.
163 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000164 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000165
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000166 return 0;
167}
168
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000169Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000170 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
171 if (Known != Modules.end())
172 return Known->getValue();
173
174 return 0;
175}
176
Douglas Gregor90db2602011-12-02 01:47:07 +0000177Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
178 for(; Context; Context = Context->Parent) {
179 if (Module *Sub = lookupModuleQualified(Name, Context))
180 return Sub;
181 }
182
183 return findModule(Name);
184}
185
186Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
187 if (!Context)
188 return findModule(Name);
189
190 llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
191 if (Sub != Context->SubModules.end())
192 return Sub->getValue();
193
194 return 0;
195}
196
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000197std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000198ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
199 bool IsExplicit) {
200 // Try to find an existing module with this name.
201 if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
202 return std::make_pair(Found, false);
203
204 // Create a new module with this name.
205 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
206 IsExplicit);
207 if (Parent)
208 Parent->SubModules[Name] = Result;
209 else
210 Modules[Name] = Result;
211 return std::make_pair(Result, true);
212}
213
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000214Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000215ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000216 const DirectoryEntry *FrameworkDir,
217 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000218 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000219 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
220 return Mod;
221
222 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000223
224 // Look for an umbrella header.
225 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
226 llvm::sys::path::append(UmbrellaName, "Headers");
227 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000228 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000229
230 // FIXME: If there's no umbrella header, we could probably scan the
231 // framework to load *everything*. But, it's not clear that this is a good
232 // idea.
233 if (!UmbrellaHeader)
234 return 0;
235
Douglas Gregorac252a32011-12-06 19:39:29 +0000236 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
237 /*IsFramework=*/true, /*IsExplicit=*/false);
238
239 if (Parent)
240 Parent->SubModules[ModuleName] = Result;
241 else
242 Modules[ModuleName] = Result;
243
Douglas Gregor489ad432011-12-08 18:00:48 +0000244 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000245 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000246 Headers[UmbrellaHeader] = Result;
247 UmbrellaDirs[FrameworkDir] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000248
249 // export *
250 Result->Exports.push_back(Module::ExportDecl(0, true));
251
Douglas Gregore209e502011-12-06 01:10:29 +0000252 // module * { export * }
253 Result->InferSubmodules = true;
254 Result->InferExportWildcard = true;
255
Douglas Gregorac252a32011-12-06 19:39:29 +0000256 // Look for subframeworks.
257 llvm::error_code EC;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000258 llvm::SmallString<128> SubframeworksDirName
259 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000260 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000261 llvm::SmallString<128> SubframeworksDirNameNative;
262 llvm::sys::path::native(SubframeworksDirName.str(),
263 SubframeworksDirNameNative);
264 for (llvm::sys::fs::directory_iterator
265 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregorac252a32011-12-06 19:39:29 +0000266 Dir != DirEnd && !EC; Dir.increment(EC)) {
267 if (!StringRef(Dir->path()).endswith(".framework"))
268 continue;
269
270 if (const DirectoryEntry *SubframeworkDir
271 = FileMgr.getDirectory(Dir->path())) {
272 // FIXME: Do we want to warn about subframeworks without umbrella headers?
273 inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
274 Result);
275 }
276 }
Douglas Gregord620a842011-12-06 17:16:41 +0000277
Douglas Gregor23af6d52011-12-07 22:05:21 +0000278 // Look for private headers.
Douglas Gregor23af6d52011-12-07 22:05:21 +0000279 llvm::SmallString<128> PrivateHeadersDirName(FrameworkDir->getName());
280 llvm::sys::path::append(PrivateHeadersDirName, "PrivateHeaders");
Douglas Gregor6a1db482011-12-09 02:04:43 +0000281 if (const DirectoryEntry *Dir = FileMgr.getDirectory(PrivateHeadersDirName)) {
282 Module *Private = findOrCreateModule("Private", Result,
283 /*IsFramework=*/false,
284 /*IsExplicit=*/true).first;
285 setUmbrellaDir(Private, Dir);
286 Private->InferSubmodules = true;
287 Private->InferExplicitSubmodules = true;
288 Private->InferExportWildcard = true;
Douglas Gregor23af6d52011-12-07 22:05:21 +0000289 }
290
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000291 return Result;
292}
293
Douglas Gregore209e502011-12-06 01:10:29 +0000294void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
295 Headers[UmbrellaHeader] = Mod;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000296 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000297 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000298}
299
Douglas Gregor77d029f2011-12-08 19:11:24 +0000300void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
301 Mod->Umbrella = UmbrellaDir;
302 UmbrellaDirs[UmbrellaDir] = Mod;
303}
304
Douglas Gregore209e502011-12-06 01:10:29 +0000305void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
306 Mod->Headers.push_back(Header);
307 Headers[Header] = Mod;
308}
309
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000310const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000311ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000312 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
313 return 0;
314
315 return SourceMgr->getFileEntryForID(
316 SourceMgr->getFileID(Module->DefinitionLoc));
317}
318
Douglas Gregora30cfe52011-11-11 19:10:28 +0000319void ModuleMap::dump() {
320 llvm::errs() << "Modules:";
321 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
322 MEnd = Modules.end();
323 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000324 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000325
326 llvm::errs() << "Headers:";
327 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
328 H = Headers.begin(),
329 HEnd = Headers.end();
330 H != HEnd; ++H) {
331 llvm::errs() << " \"" << H->first->getName() << "\" -> "
332 << H->second->getFullModuleName() << "\n";
333 }
334}
335
Douglas Gregor90db2602011-12-02 01:47:07 +0000336bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
337 bool HadError = false;
338 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
339 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
340 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000341 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000342 Mod->Exports.push_back(Export);
343 else
344 HadError = true;
345 }
346 Mod->UnresolvedExports.clear();
347 return HadError;
348}
349
Douglas Gregor55988682011-12-05 16:33:54 +0000350Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
351 if (Loc.isInvalid())
352 return 0;
353
354 // Use the expansion location to determine which module we're in.
355 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
356 if (!ExpansionLoc.isFileID())
357 return 0;
358
359
360 const SourceManager &SrcMgr = Loc.getManager();
361 FileID ExpansionFileID = ExpansionLoc.getFileID();
362 const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
363 if (!ExpansionFile)
364 return 0;
365
366 // Find the module that owns this header.
367 return findModuleForHeader(ExpansionFile);
368}
369
Douglas Gregora30cfe52011-11-11 19:10:28 +0000370//----------------------------------------------------------------------------//
371// Module map file parser
372//----------------------------------------------------------------------------//
373
374namespace clang {
375 /// \brief A token in a module map file.
376 struct MMToken {
377 enum TokenKind {
378 EndOfFile,
379 HeaderKeyword,
380 Identifier,
381 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000382 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000383 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000384 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000385 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000386 UmbrellaKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000387 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000388 StringLiteral,
389 LBrace,
390 RBrace
391 } Kind;
392
393 unsigned Location;
394 unsigned StringLength;
395 const char *StringData;
396
397 void clear() {
398 Kind = EndOfFile;
399 Location = 0;
400 StringLength = 0;
401 StringData = 0;
402 }
403
404 bool is(TokenKind K) const { return Kind == K; }
405
406 SourceLocation getLocation() const {
407 return SourceLocation::getFromRawEncoding(Location);
408 }
409
410 StringRef getString() const {
411 return StringRef(StringData, StringLength);
412 }
413 };
414
415 class ModuleMapParser {
416 Lexer &L;
417 SourceManager &SourceMgr;
418 DiagnosticsEngine &Diags;
419 ModuleMap &Map;
420
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000421 /// \brief The directory that this module map resides in.
422 const DirectoryEntry *Directory;
423
Douglas Gregora30cfe52011-11-11 19:10:28 +0000424 /// \brief Whether an error occurred.
425 bool HadError;
426
427 /// \brief Default target information, used only for string literal
428 /// parsing.
429 TargetInfo *Target;
430
431 /// \brief Stores string data for the various string literals referenced
432 /// during parsing.
433 llvm::BumpPtrAllocator StringData;
434
435 /// \brief The current token.
436 MMToken Tok;
437
438 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000439 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000440
441 /// \brief Consume the current token and return its location.
442 SourceLocation consumeToken();
443
444 /// \brief Skip tokens until we reach the a token with the given kind
445 /// (or the end of the file).
446 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000447
448 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
449 ModuleId;
450 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000451 void parseModuleDecl();
Douglas Gregor489ad432011-12-08 18:00:48 +0000452 void parseHeaderDecl(SourceLocation UmbrellaLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000453 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000454 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000455 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000456
Douglas Gregor6a1db482011-12-09 02:04:43 +0000457 const DirectoryEntry *getOverriddenHeaderSearchDir();
458
Douglas Gregora30cfe52011-11-11 19:10:28 +0000459 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000460 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
461 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000462 ModuleMap &Map,
463 const DirectoryEntry *Directory)
464 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
465 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000466 {
467 TargetOptions TargetOpts;
468 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
469 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
470
471 Tok.clear();
472 consumeToken();
473 }
474
475 bool parseModuleMapFile();
476 };
477}
478
479SourceLocation ModuleMapParser::consumeToken() {
480retry:
481 SourceLocation Result = Tok.getLocation();
482 Tok.clear();
483
484 Token LToken;
485 L.LexFromRawLexer(LToken);
486 Tok.Location = LToken.getLocation().getRawEncoding();
487 switch (LToken.getKind()) {
488 case tok::raw_identifier:
489 Tok.StringData = LToken.getRawIdentifierData();
490 Tok.StringLength = LToken.getLength();
491 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
492 .Case("header", MMToken::HeaderKeyword)
493 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000494 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000495 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000496 .Case("module", MMToken::ModuleKeyword)
497 .Case("umbrella", MMToken::UmbrellaKeyword)
498 .Default(MMToken::Identifier);
499 break;
500
501 case tok::eof:
502 Tok.Kind = MMToken::EndOfFile;
503 break;
504
505 case tok::l_brace:
506 Tok.Kind = MMToken::LBrace;
507 break;
508
Douglas Gregor90db2602011-12-02 01:47:07 +0000509 case tok::period:
510 Tok.Kind = MMToken::Period;
511 break;
512
Douglas Gregora30cfe52011-11-11 19:10:28 +0000513 case tok::r_brace:
514 Tok.Kind = MMToken::RBrace;
515 break;
516
Douglas Gregor90db2602011-12-02 01:47:07 +0000517 case tok::star:
518 Tok.Kind = MMToken::Star;
519 break;
520
Douglas Gregora30cfe52011-11-11 19:10:28 +0000521 case tok::string_literal: {
522 // Parse the string literal.
523 LangOptions LangOpts;
524 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
525 if (StringLiteral.hadError)
526 goto retry;
527
528 // Copy the string literal into our string data allocator.
529 unsigned Length = StringLiteral.GetStringLength();
530 char *Saved = StringData.Allocate<char>(Length + 1);
531 memcpy(Saved, StringLiteral.GetString().data(), Length);
532 Saved[Length] = 0;
533
534 // Form the token.
535 Tok.Kind = MMToken::StringLiteral;
536 Tok.StringData = Saved;
537 Tok.StringLength = Length;
538 break;
539 }
540
541 case tok::comment:
542 goto retry;
543
544 default:
545 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
546 HadError = true;
547 goto retry;
548 }
549
550 return Result;
551}
552
553void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
554 unsigned braceDepth = 0;
555 do {
556 switch (Tok.Kind) {
557 case MMToken::EndOfFile:
558 return;
559
560 case MMToken::LBrace:
561 if (Tok.is(K) && braceDepth == 0)
562 return;
563
564 ++braceDepth;
565 break;
566
567 case MMToken::RBrace:
568 if (braceDepth > 0)
569 --braceDepth;
570 else if (Tok.is(K))
571 return;
572 break;
573
574 default:
575 if (braceDepth == 0 && Tok.is(K))
576 return;
577 break;
578 }
579
580 consumeToken();
581 } while (true);
582}
583
Douglas Gregor587986e2011-12-07 02:23:45 +0000584/// \brief Parse a module-id.
585///
586/// module-id:
587/// identifier
588/// identifier '.' module-id
589///
590/// \returns true if an error occurred, false otherwise.
591bool ModuleMapParser::parseModuleId(ModuleId &Id) {
592 Id.clear();
593 do {
594 if (Tok.is(MMToken::Identifier)) {
595 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
596 consumeToken();
597 } else {
598 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
599 return true;
600 }
601
602 if (!Tok.is(MMToken::Period))
603 break;
604
605 consumeToken();
606 } while (true);
607
608 return false;
609}
610
Douglas Gregora30cfe52011-11-11 19:10:28 +0000611/// \brief Parse a module declaration.
612///
613/// module-declaration:
Douglas Gregor587986e2011-12-07 02:23:45 +0000614/// 'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000615///
616/// module-member:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000617/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000618/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000619/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000620///
621/// submodule-declaration:
622/// module-declaration
623/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000624void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000625 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
626 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000627 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000628 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000629 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000630 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000631
Douglas Gregord620a842011-12-06 17:16:41 +0000632 // Parse 'explicit' keyword, if present.
633 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000634 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000635 Explicit = true;
636 }
637
638 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000639 if (Tok.is(MMToken::FrameworkKeyword)) {
640 consumeToken();
641 Framework = true;
642 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000643
644 // Parse 'module' keyword.
645 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000646 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000647 consumeToken();
648 HadError = true;
649 return;
650 }
651 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000652
653 // If we have a wildcard for the module name, this is an inferred submodule.
654 // Parse it.
655 if (Tok.is(MMToken::Star))
656 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000657
658 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000659 ModuleId Id;
660 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000661 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000662 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000663 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000664
665 if (ActiveModule) {
666 if (Id.size() > 1) {
667 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
668 << SourceRange(Id.front().second, Id.back().second);
669
670 HadError = true;
671 return;
672 }
673 } else if (Id.size() == 1 && Explicit) {
674 // Top-level modules can't be explicit.
675 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
676 Explicit = false;
677 ExplicitLoc = SourceLocation();
678 HadError = true;
679 }
680
681 Module *PreviousActiveModule = ActiveModule;
682 if (Id.size() > 1) {
683 // This module map defines a submodule. Go find the module of which it
684 // is a submodule.
685 ActiveModule = 0;
686 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
687 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
688 ActiveModule = Next;
689 continue;
690 }
691
692 if (ActiveModule) {
693 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
694 << Id[I].first << ActiveModule->getTopLevelModule();
695 } else {
696 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
697 }
698 HadError = true;
699 return;
700 }
701 }
702
703 StringRef ModuleName = Id.back().first;
704 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000705
706 // Parse the opening brace.
707 if (!Tok.is(MMToken::LBrace)) {
708 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
709 << ModuleName;
710 HadError = true;
711 return;
712 }
713 SourceLocation LBraceLoc = consumeToken();
714
715 // Determine whether this (sub)module has already been defined.
716 llvm::StringMap<Module *> &ModuleSpace
717 = ActiveModule? ActiveModule->SubModules : Map.Modules;
718 llvm::StringMap<Module *>::iterator ExistingModule
719 = ModuleSpace.find(ModuleName);
720 if (ExistingModule != ModuleSpace.end()) {
721 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
722 << ModuleName;
723 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
724 diag::note_mmap_prev_definition);
725
726 // Skip the module definition.
727 skipUntil(MMToken::RBrace);
728 if (Tok.is(MMToken::RBrace))
729 consumeToken();
730
731 HadError = true;
732 return;
733 }
734
735 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000736 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
737 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000738 ModuleSpace[ModuleName] = ActiveModule;
739
740 bool Done = false;
741 do {
742 switch (Tok.Kind) {
743 case MMToken::EndOfFile:
744 case MMToken::RBrace:
745 Done = true;
746 break;
747
748 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000749 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000750 case MMToken::ModuleKeyword:
751 parseModuleDecl();
752 break;
753
Douglas Gregor90db2602011-12-02 01:47:07 +0000754 case MMToken::ExportKeyword:
755 parseExportDecl();
756 break;
757
Douglas Gregor77d029f2011-12-08 19:11:24 +0000758 case MMToken::UmbrellaKeyword: {
759 SourceLocation UmbrellaLoc = consumeToken();
760 if (Tok.is(MMToken::HeaderKeyword))
761 parseHeaderDecl(UmbrellaLoc);
762 else
763 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000764 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +0000765 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000766
Douglas Gregor489ad432011-12-08 18:00:48 +0000767 case MMToken::HeaderKeyword:
768 parseHeaderDecl(SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000769 break;
Douglas Gregor489ad432011-12-08 18:00:48 +0000770
Douglas Gregora30cfe52011-11-11 19:10:28 +0000771 default:
772 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
773 consumeToken();
774 break;
775 }
776 } while (!Done);
777
778 if (Tok.is(MMToken::RBrace))
779 consumeToken();
780 else {
781 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
782 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
783 HadError = true;
784 }
785
Douglas Gregor587986e2011-12-07 02:23:45 +0000786 // We're done parsing this module. Pop back to the previous module.
787 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000788}
Douglas Gregord620a842011-12-06 17:16:41 +0000789
790/// \brief Append to \p Paths the set of paths needed to get to the
791/// subframework in which the given module lives.
792void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
793 // Collect the framework names from the given module to the top-level module.
794 llvm::SmallVector<StringRef, 2> Paths;
795 for (; Mod; Mod = Mod->Parent) {
796 if (Mod->IsFramework)
797 Paths.push_back(Mod->Name);
798 }
799
800 if (Paths.empty())
801 return;
802
803 // Add Frameworks/Name.framework for each subframework.
804 for (unsigned I = Paths.size() - 1; I != 0; --I) {
805 llvm::sys::path::append(Path, "Frameworks");
806 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
807 }
808}
809
Douglas Gregora30cfe52011-11-11 19:10:28 +0000810/// \brief Parse a header declaration.
811///
812/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +0000813/// 'umbrella'[opt] 'header' string-literal
814void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000815 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000816 consumeToken();
817
Douglas Gregor489ad432011-12-08 18:00:48 +0000818 bool Umbrella = UmbrellaLoc.isValid();
819
Douglas Gregora30cfe52011-11-11 19:10:28 +0000820 // Parse the header name.
821 if (!Tok.is(MMToken::StringLiteral)) {
822 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
823 << "header";
824 HadError = true;
825 return;
826 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000827 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000828 SourceLocation FileNameLoc = consumeToken();
829
Douglas Gregor77d029f2011-12-08 19:11:24 +0000830 // Check whether we already have an umbrella.
831 if (Umbrella && ActiveModule->Umbrella) {
832 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
833 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +0000834 HadError = true;
835 return;
836 }
837
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000838 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +0000839 const FileEntry *File = 0;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000840 llvm::SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +0000841 if (llvm::sys::path::is_absolute(FileName)) {
842 PathName = FileName;
843 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +0000844 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
845 PathName = Dir->getName();
846 llvm::sys::path::append(PathName, FileName);
847 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +0000848 } else {
849 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +0000850 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +0000851 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +0000852
Douglas Gregord620a842011-12-06 17:16:41 +0000853 if (ActiveModule->isPartOfFramework()) {
854 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +0000855
856 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +0000857 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +0000858 llvm::sys::path::append(PathName, FileName);
859 File = SourceMgr.getFileManager().getFile(PathName);
860
861 if (!File) {
862 // Check whether this file is in the private headers.
863 PathName.resize(PathLength);
864 llvm::sys::path::append(PathName, "PrivateHeaders");
865 llvm::sys::path::append(PathName, FileName);
866 File = SourceMgr.getFileManager().getFile(PathName);
867 }
868 } else {
869 // Lookup for normal headers.
870 llvm::sys::path::append(PathName, FileName);
871 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregord620a842011-12-06 17:16:41 +0000872 }
Douglas Gregor18ee5472011-11-29 21:59:16 +0000873 }
Douglas Gregora8654052011-11-17 22:09:43 +0000874
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000875 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
876 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +0000877 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000878 if (const Module *OwningModule = Map.Headers[File]) {
879 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
880 << FileName << OwningModule->getFullModuleName();
881 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +0000882 } else if (Umbrella) {
883 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor489ad432011-12-08 18:00:48 +0000884 if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
885 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
886 << OwningModule->getFullModuleName();
887 HadError = true;
888 } else {
889 // Record this umbrella header.
890 Map.setUmbrellaHeader(ActiveModule, File);
891 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000892 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +0000893 // Record this header.
Douglas Gregore209e502011-12-06 01:10:29 +0000894 Map.addHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000895 }
896 } else {
897 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +0000898 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000899 HadError = true;
900 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000901}
902
Douglas Gregor77d029f2011-12-08 19:11:24 +0000903/// \brief Parse an umbrella directory declaration.
904///
905/// umbrella-dir-declaration:
906/// umbrella string-literal
907void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
908 // Parse the directory name.
909 if (!Tok.is(MMToken::StringLiteral)) {
910 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
911 << "umbrella";
912 HadError = true;
913 return;
914 }
915
916 std::string DirName = Tok.getString();
917 SourceLocation DirNameLoc = consumeToken();
918
919 // Check whether we already have an umbrella.
920 if (ActiveModule->Umbrella) {
921 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
922 << ActiveModule->getFullModuleName();
923 HadError = true;
924 return;
925 }
926
927 // Look for this file.
928 const DirectoryEntry *Dir = 0;
929 if (llvm::sys::path::is_absolute(DirName))
930 Dir = SourceMgr.getFileManager().getDirectory(DirName);
931 else {
932 llvm::SmallString<128> PathName;
933 PathName = Directory->getName();
934 llvm::sys::path::append(PathName, DirName);
935 Dir = SourceMgr.getFileManager().getDirectory(PathName);
936 }
937
938 if (!Dir) {
939 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
940 << DirName;
941 HadError = true;
942 return;
943 }
944
945 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
946 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
947 << OwningModule->getFullModuleName();
948 HadError = true;
949 return;
950 }
951
952 // Record this umbrella directory.
953 Map.setUmbrellaDir(ActiveModule, Dir);
954}
955
Douglas Gregor90db2602011-12-02 01:47:07 +0000956/// \brief Parse a module export declaration.
957///
958/// export-declaration:
959/// 'export' wildcard-module-id
960///
961/// wildcard-module-id:
962/// identifier
963/// '*'
964/// identifier '.' wildcard-module-id
965void ModuleMapParser::parseExportDecl() {
966 assert(Tok.is(MMToken::ExportKeyword));
967 SourceLocation ExportLoc = consumeToken();
968
969 // Parse the module-id with an optional wildcard at the end.
970 ModuleId ParsedModuleId;
971 bool Wildcard = false;
972 do {
973 if (Tok.is(MMToken::Identifier)) {
974 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
975 Tok.getLocation()));
976 consumeToken();
977
978 if (Tok.is(MMToken::Period)) {
979 consumeToken();
980 continue;
981 }
982
983 break;
984 }
985
986 if(Tok.is(MMToken::Star)) {
987 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +0000988 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +0000989 break;
990 }
991
992 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
993 HadError = true;
994 return;
995 } while (true);
996
997 Module::UnresolvedExportDecl Unresolved = {
998 ExportLoc, ParsedModuleId, Wildcard
999 };
1000 ActiveModule->UnresolvedExports.push_back(Unresolved);
1001}
1002
Douglas Gregor1e123682011-12-05 22:27:44 +00001003void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1004 assert(Tok.is(MMToken::Star));
1005 SourceLocation StarLoc = consumeToken();
1006 bool Failed = false;
1007
1008 // Inferred modules must be submodules.
1009 if (!ActiveModule) {
1010 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1011 Failed = true;
1012 }
1013
Douglas Gregor77d029f2011-12-08 19:11:24 +00001014 // Inferred modules must have umbrella directories.
1015 if (!Failed && !ActiveModule->getUmbrellaDir()) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001016 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1017 Failed = true;
1018 }
1019
1020 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +00001021 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001022 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +00001023 if (ActiveModule->InferredSubmoduleLoc.isValid())
1024 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +00001025 diag::note_mmap_prev_definition);
1026 Failed = true;
1027 }
1028
1029 // If there were any problems with this inferred submodule, skip its body.
1030 if (Failed) {
1031 if (Tok.is(MMToken::LBrace)) {
1032 consumeToken();
1033 skipUntil(MMToken::RBrace);
1034 if (Tok.is(MMToken::RBrace))
1035 consumeToken();
1036 }
1037 HadError = true;
1038 return;
1039 }
1040
1041 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +00001042 ActiveModule->InferSubmodules = true;
1043 ActiveModule->InferredSubmoduleLoc = StarLoc;
1044 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +00001045
1046 // Parse the opening brace.
1047 if (!Tok.is(MMToken::LBrace)) {
1048 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1049 HadError = true;
1050 return;
1051 }
1052 SourceLocation LBraceLoc = consumeToken();
1053
1054 // Parse the body of the inferred submodule.
1055 bool Done = false;
1056 do {
1057 switch (Tok.Kind) {
1058 case MMToken::EndOfFile:
1059 case MMToken::RBrace:
1060 Done = true;
1061 break;
1062
1063 case MMToken::ExportKeyword: {
1064 consumeToken();
1065 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001066 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001067 else
1068 Diags.Report(Tok.getLocation(),
1069 diag::err_mmap_expected_export_wildcard);
1070 consumeToken();
1071 break;
1072 }
1073
1074 case MMToken::ExplicitKeyword:
1075 case MMToken::ModuleKeyword:
1076 case MMToken::HeaderKeyword:
1077 case MMToken::UmbrellaKeyword:
1078 default:
1079 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1080 consumeToken();
1081 break;
1082 }
1083 } while (!Done);
1084
1085 if (Tok.is(MMToken::RBrace))
1086 consumeToken();
1087 else {
1088 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1089 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1090 HadError = true;
1091 }
1092}
1093
Douglas Gregor6a1db482011-12-09 02:04:43 +00001094/// \brief If there is a specific header search directory due the presence
1095/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1096const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1097 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1098 // If we have an umbrella directory, use that.
1099 if (Mod->hasUmbrellaDir())
1100 return Mod->getUmbrellaDir();
1101
1102 // If we have a framework directory, stop looking.
1103 if (Mod->IsFramework)
1104 return 0;
1105 }
1106
1107 return 0;
1108}
1109
Douglas Gregora30cfe52011-11-11 19:10:28 +00001110/// \brief Parse a module map file.
1111///
1112/// module-map-file:
1113/// module-declaration*
1114bool ModuleMapParser::parseModuleMapFile() {
1115 do {
1116 switch (Tok.Kind) {
1117 case MMToken::EndOfFile:
1118 return HadError;
1119
Douglas Gregor587986e2011-12-07 02:23:45 +00001120 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001121 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001122 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001123 parseModuleDecl();
1124 break;
1125
Douglas Gregor90db2602011-12-02 01:47:07 +00001126 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001127 case MMToken::HeaderKeyword:
1128 case MMToken::Identifier:
1129 case MMToken::LBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001130 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001131 case MMToken::RBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001132 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001133 case MMToken::StringLiteral:
1134 case MMToken::UmbrellaKeyword:
1135 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1136 HadError = true;
1137 consumeToken();
1138 break;
1139 }
1140 } while (true);
1141
1142 return HadError;
1143}
1144
1145bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
1146 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1147 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1148 if (!Buffer)
1149 return true;
1150
1151 // Parse this module map file.
1152 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
1153 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001154 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001155 bool Result = Parser.parseModuleMapFile();
1156 Diags->getClient()->EndSourceFile();
1157
1158 return Result;
1159}