blob: 08a1e23d107532a42deb1122e0b8437ce0bdac17 [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 Gregor51f564f2011-12-31 04:05:44 +000072ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
73 const LangOptions &LangOpts)
74 : LangOpts(LangOpts)
75{
Douglas Gregora30cfe52011-11-11 19:10:28 +000076 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
77 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
78 new DiagnosticsEngine(DiagIDs));
79 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
80 SourceMgr = new SourceManager(*Diags, FileMgr);
81}
82
83ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +000084 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
85 IEnd = Modules.end();
86 I != IEnd; ++I) {
87 delete I->getValue();
88 }
89
Douglas Gregora30cfe52011-11-11 19:10:28 +000090 delete SourceMgr;
91}
92
Douglas Gregor1a4761e2011-11-30 23:21:26 +000093Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor65f3b5e2011-11-11 22:18:48 +000094 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
95 = Headers.find(File);
Douglas Gregor51f564f2011-12-31 04:05:44 +000096 if (Known != Headers.end()) {
97 // If a header corresponds to an unavailable module, don't report
98 // that it maps to anything.
99 if (!Known->second->isAvailable())
100 return 0;
101
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000102 return Known->second;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000103 }
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000104
Douglas Gregoradb97992011-11-16 23:02:25 +0000105 const DirectoryEntry *Dir = File->getDir();
Douglas Gregoradb97992011-11-16 23:02:25 +0000106 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
107 StringRef DirName = Dir->getName();
Douglas Gregore209e502011-12-06 01:10:29 +0000108
109 // Keep walking up the directory hierarchy, looking for a directory with
110 // an umbrella header.
111 do {
112 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
113 = UmbrellaDirs.find(Dir);
114 if (KnownDir != UmbrellaDirs.end()) {
115 Module *Result = KnownDir->second;
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000116
117 // Search up the module stack until we find a module with an umbrella
Douglas Gregor10694ce2011-12-08 17:39:04 +0000118 // directory.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000119 Module *UmbrellaModule = Result;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000120 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000121 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000122
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000123 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-12-06 01:10:29 +0000124 // Infer submodules for each of the directories we found between
125 // the directory of the umbrella header and the directory where
126 // the actual header is located.
Douglas Gregor23af6d52011-12-07 22:05:21 +0000127 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregore209e502011-12-06 01:10:29 +0000128
Douglas Gregor6a1db482011-12-09 02:04:43 +0000129 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregore209e502011-12-06 01:10:29 +0000130 // Find or create the module that corresponds to this directory name.
131 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
132 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000133 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000134
135 // Associate the module and the directory.
136 UmbrellaDirs[SkippedDirs[I-1]] = Result;
137
138 // If inferred submodules export everything they import, add a
139 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000140 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000141 Result->Exports.push_back(Module::ExportDecl(0, true));
142 }
143
144 // Infer a submodule with the same name as this header file.
145 StringRef Name = llvm::sys::path::stem(File->getName());
146 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000147 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000148
149 // If inferred submodules export everything they import, add a
150 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000151 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000152 Result->Exports.push_back(Module::ExportDecl(0, true));
153 } else {
154 // Record each of the directories we stepped through as being part of
155 // the module we found, since the umbrella header covers them all.
156 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
157 UmbrellaDirs[SkippedDirs[I]] = Result;
158 }
159
160 Headers[File] = Result;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000161
162 // If a header corresponds to an unavailable module, don't report
163 // that it maps to anything.
164 if (!Result->isAvailable())
165 return 0;
166
Douglas Gregore209e502011-12-06 01:10:29 +0000167 return Result;
168 }
169
170 SkippedDirs.push_back(Dir);
171
Douglas Gregoradb97992011-11-16 23:02:25 +0000172 // Retrieve our parent path.
173 DirName = llvm::sys::path::parent_path(DirName);
174 if (DirName.empty())
175 break;
176
177 // Resolve the parent path to a directory entry.
178 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000179 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000180
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000181 return 0;
182}
183
Douglas Gregor51f564f2011-12-31 04:05:44 +0000184bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
185 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
186 = Headers.find(Header);
187 if (Known != Headers.end())
188 return !Known->second->isAvailable();
189
190 const DirectoryEntry *Dir = Header->getDir();
191 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
192 StringRef DirName = Dir->getName();
193
194 // Keep walking up the directory hierarchy, looking for a directory with
195 // an umbrella header.
196 do {
197 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
198 = UmbrellaDirs.find(Dir);
199 if (KnownDir != UmbrellaDirs.end()) {
200 Module *Found = KnownDir->second;
201 if (!Found->isAvailable())
202 return true;
203
204 // Search up the module stack until we find a module with an umbrella
205 // directory.
206 Module *UmbrellaModule = Found;
207 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
208 UmbrellaModule = UmbrellaModule->Parent;
209
210 if (UmbrellaModule->InferSubmodules) {
211 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
212 // Find or create the module that corresponds to this directory name.
213 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
214 Found = lookupModuleQualified(Name, Found);
215 if (!Found)
216 return false;
217 if (!Found->isAvailable())
218 return true;
219 }
220
221 // Infer a submodule with the same name as this header file.
222 StringRef Name = llvm::sys::path::stem(Header->getName());
223 Found = lookupModuleQualified(Name, Found);
224 if (!Found)
225 return false;
226 }
227
228 return !Found->isAvailable();
229 }
230
231 SkippedDirs.push_back(Dir);
232
233 // Retrieve our parent path.
234 DirName = llvm::sys::path::parent_path(DirName);
235 if (DirName.empty())
236 break;
237
238 // Resolve the parent path to a directory entry.
239 Dir = SourceMgr->getFileManager().getDirectory(DirName);
240 } while (Dir);
241
242 return false;
243}
244
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000245Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000246 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
247 if (Known != Modules.end())
248 return Known->getValue();
249
250 return 0;
251}
252
Douglas Gregor90db2602011-12-02 01:47:07 +0000253Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
254 for(; Context; Context = Context->Parent) {
255 if (Module *Sub = lookupModuleQualified(Name, Context))
256 return Sub;
257 }
258
259 return findModule(Name);
260}
261
262Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
263 if (!Context)
264 return findModule(Name);
265
Douglas Gregorb7a78192012-01-04 23:32:19 +0000266 return Context->findSubmodule(Name);
Douglas Gregor90db2602011-12-02 01:47:07 +0000267}
268
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000269std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000270ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
271 bool IsExplicit) {
272 // Try to find an existing module with this name.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000273 if (Module *Sub = lookupModuleQualified(Name, Parent))
274 return std::make_pair(Sub, false);
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000275
276 // Create a new module with this name.
277 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
278 IsExplicit);
Douglas Gregorb7a78192012-01-04 23:32:19 +0000279 if (!Parent)
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000280 Modules[Name] = Result;
281 return std::make_pair(Result, true);
282}
283
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000284Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000285ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000286 const DirectoryEntry *FrameworkDir,
287 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000288 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000289 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
290 return Mod;
291
292 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000293
294 // Look for an umbrella header.
295 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
296 llvm::sys::path::append(UmbrellaName, "Headers");
297 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000298 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000299
300 // FIXME: If there's no umbrella header, we could probably scan the
301 // framework to load *everything*. But, it's not clear that this is a good
302 // idea.
303 if (!UmbrellaHeader)
304 return 0;
305
Douglas Gregorac252a32011-12-06 19:39:29 +0000306 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
307 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregorb7a78192012-01-04 23:32:19 +0000308 if (!Parent)
Douglas Gregorac252a32011-12-06 19:39:29 +0000309 Modules[ModuleName] = Result;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000310
Douglas Gregor489ad432011-12-08 18:00:48 +0000311 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000312 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000313 Headers[UmbrellaHeader] = Result;
Douglas Gregor3cee31e2011-12-12 23:55:05 +0000314 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000315
316 // export *
317 Result->Exports.push_back(Module::ExportDecl(0, true));
318
Douglas Gregore209e502011-12-06 01:10:29 +0000319 // module * { export * }
320 Result->InferSubmodules = true;
321 Result->InferExportWildcard = true;
322
Douglas Gregorac252a32011-12-06 19:39:29 +0000323 // Look for subframeworks.
324 llvm::error_code EC;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000325 llvm::SmallString<128> SubframeworksDirName
326 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000327 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000328 llvm::SmallString<128> SubframeworksDirNameNative;
329 llvm::sys::path::native(SubframeworksDirName.str(),
330 SubframeworksDirNameNative);
331 for (llvm::sys::fs::directory_iterator
332 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregorac252a32011-12-06 19:39:29 +0000333 Dir != DirEnd && !EC; Dir.increment(EC)) {
334 if (!StringRef(Dir->path()).endswith(".framework"))
335 continue;
336
337 if (const DirectoryEntry *SubframeworkDir
338 = FileMgr.getDirectory(Dir->path())) {
339 // FIXME: Do we want to warn about subframeworks without umbrella headers?
340 inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
341 Result);
342 }
343 }
Douglas Gregor3a110f72012-01-13 16:54:27 +0000344
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000345 return Result;
346}
347
Douglas Gregore209e502011-12-06 01:10:29 +0000348void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
349 Headers[UmbrellaHeader] = Mod;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000350 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000351 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000352}
353
Douglas Gregor77d029f2011-12-08 19:11:24 +0000354void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
355 Mod->Umbrella = UmbrellaDir;
356 UmbrellaDirs[UmbrellaDir] = Mod;
357}
358
Douglas Gregore209e502011-12-06 01:10:29 +0000359void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
360 Mod->Headers.push_back(Header);
361 Headers[Header] = Mod;
362}
363
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000364const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000365ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000366 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
367 return 0;
368
369 return SourceMgr->getFileEntryForID(
370 SourceMgr->getFileID(Module->DefinitionLoc));
371}
372
Douglas Gregora30cfe52011-11-11 19:10:28 +0000373void ModuleMap::dump() {
374 llvm::errs() << "Modules:";
375 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
376 MEnd = Modules.end();
377 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000378 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000379
380 llvm::errs() << "Headers:";
381 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
382 H = Headers.begin(),
383 HEnd = Headers.end();
384 H != HEnd; ++H) {
385 llvm::errs() << " \"" << H->first->getName() << "\" -> "
386 << H->second->getFullModuleName() << "\n";
387 }
388}
389
Douglas Gregor90db2602011-12-02 01:47:07 +0000390bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
391 bool HadError = false;
392 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
393 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
394 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000395 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000396 Mod->Exports.push_back(Export);
397 else
398 HadError = true;
399 }
400 Mod->UnresolvedExports.clear();
401 return HadError;
402}
403
Douglas Gregor55988682011-12-05 16:33:54 +0000404Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
405 if (Loc.isInvalid())
406 return 0;
407
408 // Use the expansion location to determine which module we're in.
409 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
410 if (!ExpansionLoc.isFileID())
411 return 0;
412
413
414 const SourceManager &SrcMgr = Loc.getManager();
415 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor55988682011-12-05 16:33:54 +0000416
Douglas Gregor303aae92012-01-06 17:19:32 +0000417 while (const FileEntry *ExpansionFile
418 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
419 // Find the module that owns this header (if any).
420 if (Module *Mod = findModuleForHeader(ExpansionFile))
421 return Mod;
422
423 // No module owns this header, so look up the inclusion chain to see if
424 // any included header has an associated module.
425 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
426 if (IncludeLoc.isInvalid())
427 return 0;
428
429 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
430 }
431
432 return 0;
Douglas Gregor55988682011-12-05 16:33:54 +0000433}
434
Douglas Gregora30cfe52011-11-11 19:10:28 +0000435//----------------------------------------------------------------------------//
436// Module map file parser
437//----------------------------------------------------------------------------//
438
439namespace clang {
440 /// \brief A token in a module map file.
441 struct MMToken {
442 enum TokenKind {
Douglas Gregor51f564f2011-12-31 04:05:44 +0000443 Comma,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000444 EndOfFile,
445 HeaderKeyword,
446 Identifier,
447 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000448 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000449 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000450 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000451 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000452 UmbrellaKeyword,
Douglas Gregor51f564f2011-12-31 04:05:44 +0000453 RequiresKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000454 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000455 StringLiteral,
456 LBrace,
457 RBrace
458 } Kind;
459
460 unsigned Location;
461 unsigned StringLength;
462 const char *StringData;
463
464 void clear() {
465 Kind = EndOfFile;
466 Location = 0;
467 StringLength = 0;
468 StringData = 0;
469 }
470
471 bool is(TokenKind K) const { return Kind == K; }
472
473 SourceLocation getLocation() const {
474 return SourceLocation::getFromRawEncoding(Location);
475 }
476
477 StringRef getString() const {
478 return StringRef(StringData, StringLength);
479 }
480 };
481
482 class ModuleMapParser {
483 Lexer &L;
484 SourceManager &SourceMgr;
485 DiagnosticsEngine &Diags;
486 ModuleMap &Map;
487
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000488 /// \brief The directory that this module map resides in.
489 const DirectoryEntry *Directory;
490
Douglas Gregora30cfe52011-11-11 19:10:28 +0000491 /// \brief Whether an error occurred.
492 bool HadError;
493
494 /// \brief Default target information, used only for string literal
495 /// parsing.
496 TargetInfo *Target;
497
498 /// \brief Stores string data for the various string literals referenced
499 /// during parsing.
500 llvm::BumpPtrAllocator StringData;
501
502 /// \brief The current token.
503 MMToken Tok;
504
505 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000506 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000507
508 /// \brief Consume the current token and return its location.
509 SourceLocation consumeToken();
510
511 /// \brief Skip tokens until we reach the a token with the given kind
512 /// (or the end of the file).
513 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000514
515 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
516 ModuleId;
517 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000518 void parseModuleDecl();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000519 void parseRequiresDecl();
Douglas Gregor489ad432011-12-08 18:00:48 +0000520 void parseHeaderDecl(SourceLocation UmbrellaLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000521 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000522 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000523 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000524
Douglas Gregor6a1db482011-12-09 02:04:43 +0000525 const DirectoryEntry *getOverriddenHeaderSearchDir();
526
Douglas Gregora30cfe52011-11-11 19:10:28 +0000527 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000528 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
529 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000530 ModuleMap &Map,
531 const DirectoryEntry *Directory)
532 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
533 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000534 {
535 TargetOptions TargetOpts;
536 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
537 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
538
539 Tok.clear();
540 consumeToken();
541 }
542
543 bool parseModuleMapFile();
544 };
545}
546
547SourceLocation ModuleMapParser::consumeToken() {
548retry:
549 SourceLocation Result = Tok.getLocation();
550 Tok.clear();
551
552 Token LToken;
553 L.LexFromRawLexer(LToken);
554 Tok.Location = LToken.getLocation().getRawEncoding();
555 switch (LToken.getKind()) {
556 case tok::raw_identifier:
557 Tok.StringData = LToken.getRawIdentifierData();
558 Tok.StringLength = LToken.getLength();
559 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
560 .Case("header", MMToken::HeaderKeyword)
561 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000562 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000563 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000564 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor51f564f2011-12-31 04:05:44 +0000565 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000566 .Case("umbrella", MMToken::UmbrellaKeyword)
567 .Default(MMToken::Identifier);
568 break;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000569
570 case tok::comma:
571 Tok.Kind = MMToken::Comma;
572 break;
573
Douglas Gregora30cfe52011-11-11 19:10:28 +0000574 case tok::eof:
575 Tok.Kind = MMToken::EndOfFile;
576 break;
577
578 case tok::l_brace:
579 Tok.Kind = MMToken::LBrace;
580 break;
581
Douglas Gregor90db2602011-12-02 01:47:07 +0000582 case tok::period:
583 Tok.Kind = MMToken::Period;
584 break;
585
Douglas Gregora30cfe52011-11-11 19:10:28 +0000586 case tok::r_brace:
587 Tok.Kind = MMToken::RBrace;
588 break;
589
Douglas Gregor90db2602011-12-02 01:47:07 +0000590 case tok::star:
591 Tok.Kind = MMToken::Star;
592 break;
593
Douglas Gregora30cfe52011-11-11 19:10:28 +0000594 case tok::string_literal: {
595 // Parse the string literal.
596 LangOptions LangOpts;
597 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
598 if (StringLiteral.hadError)
599 goto retry;
600
601 // Copy the string literal into our string data allocator.
602 unsigned Length = StringLiteral.GetStringLength();
603 char *Saved = StringData.Allocate<char>(Length + 1);
604 memcpy(Saved, StringLiteral.GetString().data(), Length);
605 Saved[Length] = 0;
606
607 // Form the token.
608 Tok.Kind = MMToken::StringLiteral;
609 Tok.StringData = Saved;
610 Tok.StringLength = Length;
611 break;
612 }
613
614 case tok::comment:
615 goto retry;
616
617 default:
618 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
619 HadError = true;
620 goto retry;
621 }
622
623 return Result;
624}
625
626void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
627 unsigned braceDepth = 0;
628 do {
629 switch (Tok.Kind) {
630 case MMToken::EndOfFile:
631 return;
632
633 case MMToken::LBrace:
634 if (Tok.is(K) && braceDepth == 0)
635 return;
636
637 ++braceDepth;
638 break;
639
640 case MMToken::RBrace:
641 if (braceDepth > 0)
642 --braceDepth;
643 else if (Tok.is(K))
644 return;
645 break;
646
647 default:
648 if (braceDepth == 0 && Tok.is(K))
649 return;
650 break;
651 }
652
653 consumeToken();
654 } while (true);
655}
656
Douglas Gregor587986e2011-12-07 02:23:45 +0000657/// \brief Parse a module-id.
658///
659/// module-id:
660/// identifier
661/// identifier '.' module-id
662///
663/// \returns true if an error occurred, false otherwise.
664bool ModuleMapParser::parseModuleId(ModuleId &Id) {
665 Id.clear();
666 do {
667 if (Tok.is(MMToken::Identifier)) {
668 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
669 consumeToken();
670 } else {
671 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
672 return true;
673 }
674
675 if (!Tok.is(MMToken::Period))
676 break;
677
678 consumeToken();
679 } while (true);
680
681 return false;
682}
683
Douglas Gregora30cfe52011-11-11 19:10:28 +0000684/// \brief Parse a module declaration.
685///
686/// module-declaration:
Douglas Gregor587986e2011-12-07 02:23:45 +0000687/// 'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000688///
689/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +0000690/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000691/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000692/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000693/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000694///
695/// submodule-declaration:
696/// module-declaration
697/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000698void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000699 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
700 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000701 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000702 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000703 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000704 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000705
Douglas Gregord620a842011-12-06 17:16:41 +0000706 // Parse 'explicit' keyword, if present.
707 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000708 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000709 Explicit = true;
710 }
711
712 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000713 if (Tok.is(MMToken::FrameworkKeyword)) {
714 consumeToken();
715 Framework = true;
716 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000717
718 // Parse 'module' keyword.
719 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000720 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000721 consumeToken();
722 HadError = true;
723 return;
724 }
725 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000726
727 // If we have a wildcard for the module name, this is an inferred submodule.
728 // Parse it.
729 if (Tok.is(MMToken::Star))
730 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000731
732 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000733 ModuleId Id;
734 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000735 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000736 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000737 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000738
739 if (ActiveModule) {
740 if (Id.size() > 1) {
741 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
742 << SourceRange(Id.front().second, Id.back().second);
743
744 HadError = true;
745 return;
746 }
747 } else if (Id.size() == 1 && Explicit) {
748 // Top-level modules can't be explicit.
749 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
750 Explicit = false;
751 ExplicitLoc = SourceLocation();
752 HadError = true;
753 }
754
755 Module *PreviousActiveModule = ActiveModule;
756 if (Id.size() > 1) {
757 // This module map defines a submodule. Go find the module of which it
758 // is a submodule.
759 ActiveModule = 0;
760 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
761 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
762 ActiveModule = Next;
763 continue;
764 }
765
766 if (ActiveModule) {
767 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
768 << Id[I].first << ActiveModule->getTopLevelModule();
769 } else {
770 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
771 }
772 HadError = true;
773 return;
774 }
775 }
776
777 StringRef ModuleName = Id.back().first;
778 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000779
780 // Parse the opening brace.
781 if (!Tok.is(MMToken::LBrace)) {
782 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
783 << ModuleName;
784 HadError = true;
785 return;
786 }
787 SourceLocation LBraceLoc = consumeToken();
788
789 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000790 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +0000791 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
792 // Skip the module definition.
793 skipUntil(MMToken::RBrace);
794 if (Tok.is(MMToken::RBrace))
795 consumeToken();
796 else {
797 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
798 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
799 HadError = true;
800 }
801 return;
802 }
803
Douglas Gregora30cfe52011-11-11 19:10:28 +0000804 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
805 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000806 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000807
808 // Skip the module definition.
809 skipUntil(MMToken::RBrace);
810 if (Tok.is(MMToken::RBrace))
811 consumeToken();
812
813 HadError = true;
814 return;
815 }
816
817 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000818 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
819 Explicit).first;
820 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000821
822 bool Done = false;
823 do {
824 switch (Tok.Kind) {
825 case MMToken::EndOfFile:
826 case MMToken::RBrace:
827 Done = true;
828 break;
829
830 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000831 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000832 case MMToken::ModuleKeyword:
833 parseModuleDecl();
834 break;
835
Douglas Gregor90db2602011-12-02 01:47:07 +0000836 case MMToken::ExportKeyword:
837 parseExportDecl();
838 break;
839
Douglas Gregor51f564f2011-12-31 04:05:44 +0000840 case MMToken::RequiresKeyword:
841 parseRequiresDecl();
842 break;
843
Douglas Gregor77d029f2011-12-08 19:11:24 +0000844 case MMToken::UmbrellaKeyword: {
845 SourceLocation UmbrellaLoc = consumeToken();
846 if (Tok.is(MMToken::HeaderKeyword))
847 parseHeaderDecl(UmbrellaLoc);
848 else
849 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000850 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +0000851 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000852
Douglas Gregor489ad432011-12-08 18:00:48 +0000853 case MMToken::HeaderKeyword:
854 parseHeaderDecl(SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000855 break;
Douglas Gregor489ad432011-12-08 18:00:48 +0000856
Douglas Gregora30cfe52011-11-11 19:10:28 +0000857 default:
858 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
859 consumeToken();
860 break;
861 }
862 } while (!Done);
863
864 if (Tok.is(MMToken::RBrace))
865 consumeToken();
866 else {
867 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
868 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
869 HadError = true;
870 }
871
Douglas Gregor587986e2011-12-07 02:23:45 +0000872 // We're done parsing this module. Pop back to the previous module.
873 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000874}
Douglas Gregord620a842011-12-06 17:16:41 +0000875
Douglas Gregor51f564f2011-12-31 04:05:44 +0000876/// \brief Parse a requires declaration.
877///
878/// requires-declaration:
879/// 'requires' feature-list
880///
881/// feature-list:
882/// identifier ',' feature-list
883/// identifier
884void ModuleMapParser::parseRequiresDecl() {
885 assert(Tok.is(MMToken::RequiresKeyword));
886
887 // Parse 'requires' keyword.
888 consumeToken();
889
890 // Parse the feature-list.
891 do {
892 if (!Tok.is(MMToken::Identifier)) {
893 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
894 HadError = true;
895 return;
896 }
897
898 // Consume the feature name.
899 std::string Feature = Tok.getString();
900 consumeToken();
901
902 // Add this feature.
903 ActiveModule->addRequirement(Feature, Map.LangOpts);
904
905 if (!Tok.is(MMToken::Comma))
906 break;
907
908 // Consume the comma.
909 consumeToken();
910 } while (true);
911}
912
Douglas Gregord620a842011-12-06 17:16:41 +0000913/// \brief Append to \p Paths the set of paths needed to get to the
914/// subframework in which the given module lives.
915void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
916 // Collect the framework names from the given module to the top-level module.
917 llvm::SmallVector<StringRef, 2> Paths;
918 for (; Mod; Mod = Mod->Parent) {
919 if (Mod->IsFramework)
920 Paths.push_back(Mod->Name);
921 }
922
923 if (Paths.empty())
924 return;
925
926 // Add Frameworks/Name.framework for each subframework.
927 for (unsigned I = Paths.size() - 1; I != 0; --I) {
928 llvm::sys::path::append(Path, "Frameworks");
929 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
930 }
931}
932
Douglas Gregora30cfe52011-11-11 19:10:28 +0000933/// \brief Parse a header declaration.
934///
935/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +0000936/// 'umbrella'[opt] 'header' string-literal
937void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000938 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +0000939 consumeToken();
940
Douglas Gregor489ad432011-12-08 18:00:48 +0000941 bool Umbrella = UmbrellaLoc.isValid();
942
Douglas Gregora30cfe52011-11-11 19:10:28 +0000943 // Parse the header name.
944 if (!Tok.is(MMToken::StringLiteral)) {
945 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
946 << "header";
947 HadError = true;
948 return;
949 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000950 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000951 SourceLocation FileNameLoc = consumeToken();
952
Douglas Gregor77d029f2011-12-08 19:11:24 +0000953 // Check whether we already have an umbrella.
954 if (Umbrella && ActiveModule->Umbrella) {
955 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
956 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +0000957 HadError = true;
958 return;
959 }
960
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000961 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +0000962 const FileEntry *File = 0;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000963 llvm::SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +0000964 if (llvm::sys::path::is_absolute(FileName)) {
965 PathName = FileName;
966 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +0000967 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
968 PathName = Dir->getName();
969 llvm::sys::path::append(PathName, FileName);
970 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +0000971 } else {
972 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +0000973 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +0000974 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +0000975
Douglas Gregord620a842011-12-06 17:16:41 +0000976 if (ActiveModule->isPartOfFramework()) {
977 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +0000978
979 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +0000980 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +0000981 llvm::sys::path::append(PathName, FileName);
982 File = SourceMgr.getFileManager().getFile(PathName);
983
984 if (!File) {
985 // Check whether this file is in the private headers.
986 PathName.resize(PathLength);
987 llvm::sys::path::append(PathName, "PrivateHeaders");
988 llvm::sys::path::append(PathName, FileName);
989 File = SourceMgr.getFileManager().getFile(PathName);
990 }
991 } else {
992 // Lookup for normal headers.
993 llvm::sys::path::append(PathName, FileName);
994 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregord620a842011-12-06 17:16:41 +0000995 }
Douglas Gregor18ee5472011-11-29 21:59:16 +0000996 }
Douglas Gregora8654052011-11-17 22:09:43 +0000997
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000998 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
999 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001000 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001001 if (const Module *OwningModule = Map.Headers[File]) {
1002 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
1003 << FileName << OwningModule->getFullModuleName();
1004 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +00001005 } else if (Umbrella) {
1006 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor489ad432011-12-08 18:00:48 +00001007 if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
1008 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1009 << OwningModule->getFullModuleName();
1010 HadError = true;
1011 } else {
1012 // Record this umbrella header.
1013 Map.setUmbrellaHeader(ActiveModule, File);
1014 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001015 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001016 // Record this header.
Douglas Gregore209e502011-12-06 01:10:29 +00001017 Map.addHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001018 }
1019 } else {
1020 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +00001021 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001022 HadError = true;
1023 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001024}
1025
Douglas Gregor77d029f2011-12-08 19:11:24 +00001026/// \brief Parse an umbrella directory declaration.
1027///
1028/// umbrella-dir-declaration:
1029/// umbrella string-literal
1030void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1031 // Parse the directory name.
1032 if (!Tok.is(MMToken::StringLiteral)) {
1033 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1034 << "umbrella";
1035 HadError = true;
1036 return;
1037 }
1038
1039 std::string DirName = Tok.getString();
1040 SourceLocation DirNameLoc = consumeToken();
1041
1042 // Check whether we already have an umbrella.
1043 if (ActiveModule->Umbrella) {
1044 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1045 << ActiveModule->getFullModuleName();
1046 HadError = true;
1047 return;
1048 }
1049
1050 // Look for this file.
1051 const DirectoryEntry *Dir = 0;
1052 if (llvm::sys::path::is_absolute(DirName))
1053 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1054 else {
1055 llvm::SmallString<128> PathName;
1056 PathName = Directory->getName();
1057 llvm::sys::path::append(PathName, DirName);
1058 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1059 }
1060
1061 if (!Dir) {
1062 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1063 << DirName;
1064 HadError = true;
1065 return;
1066 }
1067
1068 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1069 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1070 << OwningModule->getFullModuleName();
1071 HadError = true;
1072 return;
1073 }
1074
1075 // Record this umbrella directory.
1076 Map.setUmbrellaDir(ActiveModule, Dir);
1077}
1078
Douglas Gregor90db2602011-12-02 01:47:07 +00001079/// \brief Parse a module export declaration.
1080///
1081/// export-declaration:
1082/// 'export' wildcard-module-id
1083///
1084/// wildcard-module-id:
1085/// identifier
1086/// '*'
1087/// identifier '.' wildcard-module-id
1088void ModuleMapParser::parseExportDecl() {
1089 assert(Tok.is(MMToken::ExportKeyword));
1090 SourceLocation ExportLoc = consumeToken();
1091
1092 // Parse the module-id with an optional wildcard at the end.
1093 ModuleId ParsedModuleId;
1094 bool Wildcard = false;
1095 do {
1096 if (Tok.is(MMToken::Identifier)) {
1097 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1098 Tok.getLocation()));
1099 consumeToken();
1100
1101 if (Tok.is(MMToken::Period)) {
1102 consumeToken();
1103 continue;
1104 }
1105
1106 break;
1107 }
1108
1109 if(Tok.is(MMToken::Star)) {
1110 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001111 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001112 break;
1113 }
1114
1115 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1116 HadError = true;
1117 return;
1118 } while (true);
1119
1120 Module::UnresolvedExportDecl Unresolved = {
1121 ExportLoc, ParsedModuleId, Wildcard
1122 };
1123 ActiveModule->UnresolvedExports.push_back(Unresolved);
1124}
1125
Douglas Gregor1e123682011-12-05 22:27:44 +00001126void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1127 assert(Tok.is(MMToken::Star));
1128 SourceLocation StarLoc = consumeToken();
1129 bool Failed = false;
1130
1131 // Inferred modules must be submodules.
1132 if (!ActiveModule) {
1133 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1134 Failed = true;
1135 }
1136
Douglas Gregor77d029f2011-12-08 19:11:24 +00001137 // Inferred modules must have umbrella directories.
1138 if (!Failed && !ActiveModule->getUmbrellaDir()) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001139 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1140 Failed = true;
1141 }
1142
1143 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +00001144 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001145 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +00001146 if (ActiveModule->InferredSubmoduleLoc.isValid())
1147 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +00001148 diag::note_mmap_prev_definition);
1149 Failed = true;
1150 }
1151
1152 // If there were any problems with this inferred submodule, skip its body.
1153 if (Failed) {
1154 if (Tok.is(MMToken::LBrace)) {
1155 consumeToken();
1156 skipUntil(MMToken::RBrace);
1157 if (Tok.is(MMToken::RBrace))
1158 consumeToken();
1159 }
1160 HadError = true;
1161 return;
1162 }
1163
1164 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +00001165 ActiveModule->InferSubmodules = true;
1166 ActiveModule->InferredSubmoduleLoc = StarLoc;
1167 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +00001168
1169 // Parse the opening brace.
1170 if (!Tok.is(MMToken::LBrace)) {
1171 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1172 HadError = true;
1173 return;
1174 }
1175 SourceLocation LBraceLoc = consumeToken();
1176
1177 // Parse the body of the inferred submodule.
1178 bool Done = false;
1179 do {
1180 switch (Tok.Kind) {
1181 case MMToken::EndOfFile:
1182 case MMToken::RBrace:
1183 Done = true;
1184 break;
1185
1186 case MMToken::ExportKeyword: {
1187 consumeToken();
1188 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001189 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001190 else
1191 Diags.Report(Tok.getLocation(),
1192 diag::err_mmap_expected_export_wildcard);
1193 consumeToken();
1194 break;
1195 }
1196
1197 case MMToken::ExplicitKeyword:
1198 case MMToken::ModuleKeyword:
1199 case MMToken::HeaderKeyword:
1200 case MMToken::UmbrellaKeyword:
1201 default:
1202 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1203 consumeToken();
1204 break;
1205 }
1206 } while (!Done);
1207
1208 if (Tok.is(MMToken::RBrace))
1209 consumeToken();
1210 else {
1211 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1212 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1213 HadError = true;
1214 }
1215}
1216
Douglas Gregor6a1db482011-12-09 02:04:43 +00001217/// \brief If there is a specific header search directory due the presence
1218/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1219const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1220 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1221 // If we have an umbrella directory, use that.
1222 if (Mod->hasUmbrellaDir())
1223 return Mod->getUmbrellaDir();
1224
1225 // If we have a framework directory, stop looking.
1226 if (Mod->IsFramework)
1227 return 0;
1228 }
1229
1230 return 0;
1231}
1232
Douglas Gregora30cfe52011-11-11 19:10:28 +00001233/// \brief Parse a module map file.
1234///
1235/// module-map-file:
1236/// module-declaration*
1237bool ModuleMapParser::parseModuleMapFile() {
1238 do {
1239 switch (Tok.Kind) {
1240 case MMToken::EndOfFile:
1241 return HadError;
1242
Douglas Gregor587986e2011-12-07 02:23:45 +00001243 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001244 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001245 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001246 parseModuleDecl();
1247 break;
1248
Douglas Gregor51f564f2011-12-31 04:05:44 +00001249 case MMToken::Comma:
Douglas Gregor90db2602011-12-02 01:47:07 +00001250 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001251 case MMToken::HeaderKeyword:
1252 case MMToken::Identifier:
1253 case MMToken::LBrace:
Douglas Gregor90db2602011-12-02 01:47:07 +00001254 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001255 case MMToken::RBrace:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001256 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001257 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001258 case MMToken::StringLiteral:
1259 case MMToken::UmbrellaKeyword:
1260 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1261 HadError = true;
1262 consumeToken();
1263 break;
1264 }
1265 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001266}
1267
1268bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
1269 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1270 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1271 if (!Buffer)
1272 return true;
1273
1274 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00001275 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1276 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001277 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001278 bool Result = Parser.parseModuleMapFile();
1279 Diags->getClient()->EndSourceFile();
1280
1281 return Result;
1282}