blob: 72d2bee79686d4628f95f33559caf8eecffaf0da [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);
Douglas Gregor213d1be2011-11-29 22:27:12 +000085 OS << "umbrella \"";
Douglas Gregor7f5fd8e2011-11-30 15:00:49 +000086 OS.write_escaped(UmbrellaHeader->getName());
Douglas Gregor213d1be2011-11-29 22:27:12 +000087 OS << "\"\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +000088 }
89
90 for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
91 indent(OS, Indent + 2);
Douglas Gregor213d1be2011-11-29 22:27:12 +000092 OS << "header \"";
Douglas Gregor7f5fd8e2011-11-30 15:00:49 +000093 OS.write_escaped(Headers[I]->getName());
Douglas Gregor213d1be2011-11-29 22:27:12 +000094 OS << "\"\n";
Douglas Gregor804c3bf2011-11-29 18:17:59 +000095 }
96
97 for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
98 MIEnd = SubModules.end();
99 MI != MIEnd; ++MI)
100 MI->getValue()->print(OS, Indent + 2);
101
102 indent(OS, Indent);
103 OS << "}\n";
104}
105
106void ModuleMap::Module::dump() const {
107 print(llvm::errs());
108}
109
Douglas Gregora30cfe52011-11-11 19:10:28 +0000110//----------------------------------------------------------------------------//
111// Module map
112//----------------------------------------------------------------------------//
113
114ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
115 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
116 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
117 new DiagnosticsEngine(DiagIDs));
118 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
119 SourceMgr = new SourceManager(*Diags, FileMgr);
120}
121
122ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +0000123 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
124 IEnd = Modules.end();
125 I != IEnd; ++I) {
126 delete I->getValue();
127 }
128
Douglas Gregora30cfe52011-11-11 19:10:28 +0000129 delete SourceMgr;
130}
131
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000132ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
133 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
134 = Headers.find(File);
135 if (Known != Headers.end())
136 return Known->second;
137
Douglas Gregoradb97992011-11-16 23:02:25 +0000138 const DirectoryEntry *Dir = File->getDir();
139 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
140 = UmbrellaDirs.find(Dir);
141 if (KnownDir != UmbrellaDirs.end())
142 return KnownDir->second;
143
144 // Walk up the directory hierarchy looking for umbrella headers.
145 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
146 StringRef DirName = Dir->getName();
147 do {
148 // Retrieve our parent path.
149 DirName = llvm::sys::path::parent_path(DirName);
150 if (DirName.empty())
151 break;
152
153 // Resolve the parent path to a directory entry.
154 Dir = SourceMgr->getFileManager().getDirectory(DirName);
155 if (!Dir)
156 break;
157
158 KnownDir = UmbrellaDirs.find(Dir);
159 if (KnownDir != UmbrellaDirs.end()) {
160 Module *Result = KnownDir->second;
161
162 // Record each of the directories we stepped through as being part of
163 // the module we found, since the umbrella header covers them all.
164 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
165 UmbrellaDirs[SkippedDirs[I]] = Result;
166
167 return Result;
168 }
169
170 SkippedDirs.push_back(Dir);
171 } while (true);
172
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000173 return 0;
174}
175
Douglas Gregor484535e2011-11-11 23:20:24 +0000176ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
177 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
178 if (Known != Modules.end())
179 return Known->getValue();
180
181 return 0;
182}
183
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000184ModuleMap::Module *
185ModuleMap::inferFrameworkModule(StringRef ModuleName,
186 const DirectoryEntry *FrameworkDir) {
187 // Check whether we've already found this module.
188 if (Module *Module = findModule(ModuleName))
189 return Module;
190
191 // Look for an umbrella header.
192 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
193 llvm::sys::path::append(UmbrellaName, "Headers");
194 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
195 const FileEntry *UmbrellaHeader
196 = SourceMgr->getFileManager().getFile(UmbrellaName);
197
198 // FIXME: If there's no umbrella header, we could probably scan the
199 // framework to load *everything*. But, it's not clear that this is a good
200 // idea.
201 if (!UmbrellaHeader)
202 return 0;
203
Douglas Gregora8654052011-11-17 22:09:43 +0000204 Module *Result = new Module(ModuleName, SourceLocation(),
205 /*IsFramework=*/true);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000206 Result->UmbrellaHeader = UmbrellaHeader;
207 Headers[UmbrellaHeader] = Result;
208 UmbrellaDirs[FrameworkDir] = Result;
209 Modules[ModuleName] = Result;
210 return Result;
211}
212
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000213const FileEntry *
214ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) {
215 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
216 return 0;
217
218 return SourceMgr->getFileEntryForID(
219 SourceMgr->getFileID(Module->DefinitionLoc));
220}
221
Douglas Gregora30cfe52011-11-11 19:10:28 +0000222void ModuleMap::dump() {
223 llvm::errs() << "Modules:";
224 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
225 MEnd = Modules.end();
226 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000227 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000228
229 llvm::errs() << "Headers:";
230 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
231 H = Headers.begin(),
232 HEnd = Headers.end();
233 H != HEnd; ++H) {
234 llvm::errs() << " \"" << H->first->getName() << "\" -> "
235 << H->second->getFullModuleName() << "\n";
236 }
237}
238
239//----------------------------------------------------------------------------//
240// Module map file parser
241//----------------------------------------------------------------------------//
242
243namespace clang {
244 /// \brief A token in a module map file.
245 struct MMToken {
246 enum TokenKind {
247 EndOfFile,
248 HeaderKeyword,
249 Identifier,
250 ExplicitKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000251 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000252 ModuleKeyword,
253 UmbrellaKeyword,
254 StringLiteral,
255 LBrace,
256 RBrace
257 } Kind;
258
259 unsigned Location;
260 unsigned StringLength;
261 const char *StringData;
262
263 void clear() {
264 Kind = EndOfFile;
265 Location = 0;
266 StringLength = 0;
267 StringData = 0;
268 }
269
270 bool is(TokenKind K) const { return Kind == K; }
271
272 SourceLocation getLocation() const {
273 return SourceLocation::getFromRawEncoding(Location);
274 }
275
276 StringRef getString() const {
277 return StringRef(StringData, StringLength);
278 }
279 };
280
281 class ModuleMapParser {
282 Lexer &L;
283 SourceManager &SourceMgr;
284 DiagnosticsEngine &Diags;
285 ModuleMap &Map;
286
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000287 /// \brief The directory that this module map resides in.
288 const DirectoryEntry *Directory;
289
Douglas Gregora30cfe52011-11-11 19:10:28 +0000290 /// \brief Whether an error occurred.
291 bool HadError;
292
293 /// \brief Default target information, used only for string literal
294 /// parsing.
295 TargetInfo *Target;
296
297 /// \brief Stores string data for the various string literals referenced
298 /// during parsing.
299 llvm::BumpPtrAllocator StringData;
300
301 /// \brief The current token.
302 MMToken Tok;
303
304 /// \brief The active module.
305 ModuleMap::Module *ActiveModule;
306
307 /// \brief Consume the current token and return its location.
308 SourceLocation consumeToken();
309
310 /// \brief Skip tokens until we reach the a token with the given kind
311 /// (or the end of the file).
312 void skipUntil(MMToken::TokenKind K);
313
314 void parseModuleDecl();
315 void parseUmbrellaDecl();
316 void parseHeaderDecl();
317
318 public:
319 typedef ModuleMap::Module Module;
320
321 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
322 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000323 ModuleMap &Map,
324 const DirectoryEntry *Directory)
325 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
326 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000327 {
328 TargetOptions TargetOpts;
329 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
330 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
331
332 Tok.clear();
333 consumeToken();
334 }
335
336 bool parseModuleMapFile();
337 };
338}
339
340SourceLocation ModuleMapParser::consumeToken() {
341retry:
342 SourceLocation Result = Tok.getLocation();
343 Tok.clear();
344
345 Token LToken;
346 L.LexFromRawLexer(LToken);
347 Tok.Location = LToken.getLocation().getRawEncoding();
348 switch (LToken.getKind()) {
349 case tok::raw_identifier:
350 Tok.StringData = LToken.getRawIdentifierData();
351 Tok.StringLength = LToken.getLength();
352 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
353 .Case("header", MMToken::HeaderKeyword)
354 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000355 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000356 .Case("module", MMToken::ModuleKeyword)
357 .Case("umbrella", MMToken::UmbrellaKeyword)
358 .Default(MMToken::Identifier);
359 break;
360
361 case tok::eof:
362 Tok.Kind = MMToken::EndOfFile;
363 break;
364
365 case tok::l_brace:
366 Tok.Kind = MMToken::LBrace;
367 break;
368
369 case tok::r_brace:
370 Tok.Kind = MMToken::RBrace;
371 break;
372
373 case tok::string_literal: {
374 // Parse the string literal.
375 LangOptions LangOpts;
376 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
377 if (StringLiteral.hadError)
378 goto retry;
379
380 // Copy the string literal into our string data allocator.
381 unsigned Length = StringLiteral.GetStringLength();
382 char *Saved = StringData.Allocate<char>(Length + 1);
383 memcpy(Saved, StringLiteral.GetString().data(), Length);
384 Saved[Length] = 0;
385
386 // Form the token.
387 Tok.Kind = MMToken::StringLiteral;
388 Tok.StringData = Saved;
389 Tok.StringLength = Length;
390 break;
391 }
392
393 case tok::comment:
394 goto retry;
395
396 default:
397 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
398 HadError = true;
399 goto retry;
400 }
401
402 return Result;
403}
404
405void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
406 unsigned braceDepth = 0;
407 do {
408 switch (Tok.Kind) {
409 case MMToken::EndOfFile:
410 return;
411
412 case MMToken::LBrace:
413 if (Tok.is(K) && braceDepth == 0)
414 return;
415
416 ++braceDepth;
417 break;
418
419 case MMToken::RBrace:
420 if (braceDepth > 0)
421 --braceDepth;
422 else if (Tok.is(K))
423 return;
424 break;
425
426 default:
427 if (braceDepth == 0 && Tok.is(K))
428 return;
429 break;
430 }
431
432 consumeToken();
433 } while (true);
434}
435
436/// \brief Parse a module declaration.
437///
438/// module-declaration:
Douglas Gregora8654052011-11-17 22:09:43 +0000439/// 'framework'[opt] 'module' identifier { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000440///
441/// module-member:
442/// umbrella-declaration
443/// header-declaration
444/// 'explicit'[opt] module-declaration
445void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000446 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
447 Tok.is(MMToken::FrameworkKeyword));
448
449 // Parse 'framework' or 'explicit' keyword, if present.
450 bool Framework = false;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000451 bool Explicit = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000452
453 if (Tok.is(MMToken::FrameworkKeyword)) {
454 consumeToken();
455 Framework = true;
456 }
457 // Parse 'explicit' keyword, if present.
458 else if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000459 consumeToken();
460 Explicit = true;
461 }
462
463 // Parse 'module' keyword.
464 if (!Tok.is(MMToken::ModuleKeyword)) {
465 Diags.Report(Tok.getLocation(),
466 diag::err_mmap_expected_module_after_explicit);
467 consumeToken();
468 HadError = true;
469 return;
470 }
471 consumeToken(); // 'module' keyword
472
473 // Parse the module name.
474 if (!Tok.is(MMToken::Identifier)) {
475 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
476 HadError = true;
477 return;
478 }
479 StringRef ModuleName = Tok.getString();
480 SourceLocation ModuleNameLoc = consumeToken();
481
482 // Parse the opening brace.
483 if (!Tok.is(MMToken::LBrace)) {
484 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
485 << ModuleName;
486 HadError = true;
487 return;
488 }
489 SourceLocation LBraceLoc = consumeToken();
490
491 // Determine whether this (sub)module has already been defined.
492 llvm::StringMap<Module *> &ModuleSpace
493 = ActiveModule? ActiveModule->SubModules : Map.Modules;
494 llvm::StringMap<Module *>::iterator ExistingModule
495 = ModuleSpace.find(ModuleName);
496 if (ExistingModule != ModuleSpace.end()) {
497 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
498 << ModuleName;
499 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
500 diag::note_mmap_prev_definition);
501
502 // Skip the module definition.
503 skipUntil(MMToken::RBrace);
504 if (Tok.is(MMToken::RBrace))
505 consumeToken();
506
507 HadError = true;
508 return;
509 }
510
511 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000512 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
513 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000514 ModuleSpace[ModuleName] = ActiveModule;
515
516 bool Done = false;
517 do {
518 switch (Tok.Kind) {
519 case MMToken::EndOfFile:
520 case MMToken::RBrace:
521 Done = true;
522 break;
523
524 case MMToken::ExplicitKeyword:
525 case MMToken::ModuleKeyword:
526 parseModuleDecl();
527 break;
528
529 case MMToken::HeaderKeyword:
530 parseHeaderDecl();
531 break;
532
533 case MMToken::UmbrellaKeyword:
534 parseUmbrellaDecl();
535 break;
536
537 default:
538 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
539 consumeToken();
540 break;
541 }
542 } while (!Done);
543
544 if (Tok.is(MMToken::RBrace))
545 consumeToken();
546 else {
547 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
548 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
549 HadError = true;
550 }
551
552 // We're done parsing this module. Pop back to our parent scope.
553 ActiveModule = ActiveModule->Parent;
554}
555
556/// \brief Parse an umbrella header declaration.
557///
558/// umbrella-declaration:
559/// 'umbrella' string-literal
560void ModuleMapParser::parseUmbrellaDecl() {
561 assert(Tok.is(MMToken::UmbrellaKeyword));
562 SourceLocation UmbrellaLoc = consumeToken();
563
564 // Parse the header name.
565 if (!Tok.is(MMToken::StringLiteral)) {
566 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
567 << "umbrella";
568 HadError = true;
569 return;
570 }
571 StringRef FileName = Tok.getString();
572 SourceLocation FileNameLoc = consumeToken();
573
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000574 // Check whether we already have an umbrella header.
575 if (ActiveModule->UmbrellaHeader) {
576 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
577 << ActiveModule->getFullModuleName()
578 << ActiveModule->UmbrellaHeader->getName();
579 HadError = true;
580 return;
581 }
582
583 // Only top-level modules can have umbrella headers.
584 if (ActiveModule->Parent) {
585 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
586 << ActiveModule->getFullModuleName();
587 HadError = true;
588 return;
589 }
590
591 // Look for this file.
592 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000593 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000594
595 if (llvm::sys::path::is_absolute(FileName)) {
596 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000597 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000598 } else {
599 // Search for the header file within the search directory.
600 PathName += Directory->getName();
601 unsigned PathLength = PathName.size();
602 if (ActiveModule->isPartOfFramework()) {
603 // Check whether this file is in the public headers.
604 llvm::sys::path::append(PathName, "Headers");
605 llvm::sys::path::append(PathName, FileName);
606 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000607
Douglas Gregor18ee5472011-11-29 21:59:16 +0000608 if (!File) {
609 // Check whether this file is in the private headers.
610 PathName.resize(PathLength);
611 llvm::sys::path::append(PathName, "PrivateHeaders");
612 llvm::sys::path::append(PathName, FileName);
613 File = SourceMgr.getFileManager().getFile(PathName);
614 }
615
616 // FIXME: Deal with subframeworks.
617 } else {
618 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000619 llvm::sys::path::append(PathName, FileName);
620 File = SourceMgr.getFileManager().getFile(PathName);
621 }
Douglas Gregora8654052011-11-17 22:09:43 +0000622 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000623
624 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
625 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000626 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000627 if (const Module *OwningModule = Map.Headers[File]) {
628 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
629 << FileName << OwningModule->getFullModuleName();
630 HadError = true;
Douglas Gregoradb97992011-11-16 23:02:25 +0000631 } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
632 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
633 << OwningModule->getFullModuleName();
634 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000635 } else {
636 // Record this umbrella header.
637 ActiveModule->UmbrellaHeader = File;
638 Map.Headers[File] = ActiveModule;
Douglas Gregoradb97992011-11-16 23:02:25 +0000639 Map.UmbrellaDirs[Directory] = ActiveModule;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000640 }
641 } else {
642 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
643 << true << FileName;
644 HadError = true;
645 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000646}
647
648/// \brief Parse a header declaration.
649///
650/// header-declaration:
651/// 'header' string-literal
652void ModuleMapParser::parseHeaderDecl() {
653 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000654 consumeToken();
655
Douglas Gregora30cfe52011-11-11 19:10:28 +0000656 // Parse the header name.
657 if (!Tok.is(MMToken::StringLiteral)) {
658 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
659 << "header";
660 HadError = true;
661 return;
662 }
663 StringRef FileName = Tok.getString();
664 SourceLocation FileNameLoc = consumeToken();
665
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000666 // Look for this file.
667 llvm::SmallString<128> PathName;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000668 if (llvm::sys::path::is_relative(FileName)) {
669 // FIXME: Change this search to also look for private headers!
670 PathName += Directory->getName();
671
672 if (ActiveModule->isPartOfFramework())
673 llvm::sys::path::append(PathName, "Headers");
674 }
Douglas Gregora8654052011-11-17 22:09:43 +0000675
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000676 llvm::sys::path::append(PathName, FileName);
677
678 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
679 // Come up with a lazy way to do this.
680 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
681 if (const Module *OwningModule = Map.Headers[File]) {
682 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
683 << FileName << OwningModule->getFullModuleName();
684 HadError = true;
685 } else {
686 // Record this file.
687 ActiveModule->Headers.push_back(File);
688 Map.Headers[File] = ActiveModule;
689 }
690 } else {
691 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
692 << false << FileName;
693 HadError = true;
694 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000695}
696
697/// \brief Parse a module map file.
698///
699/// module-map-file:
700/// module-declaration*
701bool ModuleMapParser::parseModuleMapFile() {
702 do {
703 switch (Tok.Kind) {
704 case MMToken::EndOfFile:
705 return HadError;
706
707 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +0000708 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000709 parseModuleDecl();
710 break;
711
712 case MMToken::ExplicitKeyword:
713 case MMToken::HeaderKeyword:
714 case MMToken::Identifier:
715 case MMToken::LBrace:
716 case MMToken::RBrace:
717 case MMToken::StringLiteral:
718 case MMToken::UmbrellaKeyword:
719 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
720 HadError = true;
721 consumeToken();
722 break;
723 }
724 } while (true);
725
726 return HadError;
727}
728
729bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
730 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
731 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
732 if (!Buffer)
733 return true;
734
735 // Parse this module map file.
736 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
737 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000738 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000739 bool Result = Parser.parseModuleMapFile();
740 Diags->getClient()->EndSourceFile();
741
742 return Result;
743}