blob: 3583b034d53873393b0ca993d8526d43f6bb2b1a [file] [log] [blame]
Douglas Gregor718292f2011-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 Gregore89dbc12011-12-06 19:39:29 +000023#include "llvm/Support/FileSystem.h"
Douglas Gregor718292f2011-11-11 19:10:28 +000024#include "llvm/Support/Host.h"
Douglas Gregor5257fc62011-11-11 21:55:48 +000025#include "llvm/Support/PathV2.h"
Douglas Gregor718292f2011-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 Gregor2b82c2a2011-12-02 01:47:07 +000031Module::ExportDecl
32ModuleMap::resolveExport(Module *Mod,
33 const Module::UnresolvedExportDecl &Unresolved,
34 bool Complain) {
Douglas Gregorf5eedd02011-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 Gregor2b82c2a2011-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 Gregor1fb5c3a2011-12-31 04:05:44 +000072ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
Douglas Gregor89929282012-01-30 06:01:29 +000073 const LangOptions &LangOpts, const TargetInfo *Target)
74 : LangOpts(LangOpts), Target(Target)
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +000075{
Douglas Gregor718292f2011-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 Gregor5acdf592011-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 Gregor718292f2011-11-11 19:10:28 +000090 delete SourceMgr;
91}
92
Douglas Gregor89929282012-01-30 06:01:29 +000093void ModuleMap::setTarget(const TargetInfo &Target) {
94 assert((!this->Target || this->Target == &Target) &&
95 "Improper target override");
96 this->Target = &Target;
97}
98
Douglas Gregorde3ef502011-11-30 23:21:26 +000099Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregorab0c8a82011-11-11 22:18:48 +0000100 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
101 = Headers.find(File);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000102 if (Known != Headers.end()) {
103 // If a header corresponds to an unavailable module, don't report
104 // that it maps to anything.
105 if (!Known->second->isAvailable())
106 return 0;
107
Douglas Gregorab0c8a82011-11-11 22:18:48 +0000108 return Known->second;
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000109 }
Douglas Gregorab0c8a82011-11-11 22:18:48 +0000110
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000111 const DirectoryEntry *Dir = File->getDir();
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000112 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
113 StringRef DirName = Dir->getName();
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000114
115 // Keep walking up the directory hierarchy, looking for a directory with
116 // an umbrella header.
117 do {
118 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
119 = UmbrellaDirs.find(Dir);
120 if (KnownDir != UmbrellaDirs.end()) {
121 Module *Result = KnownDir->second;
Douglas Gregor930a85c2011-12-06 16:17:15 +0000122
123 // Search up the module stack until we find a module with an umbrella
Douglas Gregor73141fa2011-12-08 17:39:04 +0000124 // directory.
Douglas Gregor930a85c2011-12-06 16:17:15 +0000125 Module *UmbrellaModule = Result;
Douglas Gregor73141fa2011-12-08 17:39:04 +0000126 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor930a85c2011-12-06 16:17:15 +0000127 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000128
Douglas Gregor930a85c2011-12-06 16:17:15 +0000129 if (UmbrellaModule->InferSubmodules) {
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000130 // Infer submodules for each of the directories we found between
131 // the directory of the umbrella header and the directory where
132 // the actual header is located.
Douglas Gregor9458f822011-12-07 22:05:21 +0000133 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000134
Douglas Gregor70331272011-12-09 02:04:43 +0000135 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000136 // Find or create the module that corresponds to this directory name.
137 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
138 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9458f822011-12-07 22:05:21 +0000139 Explicit).first;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000140
141 // Associate the module and the directory.
142 UmbrellaDirs[SkippedDirs[I-1]] = Result;
143
144 // If inferred submodules export everything they import, add a
145 // wildcard to the set of exports.
Douglas Gregor930a85c2011-12-06 16:17:15 +0000146 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000147 Result->Exports.push_back(Module::ExportDecl(0, true));
148 }
149
150 // Infer a submodule with the same name as this header file.
151 StringRef Name = llvm::sys::path::stem(File->getName());
152 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor9458f822011-12-07 22:05:21 +0000153 Explicit).first;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000154
155 // If inferred submodules export everything they import, add a
156 // wildcard to the set of exports.
Douglas Gregor930a85c2011-12-06 16:17:15 +0000157 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000158 Result->Exports.push_back(Module::ExportDecl(0, true));
159 } else {
160 // Record each of the directories we stepped through as being part of
161 // the module we found, since the umbrella header covers them all.
162 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
163 UmbrellaDirs[SkippedDirs[I]] = Result;
164 }
165
166 Headers[File] = Result;
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000167
168 // If a header corresponds to an unavailable module, don't report
169 // that it maps to anything.
170 if (!Result->isAvailable())
171 return 0;
172
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000173 return Result;
174 }
175
176 SkippedDirs.push_back(Dir);
177
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000178 // Retrieve our parent path.
179 DirName = llvm::sys::path::parent_path(DirName);
180 if (DirName.empty())
181 break;
182
183 // Resolve the parent path to a directory entry.
184 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000185 } while (Dir);
Douglas Gregorb65dbff2011-11-16 23:02:25 +0000186
Douglas Gregorab0c8a82011-11-11 22:18:48 +0000187 return 0;
188}
189
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000190bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
191 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
192 = Headers.find(Header);
193 if (Known != Headers.end())
194 return !Known->second->isAvailable();
195
196 const DirectoryEntry *Dir = Header->getDir();
197 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
198 StringRef DirName = Dir->getName();
199
200 // Keep walking up the directory hierarchy, looking for a directory with
201 // an umbrella header.
202 do {
203 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
204 = UmbrellaDirs.find(Dir);
205 if (KnownDir != UmbrellaDirs.end()) {
206 Module *Found = KnownDir->second;
207 if (!Found->isAvailable())
208 return true;
209
210 // Search up the module stack until we find a module with an umbrella
211 // directory.
212 Module *UmbrellaModule = Found;
213 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
214 UmbrellaModule = UmbrellaModule->Parent;
215
216 if (UmbrellaModule->InferSubmodules) {
217 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
218 // Find or create the module that corresponds to this directory name.
219 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
220 Found = lookupModuleQualified(Name, Found);
221 if (!Found)
222 return false;
223 if (!Found->isAvailable())
224 return true;
225 }
226
227 // Infer a submodule with the same name as this header file.
228 StringRef Name = llvm::sys::path::stem(Header->getName());
229 Found = lookupModuleQualified(Name, Found);
230 if (!Found)
231 return false;
232 }
233
234 return !Found->isAvailable();
235 }
236
237 SkippedDirs.push_back(Dir);
238
239 // Retrieve our parent path.
240 DirName = llvm::sys::path::parent_path(DirName);
241 if (DirName.empty())
242 break;
243
244 // Resolve the parent path to a directory entry.
245 Dir = SourceMgr->getFileManager().getDirectory(DirName);
246 } while (Dir);
247
248 return false;
249}
250
Douglas Gregorde3ef502011-11-30 23:21:26 +0000251Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor88bdfb02011-11-11 23:20:24 +0000252 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
253 if (Known != Modules.end())
254 return Known->getValue();
255
256 return 0;
257}
258
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000259Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
260 for(; Context; Context = Context->Parent) {
261 if (Module *Sub = lookupModuleQualified(Name, Context))
262 return Sub;
263 }
264
265 return findModule(Name);
266}
267
268Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
269 if (!Context)
270 return findModule(Name);
271
Douglas Gregoreb90e832012-01-04 23:32:19 +0000272 return Context->findSubmodule(Name);
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000273}
274
Douglas Gregorde3ef502011-11-30 23:21:26 +0000275std::pair<Module *, bool>
Douglas Gregor69021972011-11-30 17:33:56 +0000276ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
277 bool IsExplicit) {
278 // Try to find an existing module with this name.
Douglas Gregoreb90e832012-01-04 23:32:19 +0000279 if (Module *Sub = lookupModuleQualified(Name, Parent))
280 return std::make_pair(Sub, false);
Douglas Gregor69021972011-11-30 17:33:56 +0000281
282 // Create a new module with this name.
283 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
284 IsExplicit);
Douglas Gregoreb90e832012-01-04 23:32:19 +0000285 if (!Parent)
Douglas Gregor69021972011-11-30 17:33:56 +0000286 Modules[Name] = Result;
287 return std::make_pair(Result, true);
288}
289
Douglas Gregorde3ef502011-11-30 23:21:26 +0000290Module *
Douglas Gregor56c64012011-11-17 01:41:17 +0000291ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregore89dbc12011-12-06 19:39:29 +0000292 const DirectoryEntry *FrameworkDir,
Douglas Gregora686e1b2012-01-27 19:52:33 +0000293 bool IsSystem,
Douglas Gregore89dbc12011-12-06 19:39:29 +0000294 Module *Parent) {
Douglas Gregor56c64012011-11-17 01:41:17 +0000295 // Check whether we've already found this module.
Douglas Gregore89dbc12011-12-06 19:39:29 +0000296 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
297 return Mod;
298
299 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor56c64012011-11-17 01:41:17 +0000300
301 // Look for an umbrella header.
302 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
303 llvm::sys::path::append(UmbrellaName, "Headers");
304 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregore89dbc12011-12-06 19:39:29 +0000305 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor56c64012011-11-17 01:41:17 +0000306
307 // FIXME: If there's no umbrella header, we could probably scan the
308 // framework to load *everything*. But, it's not clear that this is a good
309 // idea.
310 if (!UmbrellaHeader)
311 return 0;
312
Douglas Gregore89dbc12011-12-06 19:39:29 +0000313 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
314 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora686e1b2012-01-27 19:52:33 +0000315 if (IsSystem)
316 Result->IsSystem = IsSystem;
317
Douglas Gregoreb90e832012-01-04 23:32:19 +0000318 if (!Parent)
Douglas Gregore89dbc12011-12-06 19:39:29 +0000319 Modules[ModuleName] = Result;
Douglas Gregoreb90e832012-01-04 23:32:19 +0000320
Douglas Gregor322f6332011-12-08 18:00:48 +0000321 // umbrella header "umbrella-header-name"
Douglas Gregor73141fa2011-12-08 17:39:04 +0000322 Result->Umbrella = UmbrellaHeader;
Douglas Gregor56c64012011-11-17 01:41:17 +0000323 Headers[UmbrellaHeader] = Result;
Douglas Gregor4dc71832011-12-12 23:55:05 +0000324 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregord8bd7532011-12-05 17:40:25 +0000325
326 // export *
327 Result->Exports.push_back(Module::ExportDecl(0, true));
328
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000329 // module * { export * }
330 Result->InferSubmodules = true;
331 Result->InferExportWildcard = true;
332
Douglas Gregore89dbc12011-12-06 19:39:29 +0000333 // Look for subframeworks.
334 llvm::error_code EC;
Douglas Gregorddaa69c2011-12-08 16:13:24 +0000335 llvm::SmallString<128> SubframeworksDirName
336 = StringRef(FrameworkDir->getName());
Douglas Gregore89dbc12011-12-06 19:39:29 +0000337 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Douglas Gregorddaa69c2011-12-08 16:13:24 +0000338 llvm::SmallString<128> SubframeworksDirNameNative;
339 llvm::sys::path::native(SubframeworksDirName.str(),
340 SubframeworksDirNameNative);
341 for (llvm::sys::fs::directory_iterator
342 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregore89dbc12011-12-06 19:39:29 +0000343 Dir != DirEnd && !EC; Dir.increment(EC)) {
344 if (!StringRef(Dir->path()).endswith(".framework"))
345 continue;
346
347 if (const DirectoryEntry *SubframeworkDir
348 = FileMgr.getDirectory(Dir->path())) {
349 // FIXME: Do we want to warn about subframeworks without umbrella headers?
350 inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
Douglas Gregora686e1b2012-01-27 19:52:33 +0000351 IsSystem, Result);
Douglas Gregore89dbc12011-12-06 19:39:29 +0000352 }
353 }
Douglas Gregor09a22f02012-01-13 16:54:27 +0000354
Douglas Gregor56c64012011-11-17 01:41:17 +0000355 return Result;
356}
357
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000358void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
359 Headers[UmbrellaHeader] = Mod;
Douglas Gregor73141fa2011-12-08 17:39:04 +0000360 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor70331272011-12-09 02:04:43 +0000361 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000362}
363
Douglas Gregor524e33e2011-12-08 19:11:24 +0000364void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
365 Mod->Umbrella = UmbrellaDir;
366 UmbrellaDirs[UmbrellaDir] = Mod;
367}
368
Douglas Gregora89c5ac2011-12-06 01:10:29 +0000369void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
370 Mod->Headers.push_back(Header);
371 Headers[Header] = Mod;
372}
373
Douglas Gregor514b6362011-11-29 19:06:37 +0000374const FileEntry *
Douglas Gregorde3ef502011-11-30 23:21:26 +0000375ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregor514b6362011-11-29 19:06:37 +0000376 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
377 return 0;
378
379 return SourceMgr->getFileEntryForID(
380 SourceMgr->getFileID(Module->DefinitionLoc));
381}
382
Douglas Gregor718292f2011-11-11 19:10:28 +0000383void ModuleMap::dump() {
384 llvm::errs() << "Modules:";
385 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
386 MEnd = Modules.end();
387 M != MEnd; ++M)
Douglas Gregord28d1b82011-11-29 18:17:59 +0000388 M->getValue()->print(llvm::errs(), 2);
Douglas Gregor718292f2011-11-11 19:10:28 +0000389
390 llvm::errs() << "Headers:";
391 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
392 H = Headers.begin(),
393 HEnd = Headers.end();
394 H != HEnd; ++H) {
395 llvm::errs() << " \"" << H->first->getName() << "\" -> "
396 << H->second->getFullModuleName() << "\n";
397 }
398}
399
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000400bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
401 bool HadError = false;
402 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
403 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
404 Complain);
Douglas Gregorf5eedd02011-12-05 17:28:06 +0000405 if (Export.getPointer() || Export.getInt())
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000406 Mod->Exports.push_back(Export);
407 else
408 HadError = true;
409 }
410 Mod->UnresolvedExports.clear();
411 return HadError;
412}
413
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000414Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
415 if (Loc.isInvalid())
416 return 0;
417
418 // Use the expansion location to determine which module we're in.
419 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
420 if (!ExpansionLoc.isFileID())
421 return 0;
422
423
424 const SourceManager &SrcMgr = Loc.getManager();
425 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000426
Douglas Gregor224d8a72012-01-06 17:19:32 +0000427 while (const FileEntry *ExpansionFile
428 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
429 // Find the module that owns this header (if any).
430 if (Module *Mod = findModuleForHeader(ExpansionFile))
431 return Mod;
432
433 // No module owns this header, so look up the inclusion chain to see if
434 // any included header has an associated module.
435 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
436 if (IncludeLoc.isInvalid())
437 return 0;
438
439 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
440 }
441
442 return 0;
Douglas Gregor0093b3c2011-12-05 16:33:54 +0000443}
444
Douglas Gregor718292f2011-11-11 19:10:28 +0000445//----------------------------------------------------------------------------//
446// Module map file parser
447//----------------------------------------------------------------------------//
448
449namespace clang {
450 /// \brief A token in a module map file.
451 struct MMToken {
452 enum TokenKind {
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000453 Comma,
Douglas Gregor718292f2011-11-11 19:10:28 +0000454 EndOfFile,
455 HeaderKeyword,
456 Identifier,
457 ExplicitKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000458 ExportKeyword,
Douglas Gregor755b2052011-11-17 22:09:43 +0000459 FrameworkKeyword,
Douglas Gregor718292f2011-11-11 19:10:28 +0000460 ModuleKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000461 Period,
Douglas Gregor718292f2011-11-11 19:10:28 +0000462 UmbrellaKeyword,
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000463 RequiresKeyword,
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000464 Star,
Douglas Gregor718292f2011-11-11 19:10:28 +0000465 StringLiteral,
466 LBrace,
Douglas Gregora686e1b2012-01-27 19:52:33 +0000467 RBrace,
468 LSquare,
469 RSquare
Douglas Gregor718292f2011-11-11 19:10:28 +0000470 } Kind;
471
472 unsigned Location;
473 unsigned StringLength;
474 const char *StringData;
475
476 void clear() {
477 Kind = EndOfFile;
478 Location = 0;
479 StringLength = 0;
480 StringData = 0;
481 }
482
483 bool is(TokenKind K) const { return Kind == K; }
484
485 SourceLocation getLocation() const {
486 return SourceLocation::getFromRawEncoding(Location);
487 }
488
489 StringRef getString() const {
490 return StringRef(StringData, StringLength);
491 }
492 };
493
494 class ModuleMapParser {
495 Lexer &L;
496 SourceManager &SourceMgr;
497 DiagnosticsEngine &Diags;
498 ModuleMap &Map;
499
Douglas Gregor5257fc62011-11-11 21:55:48 +0000500 /// \brief The directory that this module map resides in.
501 const DirectoryEntry *Directory;
502
Douglas Gregor718292f2011-11-11 19:10:28 +0000503 /// \brief Whether an error occurred.
504 bool HadError;
505
506 /// \brief Default target information, used only for string literal
507 /// parsing.
508 TargetInfo *Target;
509
510 /// \brief Stores string data for the various string literals referenced
511 /// during parsing.
512 llvm::BumpPtrAllocator StringData;
513
514 /// \brief The current token.
515 MMToken Tok;
516
517 /// \brief The active module.
Douglas Gregorde3ef502011-11-30 23:21:26 +0000518 Module *ActiveModule;
Douglas Gregor718292f2011-11-11 19:10:28 +0000519
520 /// \brief Consume the current token and return its location.
521 SourceLocation consumeToken();
522
523 /// \brief Skip tokens until we reach the a token with the given kind
524 /// (or the end of the file).
525 void skipUntil(MMToken::TokenKind K);
Douglas Gregore7ab3662011-12-07 02:23:45 +0000526
527 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
528 ModuleId;
529 bool parseModuleId(ModuleId &Id);
Douglas Gregor718292f2011-11-11 19:10:28 +0000530 void parseModuleDecl();
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000531 void parseRequiresDecl();
Douglas Gregor322f6332011-12-08 18:00:48 +0000532 void parseHeaderDecl(SourceLocation UmbrellaLoc);
Douglas Gregor524e33e2011-12-08 19:11:24 +0000533 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000534 void parseExportDecl();
Douglas Gregor73441092011-12-05 22:27:44 +0000535 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregor718292f2011-11-11 19:10:28 +0000536
Douglas Gregor70331272011-12-09 02:04:43 +0000537 const DirectoryEntry *getOverriddenHeaderSearchDir();
538
Douglas Gregor718292f2011-11-11 19:10:28 +0000539 public:
Douglas Gregor718292f2011-11-11 19:10:28 +0000540 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
541 DiagnosticsEngine &Diags,
Douglas Gregor5257fc62011-11-11 21:55:48 +0000542 ModuleMap &Map,
543 const DirectoryEntry *Directory)
544 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
545 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregor718292f2011-11-11 19:10:28 +0000546 {
547 TargetOptions TargetOpts;
548 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
549 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
550
551 Tok.clear();
552 consumeToken();
553 }
554
555 bool parseModuleMapFile();
556 };
557}
558
559SourceLocation ModuleMapParser::consumeToken() {
560retry:
561 SourceLocation Result = Tok.getLocation();
562 Tok.clear();
563
564 Token LToken;
565 L.LexFromRawLexer(LToken);
566 Tok.Location = LToken.getLocation().getRawEncoding();
567 switch (LToken.getKind()) {
568 case tok::raw_identifier:
569 Tok.StringData = LToken.getRawIdentifierData();
570 Tok.StringLength = LToken.getLength();
571 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
572 .Case("header", MMToken::HeaderKeyword)
573 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000574 .Case("export", MMToken::ExportKeyword)
Douglas Gregor755b2052011-11-17 22:09:43 +0000575 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregor718292f2011-11-11 19:10:28 +0000576 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000577 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregor718292f2011-11-11 19:10:28 +0000578 .Case("umbrella", MMToken::UmbrellaKeyword)
579 .Default(MMToken::Identifier);
580 break;
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000581
582 case tok::comma:
583 Tok.Kind = MMToken::Comma;
584 break;
585
Douglas Gregor718292f2011-11-11 19:10:28 +0000586 case tok::eof:
587 Tok.Kind = MMToken::EndOfFile;
588 break;
589
590 case tok::l_brace:
591 Tok.Kind = MMToken::LBrace;
592 break;
593
Douglas Gregora686e1b2012-01-27 19:52:33 +0000594 case tok::l_square:
595 Tok.Kind = MMToken::LSquare;
596 break;
597
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000598 case tok::period:
599 Tok.Kind = MMToken::Period;
600 break;
601
Douglas Gregor718292f2011-11-11 19:10:28 +0000602 case tok::r_brace:
603 Tok.Kind = MMToken::RBrace;
604 break;
605
Douglas Gregora686e1b2012-01-27 19:52:33 +0000606 case tok::r_square:
607 Tok.Kind = MMToken::RSquare;
608 break;
609
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000610 case tok::star:
611 Tok.Kind = MMToken::Star;
612 break;
613
Douglas Gregor718292f2011-11-11 19:10:28 +0000614 case tok::string_literal: {
615 // Parse the string literal.
616 LangOptions LangOpts;
617 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
618 if (StringLiteral.hadError)
619 goto retry;
620
621 // Copy the string literal into our string data allocator.
622 unsigned Length = StringLiteral.GetStringLength();
623 char *Saved = StringData.Allocate<char>(Length + 1);
624 memcpy(Saved, StringLiteral.GetString().data(), Length);
625 Saved[Length] = 0;
626
627 // Form the token.
628 Tok.Kind = MMToken::StringLiteral;
629 Tok.StringData = Saved;
630 Tok.StringLength = Length;
631 break;
632 }
633
634 case tok::comment:
635 goto retry;
636
637 default:
638 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
639 HadError = true;
640 goto retry;
641 }
642
643 return Result;
644}
645
646void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
647 unsigned braceDepth = 0;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000648 unsigned squareDepth = 0;
Douglas Gregor718292f2011-11-11 19:10:28 +0000649 do {
650 switch (Tok.Kind) {
651 case MMToken::EndOfFile:
652 return;
653
654 case MMToken::LBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000655 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregor718292f2011-11-11 19:10:28 +0000656 return;
657
658 ++braceDepth;
659 break;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000660
661 case MMToken::LSquare:
662 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
663 return;
664
665 ++squareDepth;
666 break;
667
Douglas Gregor718292f2011-11-11 19:10:28 +0000668 case MMToken::RBrace:
669 if (braceDepth > 0)
670 --braceDepth;
671 else if (Tok.is(K))
672 return;
673 break;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000674
675 case MMToken::RSquare:
676 if (squareDepth > 0)
677 --squareDepth;
678 else if (Tok.is(K))
679 return;
680 break;
681
Douglas Gregor718292f2011-11-11 19:10:28 +0000682 default:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000683 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregor718292f2011-11-11 19:10:28 +0000684 return;
685 break;
686 }
687
688 consumeToken();
689 } while (true);
690}
691
Douglas Gregore7ab3662011-12-07 02:23:45 +0000692/// \brief Parse a module-id.
693///
694/// module-id:
695/// identifier
696/// identifier '.' module-id
697///
698/// \returns true if an error occurred, false otherwise.
699bool ModuleMapParser::parseModuleId(ModuleId &Id) {
700 Id.clear();
701 do {
702 if (Tok.is(MMToken::Identifier)) {
703 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
704 consumeToken();
705 } else {
706 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
707 return true;
708 }
709
710 if (!Tok.is(MMToken::Period))
711 break;
712
713 consumeToken();
714 } while (true);
715
716 return false;
717}
718
Douglas Gregora686e1b2012-01-27 19:52:33 +0000719namespace {
720 /// \brief Enumerates the known attributes.
721 enum AttributeKind {
722 /// \brief An unknown attribute.
723 AT_unknown,
724 /// \brief The 'system' attribute.
725 AT_system
726 };
727}
728
Douglas Gregor718292f2011-11-11 19:10:28 +0000729/// \brief Parse a module declaration.
730///
731/// module-declaration:
Douglas Gregora686e1b2012-01-27 19:52:33 +0000732/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
733/// { module-member* }
734///
735/// attributes:
736/// attribute attributes
737/// attribute
738///
739/// attribute:
740/// [ identifier ]
Douglas Gregor718292f2011-11-11 19:10:28 +0000741///
742/// module-member:
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000743/// requires-declaration
Douglas Gregor718292f2011-11-11 19:10:28 +0000744/// header-declaration
Douglas Gregore7ab3662011-12-07 02:23:45 +0000745/// submodule-declaration
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000746/// export-declaration
Douglas Gregor73441092011-12-05 22:27:44 +0000747///
748/// submodule-declaration:
749/// module-declaration
750/// inferred-submodule-declaration
Douglas Gregor718292f2011-11-11 19:10:28 +0000751void ModuleMapParser::parseModuleDecl() {
Douglas Gregor755b2052011-11-17 22:09:43 +0000752 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
753 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregorf2161a72011-12-06 17:16:41 +0000754 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregore7ab3662011-12-07 02:23:45 +0000755 SourceLocation ExplicitLoc;
Douglas Gregor718292f2011-11-11 19:10:28 +0000756 bool Explicit = false;
Douglas Gregorf2161a72011-12-06 17:16:41 +0000757 bool Framework = false;
Douglas Gregor755b2052011-11-17 22:09:43 +0000758
Douglas Gregorf2161a72011-12-06 17:16:41 +0000759 // Parse 'explicit' keyword, if present.
760 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregore7ab3662011-12-07 02:23:45 +0000761 ExplicitLoc = consumeToken();
Douglas Gregorf2161a72011-12-06 17:16:41 +0000762 Explicit = true;
763 }
764
765 // Parse 'framework' keyword, if present.
Douglas Gregor755b2052011-11-17 22:09:43 +0000766 if (Tok.is(MMToken::FrameworkKeyword)) {
767 consumeToken();
768 Framework = true;
769 }
Douglas Gregor718292f2011-11-11 19:10:28 +0000770
771 // Parse 'module' keyword.
772 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregord6343c92011-12-06 19:57:48 +0000773 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregor718292f2011-11-11 19:10:28 +0000774 consumeToken();
775 HadError = true;
776 return;
777 }
778 consumeToken(); // 'module' keyword
Douglas Gregor73441092011-12-05 22:27:44 +0000779
780 // If we have a wildcard for the module name, this is an inferred submodule.
781 // Parse it.
782 if (Tok.is(MMToken::Star))
783 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregor718292f2011-11-11 19:10:28 +0000784
785 // Parse the module name.
Douglas Gregore7ab3662011-12-07 02:23:45 +0000786 ModuleId Id;
787 if (parseModuleId(Id)) {
Douglas Gregor718292f2011-11-11 19:10:28 +0000788 HadError = true;
Douglas Gregore7ab3662011-12-07 02:23:45 +0000789 return;
Douglas Gregor718292f2011-11-11 19:10:28 +0000790 }
Douglas Gregore7ab3662011-12-07 02:23:45 +0000791
792 if (ActiveModule) {
793 if (Id.size() > 1) {
794 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
795 << SourceRange(Id.front().second, Id.back().second);
796
797 HadError = true;
798 return;
799 }
800 } else if (Id.size() == 1 && Explicit) {
801 // Top-level modules can't be explicit.
802 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
803 Explicit = false;
804 ExplicitLoc = SourceLocation();
805 HadError = true;
806 }
807
808 Module *PreviousActiveModule = ActiveModule;
809 if (Id.size() > 1) {
810 // This module map defines a submodule. Go find the module of which it
811 // is a submodule.
812 ActiveModule = 0;
813 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
814 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
815 ActiveModule = Next;
816 continue;
817 }
818
819 if (ActiveModule) {
820 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
821 << Id[I].first << ActiveModule->getTopLevelModule();
822 } else {
823 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
824 }
825 HadError = true;
826 return;
827 }
828 }
829
830 StringRef ModuleName = Id.back().first;
831 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregor718292f2011-11-11 19:10:28 +0000832
Douglas Gregora686e1b2012-01-27 19:52:33 +0000833 // Parse the optional attribute list.
834 bool IsSystem = false;
835 while (Tok.is(MMToken::LSquare)) {
836 // Consume the '['.
837 SourceLocation LSquareLoc = consumeToken();
838
839 // Check whether we have an attribute name here.
840 if (!Tok.is(MMToken::Identifier)) {
841 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
842 skipUntil(MMToken::RSquare);
843 if (Tok.is(MMToken::RSquare))
844 consumeToken();
845 continue;
846 }
847
848 // Decode the attribute name.
849 AttributeKind Attribute
850 = llvm::StringSwitch<AttributeKind>(Tok.getString())
851 .Case("system", AT_system)
852 .Default(AT_unknown);
853 switch (Attribute) {
854 case AT_unknown:
855 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
856 << Tok.getString();
857 break;
858
859 case AT_system:
860 IsSystem = true;
861 break;
862 }
863 consumeToken();
864
865 // Consume the ']'.
866 if (!Tok.is(MMToken::RSquare)) {
867 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
868 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
869 skipUntil(MMToken::RSquare);
870 }
871
872 if (Tok.is(MMToken::RSquare))
873 consumeToken();
874 }
875
Douglas Gregor718292f2011-11-11 19:10:28 +0000876 // Parse the opening brace.
877 if (!Tok.is(MMToken::LBrace)) {
878 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
879 << ModuleName;
880 HadError = true;
881 return;
882 }
883 SourceLocation LBraceLoc = consumeToken();
884
885 // Determine whether this (sub)module has already been defined.
Douglas Gregoreb90e832012-01-04 23:32:19 +0000886 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorfcc54a32012-01-05 00:12:00 +0000887 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
888 // Skip the module definition.
889 skipUntil(MMToken::RBrace);
890 if (Tok.is(MMToken::RBrace))
891 consumeToken();
892 else {
893 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
894 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
895 HadError = true;
896 }
897 return;
898 }
899
Douglas Gregor718292f2011-11-11 19:10:28 +0000900 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
901 << ModuleName;
Douglas Gregoreb90e832012-01-04 23:32:19 +0000902 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregor718292f2011-11-11 19:10:28 +0000903
904 // Skip the module definition.
905 skipUntil(MMToken::RBrace);
906 if (Tok.is(MMToken::RBrace))
907 consumeToken();
908
909 HadError = true;
910 return;
911 }
912
913 // Start defining this module.
Douglas Gregoreb90e832012-01-04 23:32:19 +0000914 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
915 Explicit).first;
916 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregora686e1b2012-01-27 19:52:33 +0000917 if (IsSystem)
918 ActiveModule->IsSystem = true;
Douglas Gregor718292f2011-11-11 19:10:28 +0000919
920 bool Done = false;
921 do {
922 switch (Tok.Kind) {
923 case MMToken::EndOfFile:
924 case MMToken::RBrace:
925 Done = true;
926 break;
927
928 case MMToken::ExplicitKeyword:
Douglas Gregorf2161a72011-12-06 17:16:41 +0000929 case MMToken::FrameworkKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +0000930 case MMToken::ModuleKeyword:
931 parseModuleDecl();
932 break;
933
Douglas Gregor2b82c2a2011-12-02 01:47:07 +0000934 case MMToken::ExportKeyword:
935 parseExportDecl();
936 break;
937
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000938 case MMToken::RequiresKeyword:
939 parseRequiresDecl();
940 break;
941
Douglas Gregor524e33e2011-12-08 19:11:24 +0000942 case MMToken::UmbrellaKeyword: {
943 SourceLocation UmbrellaLoc = consumeToken();
944 if (Tok.is(MMToken::HeaderKeyword))
945 parseHeaderDecl(UmbrellaLoc);
946 else
947 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregor718292f2011-11-11 19:10:28 +0000948 break;
Douglas Gregor524e33e2011-12-08 19:11:24 +0000949 }
Douglas Gregor718292f2011-11-11 19:10:28 +0000950
Douglas Gregor322f6332011-12-08 18:00:48 +0000951 case MMToken::HeaderKeyword:
952 parseHeaderDecl(SourceLocation());
Douglas Gregor718292f2011-11-11 19:10:28 +0000953 break;
Douglas Gregor322f6332011-12-08 18:00:48 +0000954
Douglas Gregor718292f2011-11-11 19:10:28 +0000955 default:
956 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
957 consumeToken();
958 break;
959 }
960 } while (!Done);
961
962 if (Tok.is(MMToken::RBrace))
963 consumeToken();
964 else {
965 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
966 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
967 HadError = true;
968 }
969
Douglas Gregore7ab3662011-12-07 02:23:45 +0000970 // We're done parsing this module. Pop back to the previous module.
971 ActiveModule = PreviousActiveModule;
Douglas Gregor718292f2011-11-11 19:10:28 +0000972}
Douglas Gregorf2161a72011-12-06 17:16:41 +0000973
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +0000974/// \brief Parse a requires declaration.
975///
976/// requires-declaration:
977/// 'requires' feature-list
978///
979/// feature-list:
980/// identifier ',' feature-list
981/// identifier
982void ModuleMapParser::parseRequiresDecl() {
983 assert(Tok.is(MMToken::RequiresKeyword));
984
985 // Parse 'requires' keyword.
986 consumeToken();
987
988 // Parse the feature-list.
989 do {
990 if (!Tok.is(MMToken::Identifier)) {
991 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
992 HadError = true;
993 return;
994 }
995
996 // Consume the feature name.
997 std::string Feature = Tok.getString();
998 consumeToken();
999
1000 // Add this feature.
Douglas Gregor89929282012-01-30 06:01:29 +00001001 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001002
1003 if (!Tok.is(MMToken::Comma))
1004 break;
1005
1006 // Consume the comma.
1007 consumeToken();
1008 } while (true);
1009}
1010
Douglas Gregorf2161a72011-12-06 17:16:41 +00001011/// \brief Append to \p Paths the set of paths needed to get to the
1012/// subframework in which the given module lives.
1013void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
1014 // Collect the framework names from the given module to the top-level module.
1015 llvm::SmallVector<StringRef, 2> Paths;
1016 for (; Mod; Mod = Mod->Parent) {
1017 if (Mod->IsFramework)
1018 Paths.push_back(Mod->Name);
1019 }
1020
1021 if (Paths.empty())
1022 return;
1023
1024 // Add Frameworks/Name.framework for each subframework.
1025 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1026 llvm::sys::path::append(Path, "Frameworks");
1027 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1028 }
1029}
1030
Douglas Gregor718292f2011-11-11 19:10:28 +00001031/// \brief Parse a header declaration.
1032///
1033/// header-declaration:
Douglas Gregor322f6332011-12-08 18:00:48 +00001034/// 'umbrella'[opt] 'header' string-literal
1035void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
Douglas Gregor718292f2011-11-11 19:10:28 +00001036 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramer1871ed32011-11-13 16:52:09 +00001037 consumeToken();
1038
Douglas Gregor322f6332011-12-08 18:00:48 +00001039 bool Umbrella = UmbrellaLoc.isValid();
1040
Douglas Gregor718292f2011-11-11 19:10:28 +00001041 // Parse the header name.
1042 if (!Tok.is(MMToken::StringLiteral)) {
1043 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1044 << "header";
1045 HadError = true;
1046 return;
1047 }
Douglas Gregore7ab3662011-12-07 02:23:45 +00001048 std::string FileName = Tok.getString();
Douglas Gregor718292f2011-11-11 19:10:28 +00001049 SourceLocation FileNameLoc = consumeToken();
1050
Douglas Gregor524e33e2011-12-08 19:11:24 +00001051 // Check whether we already have an umbrella.
1052 if (Umbrella && ActiveModule->Umbrella) {
1053 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1054 << ActiveModule->getFullModuleName();
Douglas Gregor322f6332011-12-08 18:00:48 +00001055 HadError = true;
1056 return;
1057 }
1058
Douglas Gregor5257fc62011-11-11 21:55:48 +00001059 // Look for this file.
Douglas Gregore7ab3662011-12-07 02:23:45 +00001060 const FileEntry *File = 0;
Douglas Gregor5257fc62011-11-11 21:55:48 +00001061 llvm::SmallString<128> PathName;
Douglas Gregore7ab3662011-12-07 02:23:45 +00001062 if (llvm::sys::path::is_absolute(FileName)) {
1063 PathName = FileName;
1064 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor70331272011-12-09 02:04:43 +00001065 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1066 PathName = Dir->getName();
1067 llvm::sys::path::append(PathName, FileName);
1068 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregore7ab3662011-12-07 02:23:45 +00001069 } else {
1070 // Search for the header file within the search directory.
Douglas Gregor70331272011-12-09 02:04:43 +00001071 PathName = Directory->getName();
Douglas Gregore7ab3662011-12-07 02:23:45 +00001072 unsigned PathLength = PathName.size();
Douglas Gregorf545f672011-11-29 21:59:16 +00001073
Douglas Gregorf2161a72011-12-06 17:16:41 +00001074 if (ActiveModule->isPartOfFramework()) {
1075 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregore7ab3662011-12-07 02:23:45 +00001076
1077 // Check whether this file is in the public headers.
Douglas Gregorf545f672011-11-29 21:59:16 +00001078 llvm::sys::path::append(PathName, "Headers");
Douglas Gregore7ab3662011-12-07 02:23:45 +00001079 llvm::sys::path::append(PathName, FileName);
1080 File = SourceMgr.getFileManager().getFile(PathName);
1081
1082 if (!File) {
1083 // Check whether this file is in the private headers.
1084 PathName.resize(PathLength);
1085 llvm::sys::path::append(PathName, "PrivateHeaders");
1086 llvm::sys::path::append(PathName, FileName);
1087 File = SourceMgr.getFileManager().getFile(PathName);
1088 }
1089 } else {
1090 // Lookup for normal headers.
1091 llvm::sys::path::append(PathName, FileName);
1092 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregorf2161a72011-12-06 17:16:41 +00001093 }
Douglas Gregorf545f672011-11-29 21:59:16 +00001094 }
Douglas Gregor755b2052011-11-17 22:09:43 +00001095
Douglas Gregor5257fc62011-11-11 21:55:48 +00001096 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1097 // Come up with a lazy way to do this.
Douglas Gregore7ab3662011-12-07 02:23:45 +00001098 if (File) {
Douglas Gregor5257fc62011-11-11 21:55:48 +00001099 if (const Module *OwningModule = Map.Headers[File]) {
1100 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
1101 << FileName << OwningModule->getFullModuleName();
1102 HadError = true;
Douglas Gregor322f6332011-12-08 18:00:48 +00001103 } else if (Umbrella) {
1104 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor322f6332011-12-08 18:00:48 +00001105 if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
1106 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1107 << OwningModule->getFullModuleName();
1108 HadError = true;
1109 } else {
1110 // Record this umbrella header.
1111 Map.setUmbrellaHeader(ActiveModule, File);
1112 }
Douglas Gregor5257fc62011-11-11 21:55:48 +00001113 } else {
Douglas Gregor322f6332011-12-08 18:00:48 +00001114 // Record this header.
Douglas Gregora89c5ac2011-12-06 01:10:29 +00001115 Map.addHeader(ActiveModule, File);
Douglas Gregor5257fc62011-11-11 21:55:48 +00001116 }
1117 } else {
1118 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor524e33e2011-12-08 19:11:24 +00001119 << Umbrella << FileName;
Douglas Gregor5257fc62011-11-11 21:55:48 +00001120 HadError = true;
1121 }
Douglas Gregor718292f2011-11-11 19:10:28 +00001122}
1123
Douglas Gregor524e33e2011-12-08 19:11:24 +00001124/// \brief Parse an umbrella directory declaration.
1125///
1126/// umbrella-dir-declaration:
1127/// umbrella string-literal
1128void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1129 // Parse the directory name.
1130 if (!Tok.is(MMToken::StringLiteral)) {
1131 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1132 << "umbrella";
1133 HadError = true;
1134 return;
1135 }
1136
1137 std::string DirName = Tok.getString();
1138 SourceLocation DirNameLoc = consumeToken();
1139
1140 // Check whether we already have an umbrella.
1141 if (ActiveModule->Umbrella) {
1142 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1143 << ActiveModule->getFullModuleName();
1144 HadError = true;
1145 return;
1146 }
1147
1148 // Look for this file.
1149 const DirectoryEntry *Dir = 0;
1150 if (llvm::sys::path::is_absolute(DirName))
1151 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1152 else {
1153 llvm::SmallString<128> PathName;
1154 PathName = Directory->getName();
1155 llvm::sys::path::append(PathName, DirName);
1156 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1157 }
1158
1159 if (!Dir) {
1160 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1161 << DirName;
1162 HadError = true;
1163 return;
1164 }
1165
1166 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1167 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1168 << OwningModule->getFullModuleName();
1169 HadError = true;
1170 return;
1171 }
1172
1173 // Record this umbrella directory.
1174 Map.setUmbrellaDir(ActiveModule, Dir);
1175}
1176
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001177/// \brief Parse a module export declaration.
1178///
1179/// export-declaration:
1180/// 'export' wildcard-module-id
1181///
1182/// wildcard-module-id:
1183/// identifier
1184/// '*'
1185/// identifier '.' wildcard-module-id
1186void ModuleMapParser::parseExportDecl() {
1187 assert(Tok.is(MMToken::ExportKeyword));
1188 SourceLocation ExportLoc = consumeToken();
1189
1190 // Parse the module-id with an optional wildcard at the end.
1191 ModuleId ParsedModuleId;
1192 bool Wildcard = false;
1193 do {
1194 if (Tok.is(MMToken::Identifier)) {
1195 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1196 Tok.getLocation()));
1197 consumeToken();
1198
1199 if (Tok.is(MMToken::Period)) {
1200 consumeToken();
1201 continue;
1202 }
1203
1204 break;
1205 }
1206
1207 if(Tok.is(MMToken::Star)) {
1208 Wildcard = true;
Douglas Gregorf5eedd02011-12-05 17:28:06 +00001209 consumeToken();
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001210 break;
1211 }
1212
1213 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1214 HadError = true;
1215 return;
1216 } while (true);
1217
1218 Module::UnresolvedExportDecl Unresolved = {
1219 ExportLoc, ParsedModuleId, Wildcard
1220 };
1221 ActiveModule->UnresolvedExports.push_back(Unresolved);
1222}
1223
Douglas Gregor73441092011-12-05 22:27:44 +00001224void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1225 assert(Tok.is(MMToken::Star));
1226 SourceLocation StarLoc = consumeToken();
1227 bool Failed = false;
1228
1229 // Inferred modules must be submodules.
1230 if (!ActiveModule) {
1231 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1232 Failed = true;
1233 }
1234
Douglas Gregor524e33e2011-12-08 19:11:24 +00001235 // Inferred modules must have umbrella directories.
1236 if (!Failed && !ActiveModule->getUmbrellaDir()) {
Douglas Gregor73441092011-12-05 22:27:44 +00001237 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1238 Failed = true;
1239 }
1240
1241 // Check for redefinition of an inferred module.
Douglas Gregordd005f62011-12-06 17:34:58 +00001242 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor73441092011-12-05 22:27:44 +00001243 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregordd005f62011-12-06 17:34:58 +00001244 if (ActiveModule->InferredSubmoduleLoc.isValid())
1245 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor73441092011-12-05 22:27:44 +00001246 diag::note_mmap_prev_definition);
1247 Failed = true;
1248 }
1249
1250 // If there were any problems with this inferred submodule, skip its body.
1251 if (Failed) {
1252 if (Tok.is(MMToken::LBrace)) {
1253 consumeToken();
1254 skipUntil(MMToken::RBrace);
1255 if (Tok.is(MMToken::RBrace))
1256 consumeToken();
1257 }
1258 HadError = true;
1259 return;
1260 }
1261
1262 // Note that we have an inferred submodule.
Douglas Gregordd005f62011-12-06 17:34:58 +00001263 ActiveModule->InferSubmodules = true;
1264 ActiveModule->InferredSubmoduleLoc = StarLoc;
1265 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor73441092011-12-05 22:27:44 +00001266
1267 // Parse the opening brace.
1268 if (!Tok.is(MMToken::LBrace)) {
1269 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1270 HadError = true;
1271 return;
1272 }
1273 SourceLocation LBraceLoc = consumeToken();
1274
1275 // Parse the body of the inferred submodule.
1276 bool Done = false;
1277 do {
1278 switch (Tok.Kind) {
1279 case MMToken::EndOfFile:
1280 case MMToken::RBrace:
1281 Done = true;
1282 break;
1283
1284 case MMToken::ExportKeyword: {
1285 consumeToken();
1286 if (Tok.is(MMToken::Star))
Douglas Gregordd005f62011-12-06 17:34:58 +00001287 ActiveModule->InferExportWildcard = true;
Douglas Gregor73441092011-12-05 22:27:44 +00001288 else
1289 Diags.Report(Tok.getLocation(),
1290 diag::err_mmap_expected_export_wildcard);
1291 consumeToken();
1292 break;
1293 }
1294
1295 case MMToken::ExplicitKeyword:
1296 case MMToken::ModuleKeyword:
1297 case MMToken::HeaderKeyword:
1298 case MMToken::UmbrellaKeyword:
1299 default:
1300 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1301 consumeToken();
1302 break;
1303 }
1304 } while (!Done);
1305
1306 if (Tok.is(MMToken::RBrace))
1307 consumeToken();
1308 else {
1309 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1310 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1311 HadError = true;
1312 }
1313}
1314
Douglas Gregor70331272011-12-09 02:04:43 +00001315/// \brief If there is a specific header search directory due the presence
1316/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1317const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1318 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1319 // If we have an umbrella directory, use that.
1320 if (Mod->hasUmbrellaDir())
1321 return Mod->getUmbrellaDir();
1322
1323 // If we have a framework directory, stop looking.
1324 if (Mod->IsFramework)
1325 return 0;
1326 }
1327
1328 return 0;
1329}
1330
Douglas Gregor718292f2011-11-11 19:10:28 +00001331/// \brief Parse a module map file.
1332///
1333/// module-map-file:
1334/// module-declaration*
1335bool ModuleMapParser::parseModuleMapFile() {
1336 do {
1337 switch (Tok.Kind) {
1338 case MMToken::EndOfFile:
1339 return HadError;
1340
Douglas Gregore7ab3662011-12-07 02:23:45 +00001341 case MMToken::ExplicitKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001342 case MMToken::ModuleKeyword:
Douglas Gregor755b2052011-11-17 22:09:43 +00001343 case MMToken::FrameworkKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001344 parseModuleDecl();
1345 break;
1346
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001347 case MMToken::Comma:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001348 case MMToken::ExportKeyword:
Douglas Gregor718292f2011-11-11 19:10:28 +00001349 case MMToken::HeaderKeyword:
1350 case MMToken::Identifier:
1351 case MMToken::LBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +00001352 case MMToken::LSquare:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001353 case MMToken::Period:
Douglas Gregor718292f2011-11-11 19:10:28 +00001354 case MMToken::RBrace:
Douglas Gregora686e1b2012-01-27 19:52:33 +00001355 case MMToken::RSquare:
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001356 case MMToken::RequiresKeyword:
Douglas Gregor2b82c2a2011-12-02 01:47:07 +00001357 case MMToken::Star:
Douglas Gregor718292f2011-11-11 19:10:28 +00001358 case MMToken::StringLiteral:
1359 case MMToken::UmbrellaKeyword:
1360 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1361 HadError = true;
1362 consumeToken();
1363 break;
1364 }
1365 } while (true);
Douglas Gregor718292f2011-11-11 19:10:28 +00001366}
1367
1368bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregor89929282012-01-30 06:01:29 +00001369 assert(Target != 0 && "Missing target information");
Douglas Gregor718292f2011-11-11 19:10:28 +00001370 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1371 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1372 if (!Buffer)
1373 return true;
1374
1375 // Parse this module map file.
Douglas Gregor1fb5c3a2011-12-31 04:05:44 +00001376 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1377 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor5257fc62011-11-11 21:55:48 +00001378 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregor718292f2011-11-11 19:10:28 +00001379 bool Result = Parser.parseModuleMapFile();
1380 Diags->getClient()->EndSourceFile();
1381
1382 return Result;
1383}