blob: 708da94585604e57ab50b44b0a977959745ca4e0 [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,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000287 bool IsSystem,
Douglas Gregorac252a32011-12-06 19:39:29 +0000288 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000289 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000290 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
291 return Mod;
292
293 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000294
295 // Look for an umbrella header.
296 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
297 llvm::sys::path::append(UmbrellaName, "Headers");
298 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000299 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000300
301 // FIXME: If there's no umbrella header, we could probably scan the
302 // framework to load *everything*. But, it's not clear that this is a good
303 // idea.
304 if (!UmbrellaHeader)
305 return 0;
306
Douglas Gregorac252a32011-12-06 19:39:29 +0000307 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
308 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000309 if (IsSystem)
310 Result->IsSystem = IsSystem;
311
Douglas Gregorb7a78192012-01-04 23:32:19 +0000312 if (!Parent)
Douglas Gregorac252a32011-12-06 19:39:29 +0000313 Modules[ModuleName] = Result;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000314
Douglas Gregor489ad432011-12-08 18:00:48 +0000315 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000316 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000317 Headers[UmbrellaHeader] = Result;
Douglas Gregor3cee31e2011-12-12 23:55:05 +0000318 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000319
320 // export *
321 Result->Exports.push_back(Module::ExportDecl(0, true));
322
Douglas Gregore209e502011-12-06 01:10:29 +0000323 // module * { export * }
324 Result->InferSubmodules = true;
325 Result->InferExportWildcard = true;
326
Douglas Gregorac252a32011-12-06 19:39:29 +0000327 // Look for subframeworks.
328 llvm::error_code EC;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000329 llvm::SmallString<128> SubframeworksDirName
330 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000331 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000332 llvm::SmallString<128> SubframeworksDirNameNative;
333 llvm::sys::path::native(SubframeworksDirName.str(),
334 SubframeworksDirNameNative);
335 for (llvm::sys::fs::directory_iterator
336 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregorac252a32011-12-06 19:39:29 +0000337 Dir != DirEnd && !EC; Dir.increment(EC)) {
338 if (!StringRef(Dir->path()).endswith(".framework"))
339 continue;
340
341 if (const DirectoryEntry *SubframeworkDir
342 = FileMgr.getDirectory(Dir->path())) {
343 // FIXME: Do we want to warn about subframeworks without umbrella headers?
344 inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000345 IsSystem, Result);
Douglas Gregorac252a32011-12-06 19:39:29 +0000346 }
347 }
Douglas Gregor3a110f72012-01-13 16:54:27 +0000348
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000349 return Result;
350}
351
Douglas Gregore209e502011-12-06 01:10:29 +0000352void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
353 Headers[UmbrellaHeader] = Mod;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000354 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000355 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000356}
357
Douglas Gregor77d029f2011-12-08 19:11:24 +0000358void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
359 Mod->Umbrella = UmbrellaDir;
360 UmbrellaDirs[UmbrellaDir] = Mod;
361}
362
Douglas Gregore209e502011-12-06 01:10:29 +0000363void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
364 Mod->Headers.push_back(Header);
365 Headers[Header] = Mod;
366}
367
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000368const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000369ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000370 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
371 return 0;
372
373 return SourceMgr->getFileEntryForID(
374 SourceMgr->getFileID(Module->DefinitionLoc));
375}
376
Douglas Gregora30cfe52011-11-11 19:10:28 +0000377void ModuleMap::dump() {
378 llvm::errs() << "Modules:";
379 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
380 MEnd = Modules.end();
381 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000382 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000383
384 llvm::errs() << "Headers:";
385 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
386 H = Headers.begin(),
387 HEnd = Headers.end();
388 H != HEnd; ++H) {
389 llvm::errs() << " \"" << H->first->getName() << "\" -> "
390 << H->second->getFullModuleName() << "\n";
391 }
392}
393
Douglas Gregor90db2602011-12-02 01:47:07 +0000394bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
395 bool HadError = false;
396 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
397 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
398 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000399 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000400 Mod->Exports.push_back(Export);
401 else
402 HadError = true;
403 }
404 Mod->UnresolvedExports.clear();
405 return HadError;
406}
407
Douglas Gregor55988682011-12-05 16:33:54 +0000408Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
409 if (Loc.isInvalid())
410 return 0;
411
412 // Use the expansion location to determine which module we're in.
413 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
414 if (!ExpansionLoc.isFileID())
415 return 0;
416
417
418 const SourceManager &SrcMgr = Loc.getManager();
419 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor55988682011-12-05 16:33:54 +0000420
Douglas Gregor303aae92012-01-06 17:19:32 +0000421 while (const FileEntry *ExpansionFile
422 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
423 // Find the module that owns this header (if any).
424 if (Module *Mod = findModuleForHeader(ExpansionFile))
425 return Mod;
426
427 // No module owns this header, so look up the inclusion chain to see if
428 // any included header has an associated module.
429 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
430 if (IncludeLoc.isInvalid())
431 return 0;
432
433 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
434 }
435
436 return 0;
Douglas Gregor55988682011-12-05 16:33:54 +0000437}
438
Douglas Gregora30cfe52011-11-11 19:10:28 +0000439//----------------------------------------------------------------------------//
440// Module map file parser
441//----------------------------------------------------------------------------//
442
443namespace clang {
444 /// \brief A token in a module map file.
445 struct MMToken {
446 enum TokenKind {
Douglas Gregor51f564f2011-12-31 04:05:44 +0000447 Comma,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000448 EndOfFile,
449 HeaderKeyword,
450 Identifier,
451 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000452 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000453 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000454 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000455 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000456 UmbrellaKeyword,
Douglas Gregor51f564f2011-12-31 04:05:44 +0000457 RequiresKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000458 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000459 StringLiteral,
460 LBrace,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000461 RBrace,
462 LSquare,
463 RSquare
Douglas Gregora30cfe52011-11-11 19:10:28 +0000464 } Kind;
465
466 unsigned Location;
467 unsigned StringLength;
468 const char *StringData;
469
470 void clear() {
471 Kind = EndOfFile;
472 Location = 0;
473 StringLength = 0;
474 StringData = 0;
475 }
476
477 bool is(TokenKind K) const { return Kind == K; }
478
479 SourceLocation getLocation() const {
480 return SourceLocation::getFromRawEncoding(Location);
481 }
482
483 StringRef getString() const {
484 return StringRef(StringData, StringLength);
485 }
486 };
487
488 class ModuleMapParser {
489 Lexer &L;
490 SourceManager &SourceMgr;
491 DiagnosticsEngine &Diags;
492 ModuleMap &Map;
493
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000494 /// \brief The directory that this module map resides in.
495 const DirectoryEntry *Directory;
496
Douglas Gregora30cfe52011-11-11 19:10:28 +0000497 /// \brief Whether an error occurred.
498 bool HadError;
499
500 /// \brief Default target information, used only for string literal
501 /// parsing.
502 TargetInfo *Target;
503
504 /// \brief Stores string data for the various string literals referenced
505 /// during parsing.
506 llvm::BumpPtrAllocator StringData;
507
508 /// \brief The current token.
509 MMToken Tok;
510
511 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000512 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000513
514 /// \brief Consume the current token and return its location.
515 SourceLocation consumeToken();
516
517 /// \brief Skip tokens until we reach the a token with the given kind
518 /// (or the end of the file).
519 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000520
521 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
522 ModuleId;
523 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000524 void parseModuleDecl();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000525 void parseRequiresDecl();
Douglas Gregor489ad432011-12-08 18:00:48 +0000526 void parseHeaderDecl(SourceLocation UmbrellaLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000527 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000528 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000529 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000530
Douglas Gregor6a1db482011-12-09 02:04:43 +0000531 const DirectoryEntry *getOverriddenHeaderSearchDir();
532
Douglas Gregora30cfe52011-11-11 19:10:28 +0000533 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000534 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
535 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000536 ModuleMap &Map,
537 const DirectoryEntry *Directory)
538 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
539 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000540 {
541 TargetOptions TargetOpts;
542 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
543 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
544
545 Tok.clear();
546 consumeToken();
547 }
548
549 bool parseModuleMapFile();
550 };
551}
552
553SourceLocation ModuleMapParser::consumeToken() {
554retry:
555 SourceLocation Result = Tok.getLocation();
556 Tok.clear();
557
558 Token LToken;
559 L.LexFromRawLexer(LToken);
560 Tok.Location = LToken.getLocation().getRawEncoding();
561 switch (LToken.getKind()) {
562 case tok::raw_identifier:
563 Tok.StringData = LToken.getRawIdentifierData();
564 Tok.StringLength = LToken.getLength();
565 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
566 .Case("header", MMToken::HeaderKeyword)
567 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000568 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000569 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000570 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor51f564f2011-12-31 04:05:44 +0000571 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000572 .Case("umbrella", MMToken::UmbrellaKeyword)
573 .Default(MMToken::Identifier);
574 break;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000575
576 case tok::comma:
577 Tok.Kind = MMToken::Comma;
578 break;
579
Douglas Gregora30cfe52011-11-11 19:10:28 +0000580 case tok::eof:
581 Tok.Kind = MMToken::EndOfFile;
582 break;
583
584 case tok::l_brace:
585 Tok.Kind = MMToken::LBrace;
586 break;
587
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000588 case tok::l_square:
589 Tok.Kind = MMToken::LSquare;
590 break;
591
Douglas Gregor90db2602011-12-02 01:47:07 +0000592 case tok::period:
593 Tok.Kind = MMToken::Period;
594 break;
595
Douglas Gregora30cfe52011-11-11 19:10:28 +0000596 case tok::r_brace:
597 Tok.Kind = MMToken::RBrace;
598 break;
599
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000600 case tok::r_square:
601 Tok.Kind = MMToken::RSquare;
602 break;
603
Douglas Gregor90db2602011-12-02 01:47:07 +0000604 case tok::star:
605 Tok.Kind = MMToken::Star;
606 break;
607
Douglas Gregora30cfe52011-11-11 19:10:28 +0000608 case tok::string_literal: {
609 // Parse the string literal.
610 LangOptions LangOpts;
611 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
612 if (StringLiteral.hadError)
613 goto retry;
614
615 // Copy the string literal into our string data allocator.
616 unsigned Length = StringLiteral.GetStringLength();
617 char *Saved = StringData.Allocate<char>(Length + 1);
618 memcpy(Saved, StringLiteral.GetString().data(), Length);
619 Saved[Length] = 0;
620
621 // Form the token.
622 Tok.Kind = MMToken::StringLiteral;
623 Tok.StringData = Saved;
624 Tok.StringLength = Length;
625 break;
626 }
627
628 case tok::comment:
629 goto retry;
630
631 default:
632 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
633 HadError = true;
634 goto retry;
635 }
636
637 return Result;
638}
639
640void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
641 unsigned braceDepth = 0;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000642 unsigned squareDepth = 0;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000643 do {
644 switch (Tok.Kind) {
645 case MMToken::EndOfFile:
646 return;
647
648 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000649 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000650 return;
651
652 ++braceDepth;
653 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000654
655 case MMToken::LSquare:
656 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
657 return;
658
659 ++squareDepth;
660 break;
661
Douglas Gregora30cfe52011-11-11 19:10:28 +0000662 case MMToken::RBrace:
663 if (braceDepth > 0)
664 --braceDepth;
665 else if (Tok.is(K))
666 return;
667 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000668
669 case MMToken::RSquare:
670 if (squareDepth > 0)
671 --squareDepth;
672 else if (Tok.is(K))
673 return;
674 break;
675
Douglas Gregora30cfe52011-11-11 19:10:28 +0000676 default:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000677 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregora30cfe52011-11-11 19:10:28 +0000678 return;
679 break;
680 }
681
682 consumeToken();
683 } while (true);
684}
685
Douglas Gregor587986e2011-12-07 02:23:45 +0000686/// \brief Parse a module-id.
687///
688/// module-id:
689/// identifier
690/// identifier '.' module-id
691///
692/// \returns true if an error occurred, false otherwise.
693bool ModuleMapParser::parseModuleId(ModuleId &Id) {
694 Id.clear();
695 do {
696 if (Tok.is(MMToken::Identifier)) {
697 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
698 consumeToken();
699 } else {
700 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
701 return true;
702 }
703
704 if (!Tok.is(MMToken::Period))
705 break;
706
707 consumeToken();
708 } while (true);
709
710 return false;
711}
712
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000713namespace {
714 /// \brief Enumerates the known attributes.
715 enum AttributeKind {
716 /// \brief An unknown attribute.
717 AT_unknown,
718 /// \brief The 'system' attribute.
719 AT_system
720 };
721}
722
Douglas Gregora30cfe52011-11-11 19:10:28 +0000723/// \brief Parse a module declaration.
724///
725/// module-declaration:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000726/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
727/// { module-member* }
728///
729/// attributes:
730/// attribute attributes
731/// attribute
732///
733/// attribute:
734/// [ identifier ]
Douglas Gregora30cfe52011-11-11 19:10:28 +0000735///
736/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +0000737/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000738/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000739/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000740/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000741///
742/// submodule-declaration:
743/// module-declaration
744/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000745void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000746 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
747 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000748 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000749 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000750 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000751 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000752
Douglas Gregord620a842011-12-06 17:16:41 +0000753 // Parse 'explicit' keyword, if present.
754 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000755 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000756 Explicit = true;
757 }
758
759 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000760 if (Tok.is(MMToken::FrameworkKeyword)) {
761 consumeToken();
762 Framework = true;
763 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000764
765 // Parse 'module' keyword.
766 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000767 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000768 consumeToken();
769 HadError = true;
770 return;
771 }
772 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000773
774 // If we have a wildcard for the module name, this is an inferred submodule.
775 // Parse it.
776 if (Tok.is(MMToken::Star))
777 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000778
779 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000780 ModuleId Id;
781 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000782 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000783 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000784 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000785
786 if (ActiveModule) {
787 if (Id.size() > 1) {
788 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
789 << SourceRange(Id.front().second, Id.back().second);
790
791 HadError = true;
792 return;
793 }
794 } else if (Id.size() == 1 && Explicit) {
795 // Top-level modules can't be explicit.
796 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
797 Explicit = false;
798 ExplicitLoc = SourceLocation();
799 HadError = true;
800 }
801
802 Module *PreviousActiveModule = ActiveModule;
803 if (Id.size() > 1) {
804 // This module map defines a submodule. Go find the module of which it
805 // is a submodule.
806 ActiveModule = 0;
807 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
808 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
809 ActiveModule = Next;
810 continue;
811 }
812
813 if (ActiveModule) {
814 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
815 << Id[I].first << ActiveModule->getTopLevelModule();
816 } else {
817 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
818 }
819 HadError = true;
820 return;
821 }
822 }
823
824 StringRef ModuleName = Id.back().first;
825 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000826
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000827 // Parse the optional attribute list.
828 bool IsSystem = false;
829 while (Tok.is(MMToken::LSquare)) {
830 // Consume the '['.
831 SourceLocation LSquareLoc = consumeToken();
832
833 // Check whether we have an attribute name here.
834 if (!Tok.is(MMToken::Identifier)) {
835 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
836 skipUntil(MMToken::RSquare);
837 if (Tok.is(MMToken::RSquare))
838 consumeToken();
839 continue;
840 }
841
842 // Decode the attribute name.
843 AttributeKind Attribute
844 = llvm::StringSwitch<AttributeKind>(Tok.getString())
845 .Case("system", AT_system)
846 .Default(AT_unknown);
847 switch (Attribute) {
848 case AT_unknown:
849 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
850 << Tok.getString();
851 break;
852
853 case AT_system:
854 IsSystem = true;
855 break;
856 }
857 consumeToken();
858
859 // Consume the ']'.
860 if (!Tok.is(MMToken::RSquare)) {
861 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
862 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
863 skipUntil(MMToken::RSquare);
864 }
865
866 if (Tok.is(MMToken::RSquare))
867 consumeToken();
868 }
869
Douglas Gregora30cfe52011-11-11 19:10:28 +0000870 // Parse the opening brace.
871 if (!Tok.is(MMToken::LBrace)) {
872 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
873 << ModuleName;
874 HadError = true;
875 return;
876 }
877 SourceLocation LBraceLoc = consumeToken();
878
879 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000880 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +0000881 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
882 // Skip the module definition.
883 skipUntil(MMToken::RBrace);
884 if (Tok.is(MMToken::RBrace))
885 consumeToken();
886 else {
887 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
888 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
889 HadError = true;
890 }
891 return;
892 }
893
Douglas Gregora30cfe52011-11-11 19:10:28 +0000894 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
895 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000896 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000897
898 // Skip the module definition.
899 skipUntil(MMToken::RBrace);
900 if (Tok.is(MMToken::RBrace))
901 consumeToken();
902
903 HadError = true;
904 return;
905 }
906
907 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000908 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
909 Explicit).first;
910 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000911 if (IsSystem)
912 ActiveModule->IsSystem = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000913
914 bool Done = false;
915 do {
916 switch (Tok.Kind) {
917 case MMToken::EndOfFile:
918 case MMToken::RBrace:
919 Done = true;
920 break;
921
922 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000923 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000924 case MMToken::ModuleKeyword:
925 parseModuleDecl();
926 break;
927
Douglas Gregor90db2602011-12-02 01:47:07 +0000928 case MMToken::ExportKeyword:
929 parseExportDecl();
930 break;
931
Douglas Gregor51f564f2011-12-31 04:05:44 +0000932 case MMToken::RequiresKeyword:
933 parseRequiresDecl();
934 break;
935
Douglas Gregor77d029f2011-12-08 19:11:24 +0000936 case MMToken::UmbrellaKeyword: {
937 SourceLocation UmbrellaLoc = consumeToken();
938 if (Tok.is(MMToken::HeaderKeyword))
939 parseHeaderDecl(UmbrellaLoc);
940 else
941 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000942 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +0000943 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000944
Douglas Gregor489ad432011-12-08 18:00:48 +0000945 case MMToken::HeaderKeyword:
946 parseHeaderDecl(SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000947 break;
Douglas Gregor489ad432011-12-08 18:00:48 +0000948
Douglas Gregora30cfe52011-11-11 19:10:28 +0000949 default:
950 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
951 consumeToken();
952 break;
953 }
954 } while (!Done);
955
956 if (Tok.is(MMToken::RBrace))
957 consumeToken();
958 else {
959 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
960 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
961 HadError = true;
962 }
963
Douglas Gregor587986e2011-12-07 02:23:45 +0000964 // We're done parsing this module. Pop back to the previous module.
965 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000966}
Douglas Gregord620a842011-12-06 17:16:41 +0000967
Douglas Gregor51f564f2011-12-31 04:05:44 +0000968/// \brief Parse a requires declaration.
969///
970/// requires-declaration:
971/// 'requires' feature-list
972///
973/// feature-list:
974/// identifier ',' feature-list
975/// identifier
976void ModuleMapParser::parseRequiresDecl() {
977 assert(Tok.is(MMToken::RequiresKeyword));
978
979 // Parse 'requires' keyword.
980 consumeToken();
981
982 // Parse the feature-list.
983 do {
984 if (!Tok.is(MMToken::Identifier)) {
985 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
986 HadError = true;
987 return;
988 }
989
990 // Consume the feature name.
991 std::string Feature = Tok.getString();
992 consumeToken();
993
994 // Add this feature.
995 ActiveModule->addRequirement(Feature, Map.LangOpts);
996
997 if (!Tok.is(MMToken::Comma))
998 break;
999
1000 // Consume the comma.
1001 consumeToken();
1002 } while (true);
1003}
1004
Douglas Gregord620a842011-12-06 17:16:41 +00001005/// \brief Append to \p Paths the set of paths needed to get to the
1006/// subframework in which the given module lives.
1007void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
1008 // Collect the framework names from the given module to the top-level module.
1009 llvm::SmallVector<StringRef, 2> Paths;
1010 for (; Mod; Mod = Mod->Parent) {
1011 if (Mod->IsFramework)
1012 Paths.push_back(Mod->Name);
1013 }
1014
1015 if (Paths.empty())
1016 return;
1017
1018 // Add Frameworks/Name.framework for each subframework.
1019 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1020 llvm::sys::path::append(Path, "Frameworks");
1021 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1022 }
1023}
1024
Douglas Gregora30cfe52011-11-11 19:10:28 +00001025/// \brief Parse a header declaration.
1026///
1027/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +00001028/// 'umbrella'[opt] 'header' string-literal
1029void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001030 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +00001031 consumeToken();
1032
Douglas Gregor489ad432011-12-08 18:00:48 +00001033 bool Umbrella = UmbrellaLoc.isValid();
1034
Douglas Gregora30cfe52011-11-11 19:10:28 +00001035 // Parse the header name.
1036 if (!Tok.is(MMToken::StringLiteral)) {
1037 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1038 << "header";
1039 HadError = true;
1040 return;
1041 }
Douglas Gregor587986e2011-12-07 02:23:45 +00001042 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +00001043 SourceLocation FileNameLoc = consumeToken();
1044
Douglas Gregor77d029f2011-12-08 19:11:24 +00001045 // Check whether we already have an umbrella.
1046 if (Umbrella && ActiveModule->Umbrella) {
1047 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1048 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001049 HadError = true;
1050 return;
1051 }
1052
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001053 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +00001054 const FileEntry *File = 0;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001055 llvm::SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +00001056 if (llvm::sys::path::is_absolute(FileName)) {
1057 PathName = FileName;
1058 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +00001059 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1060 PathName = Dir->getName();
1061 llvm::sys::path::append(PathName, FileName);
1062 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001063 } else {
1064 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +00001065 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +00001066 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +00001067
Douglas Gregord620a842011-12-06 17:16:41 +00001068 if (ActiveModule->isPartOfFramework()) {
1069 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001070
1071 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +00001072 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +00001073 llvm::sys::path::append(PathName, FileName);
1074 File = SourceMgr.getFileManager().getFile(PathName);
1075
1076 if (!File) {
1077 // Check whether this file is in the private headers.
1078 PathName.resize(PathLength);
1079 llvm::sys::path::append(PathName, "PrivateHeaders");
1080 llvm::sys::path::append(PathName, FileName);
1081 File = SourceMgr.getFileManager().getFile(PathName);
1082 }
1083 } else {
1084 // Lookup for normal headers.
1085 llvm::sys::path::append(PathName, FileName);
1086 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregord620a842011-12-06 17:16:41 +00001087 }
Douglas Gregor18ee5472011-11-29 21:59:16 +00001088 }
Douglas Gregora8654052011-11-17 22:09:43 +00001089
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001090 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1091 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001092 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001093 if (const Module *OwningModule = Map.Headers[File]) {
1094 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
1095 << FileName << OwningModule->getFullModuleName();
1096 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +00001097 } else if (Umbrella) {
1098 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor489ad432011-12-08 18:00:48 +00001099 if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
1100 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1101 << OwningModule->getFullModuleName();
1102 HadError = true;
1103 } else {
1104 // Record this umbrella header.
1105 Map.setUmbrellaHeader(ActiveModule, File);
1106 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001107 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001108 // Record this header.
Douglas Gregore209e502011-12-06 01:10:29 +00001109 Map.addHeader(ActiveModule, File);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001110 }
1111 } else {
1112 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +00001113 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001114 HadError = true;
1115 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001116}
1117
Douglas Gregor77d029f2011-12-08 19:11:24 +00001118/// \brief Parse an umbrella directory declaration.
1119///
1120/// umbrella-dir-declaration:
1121/// umbrella string-literal
1122void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1123 // Parse the directory name.
1124 if (!Tok.is(MMToken::StringLiteral)) {
1125 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1126 << "umbrella";
1127 HadError = true;
1128 return;
1129 }
1130
1131 std::string DirName = Tok.getString();
1132 SourceLocation DirNameLoc = consumeToken();
1133
1134 // Check whether we already have an umbrella.
1135 if (ActiveModule->Umbrella) {
1136 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1137 << ActiveModule->getFullModuleName();
1138 HadError = true;
1139 return;
1140 }
1141
1142 // Look for this file.
1143 const DirectoryEntry *Dir = 0;
1144 if (llvm::sys::path::is_absolute(DirName))
1145 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1146 else {
1147 llvm::SmallString<128> PathName;
1148 PathName = Directory->getName();
1149 llvm::sys::path::append(PathName, DirName);
1150 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1151 }
1152
1153 if (!Dir) {
1154 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1155 << DirName;
1156 HadError = true;
1157 return;
1158 }
1159
1160 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1161 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1162 << OwningModule->getFullModuleName();
1163 HadError = true;
1164 return;
1165 }
1166
1167 // Record this umbrella directory.
1168 Map.setUmbrellaDir(ActiveModule, Dir);
1169}
1170
Douglas Gregor90db2602011-12-02 01:47:07 +00001171/// \brief Parse a module export declaration.
1172///
1173/// export-declaration:
1174/// 'export' wildcard-module-id
1175///
1176/// wildcard-module-id:
1177/// identifier
1178/// '*'
1179/// identifier '.' wildcard-module-id
1180void ModuleMapParser::parseExportDecl() {
1181 assert(Tok.is(MMToken::ExportKeyword));
1182 SourceLocation ExportLoc = consumeToken();
1183
1184 // Parse the module-id with an optional wildcard at the end.
1185 ModuleId ParsedModuleId;
1186 bool Wildcard = false;
1187 do {
1188 if (Tok.is(MMToken::Identifier)) {
1189 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1190 Tok.getLocation()));
1191 consumeToken();
1192
1193 if (Tok.is(MMToken::Period)) {
1194 consumeToken();
1195 continue;
1196 }
1197
1198 break;
1199 }
1200
1201 if(Tok.is(MMToken::Star)) {
1202 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001203 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001204 break;
1205 }
1206
1207 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1208 HadError = true;
1209 return;
1210 } while (true);
1211
1212 Module::UnresolvedExportDecl Unresolved = {
1213 ExportLoc, ParsedModuleId, Wildcard
1214 };
1215 ActiveModule->UnresolvedExports.push_back(Unresolved);
1216}
1217
Douglas Gregor1e123682011-12-05 22:27:44 +00001218void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1219 assert(Tok.is(MMToken::Star));
1220 SourceLocation StarLoc = consumeToken();
1221 bool Failed = false;
1222
1223 // Inferred modules must be submodules.
1224 if (!ActiveModule) {
1225 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1226 Failed = true;
1227 }
1228
Douglas Gregor77d029f2011-12-08 19:11:24 +00001229 // Inferred modules must have umbrella directories.
1230 if (!Failed && !ActiveModule->getUmbrellaDir()) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001231 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1232 Failed = true;
1233 }
1234
1235 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +00001236 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001237 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +00001238 if (ActiveModule->InferredSubmoduleLoc.isValid())
1239 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +00001240 diag::note_mmap_prev_definition);
1241 Failed = true;
1242 }
1243
1244 // If there were any problems with this inferred submodule, skip its body.
1245 if (Failed) {
1246 if (Tok.is(MMToken::LBrace)) {
1247 consumeToken();
1248 skipUntil(MMToken::RBrace);
1249 if (Tok.is(MMToken::RBrace))
1250 consumeToken();
1251 }
1252 HadError = true;
1253 return;
1254 }
1255
1256 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +00001257 ActiveModule->InferSubmodules = true;
1258 ActiveModule->InferredSubmoduleLoc = StarLoc;
1259 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +00001260
1261 // Parse the opening brace.
1262 if (!Tok.is(MMToken::LBrace)) {
1263 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1264 HadError = true;
1265 return;
1266 }
1267 SourceLocation LBraceLoc = consumeToken();
1268
1269 // Parse the body of the inferred submodule.
1270 bool Done = false;
1271 do {
1272 switch (Tok.Kind) {
1273 case MMToken::EndOfFile:
1274 case MMToken::RBrace:
1275 Done = true;
1276 break;
1277
1278 case MMToken::ExportKeyword: {
1279 consumeToken();
1280 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001281 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001282 else
1283 Diags.Report(Tok.getLocation(),
1284 diag::err_mmap_expected_export_wildcard);
1285 consumeToken();
1286 break;
1287 }
1288
1289 case MMToken::ExplicitKeyword:
1290 case MMToken::ModuleKeyword:
1291 case MMToken::HeaderKeyword:
1292 case MMToken::UmbrellaKeyword:
1293 default:
1294 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1295 consumeToken();
1296 break;
1297 }
1298 } while (!Done);
1299
1300 if (Tok.is(MMToken::RBrace))
1301 consumeToken();
1302 else {
1303 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1304 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1305 HadError = true;
1306 }
1307}
1308
Douglas Gregor6a1db482011-12-09 02:04:43 +00001309/// \brief If there is a specific header search directory due the presence
1310/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1311const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1312 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1313 // If we have an umbrella directory, use that.
1314 if (Mod->hasUmbrellaDir())
1315 return Mod->getUmbrellaDir();
1316
1317 // If we have a framework directory, stop looking.
1318 if (Mod->IsFramework)
1319 return 0;
1320 }
1321
1322 return 0;
1323}
1324
Douglas Gregora30cfe52011-11-11 19:10:28 +00001325/// \brief Parse a module map file.
1326///
1327/// module-map-file:
1328/// module-declaration*
1329bool ModuleMapParser::parseModuleMapFile() {
1330 do {
1331 switch (Tok.Kind) {
1332 case MMToken::EndOfFile:
1333 return HadError;
1334
Douglas Gregor587986e2011-12-07 02:23:45 +00001335 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001336 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001337 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001338 parseModuleDecl();
1339 break;
1340
Douglas Gregor51f564f2011-12-31 04:05:44 +00001341 case MMToken::Comma:
Douglas Gregor90db2602011-12-02 01:47:07 +00001342 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001343 case MMToken::HeaderKeyword:
1344 case MMToken::Identifier:
1345 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001346 case MMToken::LSquare:
Douglas Gregor90db2602011-12-02 01:47:07 +00001347 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001348 case MMToken::RBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001349 case MMToken::RSquare:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001350 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001351 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001352 case MMToken::StringLiteral:
1353 case MMToken::UmbrellaKeyword:
1354 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1355 HadError = true;
1356 consumeToken();
1357 break;
1358 }
1359 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001360}
1361
1362bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
1363 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1364 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1365 if (!Buffer)
1366 return true;
1367
1368 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00001369 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1370 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001371 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001372 bool Result = Parser.parseModuleMapFile();
1373 Diags->getClient()->EndSourceFile();
1374
1375 return Result;
1376}