blob: e6851afada51716799c97c3e4b6bb546f1cca928 [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{
Dylan Noblesmithc93dc782012-02-20 14:00:23 +000076 IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
77 Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
Douglas Gregora30cfe52011-11-11 19:10:28 +000078 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.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000302 SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000303 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;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000335 SmallString<128> SubframeworksDirName
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000336 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000337 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000338 SmallString<128> SubframeworksDirNameNative;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000339 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: {
Richard Smith99831e42012-03-06 03:21:47 +0000620 if (LToken.hasUDSuffix()) {
621 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
622 HadError = true;
623 goto retry;
624 }
625
Douglas Gregora30cfe52011-11-11 19:10:28 +0000626 // Parse the string literal.
627 LangOptions LangOpts;
628 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
629 if (StringLiteral.hadError)
630 goto retry;
631
632 // Copy the string literal into our string data allocator.
633 unsigned Length = StringLiteral.GetStringLength();
634 char *Saved = StringData.Allocate<char>(Length + 1);
635 memcpy(Saved, StringLiteral.GetString().data(), Length);
636 Saved[Length] = 0;
637
638 // Form the token.
639 Tok.Kind = MMToken::StringLiteral;
640 Tok.StringData = Saved;
641 Tok.StringLength = Length;
642 break;
643 }
644
645 case tok::comment:
646 goto retry;
647
648 default:
649 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
650 HadError = true;
651 goto retry;
652 }
653
654 return Result;
655}
656
657void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
658 unsigned braceDepth = 0;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000659 unsigned squareDepth = 0;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000660 do {
661 switch (Tok.Kind) {
662 case MMToken::EndOfFile:
663 return;
664
665 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000666 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000667 return;
668
669 ++braceDepth;
670 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000671
672 case MMToken::LSquare:
673 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
674 return;
675
676 ++squareDepth;
677 break;
678
Douglas Gregora30cfe52011-11-11 19:10:28 +0000679 case MMToken::RBrace:
680 if (braceDepth > 0)
681 --braceDepth;
682 else if (Tok.is(K))
683 return;
684 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000685
686 case MMToken::RSquare:
687 if (squareDepth > 0)
688 --squareDepth;
689 else if (Tok.is(K))
690 return;
691 break;
692
Douglas Gregora30cfe52011-11-11 19:10:28 +0000693 default:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000694 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregora30cfe52011-11-11 19:10:28 +0000695 return;
696 break;
697 }
698
699 consumeToken();
700 } while (true);
701}
702
Douglas Gregor587986e2011-12-07 02:23:45 +0000703/// \brief Parse a module-id.
704///
705/// module-id:
706/// identifier
707/// identifier '.' module-id
708///
709/// \returns true if an error occurred, false otherwise.
710bool ModuleMapParser::parseModuleId(ModuleId &Id) {
711 Id.clear();
712 do {
713 if (Tok.is(MMToken::Identifier)) {
714 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
715 consumeToken();
716 } else {
717 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
718 return true;
719 }
720
721 if (!Tok.is(MMToken::Period))
722 break;
723
724 consumeToken();
725 } while (true);
726
727 return false;
728}
729
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000730namespace {
731 /// \brief Enumerates the known attributes.
732 enum AttributeKind {
733 /// \brief An unknown attribute.
734 AT_unknown,
735 /// \brief The 'system' attribute.
736 AT_system
737 };
738}
739
Douglas Gregora30cfe52011-11-11 19:10:28 +0000740/// \brief Parse a module declaration.
741///
742/// module-declaration:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000743/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
744/// { module-member* }
745///
746/// attributes:
747/// attribute attributes
748/// attribute
749///
750/// attribute:
751/// [ identifier ]
Douglas Gregora30cfe52011-11-11 19:10:28 +0000752///
753/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +0000754/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000755/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000756/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000757/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000758///
759/// submodule-declaration:
760/// module-declaration
761/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000762void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000763 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
764 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000765 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000766 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000767 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000768 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000769
Douglas Gregord620a842011-12-06 17:16:41 +0000770 // Parse 'explicit' keyword, if present.
771 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000772 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000773 Explicit = true;
774 }
775
776 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000777 if (Tok.is(MMToken::FrameworkKeyword)) {
778 consumeToken();
779 Framework = true;
780 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000781
782 // Parse 'module' keyword.
783 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000784 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000785 consumeToken();
786 HadError = true;
787 return;
788 }
789 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000790
791 // If we have a wildcard for the module name, this is an inferred submodule.
792 // Parse it.
793 if (Tok.is(MMToken::Star))
794 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000795
796 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000797 ModuleId Id;
798 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000799 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000800 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000801 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000802
803 if (ActiveModule) {
804 if (Id.size() > 1) {
805 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
806 << SourceRange(Id.front().second, Id.back().second);
807
808 HadError = true;
809 return;
810 }
811 } else if (Id.size() == 1 && Explicit) {
812 // Top-level modules can't be explicit.
813 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
814 Explicit = false;
815 ExplicitLoc = SourceLocation();
816 HadError = true;
817 }
818
819 Module *PreviousActiveModule = ActiveModule;
820 if (Id.size() > 1) {
821 // This module map defines a submodule. Go find the module of which it
822 // is a submodule.
823 ActiveModule = 0;
824 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
825 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
826 ActiveModule = Next;
827 continue;
828 }
829
830 if (ActiveModule) {
831 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
832 << Id[I].first << ActiveModule->getTopLevelModule();
833 } else {
834 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
835 }
836 HadError = true;
837 return;
838 }
839 }
840
841 StringRef ModuleName = Id.back().first;
842 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000843
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000844 // Parse the optional attribute list.
845 bool IsSystem = false;
846 while (Tok.is(MMToken::LSquare)) {
847 // Consume the '['.
848 SourceLocation LSquareLoc = consumeToken();
849
850 // Check whether we have an attribute name here.
851 if (!Tok.is(MMToken::Identifier)) {
852 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
853 skipUntil(MMToken::RSquare);
854 if (Tok.is(MMToken::RSquare))
855 consumeToken();
856 continue;
857 }
858
859 // Decode the attribute name.
860 AttributeKind Attribute
861 = llvm::StringSwitch<AttributeKind>(Tok.getString())
862 .Case("system", AT_system)
863 .Default(AT_unknown);
864 switch (Attribute) {
865 case AT_unknown:
866 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
867 << Tok.getString();
868 break;
869
870 case AT_system:
871 IsSystem = true;
872 break;
873 }
874 consumeToken();
875
876 // Consume the ']'.
877 if (!Tok.is(MMToken::RSquare)) {
878 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
879 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
880 skipUntil(MMToken::RSquare);
881 }
882
883 if (Tok.is(MMToken::RSquare))
884 consumeToken();
885 }
886
Douglas Gregora30cfe52011-11-11 19:10:28 +0000887 // Parse the opening brace.
888 if (!Tok.is(MMToken::LBrace)) {
889 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
890 << ModuleName;
891 HadError = true;
892 return;
893 }
894 SourceLocation LBraceLoc = consumeToken();
895
896 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000897 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +0000898 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
899 // Skip the module definition.
900 skipUntil(MMToken::RBrace);
901 if (Tok.is(MMToken::RBrace))
902 consumeToken();
903 else {
904 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
905 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
906 HadError = true;
907 }
908 return;
909 }
910
Douglas Gregora30cfe52011-11-11 19:10:28 +0000911 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
912 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000913 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000914
915 // Skip the module definition.
916 skipUntil(MMToken::RBrace);
917 if (Tok.is(MMToken::RBrace))
918 consumeToken();
919
920 HadError = true;
921 return;
922 }
923
924 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000925 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
926 Explicit).first;
927 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000928 if (IsSystem)
929 ActiveModule->IsSystem = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000930
931 bool Done = false;
932 do {
933 switch (Tok.Kind) {
934 case MMToken::EndOfFile:
935 case MMToken::RBrace:
936 Done = true;
937 break;
938
939 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000940 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000941 case MMToken::ModuleKeyword:
942 parseModuleDecl();
943 break;
944
Douglas Gregor90db2602011-12-02 01:47:07 +0000945 case MMToken::ExportKeyword:
946 parseExportDecl();
947 break;
948
Douglas Gregor51f564f2011-12-31 04:05:44 +0000949 case MMToken::RequiresKeyword:
950 parseRequiresDecl();
951 break;
952
Douglas Gregor77d029f2011-12-08 19:11:24 +0000953 case MMToken::UmbrellaKeyword: {
954 SourceLocation UmbrellaLoc = consumeToken();
955 if (Tok.is(MMToken::HeaderKeyword))
956 parseHeaderDecl(UmbrellaLoc);
957 else
958 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000959 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +0000960 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000961
Douglas Gregor489ad432011-12-08 18:00:48 +0000962 case MMToken::HeaderKeyword:
963 parseHeaderDecl(SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000964 break;
Douglas Gregor489ad432011-12-08 18:00:48 +0000965
Douglas Gregora30cfe52011-11-11 19:10:28 +0000966 default:
967 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
968 consumeToken();
969 break;
970 }
971 } while (!Done);
972
973 if (Tok.is(MMToken::RBrace))
974 consumeToken();
975 else {
976 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
977 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
978 HadError = true;
979 }
980
Douglas Gregor587986e2011-12-07 02:23:45 +0000981 // We're done parsing this module. Pop back to the previous module.
982 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000983}
Douglas Gregord620a842011-12-06 17:16:41 +0000984
Douglas Gregor51f564f2011-12-31 04:05:44 +0000985/// \brief Parse a requires declaration.
986///
987/// requires-declaration:
988/// 'requires' feature-list
989///
990/// feature-list:
991/// identifier ',' feature-list
992/// identifier
993void ModuleMapParser::parseRequiresDecl() {
994 assert(Tok.is(MMToken::RequiresKeyword));
995
996 // Parse 'requires' keyword.
997 consumeToken();
998
999 // Parse the feature-list.
1000 do {
1001 if (!Tok.is(MMToken::Identifier)) {
1002 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1003 HadError = true;
1004 return;
1005 }
1006
1007 // Consume the feature name.
1008 std::string Feature = Tok.getString();
1009 consumeToken();
1010
1011 // Add this feature.
Douglas Gregordc58aa72012-01-30 06:01:29 +00001012 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor51f564f2011-12-31 04:05:44 +00001013
1014 if (!Tok.is(MMToken::Comma))
1015 break;
1016
1017 // Consume the comma.
1018 consumeToken();
1019 } while (true);
1020}
1021
Douglas Gregord620a842011-12-06 17:16:41 +00001022/// \brief Append to \p Paths the set of paths needed to get to the
1023/// subframework in which the given module lives.
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001024static void appendSubframeworkPaths(Module *Mod,
1025 llvm::SmallVectorImpl<char> &Path) {
Douglas Gregord620a842011-12-06 17:16:41 +00001026 // Collect the framework names from the given module to the top-level module.
1027 llvm::SmallVector<StringRef, 2> Paths;
1028 for (; Mod; Mod = Mod->Parent) {
1029 if (Mod->IsFramework)
1030 Paths.push_back(Mod->Name);
1031 }
1032
1033 if (Paths.empty())
1034 return;
1035
1036 // Add Frameworks/Name.framework for each subframework.
1037 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1038 llvm::sys::path::append(Path, "Frameworks");
1039 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1040 }
1041}
1042
Douglas Gregor2f04f182012-02-02 18:42:48 +00001043/// \brief Determine whether the given file name is the name of a builtin
1044/// header, supplied by Clang to replace, override, or augment existing system
1045/// headers.
1046static bool isBuiltinHeader(StringRef FileName) {
1047 return llvm::StringSwitch<bool>(FileName)
1048 .Case("float.h", true)
1049 .Case("iso646.h", true)
1050 .Case("limits.h", true)
1051 .Case("stdalign.h", true)
1052 .Case("stdarg.h", true)
1053 .Case("stdbool.h", true)
1054 .Case("stddef.h", true)
1055 .Case("stdint.h", true)
1056 .Case("tgmath.h", true)
1057 .Case("unwind.h", true)
1058 .Default(false);
1059}
1060
Douglas Gregora30cfe52011-11-11 19:10:28 +00001061/// \brief Parse a header declaration.
1062///
1063/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +00001064/// 'umbrella'[opt] 'header' string-literal
1065void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001066 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +00001067 consumeToken();
1068
Douglas Gregor489ad432011-12-08 18:00:48 +00001069 bool Umbrella = UmbrellaLoc.isValid();
1070
Douglas Gregora30cfe52011-11-11 19:10:28 +00001071 // Parse the header name.
1072 if (!Tok.is(MMToken::StringLiteral)) {
1073 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1074 << "header";
1075 HadError = true;
1076 return;
1077 }
Douglas Gregor587986e2011-12-07 02:23:45 +00001078 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +00001079 SourceLocation FileNameLoc = consumeToken();
1080
Douglas Gregor77d029f2011-12-08 19:11:24 +00001081 // Check whether we already have an umbrella.
1082 if (Umbrella && ActiveModule->Umbrella) {
1083 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1084 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001085 HadError = true;
1086 return;
1087 }
1088
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001089 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +00001090 const FileEntry *File = 0;
Douglas Gregor2f04f182012-02-02 18:42:48 +00001091 const FileEntry *BuiltinFile = 0;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001092 SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +00001093 if (llvm::sys::path::is_absolute(FileName)) {
1094 PathName = FileName;
1095 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +00001096 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1097 PathName = Dir->getName();
1098 llvm::sys::path::append(PathName, FileName);
1099 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001100 } else {
1101 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +00001102 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +00001103 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +00001104
Douglas Gregord620a842011-12-06 17:16:41 +00001105 if (ActiveModule->isPartOfFramework()) {
1106 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001107
1108 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +00001109 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +00001110 llvm::sys::path::append(PathName, FileName);
1111 File = SourceMgr.getFileManager().getFile(PathName);
1112
1113 if (!File) {
1114 // Check whether this file is in the private headers.
1115 PathName.resize(PathLength);
1116 llvm::sys::path::append(PathName, "PrivateHeaders");
1117 llvm::sys::path::append(PathName, FileName);
1118 File = SourceMgr.getFileManager().getFile(PathName);
1119 }
1120 } else {
1121 // Lookup for normal headers.
1122 llvm::sys::path::append(PathName, FileName);
1123 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001124
1125 // If this is a system module with a top-level header, this header
1126 // may have a counterpart (or replacement) in the set of headers
1127 // supplied by Clang. Find that builtin header.
1128 if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
1129 BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001130 SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
Douglas Gregor2f04f182012-02-02 18:42:48 +00001131 llvm::sys::path::append(BuiltinPathName, FileName);
1132 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1133
1134 // If Clang supplies this header but the underlying system does not,
1135 // just silently swap in our builtin version. Otherwise, we'll end
1136 // up adding both (later).
1137 if (!File && BuiltinFile) {
1138 File = BuiltinFile;
1139 BuiltinFile = 0;
1140 }
1141 }
Douglas Gregord620a842011-12-06 17:16:41 +00001142 }
Douglas Gregor18ee5472011-11-29 21:59:16 +00001143 }
Douglas Gregora8654052011-11-17 22:09:43 +00001144
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001145 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1146 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001147 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001148 if (const Module *OwningModule = Map.Headers[File]) {
1149 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
1150 << FileName << OwningModule->getFullModuleName();
1151 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +00001152 } else if (Umbrella) {
1153 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor489ad432011-12-08 18:00:48 +00001154 if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
1155 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1156 << OwningModule->getFullModuleName();
1157 HadError = true;
1158 } else {
1159 // Record this umbrella header.
1160 Map.setUmbrellaHeader(ActiveModule, File);
1161 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001162 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001163 // Record this header.
Douglas Gregore209e502011-12-06 01:10:29 +00001164 Map.addHeader(ActiveModule, File);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001165
1166 // If there is a builtin counterpart to this file, add it now.
1167 if (BuiltinFile)
1168 Map.addHeader(ActiveModule, BuiltinFile);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001169 }
1170 } else {
1171 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +00001172 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001173 HadError = true;
1174 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001175}
1176
Douglas Gregor77d029f2011-12-08 19:11:24 +00001177/// \brief Parse an umbrella directory declaration.
1178///
1179/// umbrella-dir-declaration:
1180/// umbrella string-literal
1181void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1182 // Parse the directory name.
1183 if (!Tok.is(MMToken::StringLiteral)) {
1184 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1185 << "umbrella";
1186 HadError = true;
1187 return;
1188 }
1189
1190 std::string DirName = Tok.getString();
1191 SourceLocation DirNameLoc = consumeToken();
1192
1193 // Check whether we already have an umbrella.
1194 if (ActiveModule->Umbrella) {
1195 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1196 << ActiveModule->getFullModuleName();
1197 HadError = true;
1198 return;
1199 }
1200
1201 // Look for this file.
1202 const DirectoryEntry *Dir = 0;
1203 if (llvm::sys::path::is_absolute(DirName))
1204 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1205 else {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001206 SmallString<128> PathName;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001207 PathName = Directory->getName();
1208 llvm::sys::path::append(PathName, DirName);
1209 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1210 }
1211
1212 if (!Dir) {
1213 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1214 << DirName;
1215 HadError = true;
1216 return;
1217 }
1218
1219 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1220 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1221 << OwningModule->getFullModuleName();
1222 HadError = true;
1223 return;
1224 }
1225
1226 // Record this umbrella directory.
1227 Map.setUmbrellaDir(ActiveModule, Dir);
1228}
1229
Douglas Gregor90db2602011-12-02 01:47:07 +00001230/// \brief Parse a module export declaration.
1231///
1232/// export-declaration:
1233/// 'export' wildcard-module-id
1234///
1235/// wildcard-module-id:
1236/// identifier
1237/// '*'
1238/// identifier '.' wildcard-module-id
1239void ModuleMapParser::parseExportDecl() {
1240 assert(Tok.is(MMToken::ExportKeyword));
1241 SourceLocation ExportLoc = consumeToken();
1242
1243 // Parse the module-id with an optional wildcard at the end.
1244 ModuleId ParsedModuleId;
1245 bool Wildcard = false;
1246 do {
1247 if (Tok.is(MMToken::Identifier)) {
1248 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1249 Tok.getLocation()));
1250 consumeToken();
1251
1252 if (Tok.is(MMToken::Period)) {
1253 consumeToken();
1254 continue;
1255 }
1256
1257 break;
1258 }
1259
1260 if(Tok.is(MMToken::Star)) {
1261 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001262 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001263 break;
1264 }
1265
1266 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1267 HadError = true;
1268 return;
1269 } while (true);
1270
1271 Module::UnresolvedExportDecl Unresolved = {
1272 ExportLoc, ParsedModuleId, Wildcard
1273 };
1274 ActiveModule->UnresolvedExports.push_back(Unresolved);
1275}
1276
Douglas Gregor1e123682011-12-05 22:27:44 +00001277void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1278 assert(Tok.is(MMToken::Star));
1279 SourceLocation StarLoc = consumeToken();
1280 bool Failed = false;
1281
1282 // Inferred modules must be submodules.
1283 if (!ActiveModule) {
1284 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1285 Failed = true;
1286 }
1287
Douglas Gregor77d029f2011-12-08 19:11:24 +00001288 // Inferred modules must have umbrella directories.
1289 if (!Failed && !ActiveModule->getUmbrellaDir()) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001290 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1291 Failed = true;
1292 }
1293
1294 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +00001295 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001296 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +00001297 if (ActiveModule->InferredSubmoduleLoc.isValid())
1298 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +00001299 diag::note_mmap_prev_definition);
1300 Failed = true;
1301 }
1302
1303 // If there were any problems with this inferred submodule, skip its body.
1304 if (Failed) {
1305 if (Tok.is(MMToken::LBrace)) {
1306 consumeToken();
1307 skipUntil(MMToken::RBrace);
1308 if (Tok.is(MMToken::RBrace))
1309 consumeToken();
1310 }
1311 HadError = true;
1312 return;
1313 }
1314
1315 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +00001316 ActiveModule->InferSubmodules = true;
1317 ActiveModule->InferredSubmoduleLoc = StarLoc;
1318 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +00001319
1320 // Parse the opening brace.
1321 if (!Tok.is(MMToken::LBrace)) {
1322 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1323 HadError = true;
1324 return;
1325 }
1326 SourceLocation LBraceLoc = consumeToken();
1327
1328 // Parse the body of the inferred submodule.
1329 bool Done = false;
1330 do {
1331 switch (Tok.Kind) {
1332 case MMToken::EndOfFile:
1333 case MMToken::RBrace:
1334 Done = true;
1335 break;
1336
1337 case MMToken::ExportKeyword: {
1338 consumeToken();
1339 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001340 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001341 else
1342 Diags.Report(Tok.getLocation(),
1343 diag::err_mmap_expected_export_wildcard);
1344 consumeToken();
1345 break;
1346 }
1347
1348 case MMToken::ExplicitKeyword:
1349 case MMToken::ModuleKeyword:
1350 case MMToken::HeaderKeyword:
1351 case MMToken::UmbrellaKeyword:
1352 default:
1353 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1354 consumeToken();
1355 break;
1356 }
1357 } while (!Done);
1358
1359 if (Tok.is(MMToken::RBrace))
1360 consumeToken();
1361 else {
1362 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1363 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1364 HadError = true;
1365 }
1366}
1367
Douglas Gregor6a1db482011-12-09 02:04:43 +00001368/// \brief If there is a specific header search directory due the presence
1369/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1370const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1371 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1372 // If we have an umbrella directory, use that.
1373 if (Mod->hasUmbrellaDir())
1374 return Mod->getUmbrellaDir();
1375
1376 // If we have a framework directory, stop looking.
1377 if (Mod->IsFramework)
1378 return 0;
1379 }
1380
1381 return 0;
1382}
1383
Douglas Gregora30cfe52011-11-11 19:10:28 +00001384/// \brief Parse a module map file.
1385///
1386/// module-map-file:
1387/// module-declaration*
1388bool ModuleMapParser::parseModuleMapFile() {
1389 do {
1390 switch (Tok.Kind) {
1391 case MMToken::EndOfFile:
1392 return HadError;
1393
Douglas Gregor587986e2011-12-07 02:23:45 +00001394 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001395 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001396 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001397 parseModuleDecl();
1398 break;
1399
Douglas Gregor51f564f2011-12-31 04:05:44 +00001400 case MMToken::Comma:
Douglas Gregor90db2602011-12-02 01:47:07 +00001401 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001402 case MMToken::HeaderKeyword:
1403 case MMToken::Identifier:
1404 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001405 case MMToken::LSquare:
Douglas Gregor90db2602011-12-02 01:47:07 +00001406 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001407 case MMToken::RBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001408 case MMToken::RSquare:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001409 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001410 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001411 case MMToken::StringLiteral:
1412 case MMToken::UmbrellaKeyword:
1413 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1414 HadError = true;
1415 consumeToken();
1416 break;
1417 }
1418 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001419}
1420
1421bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregordc58aa72012-01-30 06:01:29 +00001422 assert(Target != 0 && "Missing target information");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001423 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1424 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1425 if (!Buffer)
1426 return true;
1427
1428 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00001429 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1430 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001431 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir(),
1432 BuiltinIncludeDir);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001433 bool Result = Parser.parseModuleMapFile();
1434 Diags->getClient()->EndSourceFile();
1435
1436 return Result;
1437}