blob: 11a20e006210c6332676b9ba7a2b70cf68700f1a [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 +000071void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
Benjamin Kramerc55edcf2011-11-30 15:07:30 +000072 OS.indent(Indent);
Douglas Gregor804c3bf2011-11-29 18:17:59 +000073 if (IsFramework)
74 OS << "framework ";
75 if (IsExplicit)
76 OS << "explicit ";
Douglas Gregor18ee5472011-11-29 21:59:16 +000077 OS << "module " << Name << " {\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +000078
79 if (UmbrellaHeader) {
Benjamin Kramerc55edcf2011-11-30 15:07:30 +000080 OS.indent(Indent + 2);
Douglas Gregor213d1be2011-11-29 22:27:12 +000081 OS << "umbrella \"";
Douglas Gregor7f5fd8e2011-11-30 15:00:49 +000082 OS.write_escaped(UmbrellaHeader->getName());
Douglas Gregor213d1be2011-11-29 22:27:12 +000083 OS << "\"\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +000084 }
85
86 for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
Benjamin Kramerc55edcf2011-11-30 15:07:30 +000087 OS.indent(Indent + 2);
Douglas Gregor213d1be2011-11-29 22:27:12 +000088 OS << "header \"";
Douglas Gregor7f5fd8e2011-11-30 15:00:49 +000089 OS.write_escaped(Headers[I]->getName());
Douglas Gregor213d1be2011-11-29 22:27:12 +000090 OS << "\"\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +000091 }
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
Benjamin Kramerc55edcf2011-11-30 15:07:30 +000098 OS.indent(Indent);
Douglas Gregor804c3bf2011-11-29 18:17:59 +000099 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 Gregor392ed2b2011-11-30 17:33:56 +0000180std::pair<ModuleMap::Module *, bool>
181ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
182 bool IsExplicit) {
183 // Try to find an existing module with this name.
184 if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
185 return std::make_pair(Found, false);
186
187 // Create a new module with this name.
188 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
189 IsExplicit);
190 if (Parent)
191 Parent->SubModules[Name] = Result;
192 else
193 Modules[Name] = Result;
194 return std::make_pair(Result, true);
195}
196
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000197ModuleMap::Module *
198ModuleMap::inferFrameworkModule(StringRef ModuleName,
199 const DirectoryEntry *FrameworkDir) {
200 // Check whether we've already found this module.
201 if (Module *Module = findModule(ModuleName))
202 return Module;
203
204 // Look for an umbrella header.
205 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
206 llvm::sys::path::append(UmbrellaName, "Headers");
207 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
208 const FileEntry *UmbrellaHeader
209 = SourceMgr->getFileManager().getFile(UmbrellaName);
210
211 // FIXME: If there's no umbrella header, we could probably scan the
212 // framework to load *everything*. But, it's not clear that this is a good
213 // idea.
214 if (!UmbrellaHeader)
215 return 0;
216
Douglas Gregora8654052011-11-17 22:09:43 +0000217 Module *Result = new Module(ModuleName, SourceLocation(),
218 /*IsFramework=*/true);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000219 Result->UmbrellaHeader = UmbrellaHeader;
220 Headers[UmbrellaHeader] = Result;
221 UmbrellaDirs[FrameworkDir] = Result;
222 Modules[ModuleName] = Result;
223 return Result;
224}
225
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000226const FileEntry *
227ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) {
228 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
229 return 0;
230
231 return SourceMgr->getFileEntryForID(
232 SourceMgr->getFileID(Module->DefinitionLoc));
233}
234
Douglas Gregora30cfe52011-11-11 19:10:28 +0000235void ModuleMap::dump() {
236 llvm::errs() << "Modules:";
237 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
238 MEnd = Modules.end();
239 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000240 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000241
242 llvm::errs() << "Headers:";
243 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
244 H = Headers.begin(),
245 HEnd = Headers.end();
246 H != HEnd; ++H) {
247 llvm::errs() << " \"" << H->first->getName() << "\" -> "
248 << H->second->getFullModuleName() << "\n";
249 }
250}
251
252//----------------------------------------------------------------------------//
253// Module map file parser
254//----------------------------------------------------------------------------//
255
256namespace clang {
257 /// \brief A token in a module map file.
258 struct MMToken {
259 enum TokenKind {
260 EndOfFile,
261 HeaderKeyword,
262 Identifier,
263 ExplicitKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000264 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000265 ModuleKeyword,
266 UmbrellaKeyword,
267 StringLiteral,
268 LBrace,
269 RBrace
270 } Kind;
271
272 unsigned Location;
273 unsigned StringLength;
274 const char *StringData;
275
276 void clear() {
277 Kind = EndOfFile;
278 Location = 0;
279 StringLength = 0;
280 StringData = 0;
281 }
282
283 bool is(TokenKind K) const { return Kind == K; }
284
285 SourceLocation getLocation() const {
286 return SourceLocation::getFromRawEncoding(Location);
287 }
288
289 StringRef getString() const {
290 return StringRef(StringData, StringLength);
291 }
292 };
293
294 class ModuleMapParser {
295 Lexer &L;
296 SourceManager &SourceMgr;
297 DiagnosticsEngine &Diags;
298 ModuleMap &Map;
299
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000300 /// \brief The directory that this module map resides in.
301 const DirectoryEntry *Directory;
302
Douglas Gregora30cfe52011-11-11 19:10:28 +0000303 /// \brief Whether an error occurred.
304 bool HadError;
305
306 /// \brief Default target information, used only for string literal
307 /// parsing.
308 TargetInfo *Target;
309
310 /// \brief Stores string data for the various string literals referenced
311 /// during parsing.
312 llvm::BumpPtrAllocator StringData;
313
314 /// \brief The current token.
315 MMToken Tok;
316
317 /// \brief The active module.
318 ModuleMap::Module *ActiveModule;
319
320 /// \brief Consume the current token and return its location.
321 SourceLocation consumeToken();
322
323 /// \brief Skip tokens until we reach the a token with the given kind
324 /// (or the end of the file).
325 void skipUntil(MMToken::TokenKind K);
326
327 void parseModuleDecl();
328 void parseUmbrellaDecl();
329 void parseHeaderDecl();
330
331 public:
332 typedef ModuleMap::Module Module;
333
334 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
335 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000336 ModuleMap &Map,
337 const DirectoryEntry *Directory)
338 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
339 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000340 {
341 TargetOptions TargetOpts;
342 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
343 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
344
345 Tok.clear();
346 consumeToken();
347 }
348
349 bool parseModuleMapFile();
350 };
351}
352
353SourceLocation ModuleMapParser::consumeToken() {
354retry:
355 SourceLocation Result = Tok.getLocation();
356 Tok.clear();
357
358 Token LToken;
359 L.LexFromRawLexer(LToken);
360 Tok.Location = LToken.getLocation().getRawEncoding();
361 switch (LToken.getKind()) {
362 case tok::raw_identifier:
363 Tok.StringData = LToken.getRawIdentifierData();
364 Tok.StringLength = LToken.getLength();
365 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
366 .Case("header", MMToken::HeaderKeyword)
367 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000368 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000369 .Case("module", MMToken::ModuleKeyword)
370 .Case("umbrella", MMToken::UmbrellaKeyword)
371 .Default(MMToken::Identifier);
372 break;
373
374 case tok::eof:
375 Tok.Kind = MMToken::EndOfFile;
376 break;
377
378 case tok::l_brace:
379 Tok.Kind = MMToken::LBrace;
380 break;
381
382 case tok::r_brace:
383 Tok.Kind = MMToken::RBrace;
384 break;
385
386 case tok::string_literal: {
387 // Parse the string literal.
388 LangOptions LangOpts;
389 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
390 if (StringLiteral.hadError)
391 goto retry;
392
393 // Copy the string literal into our string data allocator.
394 unsigned Length = StringLiteral.GetStringLength();
395 char *Saved = StringData.Allocate<char>(Length + 1);
396 memcpy(Saved, StringLiteral.GetString().data(), Length);
397 Saved[Length] = 0;
398
399 // Form the token.
400 Tok.Kind = MMToken::StringLiteral;
401 Tok.StringData = Saved;
402 Tok.StringLength = Length;
403 break;
404 }
405
406 case tok::comment:
407 goto retry;
408
409 default:
410 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
411 HadError = true;
412 goto retry;
413 }
414
415 return Result;
416}
417
418void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
419 unsigned braceDepth = 0;
420 do {
421 switch (Tok.Kind) {
422 case MMToken::EndOfFile:
423 return;
424
425 case MMToken::LBrace:
426 if (Tok.is(K) && braceDepth == 0)
427 return;
428
429 ++braceDepth;
430 break;
431
432 case MMToken::RBrace:
433 if (braceDepth > 0)
434 --braceDepth;
435 else if (Tok.is(K))
436 return;
437 break;
438
439 default:
440 if (braceDepth == 0 && Tok.is(K))
441 return;
442 break;
443 }
444
445 consumeToken();
446 } while (true);
447}
448
449/// \brief Parse a module declaration.
450///
451/// module-declaration:
Douglas Gregora8654052011-11-17 22:09:43 +0000452/// 'framework'[opt] 'module' identifier { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000453///
454/// module-member:
455/// umbrella-declaration
456/// header-declaration
457/// 'explicit'[opt] module-declaration
458void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000459 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
460 Tok.is(MMToken::FrameworkKeyword));
461
462 // Parse 'framework' or 'explicit' keyword, if present.
463 bool Framework = false;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000464 bool Explicit = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000465
466 if (Tok.is(MMToken::FrameworkKeyword)) {
467 consumeToken();
468 Framework = true;
469 }
470 // Parse 'explicit' keyword, if present.
471 else if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000472 consumeToken();
473 Explicit = true;
474 }
475
476 // Parse 'module' keyword.
477 if (!Tok.is(MMToken::ModuleKeyword)) {
478 Diags.Report(Tok.getLocation(),
479 diag::err_mmap_expected_module_after_explicit);
480 consumeToken();
481 HadError = true;
482 return;
483 }
484 consumeToken(); // 'module' keyword
485
486 // Parse the module name.
487 if (!Tok.is(MMToken::Identifier)) {
488 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
489 HadError = true;
490 return;
491 }
492 StringRef ModuleName = Tok.getString();
493 SourceLocation ModuleNameLoc = consumeToken();
494
495 // Parse the opening brace.
496 if (!Tok.is(MMToken::LBrace)) {
497 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
498 << ModuleName;
499 HadError = true;
500 return;
501 }
502 SourceLocation LBraceLoc = consumeToken();
503
504 // Determine whether this (sub)module has already been defined.
505 llvm::StringMap<Module *> &ModuleSpace
506 = ActiveModule? ActiveModule->SubModules : Map.Modules;
507 llvm::StringMap<Module *>::iterator ExistingModule
508 = ModuleSpace.find(ModuleName);
509 if (ExistingModule != ModuleSpace.end()) {
510 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
511 << ModuleName;
512 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
513 diag::note_mmap_prev_definition);
514
515 // Skip the module definition.
516 skipUntil(MMToken::RBrace);
517 if (Tok.is(MMToken::RBrace))
518 consumeToken();
519
520 HadError = true;
521 return;
522 }
523
524 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000525 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
526 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000527 ModuleSpace[ModuleName] = ActiveModule;
528
529 bool Done = false;
530 do {
531 switch (Tok.Kind) {
532 case MMToken::EndOfFile:
533 case MMToken::RBrace:
534 Done = true;
535 break;
536
537 case MMToken::ExplicitKeyword:
538 case MMToken::ModuleKeyword:
539 parseModuleDecl();
540 break;
541
542 case MMToken::HeaderKeyword:
543 parseHeaderDecl();
544 break;
545
546 case MMToken::UmbrellaKeyword:
547 parseUmbrellaDecl();
548 break;
549
550 default:
551 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
552 consumeToken();
553 break;
554 }
555 } while (!Done);
556
557 if (Tok.is(MMToken::RBrace))
558 consumeToken();
559 else {
560 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
561 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
562 HadError = true;
563 }
564
565 // We're done parsing this module. Pop back to our parent scope.
566 ActiveModule = ActiveModule->Parent;
567}
568
569/// \brief Parse an umbrella header declaration.
570///
571/// umbrella-declaration:
572/// 'umbrella' string-literal
573void ModuleMapParser::parseUmbrellaDecl() {
574 assert(Tok.is(MMToken::UmbrellaKeyword));
575 SourceLocation UmbrellaLoc = consumeToken();
576
577 // Parse the header name.
578 if (!Tok.is(MMToken::StringLiteral)) {
579 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
580 << "umbrella";
581 HadError = true;
582 return;
583 }
584 StringRef FileName = Tok.getString();
585 SourceLocation FileNameLoc = consumeToken();
586
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000587 // Check whether we already have an umbrella header.
588 if (ActiveModule->UmbrellaHeader) {
589 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
590 << ActiveModule->getFullModuleName()
591 << ActiveModule->UmbrellaHeader->getName();
592 HadError = true;
593 return;
594 }
595
596 // Only top-level modules can have umbrella headers.
597 if (ActiveModule->Parent) {
598 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
599 << ActiveModule->getFullModuleName();
600 HadError = true;
601 return;
602 }
603
604 // Look for this file.
605 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000606 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000607
608 if (llvm::sys::path::is_absolute(FileName)) {
609 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000610 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000611 } else {
612 // Search for the header file within the search directory.
613 PathName += Directory->getName();
614 unsigned PathLength = PathName.size();
615 if (ActiveModule->isPartOfFramework()) {
616 // Check whether this file is in the public headers.
617 llvm::sys::path::append(PathName, "Headers");
618 llvm::sys::path::append(PathName, FileName);
619 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000620
Douglas Gregor18ee5472011-11-29 21:59:16 +0000621 if (!File) {
622 // Check whether this file is in the private headers.
623 PathName.resize(PathLength);
624 llvm::sys::path::append(PathName, "PrivateHeaders");
625 llvm::sys::path::append(PathName, FileName);
626 File = SourceMgr.getFileManager().getFile(PathName);
627 }
628
629 // FIXME: Deal with subframeworks.
630 } else {
631 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000632 llvm::sys::path::append(PathName, FileName);
633 File = SourceMgr.getFileManager().getFile(PathName);
634 }
Douglas Gregora8654052011-11-17 22:09:43 +0000635 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000636
637 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
638 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000639 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000640 if (const Module *OwningModule = Map.Headers[File]) {
641 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
642 << FileName << OwningModule->getFullModuleName();
643 HadError = true;
Douglas Gregoradb97992011-11-16 23:02:25 +0000644 } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
645 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
646 << OwningModule->getFullModuleName();
647 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000648 } else {
649 // Record this umbrella header.
650 ActiveModule->UmbrellaHeader = File;
651 Map.Headers[File] = ActiveModule;
Douglas Gregoradb97992011-11-16 23:02:25 +0000652 Map.UmbrellaDirs[Directory] = ActiveModule;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000653 }
654 } else {
655 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
656 << true << FileName;
657 HadError = true;
658 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000659}
660
661/// \brief Parse a header declaration.
662///
663/// header-declaration:
664/// 'header' string-literal
665void ModuleMapParser::parseHeaderDecl() {
666 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000667 consumeToken();
668
Douglas Gregora30cfe52011-11-11 19:10:28 +0000669 // Parse the header name.
670 if (!Tok.is(MMToken::StringLiteral)) {
671 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
672 << "header";
673 HadError = true;
674 return;
675 }
676 StringRef FileName = Tok.getString();
677 SourceLocation FileNameLoc = consumeToken();
678
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000679 // Look for this file.
680 llvm::SmallString<128> PathName;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000681 if (llvm::sys::path::is_relative(FileName)) {
682 // FIXME: Change this search to also look for private headers!
683 PathName += Directory->getName();
684
685 if (ActiveModule->isPartOfFramework())
686 llvm::sys::path::append(PathName, "Headers");
687 }
Douglas Gregora8654052011-11-17 22:09:43 +0000688
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000689 llvm::sys::path::append(PathName, FileName);
690
691 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
692 // Come up with a lazy way to do this.
693 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
694 if (const Module *OwningModule = Map.Headers[File]) {
695 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
696 << FileName << OwningModule->getFullModuleName();
697 HadError = true;
698 } else {
699 // Record this file.
700 ActiveModule->Headers.push_back(File);
701 Map.Headers[File] = ActiveModule;
702 }
703 } else {
704 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
705 << false << FileName;
706 HadError = true;
707 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000708}
709
710/// \brief Parse a module map file.
711///
712/// module-map-file:
713/// module-declaration*
714bool ModuleMapParser::parseModuleMapFile() {
715 do {
716 switch (Tok.Kind) {
717 case MMToken::EndOfFile:
718 return HadError;
719
720 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +0000721 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000722 parseModuleDecl();
723 break;
724
725 case MMToken::ExplicitKeyword:
726 case MMToken::HeaderKeyword:
727 case MMToken::Identifier:
728 case MMToken::LBrace:
729 case MMToken::RBrace:
730 case MMToken::StringLiteral:
731 case MMToken::UmbrellaKeyword:
732 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
733 HadError = true;
734 consumeToken();
735 break;
736 }
737 } while (true);
738
739 return HadError;
740}
741
742bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
743 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
744 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
745 if (!Buffer)
746 return true;
747
748 // Parse this module map file.
749 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
750 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000751 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000752 bool Result = Parser.parseModuleMapFile();
753 Diags->getClient()->EndSourceFile();
754
755 return Result;
756}