blob: 60c797c362a4eb388f8fc396831cbae81de8025b [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
30//----------------------------------------------------------------------------//
31// Module
32//----------------------------------------------------------------------------//
33
Douglas Gregor09fe1bb2011-11-17 02:05:44 +000034ModuleMap::Module::~Module() {
35 for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
36 IEnd = SubModules.end();
37 I != IEnd; ++I) {
38 delete I->getValue();
39 }
40
41}
42
Douglas Gregora30cfe52011-11-11 19:10:28 +000043std::string ModuleMap::Module::getFullModuleName() const {
44 llvm::SmallVector<StringRef, 2> Names;
45
46 // Build up the set of module names (from innermost to outermost).
47 for (const Module *M = this; M; M = M->Parent)
48 Names.push_back(M->Name);
49
50 std::string Result;
51 for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
52 IEnd = Names.rend();
53 I != IEnd; ++I) {
54 if (!Result.empty())
55 Result += '.';
56
57 Result += *I;
58 }
59
60 return Result;
61}
62
Douglas Gregor65f3b5e2011-11-11 22:18:48 +000063StringRef ModuleMap::Module::getTopLevelModuleName() const {
64 const Module *Top = this;
65 while (Top->Parent)
66 Top = Top->Parent;
67
68 return Top->Name;
69}
70
Douglas Gregor804c3bf2011-11-29 18:17:59 +000071static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
Douglas Gregor18ee5472011-11-29 21:59:16 +000072 OS << std::string(Spaces, ' ');
Douglas Gregor804c3bf2011-11-29 18:17:59 +000073}
74
75void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
76 indent(OS, Indent);
77 if (IsFramework)
78 OS << "framework ";
79 if (IsExplicit)
80 OS << "explicit ";
Douglas Gregor18ee5472011-11-29 21:59:16 +000081 OS << "module " << Name << " {\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +000082
83 if (UmbrellaHeader) {
84 indent(OS, Indent + 2);
85 OS << "umbrella \"" << UmbrellaHeader->getName() << "\"\n";
86 }
87
88 for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
89 indent(OS, Indent + 2);
90 OS << "header \"" << Headers[I]->getName() << "\"\n";
91 }
92
93 for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
94 MIEnd = SubModules.end();
95 MI != MIEnd; ++MI)
96 MI->getValue()->print(OS, Indent + 2);
97
98 indent(OS, Indent);
99 OS << "}\n";
100}
101
102void ModuleMap::Module::dump() const {
103 print(llvm::errs());
104}
105
Douglas Gregora30cfe52011-11-11 19:10:28 +0000106//----------------------------------------------------------------------------//
107// Module map
108//----------------------------------------------------------------------------//
109
110ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
111 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
112 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
113 new DiagnosticsEngine(DiagIDs));
114 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
115 SourceMgr = new SourceManager(*Diags, FileMgr);
116}
117
118ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +0000119 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
120 IEnd = Modules.end();
121 I != IEnd; ++I) {
122 delete I->getValue();
123 }
124
Douglas Gregora30cfe52011-11-11 19:10:28 +0000125 delete SourceMgr;
126}
127
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000128ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
129 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
130 = Headers.find(File);
131 if (Known != Headers.end())
132 return Known->second;
133
Douglas Gregoradb97992011-11-16 23:02:25 +0000134 const DirectoryEntry *Dir = File->getDir();
135 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
136 = UmbrellaDirs.find(Dir);
137 if (KnownDir != UmbrellaDirs.end())
138 return KnownDir->second;
139
140 // Walk up the directory hierarchy looking for umbrella headers.
141 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
142 StringRef DirName = Dir->getName();
143 do {
144 // Retrieve our parent path.
145 DirName = llvm::sys::path::parent_path(DirName);
146 if (DirName.empty())
147 break;
148
149 // Resolve the parent path to a directory entry.
150 Dir = SourceMgr->getFileManager().getDirectory(DirName);
151 if (!Dir)
152 break;
153
154 KnownDir = UmbrellaDirs.find(Dir);
155 if (KnownDir != UmbrellaDirs.end()) {
156 Module *Result = KnownDir->second;
157
158 // Record each of the directories we stepped through as being part of
159 // the module we found, since the umbrella header covers them all.
160 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
161 UmbrellaDirs[SkippedDirs[I]] = Result;
162
163 return Result;
164 }
165
166 SkippedDirs.push_back(Dir);
167 } while (true);
168
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000169 return 0;
170}
171
Douglas Gregor484535e2011-11-11 23:20:24 +0000172ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
173 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
174 if (Known != Modules.end())
175 return Known->getValue();
176
177 return 0;
178}
179
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000180ModuleMap::Module *
181ModuleMap::inferFrameworkModule(StringRef ModuleName,
182 const DirectoryEntry *FrameworkDir) {
183 // Check whether we've already found this module.
184 if (Module *Module = findModule(ModuleName))
185 return Module;
186
187 // Look for an umbrella header.
188 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
189 llvm::sys::path::append(UmbrellaName, "Headers");
190 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
191 const FileEntry *UmbrellaHeader
192 = SourceMgr->getFileManager().getFile(UmbrellaName);
193
194 // FIXME: If there's no umbrella header, we could probably scan the
195 // framework to load *everything*. But, it's not clear that this is a good
196 // idea.
197 if (!UmbrellaHeader)
198 return 0;
199
Douglas Gregora8654052011-11-17 22:09:43 +0000200 Module *Result = new Module(ModuleName, SourceLocation(),
201 /*IsFramework=*/true);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000202 Result->UmbrellaHeader = UmbrellaHeader;
203 Headers[UmbrellaHeader] = Result;
204 UmbrellaDirs[FrameworkDir] = Result;
205 Modules[ModuleName] = Result;
206 return Result;
207}
208
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000209const FileEntry *
210ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) {
211 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
212 return 0;
213
214 return SourceMgr->getFileEntryForID(
215 SourceMgr->getFileID(Module->DefinitionLoc));
216}
217
Douglas Gregora30cfe52011-11-11 19:10:28 +0000218void ModuleMap::dump() {
219 llvm::errs() << "Modules:";
220 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
221 MEnd = Modules.end();
222 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000223 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000224
225 llvm::errs() << "Headers:";
226 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
227 H = Headers.begin(),
228 HEnd = Headers.end();
229 H != HEnd; ++H) {
230 llvm::errs() << " \"" << H->first->getName() << "\" -> "
231 << H->second->getFullModuleName() << "\n";
232 }
233}
234
235//----------------------------------------------------------------------------//
236// Module map file parser
237//----------------------------------------------------------------------------//
238
239namespace clang {
240 /// \brief A token in a module map file.
241 struct MMToken {
242 enum TokenKind {
243 EndOfFile,
244 HeaderKeyword,
245 Identifier,
246 ExplicitKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000247 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000248 ModuleKeyword,
249 UmbrellaKeyword,
250 StringLiteral,
251 LBrace,
252 RBrace
253 } Kind;
254
255 unsigned Location;
256 unsigned StringLength;
257 const char *StringData;
258
259 void clear() {
260 Kind = EndOfFile;
261 Location = 0;
262 StringLength = 0;
263 StringData = 0;
264 }
265
266 bool is(TokenKind K) const { return Kind == K; }
267
268 SourceLocation getLocation() const {
269 return SourceLocation::getFromRawEncoding(Location);
270 }
271
272 StringRef getString() const {
273 return StringRef(StringData, StringLength);
274 }
275 };
276
277 class ModuleMapParser {
278 Lexer &L;
279 SourceManager &SourceMgr;
280 DiagnosticsEngine &Diags;
281 ModuleMap &Map;
282
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000283 /// \brief The directory that this module map resides in.
284 const DirectoryEntry *Directory;
285
Douglas Gregora30cfe52011-11-11 19:10:28 +0000286 /// \brief Whether an error occurred.
287 bool HadError;
288
289 /// \brief Default target information, used only for string literal
290 /// parsing.
291 TargetInfo *Target;
292
293 /// \brief Stores string data for the various string literals referenced
294 /// during parsing.
295 llvm::BumpPtrAllocator StringData;
296
297 /// \brief The current token.
298 MMToken Tok;
299
300 /// \brief The active module.
301 ModuleMap::Module *ActiveModule;
302
303 /// \brief Consume the current token and return its location.
304 SourceLocation consumeToken();
305
306 /// \brief Skip tokens until we reach the a token with the given kind
307 /// (or the end of the file).
308 void skipUntil(MMToken::TokenKind K);
309
310 void parseModuleDecl();
311 void parseUmbrellaDecl();
312 void parseHeaderDecl();
313
314 public:
315 typedef ModuleMap::Module Module;
316
317 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
318 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000319 ModuleMap &Map,
320 const DirectoryEntry *Directory)
321 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
322 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000323 {
324 TargetOptions TargetOpts;
325 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
326 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
327
328 Tok.clear();
329 consumeToken();
330 }
331
332 bool parseModuleMapFile();
333 };
334}
335
336SourceLocation ModuleMapParser::consumeToken() {
337retry:
338 SourceLocation Result = Tok.getLocation();
339 Tok.clear();
340
341 Token LToken;
342 L.LexFromRawLexer(LToken);
343 Tok.Location = LToken.getLocation().getRawEncoding();
344 switch (LToken.getKind()) {
345 case tok::raw_identifier:
346 Tok.StringData = LToken.getRawIdentifierData();
347 Tok.StringLength = LToken.getLength();
348 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
349 .Case("header", MMToken::HeaderKeyword)
350 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000351 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000352 .Case("module", MMToken::ModuleKeyword)
353 .Case("umbrella", MMToken::UmbrellaKeyword)
354 .Default(MMToken::Identifier);
355 break;
356
357 case tok::eof:
358 Tok.Kind = MMToken::EndOfFile;
359 break;
360
361 case tok::l_brace:
362 Tok.Kind = MMToken::LBrace;
363 break;
364
365 case tok::r_brace:
366 Tok.Kind = MMToken::RBrace;
367 break;
368
369 case tok::string_literal: {
370 // Parse the string literal.
371 LangOptions LangOpts;
372 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
373 if (StringLiteral.hadError)
374 goto retry;
375
376 // Copy the string literal into our string data allocator.
377 unsigned Length = StringLiteral.GetStringLength();
378 char *Saved = StringData.Allocate<char>(Length + 1);
379 memcpy(Saved, StringLiteral.GetString().data(), Length);
380 Saved[Length] = 0;
381
382 // Form the token.
383 Tok.Kind = MMToken::StringLiteral;
384 Tok.StringData = Saved;
385 Tok.StringLength = Length;
386 break;
387 }
388
389 case tok::comment:
390 goto retry;
391
392 default:
393 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
394 HadError = true;
395 goto retry;
396 }
397
398 return Result;
399}
400
401void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
402 unsigned braceDepth = 0;
403 do {
404 switch (Tok.Kind) {
405 case MMToken::EndOfFile:
406 return;
407
408 case MMToken::LBrace:
409 if (Tok.is(K) && braceDepth == 0)
410 return;
411
412 ++braceDepth;
413 break;
414
415 case MMToken::RBrace:
416 if (braceDepth > 0)
417 --braceDepth;
418 else if (Tok.is(K))
419 return;
420 break;
421
422 default:
423 if (braceDepth == 0 && Tok.is(K))
424 return;
425 break;
426 }
427
428 consumeToken();
429 } while (true);
430}
431
432/// \brief Parse a module declaration.
433///
434/// module-declaration:
Douglas Gregora8654052011-11-17 22:09:43 +0000435/// 'framework'[opt] 'module' identifier { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000436///
437/// module-member:
438/// umbrella-declaration
439/// header-declaration
440/// 'explicit'[opt] module-declaration
441void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000442 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
443 Tok.is(MMToken::FrameworkKeyword));
444
445 // Parse 'framework' or 'explicit' keyword, if present.
446 bool Framework = false;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000447 bool Explicit = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000448
449 if (Tok.is(MMToken::FrameworkKeyword)) {
450 consumeToken();
451 Framework = true;
452 }
453 // Parse 'explicit' keyword, if present.
454 else if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000455 consumeToken();
456 Explicit = true;
457 }
458
459 // Parse 'module' keyword.
460 if (!Tok.is(MMToken::ModuleKeyword)) {
461 Diags.Report(Tok.getLocation(),
462 diag::err_mmap_expected_module_after_explicit);
463 consumeToken();
464 HadError = true;
465 return;
466 }
467 consumeToken(); // 'module' keyword
468
469 // Parse the module name.
470 if (!Tok.is(MMToken::Identifier)) {
471 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
472 HadError = true;
473 return;
474 }
475 StringRef ModuleName = Tok.getString();
476 SourceLocation ModuleNameLoc = consumeToken();
477
478 // Parse the opening brace.
479 if (!Tok.is(MMToken::LBrace)) {
480 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
481 << ModuleName;
482 HadError = true;
483 return;
484 }
485 SourceLocation LBraceLoc = consumeToken();
486
487 // Determine whether this (sub)module has already been defined.
488 llvm::StringMap<Module *> &ModuleSpace
489 = ActiveModule? ActiveModule->SubModules : Map.Modules;
490 llvm::StringMap<Module *>::iterator ExistingModule
491 = ModuleSpace.find(ModuleName);
492 if (ExistingModule != ModuleSpace.end()) {
493 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
494 << ModuleName;
495 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
496 diag::note_mmap_prev_definition);
497
498 // Skip the module definition.
499 skipUntil(MMToken::RBrace);
500 if (Tok.is(MMToken::RBrace))
501 consumeToken();
502
503 HadError = true;
504 return;
505 }
506
507 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000508 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
509 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000510 ModuleSpace[ModuleName] = ActiveModule;
511
512 bool Done = false;
513 do {
514 switch (Tok.Kind) {
515 case MMToken::EndOfFile:
516 case MMToken::RBrace:
517 Done = true;
518 break;
519
520 case MMToken::ExplicitKeyword:
521 case MMToken::ModuleKeyword:
522 parseModuleDecl();
523 break;
524
525 case MMToken::HeaderKeyword:
526 parseHeaderDecl();
527 break;
528
529 case MMToken::UmbrellaKeyword:
530 parseUmbrellaDecl();
531 break;
532
533 default:
534 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
535 consumeToken();
536 break;
537 }
538 } while (!Done);
539
540 if (Tok.is(MMToken::RBrace))
541 consumeToken();
542 else {
543 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
544 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
545 HadError = true;
546 }
547
548 // We're done parsing this module. Pop back to our parent scope.
549 ActiveModule = ActiveModule->Parent;
550}
551
552/// \brief Parse an umbrella header declaration.
553///
554/// umbrella-declaration:
555/// 'umbrella' string-literal
556void ModuleMapParser::parseUmbrellaDecl() {
557 assert(Tok.is(MMToken::UmbrellaKeyword));
558 SourceLocation UmbrellaLoc = consumeToken();
559
560 // Parse the header name.
561 if (!Tok.is(MMToken::StringLiteral)) {
562 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
563 << "umbrella";
564 HadError = true;
565 return;
566 }
567 StringRef FileName = Tok.getString();
568 SourceLocation FileNameLoc = consumeToken();
569
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000570 // Check whether we already have an umbrella header.
571 if (ActiveModule->UmbrellaHeader) {
572 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
573 << ActiveModule->getFullModuleName()
574 << ActiveModule->UmbrellaHeader->getName();
575 HadError = true;
576 return;
577 }
578
579 // Only top-level modules can have umbrella headers.
580 if (ActiveModule->Parent) {
581 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
582 << ActiveModule->getFullModuleName();
583 HadError = true;
584 return;
585 }
586
587 // Look for this file.
588 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000589 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000590
591 if (llvm::sys::path::is_absolute(FileName)) {
592 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000593 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000594 } else {
595 // Search for the header file within the search directory.
596 PathName += Directory->getName();
597 unsigned PathLength = PathName.size();
598 if (ActiveModule->isPartOfFramework()) {
599 // Check whether this file is in the public headers.
600 llvm::sys::path::append(PathName, "Headers");
601 llvm::sys::path::append(PathName, FileName);
602 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000603
Douglas Gregor18ee5472011-11-29 21:59:16 +0000604 if (!File) {
605 // Check whether this file is in the private headers.
606 PathName.resize(PathLength);
607 llvm::sys::path::append(PathName, "PrivateHeaders");
608 llvm::sys::path::append(PathName, FileName);
609 File = SourceMgr.getFileManager().getFile(PathName);
610 }
611
612 // FIXME: Deal with subframeworks.
613 } else {
614 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000615 llvm::sys::path::append(PathName, FileName);
616 File = SourceMgr.getFileManager().getFile(PathName);
617 }
Douglas Gregora8654052011-11-17 22:09:43 +0000618 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000619
620 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
621 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000622 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000623 if (const Module *OwningModule = Map.Headers[File]) {
624 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
625 << FileName << OwningModule->getFullModuleName();
626 HadError = true;
Douglas Gregoradb97992011-11-16 23:02:25 +0000627 } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
628 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
629 << OwningModule->getFullModuleName();
630 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000631 } else {
632 // Record this umbrella header.
633 ActiveModule->UmbrellaHeader = File;
634 Map.Headers[File] = ActiveModule;
Douglas Gregoradb97992011-11-16 23:02:25 +0000635 Map.UmbrellaDirs[Directory] = ActiveModule;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000636 }
637 } else {
638 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
639 << true << FileName;
640 HadError = true;
641 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000642}
643
644/// \brief Parse a header declaration.
645///
646/// header-declaration:
647/// 'header' string-literal
648void ModuleMapParser::parseHeaderDecl() {
649 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000650 consumeToken();
651
Douglas Gregora30cfe52011-11-11 19:10:28 +0000652 // Parse the header name.
653 if (!Tok.is(MMToken::StringLiteral)) {
654 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
655 << "header";
656 HadError = true;
657 return;
658 }
659 StringRef FileName = Tok.getString();
660 SourceLocation FileNameLoc = consumeToken();
661
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000662 // Look for this file.
663 llvm::SmallString<128> PathName;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000664 if (llvm::sys::path::is_relative(FileName)) {
665 // FIXME: Change this search to also look for private headers!
666 PathName += Directory->getName();
667
668 if (ActiveModule->isPartOfFramework())
669 llvm::sys::path::append(PathName, "Headers");
670 }
Douglas Gregora8654052011-11-17 22:09:43 +0000671
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000672 llvm::sys::path::append(PathName, FileName);
673
674 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
675 // Come up with a lazy way to do this.
676 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
677 if (const Module *OwningModule = Map.Headers[File]) {
678 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
679 << FileName << OwningModule->getFullModuleName();
680 HadError = true;
681 } else {
682 // Record this file.
683 ActiveModule->Headers.push_back(File);
684 Map.Headers[File] = ActiveModule;
685 }
686 } else {
687 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
688 << false << FileName;
689 HadError = true;
690 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000691}
692
693/// \brief Parse a module map file.
694///
695/// module-map-file:
696/// module-declaration*
697bool ModuleMapParser::parseModuleMapFile() {
698 do {
699 switch (Tok.Kind) {
700 case MMToken::EndOfFile:
701 return HadError;
702
703 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +0000704 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000705 parseModuleDecl();
706 break;
707
708 case MMToken::ExplicitKeyword:
709 case MMToken::HeaderKeyword:
710 case MMToken::Identifier:
711 case MMToken::LBrace:
712 case MMToken::RBrace:
713 case MMToken::StringLiteral:
714 case MMToken::UmbrellaKeyword:
715 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
716 HadError = true;
717 consumeToken();
718 break;
719 }
720 } while (true);
721
722 return HadError;
723}
724
725bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
726 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
727 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
728 if (!Buffer)
729 return true;
730
731 // Parse this module map file.
732 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
733 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000734 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000735 bool Result = Parser.parseModuleMapFile();
736 Diags->getClient()->EndSourceFile();
737
738 return Result;
739}