blob: 198544dd5176e2616b76cfdf4ed75f9acb1c3037 [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"
23#include "llvm/Support/Host.h"
Douglas Gregor8b6d3de2011-11-11 21:55:48 +000024#include "llvm/Support/PathV2.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000025#include "llvm/Support/raw_ostream.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/ADT/StringSwitch.h"
28using namespace clang;
29
Douglas Gregor90db2602011-12-02 01:47:07 +000030Module::ExportDecl
31ModuleMap::resolveExport(Module *Mod,
32 const Module::UnresolvedExportDecl &Unresolved,
33 bool Complain) {
Douglas Gregor0adaa882011-12-05 17:28:06 +000034 // We may have just a wildcard.
35 if (Unresolved.Id.empty()) {
36 assert(Unresolved.Wildcard && "Invalid unresolved export");
37 return Module::ExportDecl(0, true);
38 }
39
Douglas Gregor90db2602011-12-02 01:47:07 +000040 // Find the starting module.
41 Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
42 if (!Context) {
43 if (Complain)
44 Diags->Report(Unresolved.Id[0].second,
45 diag::err_mmap_missing_module_unqualified)
46 << Unresolved.Id[0].first << Mod->getFullModuleName();
47
48 return Module::ExportDecl();
49 }
50
51 // Dig into the module path.
52 for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
53 Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
54 Context);
55 if (!Sub) {
56 if (Complain)
57 Diags->Report(Unresolved.Id[I].second,
58 diag::err_mmap_missing_module_qualified)
59 << Unresolved.Id[I].first << Context->getFullModuleName()
60 << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
61
62 return Module::ExportDecl();
63 }
64
65 Context = Sub;
66 }
67
68 return Module::ExportDecl(Context, Unresolved.Wildcard);
69}
70
Douglas Gregora30cfe52011-11-11 19:10:28 +000071ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
72 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
73 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
74 new DiagnosticsEngine(DiagIDs));
75 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
76 SourceMgr = new SourceManager(*Diags, FileMgr);
77}
78
79ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +000080 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
81 IEnd = Modules.end();
82 I != IEnd; ++I) {
83 delete I->getValue();
84 }
85
Douglas Gregora30cfe52011-11-11 19:10:28 +000086 delete SourceMgr;
87}
88
Douglas Gregor1a4761e2011-11-30 23:21:26 +000089Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor65f3b5e2011-11-11 22:18:48 +000090 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
91 = Headers.find(File);
92 if (Known != Headers.end())
93 return Known->second;
94
Douglas Gregoradb97992011-11-16 23:02:25 +000095 const DirectoryEntry *Dir = File->getDir();
Douglas Gregoradb97992011-11-16 23:02:25 +000096 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
97 StringRef DirName = Dir->getName();
Douglas Gregore209e502011-12-06 01:10:29 +000098
99 // Keep walking up the directory hierarchy, looking for a directory with
100 // an umbrella header.
101 do {
102 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
103 = UmbrellaDirs.find(Dir);
104 if (KnownDir != UmbrellaDirs.end()) {
105 Module *Result = KnownDir->second;
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000106
107 // Search up the module stack until we find a module with an umbrella
108 // header.
109 Module *UmbrellaModule = Result;
110 while (!UmbrellaModule->UmbrellaHeader && UmbrellaModule->Parent)
111 UmbrellaModule = UmbrellaModule->Parent;
112
113 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-12-06 01:10:29 +0000114 // Infer submodules for each of the directories we found between
115 // the directory of the umbrella header and the directory where
116 // the actual header is located.
117
118 // For a framework module, the umbrella directory is the framework
119 // directory, so strip off the "Headers" or "PrivateHeaders".
120 // FIXME: Should we tack on an "explicit" for PrivateHeaders? That
121 // might be what we want, but it feels like a hack.
122 unsigned LastSkippedDir = SkippedDirs.size();
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000123 if (LastSkippedDir && UmbrellaModule->IsFramework)
Douglas Gregore209e502011-12-06 01:10:29 +0000124 --LastSkippedDir;
125
126 for (unsigned I = LastSkippedDir; I != 0; --I) {
127 // Find or create the module that corresponds to this directory name.
128 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
129 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000130 UmbrellaModule->InferExplicitSubmodules).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000131
132 // Associate the module and the directory.
133 UmbrellaDirs[SkippedDirs[I-1]] = Result;
134
135 // If inferred submodules export everything they import, add a
136 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000137 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000138 Result->Exports.push_back(Module::ExportDecl(0, true));
139 }
140
141 // Infer a submodule with the same name as this header file.
142 StringRef Name = llvm::sys::path::stem(File->getName());
143 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000144 UmbrellaModule->InferExplicitSubmodules).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000145
146 // If inferred submodules export everything they import, add a
147 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000148 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000149 Result->Exports.push_back(Module::ExportDecl(0, true));
150 } else {
151 // Record each of the directories we stepped through as being part of
152 // the module we found, since the umbrella header covers them all.
153 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
154 UmbrellaDirs[SkippedDirs[I]] = Result;
155 }
156
157 Headers[File] = Result;
158 return Result;
159 }
160
161 SkippedDirs.push_back(Dir);
162
Douglas Gregoradb97992011-11-16 23:02:25 +0000163 // Retrieve our parent path.
164 DirName = llvm::sys::path::parent_path(DirName);
165 if (DirName.empty())
166 break;
167
168 // Resolve the parent path to a directory entry.
169 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000170 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000171
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000172 return 0;
173}
174
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000175Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000176 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
177 if (Known != Modules.end())
178 return Known->getValue();
179
180 return 0;
181}
182
Douglas Gregor90db2602011-12-02 01:47:07 +0000183Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
184 for(; Context; Context = Context->Parent) {
185 if (Module *Sub = lookupModuleQualified(Name, Context))
186 return Sub;
187 }
188
189 return findModule(Name);
190}
191
192Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
193 if (!Context)
194 return findModule(Name);
195
196 llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
197 if (Sub != Context->SubModules.end())
198 return Sub->getValue();
199
200 return 0;
201}
202
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000203std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000204ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
205 bool IsExplicit) {
206 // Try to find an existing module with this name.
207 if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
208 return std::make_pair(Found, false);
209
210 // Create a new module with this name.
211 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
212 IsExplicit);
213 if (Parent)
214 Parent->SubModules[Name] = Result;
215 else
216 Modules[Name] = Result;
217 return std::make_pair(Result, true);
218}
219
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000220Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000221ModuleMap::inferFrameworkModule(StringRef ModuleName,
222 const DirectoryEntry *FrameworkDir) {
223 // Check whether we've already found this module.
224 if (Module *Module = findModule(ModuleName))
225 return Module;
226
227 // Look for an umbrella header.
228 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
229 llvm::sys::path::append(UmbrellaName, "Headers");
230 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
231 const FileEntry *UmbrellaHeader
232 = SourceMgr->getFileManager().getFile(UmbrellaName);
233
234 // FIXME: If there's no umbrella header, we could probably scan the
235 // framework to load *everything*. But, it's not clear that this is a good
236 // idea.
237 if (!UmbrellaHeader)
238 return 0;
239
Douglas Gregora8654052011-11-17 22:09:43 +0000240 Module *Result = new Module(ModuleName, SourceLocation(),
241 /*IsFramework=*/true);
Douglas Gregor209977c2011-12-05 17:40:25 +0000242 // umbrella "umbrella-header-name"
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000243 Result->UmbrellaHeader = UmbrellaHeader;
244 Headers[UmbrellaHeader] = Result;
245 UmbrellaDirs[FrameworkDir] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000246
247 // export *
248 Result->Exports.push_back(Module::ExportDecl(0, true));
249
Douglas Gregore209e502011-12-06 01:10:29 +0000250 // module * { export * }
251 Result->InferSubmodules = true;
252 Result->InferExportWildcard = true;
253
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000254 Modules[ModuleName] = Result;
255 return Result;
256}
257
Douglas Gregore209e502011-12-06 01:10:29 +0000258void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
259 Headers[UmbrellaHeader] = Mod;
260 Mod->UmbrellaHeader = UmbrellaHeader;
261
262 const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir();
263 if (Mod->IsFramework)
264 UmbrellaDir = SourceMgr->getFileManager().getDirectory(
265 llvm::sys::path::parent_path(UmbrellaDir->getName()));
266
267 UmbrellaDirs[UmbrellaDir] = Mod;
268}
269
270void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
271 Mod->Headers.push_back(Header);
272 Headers[Header] = Mod;
273}
274
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000275const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000276ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000277 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
278 return 0;
279
280 return SourceMgr->getFileEntryForID(
281 SourceMgr->getFileID(Module->DefinitionLoc));
282}
283
Douglas Gregora30cfe52011-11-11 19:10:28 +0000284void ModuleMap::dump() {
285 llvm::errs() << "Modules:";
286 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
287 MEnd = Modules.end();
288 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000289 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000290
291 llvm::errs() << "Headers:";
292 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
293 H = Headers.begin(),
294 HEnd = Headers.end();
295 H != HEnd; ++H) {
296 llvm::errs() << " \"" << H->first->getName() << "\" -> "
297 << H->second->getFullModuleName() << "\n";
298 }
299}
300
Douglas Gregor90db2602011-12-02 01:47:07 +0000301bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
302 bool HadError = false;
303 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
304 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
305 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000306 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000307 Mod->Exports.push_back(Export);
308 else
309 HadError = true;
310 }
311 Mod->UnresolvedExports.clear();
312 return HadError;
313}
314
Douglas Gregor55988682011-12-05 16:33:54 +0000315Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
316 if (Loc.isInvalid())
317 return 0;
318
319 // Use the expansion location to determine which module we're in.
320 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
321 if (!ExpansionLoc.isFileID())
322 return 0;
323
324
325 const SourceManager &SrcMgr = Loc.getManager();
326 FileID ExpansionFileID = ExpansionLoc.getFileID();
327 const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
328 if (!ExpansionFile)
329 return 0;
330
331 // Find the module that owns this header.
332 return findModuleForHeader(ExpansionFile);
333}
334
Douglas Gregora30cfe52011-11-11 19:10:28 +0000335//----------------------------------------------------------------------------//
336// Module map file parser
337//----------------------------------------------------------------------------//
338
339namespace clang {
340 /// \brief A token in a module map file.
341 struct MMToken {
342 enum TokenKind {
343 EndOfFile,
344 HeaderKeyword,
345 Identifier,
346 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000347 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000348 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000349 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000350 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000351 UmbrellaKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000352 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000353 StringLiteral,
354 LBrace,
355 RBrace
356 } Kind;
357
358 unsigned Location;
359 unsigned StringLength;
360 const char *StringData;
361
362 void clear() {
363 Kind = EndOfFile;
364 Location = 0;
365 StringLength = 0;
366 StringData = 0;
367 }
368
369 bool is(TokenKind K) const { return Kind == K; }
370
371 SourceLocation getLocation() const {
372 return SourceLocation::getFromRawEncoding(Location);
373 }
374
375 StringRef getString() const {
376 return StringRef(StringData, StringLength);
377 }
378 };
379
380 class ModuleMapParser {
381 Lexer &L;
382 SourceManager &SourceMgr;
383 DiagnosticsEngine &Diags;
384 ModuleMap &Map;
385
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000386 /// \brief The directory that this module map resides in.
387 const DirectoryEntry *Directory;
388
Douglas Gregora30cfe52011-11-11 19:10:28 +0000389 /// \brief Whether an error occurred.
390 bool HadError;
391
392 /// \brief Default target information, used only for string literal
393 /// parsing.
394 TargetInfo *Target;
395
396 /// \brief Stores string data for the various string literals referenced
397 /// during parsing.
398 llvm::BumpPtrAllocator StringData;
399
400 /// \brief The current token.
401 MMToken Tok;
402
403 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000404 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000405
406 /// \brief Consume the current token and return its location.
407 SourceLocation consumeToken();
408
409 /// \brief Skip tokens until we reach the a token with the given kind
410 /// (or the end of the file).
411 void skipUntil(MMToken::TokenKind K);
412
413 void parseModuleDecl();
414 void parseUmbrellaDecl();
415 void parseHeaderDecl();
Douglas Gregor90db2602011-12-02 01:47:07 +0000416 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000417 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000418
419 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000420 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
421 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000422 ModuleMap &Map,
423 const DirectoryEntry *Directory)
424 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
425 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000426 {
427 TargetOptions TargetOpts;
428 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
429 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
430
431 Tok.clear();
432 consumeToken();
433 }
434
435 bool parseModuleMapFile();
436 };
437}
438
439SourceLocation ModuleMapParser::consumeToken() {
440retry:
441 SourceLocation Result = Tok.getLocation();
442 Tok.clear();
443
444 Token LToken;
445 L.LexFromRawLexer(LToken);
446 Tok.Location = LToken.getLocation().getRawEncoding();
447 switch (LToken.getKind()) {
448 case tok::raw_identifier:
449 Tok.StringData = LToken.getRawIdentifierData();
450 Tok.StringLength = LToken.getLength();
451 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
452 .Case("header", MMToken::HeaderKeyword)
453 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000454 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000455 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000456 .Case("module", MMToken::ModuleKeyword)
457 .Case("umbrella", MMToken::UmbrellaKeyword)
458 .Default(MMToken::Identifier);
459 break;
460
461 case tok::eof:
462 Tok.Kind = MMToken::EndOfFile;
463 break;
464
465 case tok::l_brace:
466 Tok.Kind = MMToken::LBrace;
467 break;
468
Douglas Gregor90db2602011-12-02 01:47:07 +0000469 case tok::period:
470 Tok.Kind = MMToken::Period;
471 break;
472
Douglas Gregora30cfe52011-11-11 19:10:28 +0000473 case tok::r_brace:
474 Tok.Kind = MMToken::RBrace;
475 break;
476
Douglas Gregor90db2602011-12-02 01:47:07 +0000477 case tok::star:
478 Tok.Kind = MMToken::Star;
479 break;
480
Douglas Gregora30cfe52011-11-11 19:10:28 +0000481 case tok::string_literal: {
482 // Parse the string literal.
483 LangOptions LangOpts;
484 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
485 if (StringLiteral.hadError)
486 goto retry;
487
488 // Copy the string literal into our string data allocator.
489 unsigned Length = StringLiteral.GetStringLength();
490 char *Saved = StringData.Allocate<char>(Length + 1);
491 memcpy(Saved, StringLiteral.GetString().data(), Length);
492 Saved[Length] = 0;
493
494 // Form the token.
495 Tok.Kind = MMToken::StringLiteral;
496 Tok.StringData = Saved;
497 Tok.StringLength = Length;
498 break;
499 }
500
501 case tok::comment:
502 goto retry;
503
504 default:
505 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
506 HadError = true;
507 goto retry;
508 }
509
510 return Result;
511}
512
513void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
514 unsigned braceDepth = 0;
515 do {
516 switch (Tok.Kind) {
517 case MMToken::EndOfFile:
518 return;
519
520 case MMToken::LBrace:
521 if (Tok.is(K) && braceDepth == 0)
522 return;
523
524 ++braceDepth;
525 break;
526
527 case MMToken::RBrace:
528 if (braceDepth > 0)
529 --braceDepth;
530 else if (Tok.is(K))
531 return;
532 break;
533
534 default:
535 if (braceDepth == 0 && Tok.is(K))
536 return;
537 break;
538 }
539
540 consumeToken();
541 } while (true);
542}
543
544/// \brief Parse a module declaration.
545///
546/// module-declaration:
Douglas Gregora8654052011-11-17 22:09:43 +0000547/// 'framework'[opt] 'module' identifier { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000548///
549/// module-member:
550/// umbrella-declaration
551/// header-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000552/// 'explicit'[opt] submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000553/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000554///
555/// submodule-declaration:
556/// module-declaration
557/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000558void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000559 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
560 Tok.is(MMToken::FrameworkKeyword));
561
562 // Parse 'framework' or 'explicit' keyword, if present.
563 bool Framework = false;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000564 bool Explicit = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000565
566 if (Tok.is(MMToken::FrameworkKeyword)) {
567 consumeToken();
568 Framework = true;
569 }
570 // Parse 'explicit' keyword, if present.
571 else if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000572 consumeToken();
573 Explicit = true;
574 }
575
576 // Parse 'module' keyword.
577 if (!Tok.is(MMToken::ModuleKeyword)) {
578 Diags.Report(Tok.getLocation(),
579 diag::err_mmap_expected_module_after_explicit);
580 consumeToken();
581 HadError = true;
582 return;
583 }
584 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000585
586 // If we have a wildcard for the module name, this is an inferred submodule.
587 // Parse it.
588 if (Tok.is(MMToken::Star))
589 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000590
591 // Parse the module name.
592 if (!Tok.is(MMToken::Identifier)) {
593 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
594 HadError = true;
595 return;
596 }
597 StringRef ModuleName = Tok.getString();
598 SourceLocation ModuleNameLoc = consumeToken();
599
600 // Parse the opening brace.
601 if (!Tok.is(MMToken::LBrace)) {
602 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
603 << ModuleName;
604 HadError = true;
605 return;
606 }
607 SourceLocation LBraceLoc = consumeToken();
608
609 // Determine whether this (sub)module has already been defined.
610 llvm::StringMap<Module *> &ModuleSpace
611 = ActiveModule? ActiveModule->SubModules : Map.Modules;
612 llvm::StringMap<Module *>::iterator ExistingModule
613 = ModuleSpace.find(ModuleName);
614 if (ExistingModule != ModuleSpace.end()) {
615 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
616 << ModuleName;
617 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
618 diag::note_mmap_prev_definition);
619
620 // Skip the module definition.
621 skipUntil(MMToken::RBrace);
622 if (Tok.is(MMToken::RBrace))
623 consumeToken();
624
625 HadError = true;
626 return;
627 }
628
629 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000630 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
631 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000632 ModuleSpace[ModuleName] = ActiveModule;
633
634 bool Done = false;
635 do {
636 switch (Tok.Kind) {
637 case MMToken::EndOfFile:
638 case MMToken::RBrace:
639 Done = true;
640 break;
641
642 case MMToken::ExplicitKeyword:
643 case MMToken::ModuleKeyword:
644 parseModuleDecl();
645 break;
646
Douglas Gregor90db2602011-12-02 01:47:07 +0000647 case MMToken::ExportKeyword:
648 parseExportDecl();
649 break;
650
Douglas Gregora30cfe52011-11-11 19:10:28 +0000651 case MMToken::HeaderKeyword:
652 parseHeaderDecl();
653 break;
654
655 case MMToken::UmbrellaKeyword:
656 parseUmbrellaDecl();
657 break;
Douglas Gregor90db2602011-12-02 01:47:07 +0000658
Douglas Gregora30cfe52011-11-11 19:10:28 +0000659 default:
660 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
661 consumeToken();
662 break;
663 }
664 } while (!Done);
665
666 if (Tok.is(MMToken::RBrace))
667 consumeToken();
668 else {
669 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
670 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
671 HadError = true;
672 }
673
674 // We're done parsing this module. Pop back to our parent scope.
675 ActiveModule = ActiveModule->Parent;
676}
677
678/// \brief Parse an umbrella header declaration.
679///
680/// umbrella-declaration:
681/// 'umbrella' string-literal
682void ModuleMapParser::parseUmbrellaDecl() {
683 assert(Tok.is(MMToken::UmbrellaKeyword));
684 SourceLocation UmbrellaLoc = consumeToken();
685
686 // Parse the header name.
687 if (!Tok.is(MMToken::StringLiteral)) {
688 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
689 << "umbrella";
690 HadError = true;
691 return;
692 }
693 StringRef FileName = Tok.getString();
694 SourceLocation FileNameLoc = consumeToken();
695
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000696 // Check whether we already have an umbrella header.
697 if (ActiveModule->UmbrellaHeader) {
698 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
699 << ActiveModule->getFullModuleName()
700 << ActiveModule->UmbrellaHeader->getName();
701 HadError = true;
702 return;
703 }
704
705 // Only top-level modules can have umbrella headers.
706 if (ActiveModule->Parent) {
707 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
708 << ActiveModule->getFullModuleName();
709 HadError = true;
710 return;
711 }
712
713 // Look for this file.
714 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000715 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000716
717 if (llvm::sys::path::is_absolute(FileName)) {
718 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000719 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000720 } else {
721 // Search for the header file within the search directory.
722 PathName += Directory->getName();
723 unsigned PathLength = PathName.size();
724 if (ActiveModule->isPartOfFramework()) {
725 // Check whether this file is in the public headers.
726 llvm::sys::path::append(PathName, "Headers");
727 llvm::sys::path::append(PathName, FileName);
728 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000729
Douglas Gregor18ee5472011-11-29 21:59:16 +0000730 if (!File) {
731 // Check whether this file is in the private headers.
732 PathName.resize(PathLength);
733 llvm::sys::path::append(PathName, "PrivateHeaders");
734 llvm::sys::path::append(PathName, FileName);
735 File = SourceMgr.getFileManager().getFile(PathName);
736 }
737
738 // FIXME: Deal with subframeworks.
739 } else {
740 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000741 llvm::sys::path::append(PathName, FileName);
742 File = SourceMgr.getFileManager().getFile(PathName);
743 }
Douglas Gregora8654052011-11-17 22:09:43 +0000744 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000745
746 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
747 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000748 if (File) {
Douglas Gregore209e502011-12-06 01:10:29 +0000749 const DirectoryEntry *UmbrellaDir = File->getDir();
750 if (ActiveModule->IsFramework) {
751 // For framework modules, use the framework directory as the umbrella
752 // directory.
753 UmbrellaDir = SourceMgr.getFileManager().getDirectory(
754 llvm::sys::path::parent_path(UmbrellaDir->getName()));
755 }
756
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000757 if (const Module *OwningModule = Map.Headers[File]) {
758 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
759 << FileName << OwningModule->getFullModuleName();
760 HadError = true;
Douglas Gregore209e502011-12-06 01:10:29 +0000761 } else if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
Douglas Gregoradb97992011-11-16 23:02:25 +0000762 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
763 << OwningModule->getFullModuleName();
764 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000765 } else {
766 // Record this umbrella header.
Douglas Gregore209e502011-12-06 01:10:29 +0000767 Map.setUmbrellaHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000768 }
769 } else {
770 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
771 << true << FileName;
772 HadError = true;
773 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000774}
775
776/// \brief Parse a header declaration.
777///
778/// header-declaration:
779/// 'header' string-literal
780void ModuleMapParser::parseHeaderDecl() {
781 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000782 consumeToken();
783
Douglas Gregora30cfe52011-11-11 19:10:28 +0000784 // Parse the header name.
785 if (!Tok.is(MMToken::StringLiteral)) {
786 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
787 << "header";
788 HadError = true;
789 return;
790 }
791 StringRef FileName = Tok.getString();
792 SourceLocation FileNameLoc = consumeToken();
793
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000794 // Look for this file.
795 llvm::SmallString<128> PathName;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000796 if (llvm::sys::path::is_relative(FileName)) {
797 // FIXME: Change this search to also look for private headers!
798 PathName += Directory->getName();
799
800 if (ActiveModule->isPartOfFramework())
801 llvm::sys::path::append(PathName, "Headers");
802 }
Douglas Gregora8654052011-11-17 22:09:43 +0000803
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000804 llvm::sys::path::append(PathName, FileName);
805
806 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
807 // Come up with a lazy way to do this.
808 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
809 if (const Module *OwningModule = Map.Headers[File]) {
810 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
811 << FileName << OwningModule->getFullModuleName();
812 HadError = true;
813 } else {
814 // Record this file.
Douglas Gregore209e502011-12-06 01:10:29 +0000815 Map.addHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000816 }
817 } else {
818 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
819 << false << FileName;
820 HadError = true;
821 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000822}
823
Douglas Gregor90db2602011-12-02 01:47:07 +0000824/// \brief Parse a module export declaration.
825///
826/// export-declaration:
827/// 'export' wildcard-module-id
828///
829/// wildcard-module-id:
830/// identifier
831/// '*'
832/// identifier '.' wildcard-module-id
833void ModuleMapParser::parseExportDecl() {
834 assert(Tok.is(MMToken::ExportKeyword));
835 SourceLocation ExportLoc = consumeToken();
836
837 // Parse the module-id with an optional wildcard at the end.
838 ModuleId ParsedModuleId;
839 bool Wildcard = false;
840 do {
841 if (Tok.is(MMToken::Identifier)) {
842 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
843 Tok.getLocation()));
844 consumeToken();
845
846 if (Tok.is(MMToken::Period)) {
847 consumeToken();
848 continue;
849 }
850
851 break;
852 }
853
854 if(Tok.is(MMToken::Star)) {
855 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +0000856 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +0000857 break;
858 }
859
860 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
861 HadError = true;
862 return;
863 } while (true);
864
865 Module::UnresolvedExportDecl Unresolved = {
866 ExportLoc, ParsedModuleId, Wildcard
867 };
868 ActiveModule->UnresolvedExports.push_back(Unresolved);
869}
870
Douglas Gregor1e123682011-12-05 22:27:44 +0000871void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
872 assert(Tok.is(MMToken::Star));
873 SourceLocation StarLoc = consumeToken();
874 bool Failed = false;
875
876 // Inferred modules must be submodules.
877 if (!ActiveModule) {
878 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
879 Failed = true;
880 }
881
882 // Inferred modules must have umbrella headers.
883 if (!Failed && !ActiveModule->getTopLevelModule()->UmbrellaHeader) {
884 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
885 Failed = true;
886 }
887
888 // Check for redefinition of an inferred module.
889 if (!Failed && ActiveModule->getTopLevelModule()->InferSubmodules) {
890 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
891 if (ActiveModule->getTopLevelModule()->InferredSubmoduleLoc.isValid())
892 Diags.Report(ActiveModule->getTopLevelModule()->InferredSubmoduleLoc,
893 diag::note_mmap_prev_definition);
894 Failed = true;
895 }
896
897 // If there were any problems with this inferred submodule, skip its body.
898 if (Failed) {
899 if (Tok.is(MMToken::LBrace)) {
900 consumeToken();
901 skipUntil(MMToken::RBrace);
902 if (Tok.is(MMToken::RBrace))
903 consumeToken();
904 }
905 HadError = true;
906 return;
907 }
908
909 // Note that we have an inferred submodule.
910 Module *TopModule = ActiveModule->getTopLevelModule();
911 TopModule->InferSubmodules = true;
912 TopModule->InferredSubmoduleLoc = StarLoc;
913 TopModule->InferExplicitSubmodules = Explicit;
914
915 // Parse the opening brace.
916 if (!Tok.is(MMToken::LBrace)) {
917 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
918 HadError = true;
919 return;
920 }
921 SourceLocation LBraceLoc = consumeToken();
922
923 // Parse the body of the inferred submodule.
924 bool Done = false;
925 do {
926 switch (Tok.Kind) {
927 case MMToken::EndOfFile:
928 case MMToken::RBrace:
929 Done = true;
930 break;
931
932 case MMToken::ExportKeyword: {
933 consumeToken();
934 if (Tok.is(MMToken::Star))
935 TopModule->InferExportWildcard = true;
936 else
937 Diags.Report(Tok.getLocation(),
938 diag::err_mmap_expected_export_wildcard);
939 consumeToken();
940 break;
941 }
942
943 case MMToken::ExplicitKeyword:
944 case MMToken::ModuleKeyword:
945 case MMToken::HeaderKeyword:
946 case MMToken::UmbrellaKeyword:
947 default:
948 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
949 consumeToken();
950 break;
951 }
952 } while (!Done);
953
954 if (Tok.is(MMToken::RBrace))
955 consumeToken();
956 else {
957 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
958 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
959 HadError = true;
960 }
961}
962
Douglas Gregora30cfe52011-11-11 19:10:28 +0000963/// \brief Parse a module map file.
964///
965/// module-map-file:
966/// module-declaration*
967bool ModuleMapParser::parseModuleMapFile() {
968 do {
969 switch (Tok.Kind) {
970 case MMToken::EndOfFile:
971 return HadError;
972
973 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +0000974 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000975 parseModuleDecl();
976 break;
977
978 case MMToken::ExplicitKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +0000979 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000980 case MMToken::HeaderKeyword:
981 case MMToken::Identifier:
982 case MMToken::LBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +0000983 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000984 case MMToken::RBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +0000985 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000986 case MMToken::StringLiteral:
987 case MMToken::UmbrellaKeyword:
988 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
989 HadError = true;
990 consumeToken();
991 break;
992 }
993 } while (true);
994
995 return HadError;
996}
997
998bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
999 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1000 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1001 if (!Buffer)
1002 return true;
1003
1004 // Parse this module map file.
1005 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
1006 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001007 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001008 bool Result = Parser.parseModuleMapFile();
1009 Diags->getClient()->EndSourceFile();
1010
1011 return Result;
1012}