blob: c1c50660125fd1cbf8a0b1c1eafbc510d0168952 [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,
Douglas Gregordc58aa72012-01-30 06:01:29 +000073 const LangOptions &LangOpts, const TargetInfo *Target)
Douglas Gregor2f04f182012-02-02 18:42:48 +000074 : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0)
Douglas Gregor51f564f2011-12-31 04:05:44 +000075{
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 Gregordc58aa72012-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 Gregor1a4761e2011-11-30 23:21:26 +000099Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000100 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
101 = Headers.find(File);
Douglas Gregor51f564f2011-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 Gregor65f3b5e2011-11-11 22:18:48 +0000108 return Known->second;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000109 }
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000110
Douglas Gregoradb97992011-11-16 23:02:25 +0000111 const DirectoryEntry *Dir = File->getDir();
Douglas Gregoradb97992011-11-16 23:02:25 +0000112 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
113 StringRef DirName = Dir->getName();
Douglas Gregore209e502011-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 Gregor9f74f4f2011-12-06 16:17:15 +0000122
123 // Search up the module stack until we find a module with an umbrella
Douglas Gregor10694ce2011-12-08 17:39:04 +0000124 // directory.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000125 Module *UmbrellaModule = Result;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000126 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000127 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000128
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000129 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-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 Gregor23af6d52011-12-07 22:05:21 +0000133 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregore209e502011-12-06 01:10:29 +0000134
Douglas Gregor6a1db482011-12-09 02:04:43 +0000135 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregore209e502011-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 Gregor23af6d52011-12-07 22:05:21 +0000139 Explicit).first;
Douglas Gregore209e502011-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 Gregor9f74f4f2011-12-06 16:17:15 +0000146 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-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 Gregor23af6d52011-12-07 22:05:21 +0000153 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000154
155 // If inferred submodules export everything they import, add a
156 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000157 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-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 Gregor51f564f2011-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 Gregore209e502011-12-06 01:10:29 +0000173 return Result;
174 }
175
176 SkippedDirs.push_back(Dir);
177
Douglas Gregoradb97992011-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 Gregore209e502011-12-06 01:10:29 +0000185 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000186
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000187 return 0;
188}
189
Douglas Gregor51f564f2011-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 Gregor1a4761e2011-11-30 23:21:26 +0000251Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-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 Gregor90db2602011-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 Gregorb7a78192012-01-04 23:32:19 +0000272 return Context->findSubmodule(Name);
Douglas Gregor90db2602011-12-02 01:47:07 +0000273}
274
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000275std::pair<Module *, bool>
Douglas Gregor392ed2b2011-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 Gregorb7a78192012-01-04 23:32:19 +0000279 if (Module *Sub = lookupModuleQualified(Name, Parent))
280 return std::make_pair(Sub, false);
Douglas Gregor392ed2b2011-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 Gregorb7a78192012-01-04 23:32:19 +0000285 if (!Parent)
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000286 Modules[Name] = Result;
287 return std::make_pair(Result, true);
288}
289
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000290Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000291ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000292 const DirectoryEntry *FrameworkDir,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000293 bool IsSystem,
Douglas Gregorac252a32011-12-06 19:39:29 +0000294 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000295 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000296 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
297 return Mod;
298
299 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor2821c7f2011-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 Gregorac252a32011-12-06 19:39:29 +0000305 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-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 Gregorac252a32011-12-06 19:39:29 +0000313 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
314 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000315 if (IsSystem)
316 Result->IsSystem = IsSystem;
317
Douglas Gregorb7a78192012-01-04 23:32:19 +0000318 if (!Parent)
Douglas Gregorac252a32011-12-06 19:39:29 +0000319 Modules[ModuleName] = Result;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000320
Douglas Gregor489ad432011-12-08 18:00:48 +0000321 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000322 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000323 Headers[UmbrellaHeader] = Result;
Douglas Gregor3cee31e2011-12-12 23:55:05 +0000324 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000325
326 // export *
327 Result->Exports.push_back(Module::ExportDecl(0, true));
328
Douglas Gregore209e502011-12-06 01:10:29 +0000329 // module * { export * }
330 Result->InferSubmodules = true;
331 Result->InferExportWildcard = true;
332
Douglas Gregorac252a32011-12-06 19:39:29 +0000333 // Look for subframeworks.
334 llvm::error_code EC;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000335 llvm::SmallString<128> SubframeworksDirName
336 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000337 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Douglas Gregor52b1ed32011-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 Gregorac252a32011-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 Gregora1f1fad2012-01-27 19:52:33 +0000351 IsSystem, Result);
Douglas Gregorac252a32011-12-06 19:39:29 +0000352 }
353 }
Douglas Gregor3a110f72012-01-13 16:54:27 +0000354
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000355 return Result;
356}
357
Douglas Gregore209e502011-12-06 01:10:29 +0000358void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
359 Headers[UmbrellaHeader] = Mod;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000360 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000361 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000362}
363
Douglas Gregor77d029f2011-12-08 19:11:24 +0000364void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
365 Mod->Umbrella = UmbrellaDir;
366 UmbrellaDirs[UmbrellaDir] = Mod;
367}
368
Douglas Gregore209e502011-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 Gregorf9e357d2011-11-29 19:06:37 +0000374const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000375ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-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 Gregora30cfe52011-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 Gregor804c3bf2011-11-29 18:17:59 +0000388 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-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 Gregor90db2602011-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 Gregor0adaa882011-12-05 17:28:06 +0000405 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-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 Gregor55988682011-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 Gregor55988682011-12-05 16:33:54 +0000426
Douglas Gregor303aae92012-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 Gregor55988682011-12-05 16:33:54 +0000443}
444
Douglas Gregora30cfe52011-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 Gregor51f564f2011-12-31 04:05:44 +0000453 Comma,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000454 EndOfFile,
455 HeaderKeyword,
456 Identifier,
457 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000458 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000459 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000460 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000461 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000462 UmbrellaKeyword,
Douglas Gregor51f564f2011-12-31 04:05:44 +0000463 RequiresKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000464 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000465 StringLiteral,
466 LBrace,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000467 RBrace,
468 LSquare,
469 RSquare
Douglas Gregora30cfe52011-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 Gregor8b6d3de2011-11-11 21:55:48 +0000500 /// \brief The directory that this module map resides in.
501 const DirectoryEntry *Directory;
Douglas Gregor2f04f182012-02-02 18:42:48 +0000502
503 /// \brief The directory containing Clang-supplied headers.
504 const DirectoryEntry *BuiltinIncludeDir;
505
Douglas Gregora30cfe52011-11-11 19:10:28 +0000506 /// \brief Whether an error occurred.
507 bool HadError;
508
509 /// \brief Default target information, used only for string literal
510 /// parsing.
511 TargetInfo *Target;
512
513 /// \brief Stores string data for the various string literals referenced
514 /// during parsing.
515 llvm::BumpPtrAllocator StringData;
516
517 /// \brief The current token.
518 MMToken Tok;
519
520 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000521 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000522
523 /// \brief Consume the current token and return its location.
524 SourceLocation consumeToken();
525
526 /// \brief Skip tokens until we reach the a token with the given kind
527 /// (or the end of the file).
528 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000529
530 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
531 ModuleId;
532 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000533 void parseModuleDecl();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000534 void parseRequiresDecl();
Douglas Gregor489ad432011-12-08 18:00:48 +0000535 void parseHeaderDecl(SourceLocation UmbrellaLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000536 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000537 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000538 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000539
Douglas Gregor6a1db482011-12-09 02:04:43 +0000540 const DirectoryEntry *getOverriddenHeaderSearchDir();
541
Douglas Gregora30cfe52011-11-11 19:10:28 +0000542 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000543 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
544 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000545 ModuleMap &Map,
Douglas Gregor2f04f182012-02-02 18:42:48 +0000546 const DirectoryEntry *Directory,
547 const DirectoryEntry *BuiltinIncludeDir)
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000548 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
Douglas Gregor2f04f182012-02-02 18:42:48 +0000549 Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
550 HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000551 {
552 TargetOptions TargetOpts;
553 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
554 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
555
556 Tok.clear();
557 consumeToken();
558 }
559
560 bool parseModuleMapFile();
561 };
562}
563
564SourceLocation ModuleMapParser::consumeToken() {
565retry:
566 SourceLocation Result = Tok.getLocation();
567 Tok.clear();
568
569 Token LToken;
570 L.LexFromRawLexer(LToken);
571 Tok.Location = LToken.getLocation().getRawEncoding();
572 switch (LToken.getKind()) {
573 case tok::raw_identifier:
574 Tok.StringData = LToken.getRawIdentifierData();
575 Tok.StringLength = LToken.getLength();
576 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
577 .Case("header", MMToken::HeaderKeyword)
578 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000579 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000580 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000581 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor51f564f2011-12-31 04:05:44 +0000582 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000583 .Case("umbrella", MMToken::UmbrellaKeyword)
584 .Default(MMToken::Identifier);
585 break;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000586
587 case tok::comma:
588 Tok.Kind = MMToken::Comma;
589 break;
590
Douglas Gregora30cfe52011-11-11 19:10:28 +0000591 case tok::eof:
592 Tok.Kind = MMToken::EndOfFile;
593 break;
594
595 case tok::l_brace:
596 Tok.Kind = MMToken::LBrace;
597 break;
598
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000599 case tok::l_square:
600 Tok.Kind = MMToken::LSquare;
601 break;
602
Douglas Gregor90db2602011-12-02 01:47:07 +0000603 case tok::period:
604 Tok.Kind = MMToken::Period;
605 break;
606
Douglas Gregora30cfe52011-11-11 19:10:28 +0000607 case tok::r_brace:
608 Tok.Kind = MMToken::RBrace;
609 break;
610
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000611 case tok::r_square:
612 Tok.Kind = MMToken::RSquare;
613 break;
614
Douglas Gregor90db2602011-12-02 01:47:07 +0000615 case tok::star:
616 Tok.Kind = MMToken::Star;
617 break;
618
Douglas Gregora30cfe52011-11-11 19:10:28 +0000619 case tok::string_literal: {
620 // Parse the string literal.
621 LangOptions LangOpts;
622 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
623 if (StringLiteral.hadError)
624 goto retry;
625
626 // Copy the string literal into our string data allocator.
627 unsigned Length = StringLiteral.GetStringLength();
628 char *Saved = StringData.Allocate<char>(Length + 1);
629 memcpy(Saved, StringLiteral.GetString().data(), Length);
630 Saved[Length] = 0;
631
632 // Form the token.
633 Tok.Kind = MMToken::StringLiteral;
634 Tok.StringData = Saved;
635 Tok.StringLength = Length;
636 break;
637 }
638
639 case tok::comment:
640 goto retry;
641
642 default:
643 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
644 HadError = true;
645 goto retry;
646 }
647
648 return Result;
649}
650
651void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
652 unsigned braceDepth = 0;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000653 unsigned squareDepth = 0;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000654 do {
655 switch (Tok.Kind) {
656 case MMToken::EndOfFile:
657 return;
658
659 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000660 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000661 return;
662
663 ++braceDepth;
664 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000665
666 case MMToken::LSquare:
667 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
668 return;
669
670 ++squareDepth;
671 break;
672
Douglas Gregora30cfe52011-11-11 19:10:28 +0000673 case MMToken::RBrace:
674 if (braceDepth > 0)
675 --braceDepth;
676 else if (Tok.is(K))
677 return;
678 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000679
680 case MMToken::RSquare:
681 if (squareDepth > 0)
682 --squareDepth;
683 else if (Tok.is(K))
684 return;
685 break;
686
Douglas Gregora30cfe52011-11-11 19:10:28 +0000687 default:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000688 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregora30cfe52011-11-11 19:10:28 +0000689 return;
690 break;
691 }
692
693 consumeToken();
694 } while (true);
695}
696
Douglas Gregor587986e2011-12-07 02:23:45 +0000697/// \brief Parse a module-id.
698///
699/// module-id:
700/// identifier
701/// identifier '.' module-id
702///
703/// \returns true if an error occurred, false otherwise.
704bool ModuleMapParser::parseModuleId(ModuleId &Id) {
705 Id.clear();
706 do {
707 if (Tok.is(MMToken::Identifier)) {
708 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
709 consumeToken();
710 } else {
711 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
712 return true;
713 }
714
715 if (!Tok.is(MMToken::Period))
716 break;
717
718 consumeToken();
719 } while (true);
720
721 return false;
722}
723
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000724namespace {
725 /// \brief Enumerates the known attributes.
726 enum AttributeKind {
727 /// \brief An unknown attribute.
728 AT_unknown,
729 /// \brief The 'system' attribute.
730 AT_system
731 };
732}
733
Douglas Gregora30cfe52011-11-11 19:10:28 +0000734/// \brief Parse a module declaration.
735///
736/// module-declaration:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000737/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
738/// { module-member* }
739///
740/// attributes:
741/// attribute attributes
742/// attribute
743///
744/// attribute:
745/// [ identifier ]
Douglas Gregora30cfe52011-11-11 19:10:28 +0000746///
747/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +0000748/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000749/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000750/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000751/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000752///
753/// submodule-declaration:
754/// module-declaration
755/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000756void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000757 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
758 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000759 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000760 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000761 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000762 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000763
Douglas Gregord620a842011-12-06 17:16:41 +0000764 // Parse 'explicit' keyword, if present.
765 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000766 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000767 Explicit = true;
768 }
769
770 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000771 if (Tok.is(MMToken::FrameworkKeyword)) {
772 consumeToken();
773 Framework = true;
774 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000775
776 // Parse 'module' keyword.
777 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000778 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000779 consumeToken();
780 HadError = true;
781 return;
782 }
783 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000784
785 // If we have a wildcard for the module name, this is an inferred submodule.
786 // Parse it.
787 if (Tok.is(MMToken::Star))
788 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000789
790 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000791 ModuleId Id;
792 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000793 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000794 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000795 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000796
797 if (ActiveModule) {
798 if (Id.size() > 1) {
799 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
800 << SourceRange(Id.front().second, Id.back().second);
801
802 HadError = true;
803 return;
804 }
805 } else if (Id.size() == 1 && Explicit) {
806 // Top-level modules can't be explicit.
807 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
808 Explicit = false;
809 ExplicitLoc = SourceLocation();
810 HadError = true;
811 }
812
813 Module *PreviousActiveModule = ActiveModule;
814 if (Id.size() > 1) {
815 // This module map defines a submodule. Go find the module of which it
816 // is a submodule.
817 ActiveModule = 0;
818 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
819 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
820 ActiveModule = Next;
821 continue;
822 }
823
824 if (ActiveModule) {
825 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
826 << Id[I].first << ActiveModule->getTopLevelModule();
827 } else {
828 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
829 }
830 HadError = true;
831 return;
832 }
833 }
834
835 StringRef ModuleName = Id.back().first;
836 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000837
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000838 // Parse the optional attribute list.
839 bool IsSystem = false;
840 while (Tok.is(MMToken::LSquare)) {
841 // Consume the '['.
842 SourceLocation LSquareLoc = consumeToken();
843
844 // Check whether we have an attribute name here.
845 if (!Tok.is(MMToken::Identifier)) {
846 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
847 skipUntil(MMToken::RSquare);
848 if (Tok.is(MMToken::RSquare))
849 consumeToken();
850 continue;
851 }
852
853 // Decode the attribute name.
854 AttributeKind Attribute
855 = llvm::StringSwitch<AttributeKind>(Tok.getString())
856 .Case("system", AT_system)
857 .Default(AT_unknown);
858 switch (Attribute) {
859 case AT_unknown:
860 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
861 << Tok.getString();
862 break;
863
864 case AT_system:
865 IsSystem = true;
866 break;
867 }
868 consumeToken();
869
870 // Consume the ']'.
871 if (!Tok.is(MMToken::RSquare)) {
872 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
873 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
874 skipUntil(MMToken::RSquare);
875 }
876
877 if (Tok.is(MMToken::RSquare))
878 consumeToken();
879 }
880
Douglas Gregora30cfe52011-11-11 19:10:28 +0000881 // Parse the opening brace.
882 if (!Tok.is(MMToken::LBrace)) {
883 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
884 << ModuleName;
885 HadError = true;
886 return;
887 }
888 SourceLocation LBraceLoc = consumeToken();
889
890 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000891 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +0000892 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
893 // Skip the module definition.
894 skipUntil(MMToken::RBrace);
895 if (Tok.is(MMToken::RBrace))
896 consumeToken();
897 else {
898 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
899 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
900 HadError = true;
901 }
902 return;
903 }
904
Douglas Gregora30cfe52011-11-11 19:10:28 +0000905 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
906 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000907 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000908
909 // Skip the module definition.
910 skipUntil(MMToken::RBrace);
911 if (Tok.is(MMToken::RBrace))
912 consumeToken();
913
914 HadError = true;
915 return;
916 }
917
918 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000919 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
920 Explicit).first;
921 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000922 if (IsSystem)
923 ActiveModule->IsSystem = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000924
925 bool Done = false;
926 do {
927 switch (Tok.Kind) {
928 case MMToken::EndOfFile:
929 case MMToken::RBrace:
930 Done = true;
931 break;
932
933 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000934 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000935 case MMToken::ModuleKeyword:
936 parseModuleDecl();
937 break;
938
Douglas Gregor90db2602011-12-02 01:47:07 +0000939 case MMToken::ExportKeyword:
940 parseExportDecl();
941 break;
942
Douglas Gregor51f564f2011-12-31 04:05:44 +0000943 case MMToken::RequiresKeyword:
944 parseRequiresDecl();
945 break;
946
Douglas Gregor77d029f2011-12-08 19:11:24 +0000947 case MMToken::UmbrellaKeyword: {
948 SourceLocation UmbrellaLoc = consumeToken();
949 if (Tok.is(MMToken::HeaderKeyword))
950 parseHeaderDecl(UmbrellaLoc);
951 else
952 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000953 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +0000954 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000955
Douglas Gregor489ad432011-12-08 18:00:48 +0000956 case MMToken::HeaderKeyword:
957 parseHeaderDecl(SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000958 break;
Douglas Gregor489ad432011-12-08 18:00:48 +0000959
Douglas Gregora30cfe52011-11-11 19:10:28 +0000960 default:
961 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
962 consumeToken();
963 break;
964 }
965 } while (!Done);
966
967 if (Tok.is(MMToken::RBrace))
968 consumeToken();
969 else {
970 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
971 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
972 HadError = true;
973 }
974
Douglas Gregor587986e2011-12-07 02:23:45 +0000975 // We're done parsing this module. Pop back to the previous module.
976 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000977}
Douglas Gregord620a842011-12-06 17:16:41 +0000978
Douglas Gregor51f564f2011-12-31 04:05:44 +0000979/// \brief Parse a requires declaration.
980///
981/// requires-declaration:
982/// 'requires' feature-list
983///
984/// feature-list:
985/// identifier ',' feature-list
986/// identifier
987void ModuleMapParser::parseRequiresDecl() {
988 assert(Tok.is(MMToken::RequiresKeyword));
989
990 // Parse 'requires' keyword.
991 consumeToken();
992
993 // Parse the feature-list.
994 do {
995 if (!Tok.is(MMToken::Identifier)) {
996 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
997 HadError = true;
998 return;
999 }
1000
1001 // Consume the feature name.
1002 std::string Feature = Tok.getString();
1003 consumeToken();
1004
1005 // Add this feature.
Douglas Gregordc58aa72012-01-30 06:01:29 +00001006 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor51f564f2011-12-31 04:05:44 +00001007
1008 if (!Tok.is(MMToken::Comma))
1009 break;
1010
1011 // Consume the comma.
1012 consumeToken();
1013 } while (true);
1014}
1015
Douglas Gregord620a842011-12-06 17:16:41 +00001016/// \brief Append to \p Paths the set of paths needed to get to the
1017/// subframework in which the given module lives.
1018void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) {
1019 // Collect the framework names from the given module to the top-level module.
1020 llvm::SmallVector<StringRef, 2> Paths;
1021 for (; Mod; Mod = Mod->Parent) {
1022 if (Mod->IsFramework)
1023 Paths.push_back(Mod->Name);
1024 }
1025
1026 if (Paths.empty())
1027 return;
1028
1029 // Add Frameworks/Name.framework for each subframework.
1030 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1031 llvm::sys::path::append(Path, "Frameworks");
1032 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1033 }
1034}
1035
Douglas Gregor2f04f182012-02-02 18:42:48 +00001036/// \brief Determine whether the given file name is the name of a builtin
1037/// header, supplied by Clang to replace, override, or augment existing system
1038/// headers.
1039static bool isBuiltinHeader(StringRef FileName) {
1040 return llvm::StringSwitch<bool>(FileName)
1041 .Case("float.h", true)
1042 .Case("iso646.h", true)
1043 .Case("limits.h", true)
1044 .Case("stdalign.h", true)
1045 .Case("stdarg.h", true)
1046 .Case("stdbool.h", true)
1047 .Case("stddef.h", true)
1048 .Case("stdint.h", true)
1049 .Case("tgmath.h", true)
1050 .Case("unwind.h", true)
1051 .Default(false);
1052}
1053
Douglas Gregora30cfe52011-11-11 19:10:28 +00001054/// \brief Parse a header declaration.
1055///
1056/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +00001057/// 'umbrella'[opt] 'header' string-literal
1058void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001059 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +00001060 consumeToken();
1061
Douglas Gregor489ad432011-12-08 18:00:48 +00001062 bool Umbrella = UmbrellaLoc.isValid();
1063
Douglas Gregora30cfe52011-11-11 19:10:28 +00001064 // Parse the header name.
1065 if (!Tok.is(MMToken::StringLiteral)) {
1066 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1067 << "header";
1068 HadError = true;
1069 return;
1070 }
Douglas Gregor587986e2011-12-07 02:23:45 +00001071 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +00001072 SourceLocation FileNameLoc = consumeToken();
1073
Douglas Gregor77d029f2011-12-08 19:11:24 +00001074 // Check whether we already have an umbrella.
1075 if (Umbrella && ActiveModule->Umbrella) {
1076 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1077 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001078 HadError = true;
1079 return;
1080 }
1081
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001082 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +00001083 const FileEntry *File = 0;
Douglas Gregor2f04f182012-02-02 18:42:48 +00001084 const FileEntry *BuiltinFile = 0;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001085 llvm::SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +00001086 if (llvm::sys::path::is_absolute(FileName)) {
1087 PathName = FileName;
1088 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +00001089 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1090 PathName = Dir->getName();
1091 llvm::sys::path::append(PathName, FileName);
1092 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001093 } else {
1094 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +00001095 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +00001096 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +00001097
Douglas Gregord620a842011-12-06 17:16:41 +00001098 if (ActiveModule->isPartOfFramework()) {
1099 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001100
1101 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +00001102 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +00001103 llvm::sys::path::append(PathName, FileName);
1104 File = SourceMgr.getFileManager().getFile(PathName);
1105
1106 if (!File) {
1107 // Check whether this file is in the private headers.
1108 PathName.resize(PathLength);
1109 llvm::sys::path::append(PathName, "PrivateHeaders");
1110 llvm::sys::path::append(PathName, FileName);
1111 File = SourceMgr.getFileManager().getFile(PathName);
1112 }
1113 } else {
1114 // Lookup for normal headers.
1115 llvm::sys::path::append(PathName, FileName);
1116 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001117
1118 // If this is a system module with a top-level header, this header
1119 // may have a counterpart (or replacement) in the set of headers
1120 // supplied by Clang. Find that builtin header.
1121 if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
1122 BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
1123 llvm::SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
1124 llvm::sys::path::append(BuiltinPathName, FileName);
1125 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1126
1127 // If Clang supplies this header but the underlying system does not,
1128 // just silently swap in our builtin version. Otherwise, we'll end
1129 // up adding both (later).
1130 if (!File && BuiltinFile) {
1131 File = BuiltinFile;
1132 BuiltinFile = 0;
1133 }
1134 }
Douglas Gregord620a842011-12-06 17:16:41 +00001135 }
Douglas Gregor18ee5472011-11-29 21:59:16 +00001136 }
Douglas Gregora8654052011-11-17 22:09:43 +00001137
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001138 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1139 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001140 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001141 if (const Module *OwningModule = Map.Headers[File]) {
1142 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
1143 << FileName << OwningModule->getFullModuleName();
1144 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +00001145 } else if (Umbrella) {
1146 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor489ad432011-12-08 18:00:48 +00001147 if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
1148 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1149 << OwningModule->getFullModuleName();
1150 HadError = true;
1151 } else {
1152 // Record this umbrella header.
1153 Map.setUmbrellaHeader(ActiveModule, File);
1154 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001155 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001156 // Record this header.
Douglas Gregore209e502011-12-06 01:10:29 +00001157 Map.addHeader(ActiveModule, File);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001158
1159 // If there is a builtin counterpart to this file, add it now.
1160 if (BuiltinFile)
1161 Map.addHeader(ActiveModule, BuiltinFile);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001162 }
1163 } else {
1164 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +00001165 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001166 HadError = true;
1167 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001168}
1169
Douglas Gregor77d029f2011-12-08 19:11:24 +00001170/// \brief Parse an umbrella directory declaration.
1171///
1172/// umbrella-dir-declaration:
1173/// umbrella string-literal
1174void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1175 // Parse the directory name.
1176 if (!Tok.is(MMToken::StringLiteral)) {
1177 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1178 << "umbrella";
1179 HadError = true;
1180 return;
1181 }
1182
1183 std::string DirName = Tok.getString();
1184 SourceLocation DirNameLoc = consumeToken();
1185
1186 // Check whether we already have an umbrella.
1187 if (ActiveModule->Umbrella) {
1188 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1189 << ActiveModule->getFullModuleName();
1190 HadError = true;
1191 return;
1192 }
1193
1194 // Look for this file.
1195 const DirectoryEntry *Dir = 0;
1196 if (llvm::sys::path::is_absolute(DirName))
1197 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1198 else {
1199 llvm::SmallString<128> PathName;
1200 PathName = Directory->getName();
1201 llvm::sys::path::append(PathName, DirName);
1202 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1203 }
1204
1205 if (!Dir) {
1206 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1207 << DirName;
1208 HadError = true;
1209 return;
1210 }
1211
1212 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1213 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1214 << OwningModule->getFullModuleName();
1215 HadError = true;
1216 return;
1217 }
1218
1219 // Record this umbrella directory.
1220 Map.setUmbrellaDir(ActiveModule, Dir);
1221}
1222
Douglas Gregor90db2602011-12-02 01:47:07 +00001223/// \brief Parse a module export declaration.
1224///
1225/// export-declaration:
1226/// 'export' wildcard-module-id
1227///
1228/// wildcard-module-id:
1229/// identifier
1230/// '*'
1231/// identifier '.' wildcard-module-id
1232void ModuleMapParser::parseExportDecl() {
1233 assert(Tok.is(MMToken::ExportKeyword));
1234 SourceLocation ExportLoc = consumeToken();
1235
1236 // Parse the module-id with an optional wildcard at the end.
1237 ModuleId ParsedModuleId;
1238 bool Wildcard = false;
1239 do {
1240 if (Tok.is(MMToken::Identifier)) {
1241 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1242 Tok.getLocation()));
1243 consumeToken();
1244
1245 if (Tok.is(MMToken::Period)) {
1246 consumeToken();
1247 continue;
1248 }
1249
1250 break;
1251 }
1252
1253 if(Tok.is(MMToken::Star)) {
1254 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001255 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001256 break;
1257 }
1258
1259 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1260 HadError = true;
1261 return;
1262 } while (true);
1263
1264 Module::UnresolvedExportDecl Unresolved = {
1265 ExportLoc, ParsedModuleId, Wildcard
1266 };
1267 ActiveModule->UnresolvedExports.push_back(Unresolved);
1268}
1269
Douglas Gregor1e123682011-12-05 22:27:44 +00001270void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1271 assert(Tok.is(MMToken::Star));
1272 SourceLocation StarLoc = consumeToken();
1273 bool Failed = false;
1274
1275 // Inferred modules must be submodules.
1276 if (!ActiveModule) {
1277 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1278 Failed = true;
1279 }
1280
Douglas Gregor77d029f2011-12-08 19:11:24 +00001281 // Inferred modules must have umbrella directories.
1282 if (!Failed && !ActiveModule->getUmbrellaDir()) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001283 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1284 Failed = true;
1285 }
1286
1287 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +00001288 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001289 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +00001290 if (ActiveModule->InferredSubmoduleLoc.isValid())
1291 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +00001292 diag::note_mmap_prev_definition);
1293 Failed = true;
1294 }
1295
1296 // If there were any problems with this inferred submodule, skip its body.
1297 if (Failed) {
1298 if (Tok.is(MMToken::LBrace)) {
1299 consumeToken();
1300 skipUntil(MMToken::RBrace);
1301 if (Tok.is(MMToken::RBrace))
1302 consumeToken();
1303 }
1304 HadError = true;
1305 return;
1306 }
1307
1308 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +00001309 ActiveModule->InferSubmodules = true;
1310 ActiveModule->InferredSubmoduleLoc = StarLoc;
1311 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +00001312
1313 // Parse the opening brace.
1314 if (!Tok.is(MMToken::LBrace)) {
1315 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1316 HadError = true;
1317 return;
1318 }
1319 SourceLocation LBraceLoc = consumeToken();
1320
1321 // Parse the body of the inferred submodule.
1322 bool Done = false;
1323 do {
1324 switch (Tok.Kind) {
1325 case MMToken::EndOfFile:
1326 case MMToken::RBrace:
1327 Done = true;
1328 break;
1329
1330 case MMToken::ExportKeyword: {
1331 consumeToken();
1332 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001333 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001334 else
1335 Diags.Report(Tok.getLocation(),
1336 diag::err_mmap_expected_export_wildcard);
1337 consumeToken();
1338 break;
1339 }
1340
1341 case MMToken::ExplicitKeyword:
1342 case MMToken::ModuleKeyword:
1343 case MMToken::HeaderKeyword:
1344 case MMToken::UmbrellaKeyword:
1345 default:
1346 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1347 consumeToken();
1348 break;
1349 }
1350 } while (!Done);
1351
1352 if (Tok.is(MMToken::RBrace))
1353 consumeToken();
1354 else {
1355 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1356 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1357 HadError = true;
1358 }
1359}
1360
Douglas Gregor6a1db482011-12-09 02:04:43 +00001361/// \brief If there is a specific header search directory due the presence
1362/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1363const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1364 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1365 // If we have an umbrella directory, use that.
1366 if (Mod->hasUmbrellaDir())
1367 return Mod->getUmbrellaDir();
1368
1369 // If we have a framework directory, stop looking.
1370 if (Mod->IsFramework)
1371 return 0;
1372 }
1373
1374 return 0;
1375}
1376
Douglas Gregora30cfe52011-11-11 19:10:28 +00001377/// \brief Parse a module map file.
1378///
1379/// module-map-file:
1380/// module-declaration*
1381bool ModuleMapParser::parseModuleMapFile() {
1382 do {
1383 switch (Tok.Kind) {
1384 case MMToken::EndOfFile:
1385 return HadError;
1386
Douglas Gregor587986e2011-12-07 02:23:45 +00001387 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001388 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001389 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001390 parseModuleDecl();
1391 break;
1392
Douglas Gregor51f564f2011-12-31 04:05:44 +00001393 case MMToken::Comma:
Douglas Gregor90db2602011-12-02 01:47:07 +00001394 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001395 case MMToken::HeaderKeyword:
1396 case MMToken::Identifier:
1397 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001398 case MMToken::LSquare:
Douglas Gregor90db2602011-12-02 01:47:07 +00001399 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001400 case MMToken::RBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001401 case MMToken::RSquare:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001402 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001403 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001404 case MMToken::StringLiteral:
1405 case MMToken::UmbrellaKeyword:
1406 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1407 HadError = true;
1408 consumeToken();
1409 break;
1410 }
1411 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001412}
1413
1414bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregordc58aa72012-01-30 06:01:29 +00001415 assert(Target != 0 && "Missing target information");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001416 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1417 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1418 if (!Buffer)
1419 return true;
1420
1421 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00001422 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1423 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001424 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir(),
1425 BuiltinIncludeDir);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001426 bool Result = Parser.parseModuleMapFile();
1427 Diags->getClient()->EndSourceFile();
1428
1429 return Result;
1430}