blob: 984c7985e09fb8f1e5f89efde446187aec913129 [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
Douglas Gregor213d1be2011-11-29 22:27:12 +000075static void printEscapedString(llvm::raw_ostream &OS, StringRef String) {
76 for (StringRef::iterator I = String.begin(), E = String.end(); I != E; ++I) {
77 unsigned char Char = *I;
78
79 switch (Char) {
80 default:
81 if (isprint(Char))
82 OS << (char)Char;
83 else // Output anything hard as an octal escape.
84 OS << '\\'
85 << (char)('0'+ ((Char >> 6) & 7))
86 << (char)('0'+ ((Char >> 3) & 7))
87 << (char)('0'+ ((Char >> 0) & 7));
88 break;
89 // Handle some common non-printable cases to make dumps prettier.
90 case '\\': OS << "\\\\"; break;
91 case '"': OS << "\\\""; break;
92 case '\n': OS << "\\n"; break;
93 case '\t': OS << "\\t"; break;
94 case '\a': OS << "\\a"; break;
95 case '\b': OS << "\\b"; break;
96 }
97 }
98}
99
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000100void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
101 indent(OS, Indent);
102 if (IsFramework)
103 OS << "framework ";
104 if (IsExplicit)
105 OS << "explicit ";
Douglas Gregor18ee5472011-11-29 21:59:16 +0000106 OS << "module " << Name << " {\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000107
108 if (UmbrellaHeader) {
109 indent(OS, Indent + 2);
Douglas Gregor213d1be2011-11-29 22:27:12 +0000110 OS << "umbrella \"";
111 printEscapedString(OS, UmbrellaHeader->getName());
112 OS << "\"\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000113 }
114
115 for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
116 indent(OS, Indent + 2);
Douglas Gregor213d1be2011-11-29 22:27:12 +0000117 OS << "header \"";
118 printEscapedString(OS, Headers[I]->getName());
119 OS << "\"\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000120 }
121
122 for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
123 MIEnd = SubModules.end();
124 MI != MIEnd; ++MI)
125 MI->getValue()->print(OS, Indent + 2);
126
127 indent(OS, Indent);
128 OS << "}\n";
129}
130
131void ModuleMap::Module::dump() const {
132 print(llvm::errs());
133}
134
Douglas Gregora30cfe52011-11-11 19:10:28 +0000135//----------------------------------------------------------------------------//
136// Module map
137//----------------------------------------------------------------------------//
138
139ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
140 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
141 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
142 new DiagnosticsEngine(DiagIDs));
143 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
144 SourceMgr = new SourceManager(*Diags, FileMgr);
145}
146
147ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +0000148 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
149 IEnd = Modules.end();
150 I != IEnd; ++I) {
151 delete I->getValue();
152 }
153
Douglas Gregora30cfe52011-11-11 19:10:28 +0000154 delete SourceMgr;
155}
156
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000157ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
158 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
159 = Headers.find(File);
160 if (Known != Headers.end())
161 return Known->second;
162
Douglas Gregoradb97992011-11-16 23:02:25 +0000163 const DirectoryEntry *Dir = File->getDir();
164 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
165 = UmbrellaDirs.find(Dir);
166 if (KnownDir != UmbrellaDirs.end())
167 return KnownDir->second;
168
169 // Walk up the directory hierarchy looking for umbrella headers.
170 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
171 StringRef DirName = Dir->getName();
172 do {
173 // Retrieve our parent path.
174 DirName = llvm::sys::path::parent_path(DirName);
175 if (DirName.empty())
176 break;
177
178 // Resolve the parent path to a directory entry.
179 Dir = SourceMgr->getFileManager().getDirectory(DirName);
180 if (!Dir)
181 break;
182
183 KnownDir = UmbrellaDirs.find(Dir);
184 if (KnownDir != UmbrellaDirs.end()) {
185 Module *Result = KnownDir->second;
186
187 // Record each of the directories we stepped through as being part of
188 // the module we found, since the umbrella header covers them all.
189 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
190 UmbrellaDirs[SkippedDirs[I]] = Result;
191
192 return Result;
193 }
194
195 SkippedDirs.push_back(Dir);
196 } while (true);
197
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000198 return 0;
199}
200
Douglas Gregor484535e2011-11-11 23:20:24 +0000201ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
202 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
203 if (Known != Modules.end())
204 return Known->getValue();
205
206 return 0;
207}
208
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000209ModuleMap::Module *
210ModuleMap::inferFrameworkModule(StringRef ModuleName,
211 const DirectoryEntry *FrameworkDir) {
212 // Check whether we've already found this module.
213 if (Module *Module = findModule(ModuleName))
214 return Module;
215
216 // Look for an umbrella header.
217 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
218 llvm::sys::path::append(UmbrellaName, "Headers");
219 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
220 const FileEntry *UmbrellaHeader
221 = SourceMgr->getFileManager().getFile(UmbrellaName);
222
223 // FIXME: If there's no umbrella header, we could probably scan the
224 // framework to load *everything*. But, it's not clear that this is a good
225 // idea.
226 if (!UmbrellaHeader)
227 return 0;
228
Douglas Gregora8654052011-11-17 22:09:43 +0000229 Module *Result = new Module(ModuleName, SourceLocation(),
230 /*IsFramework=*/true);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000231 Result->UmbrellaHeader = UmbrellaHeader;
232 Headers[UmbrellaHeader] = Result;
233 UmbrellaDirs[FrameworkDir] = Result;
234 Modules[ModuleName] = Result;
235 return Result;
236}
237
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000238const FileEntry *
239ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) {
240 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
241 return 0;
242
243 return SourceMgr->getFileEntryForID(
244 SourceMgr->getFileID(Module->DefinitionLoc));
245}
246
Douglas Gregora30cfe52011-11-11 19:10:28 +0000247void ModuleMap::dump() {
248 llvm::errs() << "Modules:";
249 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
250 MEnd = Modules.end();
251 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000252 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000253
254 llvm::errs() << "Headers:";
255 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
256 H = Headers.begin(),
257 HEnd = Headers.end();
258 H != HEnd; ++H) {
259 llvm::errs() << " \"" << H->first->getName() << "\" -> "
260 << H->second->getFullModuleName() << "\n";
261 }
262}
263
264//----------------------------------------------------------------------------//
265// Module map file parser
266//----------------------------------------------------------------------------//
267
268namespace clang {
269 /// \brief A token in a module map file.
270 struct MMToken {
271 enum TokenKind {
272 EndOfFile,
273 HeaderKeyword,
274 Identifier,
275 ExplicitKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000276 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000277 ModuleKeyword,
278 UmbrellaKeyword,
279 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.
330 ModuleMap::Module *ActiveModule;
331
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();
342
343 public:
344 typedef ModuleMap::Module Module;
345
346 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
347 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000348 ModuleMap &Map,
349 const DirectoryEntry *Directory)
350 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
351 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000352 {
353 TargetOptions TargetOpts;
354 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
355 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
356
357 Tok.clear();
358 consumeToken();
359 }
360
361 bool parseModuleMapFile();
362 };
363}
364
365SourceLocation ModuleMapParser::consumeToken() {
366retry:
367 SourceLocation Result = Tok.getLocation();
368 Tok.clear();
369
370 Token LToken;
371 L.LexFromRawLexer(LToken);
372 Tok.Location = LToken.getLocation().getRawEncoding();
373 switch (LToken.getKind()) {
374 case tok::raw_identifier:
375 Tok.StringData = LToken.getRawIdentifierData();
376 Tok.StringLength = LToken.getLength();
377 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
378 .Case("header", MMToken::HeaderKeyword)
379 .Case("explicit", MMToken::ExplicitKeyword)
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
394 case tok::r_brace:
395 Tok.Kind = MMToken::RBrace;
396 break;
397
398 case tok::string_literal: {
399 // Parse the string literal.
400 LangOptions LangOpts;
401 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
402 if (StringLiteral.hadError)
403 goto retry;
404
405 // Copy the string literal into our string data allocator.
406 unsigned Length = StringLiteral.GetStringLength();
407 char *Saved = StringData.Allocate<char>(Length + 1);
408 memcpy(Saved, StringLiteral.GetString().data(), Length);
409 Saved[Length] = 0;
410
411 // Form the token.
412 Tok.Kind = MMToken::StringLiteral;
413 Tok.StringData = Saved;
414 Tok.StringLength = Length;
415 break;
416 }
417
418 case tok::comment:
419 goto retry;
420
421 default:
422 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
423 HadError = true;
424 goto retry;
425 }
426
427 return Result;
428}
429
430void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
431 unsigned braceDepth = 0;
432 do {
433 switch (Tok.Kind) {
434 case MMToken::EndOfFile:
435 return;
436
437 case MMToken::LBrace:
438 if (Tok.is(K) && braceDepth == 0)
439 return;
440
441 ++braceDepth;
442 break;
443
444 case MMToken::RBrace:
445 if (braceDepth > 0)
446 --braceDepth;
447 else if (Tok.is(K))
448 return;
449 break;
450
451 default:
452 if (braceDepth == 0 && Tok.is(K))
453 return;
454 break;
455 }
456
457 consumeToken();
458 } while (true);
459}
460
461/// \brief Parse a module declaration.
462///
463/// module-declaration:
Douglas Gregora8654052011-11-17 22:09:43 +0000464/// 'framework'[opt] 'module' identifier { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000465///
466/// module-member:
467/// umbrella-declaration
468/// header-declaration
469/// 'explicit'[opt] module-declaration
470void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000471 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
472 Tok.is(MMToken::FrameworkKeyword));
473
474 // Parse 'framework' or 'explicit' keyword, if present.
475 bool Framework = false;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000476 bool Explicit = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000477
478 if (Tok.is(MMToken::FrameworkKeyword)) {
479 consumeToken();
480 Framework = true;
481 }
482 // Parse 'explicit' keyword, if present.
483 else if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000484 consumeToken();
485 Explicit = true;
486 }
487
488 // Parse 'module' keyword.
489 if (!Tok.is(MMToken::ModuleKeyword)) {
490 Diags.Report(Tok.getLocation(),
491 diag::err_mmap_expected_module_after_explicit);
492 consumeToken();
493 HadError = true;
494 return;
495 }
496 consumeToken(); // 'module' keyword
497
498 // Parse the module name.
499 if (!Tok.is(MMToken::Identifier)) {
500 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
501 HadError = true;
502 return;
503 }
504 StringRef ModuleName = Tok.getString();
505 SourceLocation ModuleNameLoc = consumeToken();
506
507 // Parse the opening brace.
508 if (!Tok.is(MMToken::LBrace)) {
509 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
510 << ModuleName;
511 HadError = true;
512 return;
513 }
514 SourceLocation LBraceLoc = consumeToken();
515
516 // Determine whether this (sub)module has already been defined.
517 llvm::StringMap<Module *> &ModuleSpace
518 = ActiveModule? ActiveModule->SubModules : Map.Modules;
519 llvm::StringMap<Module *>::iterator ExistingModule
520 = ModuleSpace.find(ModuleName);
521 if (ExistingModule != ModuleSpace.end()) {
522 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
523 << ModuleName;
524 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
525 diag::note_mmap_prev_definition);
526
527 // Skip the module definition.
528 skipUntil(MMToken::RBrace);
529 if (Tok.is(MMToken::RBrace))
530 consumeToken();
531
532 HadError = true;
533 return;
534 }
535
536 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000537 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
538 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000539 ModuleSpace[ModuleName] = ActiveModule;
540
541 bool Done = false;
542 do {
543 switch (Tok.Kind) {
544 case MMToken::EndOfFile:
545 case MMToken::RBrace:
546 Done = true;
547 break;
548
549 case MMToken::ExplicitKeyword:
550 case MMToken::ModuleKeyword:
551 parseModuleDecl();
552 break;
553
554 case MMToken::HeaderKeyword:
555 parseHeaderDecl();
556 break;
557
558 case MMToken::UmbrellaKeyword:
559 parseUmbrellaDecl();
560 break;
561
562 default:
563 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
564 consumeToken();
565 break;
566 }
567 } while (!Done);
568
569 if (Tok.is(MMToken::RBrace))
570 consumeToken();
571 else {
572 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
573 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
574 HadError = true;
575 }
576
577 // We're done parsing this module. Pop back to our parent scope.
578 ActiveModule = ActiveModule->Parent;
579}
580
581/// \brief Parse an umbrella header declaration.
582///
583/// umbrella-declaration:
584/// 'umbrella' string-literal
585void ModuleMapParser::parseUmbrellaDecl() {
586 assert(Tok.is(MMToken::UmbrellaKeyword));
587 SourceLocation UmbrellaLoc = consumeToken();
588
589 // Parse the header name.
590 if (!Tok.is(MMToken::StringLiteral)) {
591 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
592 << "umbrella";
593 HadError = true;
594 return;
595 }
596 StringRef FileName = Tok.getString();
597 SourceLocation FileNameLoc = consumeToken();
598
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000599 // Check whether we already have an umbrella header.
600 if (ActiveModule->UmbrellaHeader) {
601 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
602 << ActiveModule->getFullModuleName()
603 << ActiveModule->UmbrellaHeader->getName();
604 HadError = true;
605 return;
606 }
607
608 // Only top-level modules can have umbrella headers.
609 if (ActiveModule->Parent) {
610 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
611 << ActiveModule->getFullModuleName();
612 HadError = true;
613 return;
614 }
615
616 // Look for this file.
617 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000618 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000619
620 if (llvm::sys::path::is_absolute(FileName)) {
621 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000622 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000623 } else {
624 // Search for the header file within the search directory.
625 PathName += Directory->getName();
626 unsigned PathLength = PathName.size();
627 if (ActiveModule->isPartOfFramework()) {
628 // Check whether this file is in the public headers.
629 llvm::sys::path::append(PathName, "Headers");
630 llvm::sys::path::append(PathName, FileName);
631 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000632
Douglas Gregor18ee5472011-11-29 21:59:16 +0000633 if (!File) {
634 // Check whether this file is in the private headers.
635 PathName.resize(PathLength);
636 llvm::sys::path::append(PathName, "PrivateHeaders");
637 llvm::sys::path::append(PathName, FileName);
638 File = SourceMgr.getFileManager().getFile(PathName);
639 }
640
641 // FIXME: Deal with subframeworks.
642 } else {
643 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000644 llvm::sys::path::append(PathName, FileName);
645 File = SourceMgr.getFileManager().getFile(PathName);
646 }
Douglas Gregora8654052011-11-17 22:09:43 +0000647 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000648
649 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
650 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000651 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000652 if (const Module *OwningModule = Map.Headers[File]) {
653 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
654 << FileName << OwningModule->getFullModuleName();
655 HadError = true;
Douglas Gregoradb97992011-11-16 23:02:25 +0000656 } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
657 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
658 << OwningModule->getFullModuleName();
659 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000660 } else {
661 // Record this umbrella header.
662 ActiveModule->UmbrellaHeader = File;
663 Map.Headers[File] = ActiveModule;
Douglas Gregoradb97992011-11-16 23:02:25 +0000664 Map.UmbrellaDirs[Directory] = ActiveModule;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000665 }
666 } else {
667 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
668 << true << FileName;
669 HadError = true;
670 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000671}
672
673/// \brief Parse a header declaration.
674///
675/// header-declaration:
676/// 'header' string-literal
677void ModuleMapParser::parseHeaderDecl() {
678 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000679 consumeToken();
680
Douglas Gregora30cfe52011-11-11 19:10:28 +0000681 // Parse the header name.
682 if (!Tok.is(MMToken::StringLiteral)) {
683 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
684 << "header";
685 HadError = true;
686 return;
687 }
688 StringRef FileName = Tok.getString();
689 SourceLocation FileNameLoc = consumeToken();
690
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000691 // Look for this file.
692 llvm::SmallString<128> PathName;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000693 if (llvm::sys::path::is_relative(FileName)) {
694 // FIXME: Change this search to also look for private headers!
695 PathName += Directory->getName();
696
697 if (ActiveModule->isPartOfFramework())
698 llvm::sys::path::append(PathName, "Headers");
699 }
Douglas Gregora8654052011-11-17 22:09:43 +0000700
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000701 llvm::sys::path::append(PathName, FileName);
702
703 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
704 // Come up with a lazy way to do this.
705 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
706 if (const Module *OwningModule = Map.Headers[File]) {
707 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
708 << FileName << OwningModule->getFullModuleName();
709 HadError = true;
710 } else {
711 // Record this file.
712 ActiveModule->Headers.push_back(File);
713 Map.Headers[File] = ActiveModule;
714 }
715 } else {
716 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
717 << false << FileName;
718 HadError = true;
719 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000720}
721
722/// \brief Parse a module map file.
723///
724/// module-map-file:
725/// module-declaration*
726bool ModuleMapParser::parseModuleMapFile() {
727 do {
728 switch (Tok.Kind) {
729 case MMToken::EndOfFile:
730 return HadError;
731
732 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +0000733 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000734 parseModuleDecl();
735 break;
736
737 case MMToken::ExplicitKeyword:
738 case MMToken::HeaderKeyword:
739 case MMToken::Identifier:
740 case MMToken::LBrace:
741 case MMToken::RBrace:
742 case MMToken::StringLiteral:
743 case MMToken::UmbrellaKeyword:
744 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
745 HadError = true;
746 consumeToken();
747 break;
748 }
749 } while (true);
750
751 return HadError;
752}
753
754bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
755 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
756 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
757 if (!Buffer)
758 return true;
759
760 // Parse this module map file.
761 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
762 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000763 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000764 bool Result = Parser.parseModuleMapFile();
765 Diags->getClient()->EndSourceFile();
766
767 return Result;
768}