blob: b20ccd122f541d70157460f3c055b5542f0fa900 [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) {
34 // Find the starting module.
35 Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
36 if (!Context) {
37 if (Complain)
38 Diags->Report(Unresolved.Id[0].second,
39 diag::err_mmap_missing_module_unqualified)
40 << Unresolved.Id[0].first << Mod->getFullModuleName();
41
42 return Module::ExportDecl();
43 }
44
45 // Dig into the module path.
46 for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
47 Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
48 Context);
49 if (!Sub) {
50 if (Complain)
51 Diags->Report(Unresolved.Id[I].second,
52 diag::err_mmap_missing_module_qualified)
53 << Unresolved.Id[I].first << Context->getFullModuleName()
54 << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
55
56 return Module::ExportDecl();
57 }
58
59 Context = Sub;
60 }
61
62 return Module::ExportDecl(Context, Unresolved.Wildcard);
63}
64
Douglas Gregora30cfe52011-11-11 19:10:28 +000065ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
66 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
67 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
68 new DiagnosticsEngine(DiagIDs));
69 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
70 SourceMgr = new SourceManager(*Diags, FileMgr);
71}
72
73ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +000074 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
75 IEnd = Modules.end();
76 I != IEnd; ++I) {
77 delete I->getValue();
78 }
79
Douglas Gregora30cfe52011-11-11 19:10:28 +000080 delete SourceMgr;
81}
82
Douglas Gregor1a4761e2011-11-30 23:21:26 +000083Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor65f3b5e2011-11-11 22:18:48 +000084 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
85 = Headers.find(File);
86 if (Known != Headers.end())
87 return Known->second;
88
Douglas Gregoradb97992011-11-16 23:02:25 +000089 const DirectoryEntry *Dir = File->getDir();
90 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
91 = UmbrellaDirs.find(Dir);
92 if (KnownDir != UmbrellaDirs.end())
93 return KnownDir->second;
94
95 // Walk up the directory hierarchy looking for umbrella headers.
96 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
97 StringRef DirName = Dir->getName();
98 do {
99 // Retrieve our parent path.
100 DirName = llvm::sys::path::parent_path(DirName);
101 if (DirName.empty())
102 break;
103
104 // Resolve the parent path to a directory entry.
105 Dir = SourceMgr->getFileManager().getDirectory(DirName);
106 if (!Dir)
107 break;
108
109 KnownDir = UmbrellaDirs.find(Dir);
110 if (KnownDir != UmbrellaDirs.end()) {
111 Module *Result = KnownDir->second;
112
113 // Record each of the directories we stepped through as being part of
114 // the module we found, since the umbrella header covers them all.
115 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
116 UmbrellaDirs[SkippedDirs[I]] = Result;
117
118 return Result;
119 }
120
121 SkippedDirs.push_back(Dir);
122 } while (true);
123
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000124 return 0;
125}
126
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000127Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000128 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
129 if (Known != Modules.end())
130 return Known->getValue();
131
132 return 0;
133}
134
Douglas Gregor90db2602011-12-02 01:47:07 +0000135Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
136 for(; Context; Context = Context->Parent) {
137 if (Module *Sub = lookupModuleQualified(Name, Context))
138 return Sub;
139 }
140
141 return findModule(Name);
142}
143
144Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
145 if (!Context)
146 return findModule(Name);
147
148 llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
149 if (Sub != Context->SubModules.end())
150 return Sub->getValue();
151
152 return 0;
153}
154
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000155std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000156ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
157 bool IsExplicit) {
158 // Try to find an existing module with this name.
159 if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
160 return std::make_pair(Found, false);
161
162 // Create a new module with this name.
163 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
164 IsExplicit);
165 if (Parent)
166 Parent->SubModules[Name] = Result;
167 else
168 Modules[Name] = Result;
169 return std::make_pair(Result, true);
170}
171
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000172Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000173ModuleMap::inferFrameworkModule(StringRef ModuleName,
174 const DirectoryEntry *FrameworkDir) {
175 // Check whether we've already found this module.
176 if (Module *Module = findModule(ModuleName))
177 return Module;
178
179 // Look for an umbrella header.
180 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
181 llvm::sys::path::append(UmbrellaName, "Headers");
182 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
183 const FileEntry *UmbrellaHeader
184 = SourceMgr->getFileManager().getFile(UmbrellaName);
185
186 // FIXME: If there's no umbrella header, we could probably scan the
187 // framework to load *everything*. But, it's not clear that this is a good
188 // idea.
189 if (!UmbrellaHeader)
190 return 0;
191
Douglas Gregora8654052011-11-17 22:09:43 +0000192 Module *Result = new Module(ModuleName, SourceLocation(),
193 /*IsFramework=*/true);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000194 Result->UmbrellaHeader = UmbrellaHeader;
195 Headers[UmbrellaHeader] = Result;
196 UmbrellaDirs[FrameworkDir] = Result;
197 Modules[ModuleName] = Result;
198 return Result;
199}
200
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000201const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000202ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000203 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
204 return 0;
205
206 return SourceMgr->getFileEntryForID(
207 SourceMgr->getFileID(Module->DefinitionLoc));
208}
209
Douglas Gregora30cfe52011-11-11 19:10:28 +0000210void ModuleMap::dump() {
211 llvm::errs() << "Modules:";
212 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
213 MEnd = Modules.end();
214 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000215 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000216
217 llvm::errs() << "Headers:";
218 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
219 H = Headers.begin(),
220 HEnd = Headers.end();
221 H != HEnd; ++H) {
222 llvm::errs() << " \"" << H->first->getName() << "\" -> "
223 << H->second->getFullModuleName() << "\n";
224 }
225}
226
Douglas Gregor90db2602011-12-02 01:47:07 +0000227bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
228 bool HadError = false;
229 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
230 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
231 Complain);
232 if (Export.getPointer())
233 Mod->Exports.push_back(Export);
234 else
235 HadError = true;
236 }
237 Mod->UnresolvedExports.clear();
238 return HadError;
239}
240
Douglas Gregor55988682011-12-05 16:33:54 +0000241Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
242 if (Loc.isInvalid())
243 return 0;
244
245 // Use the expansion location to determine which module we're in.
246 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
247 if (!ExpansionLoc.isFileID())
248 return 0;
249
250
251 const SourceManager &SrcMgr = Loc.getManager();
252 FileID ExpansionFileID = ExpansionLoc.getFileID();
253 const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
254 if (!ExpansionFile)
255 return 0;
256
257 // Find the module that owns this header.
258 return findModuleForHeader(ExpansionFile);
259}
260
Douglas Gregora30cfe52011-11-11 19:10:28 +0000261//----------------------------------------------------------------------------//
262// Module map file parser
263//----------------------------------------------------------------------------//
264
265namespace clang {
266 /// \brief A token in a module map file.
267 struct MMToken {
268 enum TokenKind {
269 EndOfFile,
270 HeaderKeyword,
271 Identifier,
272 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000273 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000274 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000275 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000276 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000277 UmbrellaKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000278 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000279 StringLiteral,
280 LBrace,
281 RBrace
282 } Kind;
283
284 unsigned Location;
285 unsigned StringLength;
286 const char *StringData;
287
288 void clear() {
289 Kind = EndOfFile;
290 Location = 0;
291 StringLength = 0;
292 StringData = 0;
293 }
294
295 bool is(TokenKind K) const { return Kind == K; }
296
297 SourceLocation getLocation() const {
298 return SourceLocation::getFromRawEncoding(Location);
299 }
300
301 StringRef getString() const {
302 return StringRef(StringData, StringLength);
303 }
304 };
305
306 class ModuleMapParser {
307 Lexer &L;
308 SourceManager &SourceMgr;
309 DiagnosticsEngine &Diags;
310 ModuleMap &Map;
311
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000312 /// \brief The directory that this module map resides in.
313 const DirectoryEntry *Directory;
314
Douglas Gregora30cfe52011-11-11 19:10:28 +0000315 /// \brief Whether an error occurred.
316 bool HadError;
317
318 /// \brief Default target information, used only for string literal
319 /// parsing.
320 TargetInfo *Target;
321
322 /// \brief Stores string data for the various string literals referenced
323 /// during parsing.
324 llvm::BumpPtrAllocator StringData;
325
326 /// \brief The current token.
327 MMToken Tok;
328
329 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000330 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000331
332 /// \brief Consume the current token and return its location.
333 SourceLocation consumeToken();
334
335 /// \brief Skip tokens until we reach the a token with the given kind
336 /// (or the end of the file).
337 void skipUntil(MMToken::TokenKind K);
338
339 void parseModuleDecl();
340 void parseUmbrellaDecl();
341 void parseHeaderDecl();
Douglas Gregor90db2602011-12-02 01:47:07 +0000342 void parseExportDecl();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000343
344 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000345 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
346 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000347 ModuleMap &Map,
348 const DirectoryEntry *Directory)
349 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
350 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000351 {
352 TargetOptions TargetOpts;
353 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
354 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
355
356 Tok.clear();
357 consumeToken();
358 }
359
360 bool parseModuleMapFile();
361 };
362}
363
364SourceLocation ModuleMapParser::consumeToken() {
365retry:
366 SourceLocation Result = Tok.getLocation();
367 Tok.clear();
368
369 Token LToken;
370 L.LexFromRawLexer(LToken);
371 Tok.Location = LToken.getLocation().getRawEncoding();
372 switch (LToken.getKind()) {
373 case tok::raw_identifier:
374 Tok.StringData = LToken.getRawIdentifierData();
375 Tok.StringLength = LToken.getLength();
376 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
377 .Case("header", MMToken::HeaderKeyword)
378 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000379 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000380 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000381 .Case("module", MMToken::ModuleKeyword)
382 .Case("umbrella", MMToken::UmbrellaKeyword)
383 .Default(MMToken::Identifier);
384 break;
385
386 case tok::eof:
387 Tok.Kind = MMToken::EndOfFile;
388 break;
389
390 case tok::l_brace:
391 Tok.Kind = MMToken::LBrace;
392 break;
393
Douglas Gregor90db2602011-12-02 01:47:07 +0000394 case tok::period:
395 Tok.Kind = MMToken::Period;
396 break;
397
Douglas Gregora30cfe52011-11-11 19:10:28 +0000398 case tok::r_brace:
399 Tok.Kind = MMToken::RBrace;
400 break;
401
Douglas Gregor90db2602011-12-02 01:47:07 +0000402 case tok::star:
403 Tok.Kind = MMToken::Star;
404 break;
405
Douglas Gregora30cfe52011-11-11 19:10:28 +0000406 case tok::string_literal: {
407 // Parse the string literal.
408 LangOptions LangOpts;
409 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
410 if (StringLiteral.hadError)
411 goto retry;
412
413 // Copy the string literal into our string data allocator.
414 unsigned Length = StringLiteral.GetStringLength();
415 char *Saved = StringData.Allocate<char>(Length + 1);
416 memcpy(Saved, StringLiteral.GetString().data(), Length);
417 Saved[Length] = 0;
418
419 // Form the token.
420 Tok.Kind = MMToken::StringLiteral;
421 Tok.StringData = Saved;
422 Tok.StringLength = Length;
423 break;
424 }
425
426 case tok::comment:
427 goto retry;
428
429 default:
430 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
431 HadError = true;
432 goto retry;
433 }
434
435 return Result;
436}
437
438void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
439 unsigned braceDepth = 0;
440 do {
441 switch (Tok.Kind) {
442 case MMToken::EndOfFile:
443 return;
444
445 case MMToken::LBrace:
446 if (Tok.is(K) && braceDepth == 0)
447 return;
448
449 ++braceDepth;
450 break;
451
452 case MMToken::RBrace:
453 if (braceDepth > 0)
454 --braceDepth;
455 else if (Tok.is(K))
456 return;
457 break;
458
459 default:
460 if (braceDepth == 0 && Tok.is(K))
461 return;
462 break;
463 }
464
465 consumeToken();
466 } while (true);
467}
468
469/// \brief Parse a module declaration.
470///
471/// module-declaration:
Douglas Gregora8654052011-11-17 22:09:43 +0000472/// 'framework'[opt] 'module' identifier { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000473///
474/// module-member:
475/// umbrella-declaration
476/// header-declaration
477/// 'explicit'[opt] module-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000478/// export-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000479void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000480 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
481 Tok.is(MMToken::FrameworkKeyword));
482
483 // Parse 'framework' or 'explicit' keyword, if present.
484 bool Framework = false;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000485 bool Explicit = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000486
487 if (Tok.is(MMToken::FrameworkKeyword)) {
488 consumeToken();
489 Framework = true;
490 }
491 // Parse 'explicit' keyword, if present.
492 else if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000493 consumeToken();
494 Explicit = true;
495 }
496
497 // Parse 'module' keyword.
498 if (!Tok.is(MMToken::ModuleKeyword)) {
499 Diags.Report(Tok.getLocation(),
500 diag::err_mmap_expected_module_after_explicit);
501 consumeToken();
502 HadError = true;
503 return;
504 }
505 consumeToken(); // 'module' keyword
506
507 // Parse the module name.
508 if (!Tok.is(MMToken::Identifier)) {
509 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
510 HadError = true;
511 return;
512 }
513 StringRef ModuleName = Tok.getString();
514 SourceLocation ModuleNameLoc = consumeToken();
515
516 // Parse the opening brace.
517 if (!Tok.is(MMToken::LBrace)) {
518 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
519 << ModuleName;
520 HadError = true;
521 return;
522 }
523 SourceLocation LBraceLoc = consumeToken();
524
525 // Determine whether this (sub)module has already been defined.
526 llvm::StringMap<Module *> &ModuleSpace
527 = ActiveModule? ActiveModule->SubModules : Map.Modules;
528 llvm::StringMap<Module *>::iterator ExistingModule
529 = ModuleSpace.find(ModuleName);
530 if (ExistingModule != ModuleSpace.end()) {
531 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
532 << ModuleName;
533 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
534 diag::note_mmap_prev_definition);
535
536 // Skip the module definition.
537 skipUntil(MMToken::RBrace);
538 if (Tok.is(MMToken::RBrace))
539 consumeToken();
540
541 HadError = true;
542 return;
543 }
544
545 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000546 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
547 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000548 ModuleSpace[ModuleName] = ActiveModule;
549
550 bool Done = false;
551 do {
552 switch (Tok.Kind) {
553 case MMToken::EndOfFile:
554 case MMToken::RBrace:
555 Done = true;
556 break;
557
558 case MMToken::ExplicitKeyword:
559 case MMToken::ModuleKeyword:
560 parseModuleDecl();
561 break;
562
Douglas Gregor90db2602011-12-02 01:47:07 +0000563 case MMToken::ExportKeyword:
564 parseExportDecl();
565 break;
566
Douglas Gregora30cfe52011-11-11 19:10:28 +0000567 case MMToken::HeaderKeyword:
568 parseHeaderDecl();
569 break;
570
571 case MMToken::UmbrellaKeyword:
572 parseUmbrellaDecl();
573 break;
Douglas Gregor90db2602011-12-02 01:47:07 +0000574
Douglas Gregora30cfe52011-11-11 19:10:28 +0000575 default:
576 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
577 consumeToken();
578 break;
579 }
580 } while (!Done);
581
582 if (Tok.is(MMToken::RBrace))
583 consumeToken();
584 else {
585 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
586 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
587 HadError = true;
588 }
589
590 // We're done parsing this module. Pop back to our parent scope.
591 ActiveModule = ActiveModule->Parent;
592}
593
594/// \brief Parse an umbrella header declaration.
595///
596/// umbrella-declaration:
597/// 'umbrella' string-literal
598void ModuleMapParser::parseUmbrellaDecl() {
599 assert(Tok.is(MMToken::UmbrellaKeyword));
600 SourceLocation UmbrellaLoc = consumeToken();
601
602 // Parse the header name.
603 if (!Tok.is(MMToken::StringLiteral)) {
604 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
605 << "umbrella";
606 HadError = true;
607 return;
608 }
609 StringRef FileName = Tok.getString();
610 SourceLocation FileNameLoc = consumeToken();
611
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000612 // Check whether we already have an umbrella header.
613 if (ActiveModule->UmbrellaHeader) {
614 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
615 << ActiveModule->getFullModuleName()
616 << ActiveModule->UmbrellaHeader->getName();
617 HadError = true;
618 return;
619 }
620
621 // Only top-level modules can have umbrella headers.
622 if (ActiveModule->Parent) {
623 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
624 << ActiveModule->getFullModuleName();
625 HadError = true;
626 return;
627 }
628
629 // Look for this file.
630 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000631 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000632
633 if (llvm::sys::path::is_absolute(FileName)) {
634 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000635 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000636 } else {
637 // Search for the header file within the search directory.
638 PathName += Directory->getName();
639 unsigned PathLength = PathName.size();
640 if (ActiveModule->isPartOfFramework()) {
641 // Check whether this file is in the public headers.
642 llvm::sys::path::append(PathName, "Headers");
643 llvm::sys::path::append(PathName, FileName);
644 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000645
Douglas Gregor18ee5472011-11-29 21:59:16 +0000646 if (!File) {
647 // Check whether this file is in the private headers.
648 PathName.resize(PathLength);
649 llvm::sys::path::append(PathName, "PrivateHeaders");
650 llvm::sys::path::append(PathName, FileName);
651 File = SourceMgr.getFileManager().getFile(PathName);
652 }
653
654 // FIXME: Deal with subframeworks.
655 } else {
656 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000657 llvm::sys::path::append(PathName, FileName);
658 File = SourceMgr.getFileManager().getFile(PathName);
659 }
Douglas Gregora8654052011-11-17 22:09:43 +0000660 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000661
662 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
663 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000664 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000665 if (const Module *OwningModule = Map.Headers[File]) {
666 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
667 << FileName << OwningModule->getFullModuleName();
668 HadError = true;
Douglas Gregoradb97992011-11-16 23:02:25 +0000669 } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
670 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
671 << OwningModule->getFullModuleName();
672 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000673 } else {
674 // Record this umbrella header.
675 ActiveModule->UmbrellaHeader = File;
676 Map.Headers[File] = ActiveModule;
Douglas Gregoradb97992011-11-16 23:02:25 +0000677 Map.UmbrellaDirs[Directory] = ActiveModule;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000678 }
679 } else {
680 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
681 << true << FileName;
682 HadError = true;
683 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000684}
685
686/// \brief Parse a header declaration.
687///
688/// header-declaration:
689/// 'header' string-literal
690void ModuleMapParser::parseHeaderDecl() {
691 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000692 consumeToken();
693
Douglas Gregora30cfe52011-11-11 19:10:28 +0000694 // Parse the header name.
695 if (!Tok.is(MMToken::StringLiteral)) {
696 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
697 << "header";
698 HadError = true;
699 return;
700 }
701 StringRef FileName = Tok.getString();
702 SourceLocation FileNameLoc = consumeToken();
703
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000704 // Look for this file.
705 llvm::SmallString<128> PathName;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000706 if (llvm::sys::path::is_relative(FileName)) {
707 // FIXME: Change this search to also look for private headers!
708 PathName += Directory->getName();
709
710 if (ActiveModule->isPartOfFramework())
711 llvm::sys::path::append(PathName, "Headers");
712 }
Douglas Gregora8654052011-11-17 22:09:43 +0000713
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000714 llvm::sys::path::append(PathName, FileName);
715
716 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
717 // Come up with a lazy way to do this.
718 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
719 if (const Module *OwningModule = Map.Headers[File]) {
720 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
721 << FileName << OwningModule->getFullModuleName();
722 HadError = true;
723 } else {
724 // Record this file.
725 ActiveModule->Headers.push_back(File);
726 Map.Headers[File] = ActiveModule;
727 }
728 } else {
729 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
730 << false << FileName;
731 HadError = true;
732 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000733}
734
Douglas Gregor90db2602011-12-02 01:47:07 +0000735/// \brief Parse a module export declaration.
736///
737/// export-declaration:
738/// 'export' wildcard-module-id
739///
740/// wildcard-module-id:
741/// identifier
742/// '*'
743/// identifier '.' wildcard-module-id
744void ModuleMapParser::parseExportDecl() {
745 assert(Tok.is(MMToken::ExportKeyword));
746 SourceLocation ExportLoc = consumeToken();
747
748 // Parse the module-id with an optional wildcard at the end.
749 ModuleId ParsedModuleId;
750 bool Wildcard = false;
751 do {
752 if (Tok.is(MMToken::Identifier)) {
753 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
754 Tok.getLocation()));
755 consumeToken();
756
757 if (Tok.is(MMToken::Period)) {
758 consumeToken();
759 continue;
760 }
761
762 break;
763 }
764
765 if(Tok.is(MMToken::Star)) {
766 Wildcard = true;
767 break;
768 }
769
770 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
771 HadError = true;
772 return;
773 } while (true);
774
775 Module::UnresolvedExportDecl Unresolved = {
776 ExportLoc, ParsedModuleId, Wildcard
777 };
778 ActiveModule->UnresolvedExports.push_back(Unresolved);
779}
780
Douglas Gregora30cfe52011-11-11 19:10:28 +0000781/// \brief Parse a module map file.
782///
783/// module-map-file:
784/// module-declaration*
785bool ModuleMapParser::parseModuleMapFile() {
786 do {
787 switch (Tok.Kind) {
788 case MMToken::EndOfFile:
789 return HadError;
790
791 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +0000792 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000793 parseModuleDecl();
794 break;
795
796 case MMToken::ExplicitKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +0000797 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000798 case MMToken::HeaderKeyword:
799 case MMToken::Identifier:
800 case MMToken::LBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +0000801 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000802 case MMToken::RBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +0000803 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000804 case MMToken::StringLiteral:
805 case MMToken::UmbrellaKeyword:
806 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
807 HadError = true;
808 consumeToken();
809 break;
810 }
811 } while (true);
812
813 return HadError;
814}
815
816bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
817 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
818 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
819 if (!Buffer)
820 return true;
821
822 // Parse this module map file.
823 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
824 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000825 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000826 bool Result = Parser.parseModuleMapFile();
827 Diags->getClient()->EndSourceFile();
828
829 return Result;
830}