blob: 9c3a39f4f6c2fec80815bd08a4314b792d94f2c6 [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"
Douglas Gregorac252a32011-12-06 19:39:29 +000023#include "llvm/Support/FileSystem.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000024#include "llvm/Support/Host.h"
Douglas Gregor8b6d3de2011-11-11 21:55:48 +000025#include "llvm/Support/PathV2.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000026#include "llvm/Support/raw_ostream.h"
27#include "llvm/ADT/StringRef.h"
28#include "llvm/ADT/StringSwitch.h"
29using namespace clang;
30
Douglas Gregor90db2602011-12-02 01:47:07 +000031Module::ExportDecl
32ModuleMap::resolveExport(Module *Mod,
33 const Module::UnresolvedExportDecl &Unresolved,
34 bool Complain) {
Douglas Gregor0adaa882011-12-05 17:28:06 +000035 // We may have just a wildcard.
36 if (Unresolved.Id.empty()) {
37 assert(Unresolved.Wildcard && "Invalid unresolved export");
38 return Module::ExportDecl(0, true);
39 }
40
Douglas Gregor90db2602011-12-02 01:47:07 +000041 // Find the starting module.
42 Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
43 if (!Context) {
44 if (Complain)
45 Diags->Report(Unresolved.Id[0].second,
46 diag::err_mmap_missing_module_unqualified)
47 << Unresolved.Id[0].first << Mod->getFullModuleName();
48
49 return Module::ExportDecl();
50 }
51
52 // Dig into the module path.
53 for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
54 Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
55 Context);
56 if (!Sub) {
57 if (Complain)
58 Diags->Report(Unresolved.Id[I].second,
59 diag::err_mmap_missing_module_qualified)
60 << Unresolved.Id[I].first << Context->getFullModuleName()
61 << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
62
63 return Module::ExportDecl();
64 }
65
66 Context = Sub;
67 }
68
69 return Module::ExportDecl(Context, Unresolved.Wildcard);
70}
71
Douglas Gregora30cfe52011-11-11 19:10:28 +000072ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
73 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
74 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
75 new DiagnosticsEngine(DiagIDs));
76 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
77 SourceMgr = new SourceManager(*Diags, FileMgr);
78}
79
80ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +000081 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
82 IEnd = Modules.end();
83 I != IEnd; ++I) {
84 delete I->getValue();
85 }
86
Douglas Gregora30cfe52011-11-11 19:10:28 +000087 delete SourceMgr;
88}
89
Douglas Gregor1a4761e2011-11-30 23:21:26 +000090Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor65f3b5e2011-11-11 22:18:48 +000091 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
92 = Headers.find(File);
93 if (Known != Headers.end())
94 return Known->second;
95
Douglas Gregoradb97992011-11-16 23:02:25 +000096 const DirectoryEntry *Dir = File->getDir();
Douglas Gregoradb97992011-11-16 23:02:25 +000097 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
98 StringRef DirName = Dir->getName();
Douglas Gregore209e502011-12-06 01:10:29 +000099
100 // Keep walking up the directory hierarchy, looking for a directory with
101 // an umbrella header.
102 do {
103 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
104 = UmbrellaDirs.find(Dir);
105 if (KnownDir != UmbrellaDirs.end()) {
106 Module *Result = KnownDir->second;
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000107
108 // Search up the module stack until we find a module with an umbrella
109 // header.
110 Module *UmbrellaModule = Result;
111 while (!UmbrellaModule->UmbrellaHeader && UmbrellaModule->Parent)
112 UmbrellaModule = UmbrellaModule->Parent;
113
114 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-12-06 01:10:29 +0000115 // Infer submodules for each of the directories we found between
116 // the directory of the umbrella header and the directory where
117 // the actual header is located.
118
119 // For a framework module, the umbrella directory is the framework
120 // directory, so strip off the "Headers" or "PrivateHeaders".
121 // FIXME: Should we tack on an "explicit" for PrivateHeaders? That
122 // might be what we want, but it feels like a hack.
123 unsigned LastSkippedDir = SkippedDirs.size();
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000124 if (LastSkippedDir && UmbrellaModule->IsFramework)
Douglas Gregore209e502011-12-06 01:10:29 +0000125 --LastSkippedDir;
126
127 for (unsigned I = LastSkippedDir; I != 0; --I) {
128 // Find or create the module that corresponds to this directory name.
129 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
130 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000131 UmbrellaModule->InferExplicitSubmodules).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000132
133 // Associate the module and the directory.
134 UmbrellaDirs[SkippedDirs[I-1]] = Result;
135
136 // If inferred submodules export everything they import, add a
137 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000138 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000139 Result->Exports.push_back(Module::ExportDecl(0, true));
140 }
141
142 // Infer a submodule with the same name as this header file.
143 StringRef Name = llvm::sys::path::stem(File->getName());
144 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000145 UmbrellaModule->InferExplicitSubmodules).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000146
147 // If inferred submodules export everything they import, add a
148 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000149 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000150 Result->Exports.push_back(Module::ExportDecl(0, true));
151 } else {
152 // Record each of the directories we stepped through as being part of
153 // the module we found, since the umbrella header covers them all.
154 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
155 UmbrellaDirs[SkippedDirs[I]] = Result;
156 }
157
158 Headers[File] = Result;
159 return Result;
160 }
161
162 SkippedDirs.push_back(Dir);
163
Douglas Gregoradb97992011-11-16 23:02:25 +0000164 // Retrieve our parent path.
165 DirName = llvm::sys::path::parent_path(DirName);
166 if (DirName.empty())
167 break;
168
169 // Resolve the parent path to a directory entry.
170 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000171 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000172
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000173 return 0;
174}
175
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000176Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000177 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
178 if (Known != Modules.end())
179 return Known->getValue();
180
181 return 0;
182}
183
Douglas Gregor90db2602011-12-02 01:47:07 +0000184Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
185 for(; Context; Context = Context->Parent) {
186 if (Module *Sub = lookupModuleQualified(Name, Context))
187 return Sub;
188 }
189
190 return findModule(Name);
191}
192
193Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
194 if (!Context)
195 return findModule(Name);
196
197 llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name);
198 if (Sub != Context->SubModules.end())
199 return Sub->getValue();
200
201 return 0;
202}
203
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000204std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000205ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
206 bool IsExplicit) {
207 // Try to find an existing module with this name.
208 if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
209 return std::make_pair(Found, false);
210
211 // Create a new module with this name.
212 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
213 IsExplicit);
214 if (Parent)
215 Parent->SubModules[Name] = Result;
216 else
217 Modules[Name] = Result;
218 return std::make_pair(Result, true);
219}
220
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000221Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000222ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000223 const DirectoryEntry *FrameworkDir,
224 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000225 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000226 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
227 return Mod;
228
229 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000230
231 // Look for an umbrella header.
232 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
233 llvm::sys::path::append(UmbrellaName, "Headers");
234 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000235 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000236
237 // FIXME: If there's no umbrella header, we could probably scan the
238 // framework to load *everything*. But, it's not clear that this is a good
239 // idea.
240 if (!UmbrellaHeader)
241 return 0;
242
Douglas Gregorac252a32011-12-06 19:39:29 +0000243 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
244 /*IsFramework=*/true, /*IsExplicit=*/false);
245
246 if (Parent)
247 Parent->SubModules[ModuleName] = Result;
248 else
249 Modules[ModuleName] = Result;
250
Douglas Gregor209977c2011-12-05 17:40:25 +0000251 // umbrella "umbrella-header-name"
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000252 Result->UmbrellaHeader = UmbrellaHeader;
253 Headers[UmbrellaHeader] = Result;
254 UmbrellaDirs[FrameworkDir] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000255
256 // export *
257 Result->Exports.push_back(Module::ExportDecl(0, true));
258
Douglas Gregore209e502011-12-06 01:10:29 +0000259 // module * { export * }
260 Result->InferSubmodules = true;
261 Result->InferExportWildcard = true;
262
Douglas Gregorac252a32011-12-06 19:39:29 +0000263 // Look for subframeworks.
264 llvm::error_code EC;
265 llvm::SmallString<128> SubframeworksDirName = StringRef(FrameworkDir->getName());
266 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
267 for (llvm::sys::fs::directory_iterator Dir(SubframeworksDirName.str(), EC),
268 DirEnd;
269 Dir != DirEnd && !EC; Dir.increment(EC)) {
270 if (!StringRef(Dir->path()).endswith(".framework"))
271 continue;
272
273 if (const DirectoryEntry *SubframeworkDir
274 = FileMgr.getDirectory(Dir->path())) {
275 // FIXME: Do we want to warn about subframeworks without umbrella headers?
276 inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
277 Result);
278 }
279 }
Douglas Gregord620a842011-12-06 17:16:41 +0000280
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000281 return Result;
282}
283
Douglas Gregore209e502011-12-06 01:10:29 +0000284void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
285 Headers[UmbrellaHeader] = Mod;
286 Mod->UmbrellaHeader = UmbrellaHeader;
287
288 const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir();
289 if (Mod->IsFramework)
290 UmbrellaDir = SourceMgr->getFileManager().getDirectory(
291 llvm::sys::path::parent_path(UmbrellaDir->getName()));
292
293 UmbrellaDirs[UmbrellaDir] = Mod;
294}
295
296void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
297 Mod->Headers.push_back(Header);
298 Headers[Header] = Mod;
299}
300
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000301const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000302ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000303 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
304 return 0;
305
306 return SourceMgr->getFileEntryForID(
307 SourceMgr->getFileID(Module->DefinitionLoc));
308}
309
Douglas Gregora30cfe52011-11-11 19:10:28 +0000310void ModuleMap::dump() {
311 llvm::errs() << "Modules:";
312 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
313 MEnd = Modules.end();
314 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000315 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000316
317 llvm::errs() << "Headers:";
318 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
319 H = Headers.begin(),
320 HEnd = Headers.end();
321 H != HEnd; ++H) {
322 llvm::errs() << " \"" << H->first->getName() << "\" -> "
323 << H->second->getFullModuleName() << "\n";
324 }
325}
326
Douglas Gregor90db2602011-12-02 01:47:07 +0000327bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
328 bool HadError = false;
329 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
330 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
331 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000332 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000333 Mod->Exports.push_back(Export);
334 else
335 HadError = true;
336 }
337 Mod->UnresolvedExports.clear();
338 return HadError;
339}
340
Douglas Gregor55988682011-12-05 16:33:54 +0000341Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
342 if (Loc.isInvalid())
343 return 0;
344
345 // Use the expansion location to determine which module we're in.
346 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
347 if (!ExpansionLoc.isFileID())
348 return 0;
349
350
351 const SourceManager &SrcMgr = Loc.getManager();
352 FileID ExpansionFileID = ExpansionLoc.getFileID();
353 const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
354 if (!ExpansionFile)
355 return 0;
356
357 // Find the module that owns this header.
358 return findModuleForHeader(ExpansionFile);
359}
360
Douglas Gregora30cfe52011-11-11 19:10:28 +0000361//----------------------------------------------------------------------------//
362// Module map file parser
363//----------------------------------------------------------------------------//
364
365namespace clang {
366 /// \brief A token in a module map file.
367 struct MMToken {
368 enum TokenKind {
369 EndOfFile,
370 HeaderKeyword,
371 Identifier,
372 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000373 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000374 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000375 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000376 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000377 UmbrellaKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000378 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000379 StringLiteral,
380 LBrace,
381 RBrace
382 } Kind;
383
384 unsigned Location;
385 unsigned StringLength;
386 const char *StringData;
387
388 void clear() {
389 Kind = EndOfFile;
390 Location = 0;
391 StringLength = 0;
392 StringData = 0;
393 }
394
395 bool is(TokenKind K) const { return Kind == K; }
396
397 SourceLocation getLocation() const {
398 return SourceLocation::getFromRawEncoding(Location);
399 }
400
401 StringRef getString() const {
402 return StringRef(StringData, StringLength);
403 }
404 };
405
406 class ModuleMapParser {
407 Lexer &L;
408 SourceManager &SourceMgr;
409 DiagnosticsEngine &Diags;
410 ModuleMap &Map;
411
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000412 /// \brief The directory that this module map resides in.
413 const DirectoryEntry *Directory;
414
Douglas Gregora30cfe52011-11-11 19:10:28 +0000415 /// \brief Whether an error occurred.
416 bool HadError;
417
418 /// \brief Default target information, used only for string literal
419 /// parsing.
420 TargetInfo *Target;
421
422 /// \brief Stores string data for the various string literals referenced
423 /// during parsing.
424 llvm::BumpPtrAllocator StringData;
425
426 /// \brief The current token.
427 MMToken Tok;
428
429 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000430 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000431
432 /// \brief Consume the current token and return its location.
433 SourceLocation consumeToken();
434
435 /// \brief Skip tokens until we reach the a token with the given kind
436 /// (or the end of the file).
437 void skipUntil(MMToken::TokenKind K);
438
439 void parseModuleDecl();
440 void parseUmbrellaDecl();
441 void parseHeaderDecl();
Douglas Gregor90db2602011-12-02 01:47:07 +0000442 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000443 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000444
445 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000446 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
447 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000448 ModuleMap &Map,
449 const DirectoryEntry *Directory)
450 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
451 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000452 {
453 TargetOptions TargetOpts;
454 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
455 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
456
457 Tok.clear();
458 consumeToken();
459 }
460
461 bool parseModuleMapFile();
462 };
463}
464
465SourceLocation ModuleMapParser::consumeToken() {
466retry:
467 SourceLocation Result = Tok.getLocation();
468 Tok.clear();
469
470 Token LToken;
471 L.LexFromRawLexer(LToken);
472 Tok.Location = LToken.getLocation().getRawEncoding();
473 switch (LToken.getKind()) {
474 case tok::raw_identifier:
475 Tok.StringData = LToken.getRawIdentifierData();
476 Tok.StringLength = LToken.getLength();
477 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
478 .Case("header", MMToken::HeaderKeyword)
479 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000480 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000481 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000482 .Case("module", MMToken::ModuleKeyword)
483 .Case("umbrella", MMToken::UmbrellaKeyword)
484 .Default(MMToken::Identifier);
485 break;
486
487 case tok::eof:
488 Tok.Kind = MMToken::EndOfFile;
489 break;
490
491 case tok::l_brace:
492 Tok.Kind = MMToken::LBrace;
493 break;
494
Douglas Gregor90db2602011-12-02 01:47:07 +0000495 case tok::period:
496 Tok.Kind = MMToken::Period;
497 break;
498
Douglas Gregora30cfe52011-11-11 19:10:28 +0000499 case tok::r_brace:
500 Tok.Kind = MMToken::RBrace;
501 break;
502
Douglas Gregor90db2602011-12-02 01:47:07 +0000503 case tok::star:
504 Tok.Kind = MMToken::Star;
505 break;
506
Douglas Gregora30cfe52011-11-11 19:10:28 +0000507 case tok::string_literal: {
508 // Parse the string literal.
509 LangOptions LangOpts;
510 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
511 if (StringLiteral.hadError)
512 goto retry;
513
514 // Copy the string literal into our string data allocator.
515 unsigned Length = StringLiteral.GetStringLength();
516 char *Saved = StringData.Allocate<char>(Length + 1);
517 memcpy(Saved, StringLiteral.GetString().data(), Length);
518 Saved[Length] = 0;
519
520 // Form the token.
521 Tok.Kind = MMToken::StringLiteral;
522 Tok.StringData = Saved;
523 Tok.StringLength = Length;
524 break;
525 }
526
527 case tok::comment:
528 goto retry;
529
530 default:
531 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
532 HadError = true;
533 goto retry;
534 }
535
536 return Result;
537}
538
539void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
540 unsigned braceDepth = 0;
541 do {
542 switch (Tok.Kind) {
543 case MMToken::EndOfFile:
544 return;
545
546 case MMToken::LBrace:
547 if (Tok.is(K) && braceDepth == 0)
548 return;
549
550 ++braceDepth;
551 break;
552
553 case MMToken::RBrace:
554 if (braceDepth > 0)
555 --braceDepth;
556 else if (Tok.is(K))
557 return;
558 break;
559
560 default:
561 if (braceDepth == 0 && Tok.is(K))
562 return;
563 break;
564 }
565
566 consumeToken();
567 } while (true);
568}
569
570/// \brief Parse a module declaration.
571///
572/// module-declaration:
Douglas Gregora8654052011-11-17 22:09:43 +0000573/// 'framework'[opt] 'module' identifier { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000574///
575/// module-member:
576/// umbrella-declaration
577/// header-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000578/// 'explicit'[opt] submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000579/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000580///
581/// submodule-declaration:
582/// module-declaration
583/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000584void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000585 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
586 Tok.is(MMToken::FrameworkKeyword));
587
Douglas Gregord620a842011-12-06 17:16:41 +0000588 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregora30cfe52011-11-11 19:10:28 +0000589 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000590 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000591
Douglas Gregord620a842011-12-06 17:16:41 +0000592 // Parse 'explicit' keyword, if present.
593 if (Tok.is(MMToken::ExplicitKeyword)) {
594 consumeToken();
595 Explicit = true;
596 }
597
598 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000599 if (Tok.is(MMToken::FrameworkKeyword)) {
600 consumeToken();
601 Framework = true;
602 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000603
604 // Parse 'module' keyword.
605 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000606 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000607 consumeToken();
608 HadError = true;
609 return;
610 }
611 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000612
613 // If we have a wildcard for the module name, this is an inferred submodule.
614 // Parse it.
615 if (Tok.is(MMToken::Star))
616 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000617
618 // Parse the module name.
619 if (!Tok.is(MMToken::Identifier)) {
620 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
621 HadError = true;
622 return;
623 }
624 StringRef ModuleName = Tok.getString();
625 SourceLocation ModuleNameLoc = consumeToken();
626
627 // Parse the opening brace.
628 if (!Tok.is(MMToken::LBrace)) {
629 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
630 << ModuleName;
631 HadError = true;
632 return;
633 }
634 SourceLocation LBraceLoc = consumeToken();
635
636 // Determine whether this (sub)module has already been defined.
637 llvm::StringMap<Module *> &ModuleSpace
638 = ActiveModule? ActiveModule->SubModules : Map.Modules;
639 llvm::StringMap<Module *>::iterator ExistingModule
640 = ModuleSpace.find(ModuleName);
641 if (ExistingModule != ModuleSpace.end()) {
642 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
643 << ModuleName;
644 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
645 diag::note_mmap_prev_definition);
646
647 // Skip the module definition.
648 skipUntil(MMToken::RBrace);
649 if (Tok.is(MMToken::RBrace))
650 consumeToken();
651
652 HadError = true;
653 return;
654 }
655
656 // Start defining this module.
Douglas Gregora8654052011-11-17 22:09:43 +0000657 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
658 Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000659 ModuleSpace[ModuleName] = ActiveModule;
660
661 bool Done = false;
662 do {
663 switch (Tok.Kind) {
664 case MMToken::EndOfFile:
665 case MMToken::RBrace:
666 Done = true;
667 break;
668
669 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000670 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000671 case MMToken::ModuleKeyword:
672 parseModuleDecl();
673 break;
674
Douglas Gregor90db2602011-12-02 01:47:07 +0000675 case MMToken::ExportKeyword:
676 parseExportDecl();
677 break;
678
Douglas Gregora30cfe52011-11-11 19:10:28 +0000679 case MMToken::HeaderKeyword:
680 parseHeaderDecl();
681 break;
682
683 case MMToken::UmbrellaKeyword:
684 parseUmbrellaDecl();
685 break;
Douglas Gregor90db2602011-12-02 01:47:07 +0000686
Douglas Gregora30cfe52011-11-11 19:10:28 +0000687 default:
688 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
689 consumeToken();
690 break;
691 }
692 } while (!Done);
693
694 if (Tok.is(MMToken::RBrace))
695 consumeToken();
696 else {
697 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
698 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
699 HadError = true;
700 }
701
702 // We're done parsing this module. Pop back to our parent scope.
703 ActiveModule = ActiveModule->Parent;
704}
Douglas Gregord620a842011-12-06 17:16:41 +0000705
706/// \brief Append to \p Paths the set of paths needed to get to the
707/// subframework in which the given module lives.
708void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
709 // Collect the framework names from the given module to the top-level module.
710 llvm::SmallVector<StringRef, 2> Paths;
711 for (; Mod; Mod = Mod->Parent) {
712 if (Mod->IsFramework)
713 Paths.push_back(Mod->Name);
714 }
715
716 if (Paths.empty())
717 return;
718
719 // Add Frameworks/Name.framework for each subframework.
720 for (unsigned I = Paths.size() - 1; I != 0; --I) {
721 llvm::sys::path::append(Path, "Frameworks");
722 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
723 }
724}
725
Douglas Gregora30cfe52011-11-11 19:10:28 +0000726/// \brief Parse an umbrella header declaration.
727///
728/// umbrella-declaration:
729/// 'umbrella' string-literal
730void ModuleMapParser::parseUmbrellaDecl() {
731 assert(Tok.is(MMToken::UmbrellaKeyword));
732 SourceLocation UmbrellaLoc = consumeToken();
733
734 // Parse the header name.
735 if (!Tok.is(MMToken::StringLiteral)) {
736 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
737 << "umbrella";
738 HadError = true;
739 return;
740 }
741 StringRef FileName = Tok.getString();
742 SourceLocation FileNameLoc = consumeToken();
743
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000744 // Check whether we already have an umbrella header.
745 if (ActiveModule->UmbrellaHeader) {
746 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
747 << ActiveModule->getFullModuleName()
748 << ActiveModule->UmbrellaHeader->getName();
749 HadError = true;
750 return;
751 }
752
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000753 // Look for this file.
754 llvm::SmallString<128> PathName;
Douglas Gregora8654052011-11-17 22:09:43 +0000755 const FileEntry *File = 0;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000756
757 if (llvm::sys::path::is_absolute(FileName)) {
758 PathName = FileName;
Douglas Gregora8654052011-11-17 22:09:43 +0000759 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000760 } else {
761 // Search for the header file within the search directory.
762 PathName += Directory->getName();
763 unsigned PathLength = PathName.size();
Douglas Gregord620a842011-12-06 17:16:41 +0000764
Douglas Gregor18ee5472011-11-29 21:59:16 +0000765 if (ActiveModule->isPartOfFramework()) {
Douglas Gregord620a842011-12-06 17:16:41 +0000766 appendSubframeworkPaths(ActiveModule, PathName);
767
Douglas Gregor18ee5472011-11-29 21:59:16 +0000768 // Check whether this file is in the public headers.
769 llvm::sys::path::append(PathName, "Headers");
770 llvm::sys::path::append(PathName, FileName);
771 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregora8654052011-11-17 22:09:43 +0000772
Douglas Gregor18ee5472011-11-29 21:59:16 +0000773 if (!File) {
774 // Check whether this file is in the private headers.
775 PathName.resize(PathLength);
776 llvm::sys::path::append(PathName, "PrivateHeaders");
777 llvm::sys::path::append(PathName, FileName);
778 File = SourceMgr.getFileManager().getFile(PathName);
779 }
Douglas Gregor18ee5472011-11-29 21:59:16 +0000780 } else {
781 // Lookup for normal headers.
Douglas Gregora8654052011-11-17 22:09:43 +0000782 llvm::sys::path::append(PathName, FileName);
783 File = SourceMgr.getFileManager().getFile(PathName);
784 }
Douglas Gregora8654052011-11-17 22:09:43 +0000785 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000786
787 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
788 // Come up with a lazy way to do this.
Douglas Gregora8654052011-11-17 22:09:43 +0000789 if (File) {
Douglas Gregore209e502011-12-06 01:10:29 +0000790 const DirectoryEntry *UmbrellaDir = File->getDir();
791 if (ActiveModule->IsFramework) {
792 // For framework modules, use the framework directory as the umbrella
793 // directory.
794 UmbrellaDir = SourceMgr.getFileManager().getDirectory(
795 llvm::sys::path::parent_path(UmbrellaDir->getName()));
796 }
797
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000798 if (const Module *OwningModule = Map.Headers[File]) {
799 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
800 << FileName << OwningModule->getFullModuleName();
801 HadError = true;
Douglas Gregore209e502011-12-06 01:10:29 +0000802 } else if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
Douglas Gregoradb97992011-11-16 23:02:25 +0000803 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
804 << OwningModule->getFullModuleName();
805 HadError = true;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000806 } else {
807 // Record this umbrella header.
Douglas Gregore209e502011-12-06 01:10:29 +0000808 Map.setUmbrellaHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000809 }
810 } else {
811 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
812 << true << FileName;
813 HadError = true;
814 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000815}
816
817/// \brief Parse a header declaration.
818///
819/// header-declaration:
820/// 'header' string-literal
821void ModuleMapParser::parseHeaderDecl() {
822 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000823 consumeToken();
824
Douglas Gregora30cfe52011-11-11 19:10:28 +0000825 // Parse the header name.
826 if (!Tok.is(MMToken::StringLiteral)) {
827 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
828 << "header";
829 HadError = true;
830 return;
831 }
832 StringRef FileName = Tok.getString();
833 SourceLocation FileNameLoc = consumeToken();
834
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000835 // Look for this file.
836 llvm::SmallString<128> PathName;
Douglas Gregor18ee5472011-11-29 21:59:16 +0000837 if (llvm::sys::path::is_relative(FileName)) {
838 // FIXME: Change this search to also look for private headers!
839 PathName += Directory->getName();
840
Douglas Gregord620a842011-12-06 17:16:41 +0000841 if (ActiveModule->isPartOfFramework()) {
842 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor18ee5472011-11-29 21:59:16 +0000843 llvm::sys::path::append(PathName, "Headers");
Douglas Gregord620a842011-12-06 17:16:41 +0000844 }
Douglas Gregor18ee5472011-11-29 21:59:16 +0000845 }
Douglas Gregora8654052011-11-17 22:09:43 +0000846
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000847 llvm::sys::path::append(PathName, FileName);
848
849 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
850 // Come up with a lazy way to do this.
851 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
852 if (const Module *OwningModule = Map.Headers[File]) {
853 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
854 << FileName << OwningModule->getFullModuleName();
855 HadError = true;
856 } else {
857 // Record this file.
Douglas Gregore209e502011-12-06 01:10:29 +0000858 Map.addHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000859 }
860 } else {
861 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
862 << false << FileName;
863 HadError = true;
864 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000865}
866
Douglas Gregor90db2602011-12-02 01:47:07 +0000867/// \brief Parse a module export declaration.
868///
869/// export-declaration:
870/// 'export' wildcard-module-id
871///
872/// wildcard-module-id:
873/// identifier
874/// '*'
875/// identifier '.' wildcard-module-id
876void ModuleMapParser::parseExportDecl() {
877 assert(Tok.is(MMToken::ExportKeyword));
878 SourceLocation ExportLoc = consumeToken();
879
880 // Parse the module-id with an optional wildcard at the end.
881 ModuleId ParsedModuleId;
882 bool Wildcard = false;
883 do {
884 if (Tok.is(MMToken::Identifier)) {
885 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
886 Tok.getLocation()));
887 consumeToken();
888
889 if (Tok.is(MMToken::Period)) {
890 consumeToken();
891 continue;
892 }
893
894 break;
895 }
896
897 if(Tok.is(MMToken::Star)) {
898 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +0000899 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +0000900 break;
901 }
902
903 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
904 HadError = true;
905 return;
906 } while (true);
907
908 Module::UnresolvedExportDecl Unresolved = {
909 ExportLoc, ParsedModuleId, Wildcard
910 };
911 ActiveModule->UnresolvedExports.push_back(Unresolved);
912}
913
Douglas Gregor1e123682011-12-05 22:27:44 +0000914void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
915 assert(Tok.is(MMToken::Star));
916 SourceLocation StarLoc = consumeToken();
917 bool Failed = false;
918
919 // Inferred modules must be submodules.
920 if (!ActiveModule) {
921 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
922 Failed = true;
923 }
924
925 // Inferred modules must have umbrella headers.
Douglas Gregoref85b562011-12-06 17:34:58 +0000926 if (!Failed && !ActiveModule->UmbrellaHeader) {
Douglas Gregor1e123682011-12-05 22:27:44 +0000927 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
928 Failed = true;
929 }
930
931 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +0000932 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +0000933 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +0000934 if (ActiveModule->InferredSubmoduleLoc.isValid())
935 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +0000936 diag::note_mmap_prev_definition);
937 Failed = true;
938 }
939
940 // If there were any problems with this inferred submodule, skip its body.
941 if (Failed) {
942 if (Tok.is(MMToken::LBrace)) {
943 consumeToken();
944 skipUntil(MMToken::RBrace);
945 if (Tok.is(MMToken::RBrace))
946 consumeToken();
947 }
948 HadError = true;
949 return;
950 }
951
952 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +0000953 ActiveModule->InferSubmodules = true;
954 ActiveModule->InferredSubmoduleLoc = StarLoc;
955 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +0000956
957 // Parse the opening brace.
958 if (!Tok.is(MMToken::LBrace)) {
959 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
960 HadError = true;
961 return;
962 }
963 SourceLocation LBraceLoc = consumeToken();
964
965 // Parse the body of the inferred submodule.
966 bool Done = false;
967 do {
968 switch (Tok.Kind) {
969 case MMToken::EndOfFile:
970 case MMToken::RBrace:
971 Done = true;
972 break;
973
974 case MMToken::ExportKeyword: {
975 consumeToken();
976 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +0000977 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +0000978 else
979 Diags.Report(Tok.getLocation(),
980 diag::err_mmap_expected_export_wildcard);
981 consumeToken();
982 break;
983 }
984
985 case MMToken::ExplicitKeyword:
986 case MMToken::ModuleKeyword:
987 case MMToken::HeaderKeyword:
988 case MMToken::UmbrellaKeyword:
989 default:
990 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
991 consumeToken();
992 break;
993 }
994 } while (!Done);
995
996 if (Tok.is(MMToken::RBrace))
997 consumeToken();
998 else {
999 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1000 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1001 HadError = true;
1002 }
1003}
1004
Douglas Gregora30cfe52011-11-11 19:10:28 +00001005/// \brief Parse a module map file.
1006///
1007/// module-map-file:
1008/// module-declaration*
1009bool ModuleMapParser::parseModuleMapFile() {
1010 do {
1011 switch (Tok.Kind) {
1012 case MMToken::EndOfFile:
1013 return HadError;
1014
1015 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001016 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001017 parseModuleDecl();
1018 break;
1019
1020 case MMToken::ExplicitKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001021 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001022 case MMToken::HeaderKeyword:
1023 case MMToken::Identifier:
1024 case MMToken::LBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001025 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001026 case MMToken::RBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001027 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001028 case MMToken::StringLiteral:
1029 case MMToken::UmbrellaKeyword:
1030 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1031 HadError = true;
1032 consumeToken();
1033 break;
1034 }
1035 } while (true);
1036
1037 return HadError;
1038}
1039
1040bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
1041 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1042 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1043 if (!Buffer)
1044 return true;
1045
1046 // Parse this module map file.
1047 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
1048 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001049 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001050 bool Result = Parser.parseModuleMapFile();
1051 Diags->getClient()->EndSourceFile();
1052
1053 return Result;
1054}