blob: 5c9a9b4fefbbc749ff43dc7445067a68f2cba551 [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"
Douglas Gregor98cfcbf2012-09-27 14:50:15 +000029#include <stdlib.h>
Douglas Gregora30cfe52011-11-11 19:10:28 +000030using namespace clang;
31
Douglas Gregor90db2602011-12-02 01:47:07 +000032Module::ExportDecl
33ModuleMap::resolveExport(Module *Mod,
34 const Module::UnresolvedExportDecl &Unresolved,
35 bool Complain) {
Douglas Gregor0adaa882011-12-05 17:28:06 +000036 // We may have just a wildcard.
37 if (Unresolved.Id.empty()) {
38 assert(Unresolved.Wildcard && "Invalid unresolved export");
39 return Module::ExportDecl(0, true);
40 }
41
Douglas Gregor90db2602011-12-02 01:47:07 +000042 // Find the starting module.
43 Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod);
44 if (!Context) {
45 if (Complain)
46 Diags->Report(Unresolved.Id[0].second,
47 diag::err_mmap_missing_module_unqualified)
48 << Unresolved.Id[0].first << Mod->getFullModuleName();
49
50 return Module::ExportDecl();
51 }
52
53 // Dig into the module path.
54 for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) {
55 Module *Sub = lookupModuleQualified(Unresolved.Id[I].first,
56 Context);
57 if (!Sub) {
58 if (Complain)
59 Diags->Report(Unresolved.Id[I].second,
60 diag::err_mmap_missing_module_qualified)
61 << Unresolved.Id[I].first << Context->getFullModuleName()
62 << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second);
63
64 return Module::ExportDecl();
65 }
66
67 Context = Sub;
68 }
69
70 return Module::ExportDecl(Context, Unresolved.Wildcard);
71}
72
Douglas Gregor51f564f2011-12-31 04:05:44 +000073ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC,
Douglas Gregordc58aa72012-01-30 06:01:29 +000074 const LangOptions &LangOpts, const TargetInfo *Target)
Douglas Gregor2f04f182012-02-02 18:42:48 +000075 : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0)
Douglas Gregor51f564f2011-12-31 04:05:44 +000076{
Dylan Noblesmithc93dc782012-02-20 14:00:23 +000077 IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
78 Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
Douglas Gregora30cfe52011-11-11 19:10:28 +000079 new DiagnosticsEngine(DiagIDs));
80 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
81 SourceMgr = new SourceManager(*Diags, FileMgr);
82}
83
84ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +000085 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
86 IEnd = Modules.end();
87 I != IEnd; ++I) {
88 delete I->getValue();
89 }
90
Douglas Gregora30cfe52011-11-11 19:10:28 +000091 delete SourceMgr;
92}
93
Douglas Gregordc58aa72012-01-30 06:01:29 +000094void ModuleMap::setTarget(const TargetInfo &Target) {
95 assert((!this->Target || this->Target == &Target) &&
96 "Improper target override");
97 this->Target = &Target;
98}
99
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000100Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000101 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
102 = Headers.find(File);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000103 if (Known != Headers.end()) {
104 // If a header corresponds to an unavailable module, don't report
105 // that it maps to anything.
106 if (!Known->second->isAvailable())
107 return 0;
108
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000109 return Known->second;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000110 }
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000111
Douglas Gregoradb97992011-11-16 23:02:25 +0000112 const DirectoryEntry *Dir = File->getDir();
Douglas Gregoradb97992011-11-16 23:02:25 +0000113 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
114 StringRef DirName = Dir->getName();
Douglas Gregore209e502011-12-06 01:10:29 +0000115
116 // Keep walking up the directory hierarchy, looking for a directory with
117 // an umbrella header.
118 do {
119 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
120 = UmbrellaDirs.find(Dir);
121 if (KnownDir != UmbrellaDirs.end()) {
122 Module *Result = KnownDir->second;
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000123
124 // Search up the module stack until we find a module with an umbrella
Douglas Gregor10694ce2011-12-08 17:39:04 +0000125 // directory.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000126 Module *UmbrellaModule = Result;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000127 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000128 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000129
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000130 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-12-06 01:10:29 +0000131 // Infer submodules for each of the directories we found between
132 // the directory of the umbrella header and the directory where
133 // the actual header is located.
Douglas Gregor23af6d52011-12-07 22:05:21 +0000134 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregore209e502011-12-06 01:10:29 +0000135
Douglas Gregor6a1db482011-12-09 02:04:43 +0000136 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregore209e502011-12-06 01:10:29 +0000137 // Find or create the module that corresponds to this directory name.
138 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
139 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000140 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000141
142 // Associate the module and the directory.
143 UmbrellaDirs[SkippedDirs[I-1]] = Result;
144
145 // If inferred submodules export everything they import, add a
146 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000147 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000148 Result->Exports.push_back(Module::ExportDecl(0, true));
149 }
150
151 // Infer a submodule with the same name as this header file.
152 StringRef Name = llvm::sys::path::stem(File->getName());
153 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000154 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000155
156 // If inferred submodules export everything they import, add a
157 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000158 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000159 Result->Exports.push_back(Module::ExportDecl(0, true));
160 } else {
161 // Record each of the directories we stepped through as being part of
162 // the module we found, since the umbrella header covers them all.
163 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
164 UmbrellaDirs[SkippedDirs[I]] = Result;
165 }
166
167 Headers[File] = Result;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000168
169 // If a header corresponds to an unavailable module, don't report
170 // that it maps to anything.
171 if (!Result->isAvailable())
172 return 0;
173
Douglas Gregore209e502011-12-06 01:10:29 +0000174 return Result;
175 }
176
177 SkippedDirs.push_back(Dir);
178
Douglas Gregoradb97992011-11-16 23:02:25 +0000179 // Retrieve our parent path.
180 DirName = llvm::sys::path::parent_path(DirName);
181 if (DirName.empty())
182 break;
183
184 // Resolve the parent path to a directory entry.
185 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000186 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000187
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000188 return 0;
189}
190
Douglas Gregor51f564f2011-12-31 04:05:44 +0000191bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
192 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
193 = Headers.find(Header);
194 if (Known != Headers.end())
195 return !Known->second->isAvailable();
196
197 const DirectoryEntry *Dir = Header->getDir();
198 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
199 StringRef DirName = Dir->getName();
200
201 // Keep walking up the directory hierarchy, looking for a directory with
202 // an umbrella header.
203 do {
204 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
205 = UmbrellaDirs.find(Dir);
206 if (KnownDir != UmbrellaDirs.end()) {
207 Module *Found = KnownDir->second;
208 if (!Found->isAvailable())
209 return true;
210
211 // Search up the module stack until we find a module with an umbrella
212 // directory.
213 Module *UmbrellaModule = Found;
214 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
215 UmbrellaModule = UmbrellaModule->Parent;
216
217 if (UmbrellaModule->InferSubmodules) {
218 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
219 // Find or create the module that corresponds to this directory name.
220 StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName());
221 Found = lookupModuleQualified(Name, Found);
222 if (!Found)
223 return false;
224 if (!Found->isAvailable())
225 return true;
226 }
227
228 // Infer a submodule with the same name as this header file.
229 StringRef Name = llvm::sys::path::stem(Header->getName());
230 Found = lookupModuleQualified(Name, Found);
231 if (!Found)
232 return false;
233 }
234
235 return !Found->isAvailable();
236 }
237
238 SkippedDirs.push_back(Dir);
239
240 // Retrieve our parent path.
241 DirName = llvm::sys::path::parent_path(DirName);
242 if (DirName.empty())
243 break;
244
245 // Resolve the parent path to a directory entry.
246 Dir = SourceMgr->getFileManager().getDirectory(DirName);
247 } while (Dir);
248
249 return false;
250}
251
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000252Module *ModuleMap::findModule(StringRef Name) {
Douglas Gregor484535e2011-11-11 23:20:24 +0000253 llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
254 if (Known != Modules.end())
255 return Known->getValue();
256
257 return 0;
258}
259
Douglas Gregor90db2602011-12-02 01:47:07 +0000260Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) {
261 for(; Context; Context = Context->Parent) {
262 if (Module *Sub = lookupModuleQualified(Name, Context))
263 return Sub;
264 }
265
266 return findModule(Name);
267}
268
269Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) {
270 if (!Context)
271 return findModule(Name);
272
Douglas Gregorb7a78192012-01-04 23:32:19 +0000273 return Context->findSubmodule(Name);
Douglas Gregor90db2602011-12-02 01:47:07 +0000274}
275
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000276std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000277ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
278 bool IsExplicit) {
279 // Try to find an existing module with this name.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000280 if (Module *Sub = lookupModuleQualified(Name, Parent))
281 return std::make_pair(Sub, false);
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000282
283 // Create a new module with this name.
284 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
285 IsExplicit);
Douglas Gregorb7a78192012-01-04 23:32:19 +0000286 if (!Parent)
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000287 Modules[Name] = Result;
288 return std::make_pair(Result, true);
289}
290
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000291Module *
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000292ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000293 const DirectoryEntry *FrameworkDir,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000294 bool IsSystem,
Douglas Gregorac252a32011-12-06 19:39:29 +0000295 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000296 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000297 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
298 return Mod;
299
300 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000301
302 // Look for an umbrella header.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000303 SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000304 llvm::sys::path::append(UmbrellaName, "Headers");
305 llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000306 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000307
308 // FIXME: If there's no umbrella header, we could probably scan the
309 // framework to load *everything*. But, it's not clear that this is a good
310 // idea.
311 if (!UmbrellaHeader)
312 return 0;
313
Douglas Gregorac252a32011-12-06 19:39:29 +0000314 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
315 /*IsFramework=*/true, /*IsExplicit=*/false);
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000316 if (IsSystem)
317 Result->IsSystem = IsSystem;
318
Douglas Gregorb7a78192012-01-04 23:32:19 +0000319 if (!Parent)
Douglas Gregorac252a32011-12-06 19:39:29 +0000320 Modules[ModuleName] = Result;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000321
Douglas Gregor489ad432011-12-08 18:00:48 +0000322 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000323 Result->Umbrella = UmbrellaHeader;
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000324 Headers[UmbrellaHeader] = Result;
Douglas Gregor3cee31e2011-12-12 23:55:05 +0000325 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000326
327 // export *
328 Result->Exports.push_back(Module::ExportDecl(0, true));
329
Douglas Gregore209e502011-12-06 01:10:29 +0000330 // module * { export * }
331 Result->InferSubmodules = true;
332 Result->InferExportWildcard = true;
333
Douglas Gregorac252a32011-12-06 19:39:29 +0000334 // Look for subframeworks.
335 llvm::error_code EC;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000336 SmallString<128> SubframeworksDirName
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000337 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000338 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000339 SmallString<128> SubframeworksDirNameNative;
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000340 llvm::sys::path::native(SubframeworksDirName.str(),
341 SubframeworksDirNameNative);
342 for (llvm::sys::fs::directory_iterator
343 Dir(SubframeworksDirNameNative.str(), EC), DirEnd;
Douglas Gregorac252a32011-12-06 19:39:29 +0000344 Dir != DirEnd && !EC; Dir.increment(EC)) {
345 if (!StringRef(Dir->path()).endswith(".framework"))
346 continue;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000347
Douglas Gregorac252a32011-12-06 19:39:29 +0000348 if (const DirectoryEntry *SubframeworkDir
349 = FileMgr.getDirectory(Dir->path())) {
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000350 // Note: as an egregious but useful hack, we use the real path here and
351 // check whether it is actually a subdirectory of the parent directory.
352 // This will not be the case if the 'subframework' is actually a symlink
353 // out to a top-level framework.
354#ifdef LLVM_ON_UNIX
355 char RealSubframeworkDirName[PATH_MAX];
356 if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) {
357 StringRef SubframeworkDirName = RealSubframeworkDirName;
358
359 bool FoundParent = false;
360 do {
361 // Get the parent directory name.
362 SubframeworkDirName
363 = llvm::sys::path::parent_path(SubframeworkDirName);
364 if (SubframeworkDirName.empty())
365 break;
366
367 if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
368 FoundParent = true;
369 break;
370 }
371 } while (true);
372
373 if (!FoundParent)
374 continue;
375 }
376#endif
377
Douglas Gregorac252a32011-12-06 19:39:29 +0000378 // FIXME: Do we want to warn about subframeworks without umbrella headers?
379 inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000380 IsSystem, Result);
Douglas Gregorac252a32011-12-06 19:39:29 +0000381 }
382 }
Douglas Gregor3a110f72012-01-13 16:54:27 +0000383
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000384 return Result;
385}
386
Douglas Gregore209e502011-12-06 01:10:29 +0000387void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
388 Headers[UmbrellaHeader] = Mod;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000389 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000390 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000391}
392
Douglas Gregor77d029f2011-12-08 19:11:24 +0000393void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
394 Mod->Umbrella = UmbrellaDir;
395 UmbrellaDirs[UmbrellaDir] = Mod;
396}
397
Douglas Gregore209e502011-12-06 01:10:29 +0000398void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
399 Mod->Headers.push_back(Header);
400 Headers[Header] = Mod;
401}
402
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000403const FileEntry *
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000404ModuleMap::getContainingModuleMapFile(Module *Module) {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000405 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
406 return 0;
407
408 return SourceMgr->getFileEntryForID(
409 SourceMgr->getFileID(Module->DefinitionLoc));
410}
411
Douglas Gregora30cfe52011-11-11 19:10:28 +0000412void ModuleMap::dump() {
413 llvm::errs() << "Modules:";
414 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
415 MEnd = Modules.end();
416 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000417 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000418
419 llvm::errs() << "Headers:";
420 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
421 H = Headers.begin(),
422 HEnd = Headers.end();
423 H != HEnd; ++H) {
424 llvm::errs() << " \"" << H->first->getName() << "\" -> "
425 << H->second->getFullModuleName() << "\n";
426 }
427}
428
Douglas Gregor90db2602011-12-02 01:47:07 +0000429bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
430 bool HadError = false;
431 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
432 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
433 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000434 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000435 Mod->Exports.push_back(Export);
436 else
437 HadError = true;
438 }
439 Mod->UnresolvedExports.clear();
440 return HadError;
441}
442
Douglas Gregor55988682011-12-05 16:33:54 +0000443Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
444 if (Loc.isInvalid())
445 return 0;
446
447 // Use the expansion location to determine which module we're in.
448 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
449 if (!ExpansionLoc.isFileID())
450 return 0;
451
452
453 const SourceManager &SrcMgr = Loc.getManager();
454 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor55988682011-12-05 16:33:54 +0000455
Douglas Gregor303aae92012-01-06 17:19:32 +0000456 while (const FileEntry *ExpansionFile
457 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
458 // Find the module that owns this header (if any).
459 if (Module *Mod = findModuleForHeader(ExpansionFile))
460 return Mod;
461
462 // No module owns this header, so look up the inclusion chain to see if
463 // any included header has an associated module.
464 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
465 if (IncludeLoc.isInvalid())
466 return 0;
467
468 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
469 }
470
471 return 0;
Douglas Gregor55988682011-12-05 16:33:54 +0000472}
473
Douglas Gregora30cfe52011-11-11 19:10:28 +0000474//----------------------------------------------------------------------------//
475// Module map file parser
476//----------------------------------------------------------------------------//
477
478namespace clang {
479 /// \brief A token in a module map file.
480 struct MMToken {
481 enum TokenKind {
Douglas Gregor51f564f2011-12-31 04:05:44 +0000482 Comma,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000483 EndOfFile,
484 HeaderKeyword,
485 Identifier,
486 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000487 ExportKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000488 FrameworkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000489 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000490 Period,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000491 UmbrellaKeyword,
Douglas Gregor51f564f2011-12-31 04:05:44 +0000492 RequiresKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000493 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000494 StringLiteral,
495 LBrace,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000496 RBrace,
497 LSquare,
498 RSquare
Douglas Gregora30cfe52011-11-11 19:10:28 +0000499 } Kind;
500
501 unsigned Location;
502 unsigned StringLength;
503 const char *StringData;
504
505 void clear() {
506 Kind = EndOfFile;
507 Location = 0;
508 StringLength = 0;
509 StringData = 0;
510 }
511
512 bool is(TokenKind K) const { return Kind == K; }
513
514 SourceLocation getLocation() const {
515 return SourceLocation::getFromRawEncoding(Location);
516 }
517
518 StringRef getString() const {
519 return StringRef(StringData, StringLength);
520 }
521 };
522
523 class ModuleMapParser {
524 Lexer &L;
525 SourceManager &SourceMgr;
526 DiagnosticsEngine &Diags;
527 ModuleMap &Map;
528
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000529 /// \brief The directory that this module map resides in.
530 const DirectoryEntry *Directory;
Douglas Gregor2f04f182012-02-02 18:42:48 +0000531
532 /// \brief The directory containing Clang-supplied headers.
533 const DirectoryEntry *BuiltinIncludeDir;
534
Douglas Gregora30cfe52011-11-11 19:10:28 +0000535 /// \brief Whether an error occurred.
536 bool HadError;
537
538 /// \brief Default target information, used only for string literal
539 /// parsing.
Benjamin Kramerc0b6dbe2012-03-29 14:07:03 +0000540 OwningPtr<TargetInfo> Target;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000541
542 /// \brief Stores string data for the various string literals referenced
543 /// during parsing.
544 llvm::BumpPtrAllocator StringData;
545
546 /// \brief The current token.
547 MMToken Tok;
548
549 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000550 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000551
552 /// \brief Consume the current token and return its location.
553 SourceLocation consumeToken();
554
555 /// \brief Skip tokens until we reach the a token with the given kind
556 /// (or the end of the file).
557 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000558
559 typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
560 ModuleId;
561 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000562 void parseModuleDecl();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000563 void parseRequiresDecl();
Douglas Gregor489ad432011-12-08 18:00:48 +0000564 void parseHeaderDecl(SourceLocation UmbrellaLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000565 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000566 void parseExportDecl();
Douglas Gregor1e123682011-12-05 22:27:44 +0000567 void parseInferredSubmoduleDecl(bool Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000568
Douglas Gregor6a1db482011-12-09 02:04:43 +0000569 const DirectoryEntry *getOverriddenHeaderSearchDir();
570
Douglas Gregora30cfe52011-11-11 19:10:28 +0000571 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000572 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
573 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000574 ModuleMap &Map,
Douglas Gregor2f04f182012-02-02 18:42:48 +0000575 const DirectoryEntry *Directory,
576 const DirectoryEntry *BuiltinIncludeDir)
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000577 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
Douglas Gregor2f04f182012-02-02 18:42:48 +0000578 Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
579 HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000580 {
581 TargetOptions TargetOpts;
582 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
Benjamin Kramerc0b6dbe2012-03-29 14:07:03 +0000583 Target.reset(TargetInfo::CreateTargetInfo(Diags, TargetOpts));
Douglas Gregora30cfe52011-11-11 19:10:28 +0000584
585 Tok.clear();
586 consumeToken();
587 }
588
589 bool parseModuleMapFile();
590 };
591}
592
593SourceLocation ModuleMapParser::consumeToken() {
594retry:
595 SourceLocation Result = Tok.getLocation();
596 Tok.clear();
597
598 Token LToken;
599 L.LexFromRawLexer(LToken);
600 Tok.Location = LToken.getLocation().getRawEncoding();
601 switch (LToken.getKind()) {
602 case tok::raw_identifier:
603 Tok.StringData = LToken.getRawIdentifierData();
604 Tok.StringLength = LToken.getLength();
605 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
606 .Case("header", MMToken::HeaderKeyword)
607 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000608 .Case("export", MMToken::ExportKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000609 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000610 .Case("module", MMToken::ModuleKeyword)
Douglas Gregor51f564f2011-12-31 04:05:44 +0000611 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000612 .Case("umbrella", MMToken::UmbrellaKeyword)
613 .Default(MMToken::Identifier);
614 break;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000615
616 case tok::comma:
617 Tok.Kind = MMToken::Comma;
618 break;
619
Douglas Gregora30cfe52011-11-11 19:10:28 +0000620 case tok::eof:
621 Tok.Kind = MMToken::EndOfFile;
622 break;
623
624 case tok::l_brace:
625 Tok.Kind = MMToken::LBrace;
626 break;
627
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000628 case tok::l_square:
629 Tok.Kind = MMToken::LSquare;
630 break;
631
Douglas Gregor90db2602011-12-02 01:47:07 +0000632 case tok::period:
633 Tok.Kind = MMToken::Period;
634 break;
635
Douglas Gregora30cfe52011-11-11 19:10:28 +0000636 case tok::r_brace:
637 Tok.Kind = MMToken::RBrace;
638 break;
639
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000640 case tok::r_square:
641 Tok.Kind = MMToken::RSquare;
642 break;
643
Douglas Gregor90db2602011-12-02 01:47:07 +0000644 case tok::star:
645 Tok.Kind = MMToken::Star;
646 break;
647
Douglas Gregora30cfe52011-11-11 19:10:28 +0000648 case tok::string_literal: {
Richard Smith99831e42012-03-06 03:21:47 +0000649 if (LToken.hasUDSuffix()) {
650 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
651 HadError = true;
652 goto retry;
653 }
654
Douglas Gregora30cfe52011-11-11 19:10:28 +0000655 // Parse the string literal.
656 LangOptions LangOpts;
657 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
658 if (StringLiteral.hadError)
659 goto retry;
660
661 // Copy the string literal into our string data allocator.
662 unsigned Length = StringLiteral.GetStringLength();
663 char *Saved = StringData.Allocate<char>(Length + 1);
664 memcpy(Saved, StringLiteral.GetString().data(), Length);
665 Saved[Length] = 0;
666
667 // Form the token.
668 Tok.Kind = MMToken::StringLiteral;
669 Tok.StringData = Saved;
670 Tok.StringLength = Length;
671 break;
672 }
673
674 case tok::comment:
675 goto retry;
676
677 default:
678 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
679 HadError = true;
680 goto retry;
681 }
682
683 return Result;
684}
685
686void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
687 unsigned braceDepth = 0;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000688 unsigned squareDepth = 0;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000689 do {
690 switch (Tok.Kind) {
691 case MMToken::EndOfFile:
692 return;
693
694 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000695 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000696 return;
697
698 ++braceDepth;
699 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000700
701 case MMToken::LSquare:
702 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
703 return;
704
705 ++squareDepth;
706 break;
707
Douglas Gregora30cfe52011-11-11 19:10:28 +0000708 case MMToken::RBrace:
709 if (braceDepth > 0)
710 --braceDepth;
711 else if (Tok.is(K))
712 return;
713 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000714
715 case MMToken::RSquare:
716 if (squareDepth > 0)
717 --squareDepth;
718 else if (Tok.is(K))
719 return;
720 break;
721
Douglas Gregora30cfe52011-11-11 19:10:28 +0000722 default:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000723 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregora30cfe52011-11-11 19:10:28 +0000724 return;
725 break;
726 }
727
728 consumeToken();
729 } while (true);
730}
731
Douglas Gregor587986e2011-12-07 02:23:45 +0000732/// \brief Parse a module-id.
733///
734/// module-id:
735/// identifier
736/// identifier '.' module-id
737///
738/// \returns true if an error occurred, false otherwise.
739bool ModuleMapParser::parseModuleId(ModuleId &Id) {
740 Id.clear();
741 do {
742 if (Tok.is(MMToken::Identifier)) {
743 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
744 consumeToken();
745 } else {
746 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
747 return true;
748 }
749
750 if (!Tok.is(MMToken::Period))
751 break;
752
753 consumeToken();
754 } while (true);
755
756 return false;
757}
758
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000759namespace {
760 /// \brief Enumerates the known attributes.
761 enum AttributeKind {
762 /// \brief An unknown attribute.
763 AT_unknown,
764 /// \brief The 'system' attribute.
765 AT_system
766 };
767}
768
Douglas Gregora30cfe52011-11-11 19:10:28 +0000769/// \brief Parse a module declaration.
770///
771/// module-declaration:
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000772/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
773/// { module-member* }
774///
775/// attributes:
776/// attribute attributes
777/// attribute
778///
779/// attribute:
780/// [ identifier ]
Douglas Gregora30cfe52011-11-11 19:10:28 +0000781///
782/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +0000783/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000784/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +0000785/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +0000786/// export-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +0000787///
788/// submodule-declaration:
789/// module-declaration
790/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +0000791void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +0000792 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
793 Tok.is(MMToken::FrameworkKeyword));
Douglas Gregord620a842011-12-06 17:16:41 +0000794 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +0000795 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000796 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +0000797 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +0000798
Douglas Gregord620a842011-12-06 17:16:41 +0000799 // Parse 'explicit' keyword, if present.
800 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +0000801 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +0000802 Explicit = true;
803 }
804
805 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +0000806 if (Tok.is(MMToken::FrameworkKeyword)) {
807 consumeToken();
808 Framework = true;
809 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000810
811 // Parse 'module' keyword.
812 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +0000813 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000814 consumeToken();
815 HadError = true;
816 return;
817 }
818 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +0000819
820 // If we have a wildcard for the module name, this is an inferred submodule.
821 // Parse it.
822 if (Tok.is(MMToken::Star))
823 return parseInferredSubmoduleDecl(Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000824
825 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +0000826 ModuleId Id;
827 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000828 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +0000829 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000830 }
Douglas Gregor587986e2011-12-07 02:23:45 +0000831
832 if (ActiveModule) {
833 if (Id.size() > 1) {
834 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
835 << SourceRange(Id.front().second, Id.back().second);
836
837 HadError = true;
838 return;
839 }
840 } else if (Id.size() == 1 && Explicit) {
841 // Top-level modules can't be explicit.
842 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
843 Explicit = false;
844 ExplicitLoc = SourceLocation();
845 HadError = true;
846 }
847
848 Module *PreviousActiveModule = ActiveModule;
849 if (Id.size() > 1) {
850 // This module map defines a submodule. Go find the module of which it
851 // is a submodule.
852 ActiveModule = 0;
853 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
854 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
855 ActiveModule = Next;
856 continue;
857 }
858
859 if (ActiveModule) {
860 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
861 << Id[I].first << ActiveModule->getTopLevelModule();
862 } else {
863 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
864 }
865 HadError = true;
866 return;
867 }
868 }
869
870 StringRef ModuleName = Id.back().first;
871 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000872
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000873 // Parse the optional attribute list.
874 bool IsSystem = false;
875 while (Tok.is(MMToken::LSquare)) {
876 // Consume the '['.
877 SourceLocation LSquareLoc = consumeToken();
878
879 // Check whether we have an attribute name here.
880 if (!Tok.is(MMToken::Identifier)) {
881 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
882 skipUntil(MMToken::RSquare);
883 if (Tok.is(MMToken::RSquare))
884 consumeToken();
885 continue;
886 }
887
888 // Decode the attribute name.
889 AttributeKind Attribute
890 = llvm::StringSwitch<AttributeKind>(Tok.getString())
891 .Case("system", AT_system)
892 .Default(AT_unknown);
893 switch (Attribute) {
894 case AT_unknown:
895 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
896 << Tok.getString();
897 break;
898
899 case AT_system:
900 IsSystem = true;
901 break;
902 }
903 consumeToken();
904
905 // Consume the ']'.
906 if (!Tok.is(MMToken::RSquare)) {
907 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
908 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
909 skipUntil(MMToken::RSquare);
910 }
911
912 if (Tok.is(MMToken::RSquare))
913 consumeToken();
914 }
915
Douglas Gregora30cfe52011-11-11 19:10:28 +0000916 // Parse the opening brace.
917 if (!Tok.is(MMToken::LBrace)) {
918 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
919 << ModuleName;
920 HadError = true;
921 return;
922 }
923 SourceLocation LBraceLoc = consumeToken();
924
925 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000926 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +0000927 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
928 // Skip the module definition.
929 skipUntil(MMToken::RBrace);
930 if (Tok.is(MMToken::RBrace))
931 consumeToken();
932 else {
933 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
934 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
935 HadError = true;
936 }
937 return;
938 }
939
Douglas Gregora30cfe52011-11-11 19:10:28 +0000940 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
941 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000942 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000943
944 // Skip the module definition.
945 skipUntil(MMToken::RBrace);
946 if (Tok.is(MMToken::RBrace))
947 consumeToken();
948
949 HadError = true;
950 return;
951 }
952
953 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000954 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
955 Explicit).first;
956 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000957 if (IsSystem)
958 ActiveModule->IsSystem = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000959
960 bool Done = false;
961 do {
962 switch (Tok.Kind) {
963 case MMToken::EndOfFile:
964 case MMToken::RBrace:
965 Done = true;
966 break;
967
968 case MMToken::ExplicitKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +0000969 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000970 case MMToken::ModuleKeyword:
971 parseModuleDecl();
972 break;
973
Douglas Gregor90db2602011-12-02 01:47:07 +0000974 case MMToken::ExportKeyword:
975 parseExportDecl();
976 break;
977
Douglas Gregor51f564f2011-12-31 04:05:44 +0000978 case MMToken::RequiresKeyword:
979 parseRequiresDecl();
980 break;
981
Douglas Gregor77d029f2011-12-08 19:11:24 +0000982 case MMToken::UmbrellaKeyword: {
983 SourceLocation UmbrellaLoc = consumeToken();
984 if (Tok.is(MMToken::HeaderKeyword))
985 parseHeaderDecl(UmbrellaLoc);
986 else
987 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000988 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +0000989 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000990
Douglas Gregor489ad432011-12-08 18:00:48 +0000991 case MMToken::HeaderKeyword:
992 parseHeaderDecl(SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000993 break;
Douglas Gregor489ad432011-12-08 18:00:48 +0000994
Douglas Gregora30cfe52011-11-11 19:10:28 +0000995 default:
996 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
997 consumeToken();
998 break;
999 }
1000 } while (!Done);
1001
1002 if (Tok.is(MMToken::RBrace))
1003 consumeToken();
1004 else {
1005 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1006 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1007 HadError = true;
1008 }
1009
Douglas Gregor587986e2011-12-07 02:23:45 +00001010 // We're done parsing this module. Pop back to the previous module.
1011 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001012}
Douglas Gregord620a842011-12-06 17:16:41 +00001013
Douglas Gregor51f564f2011-12-31 04:05:44 +00001014/// \brief Parse a requires declaration.
1015///
1016/// requires-declaration:
1017/// 'requires' feature-list
1018///
1019/// feature-list:
1020/// identifier ',' feature-list
1021/// identifier
1022void ModuleMapParser::parseRequiresDecl() {
1023 assert(Tok.is(MMToken::RequiresKeyword));
1024
1025 // Parse 'requires' keyword.
1026 consumeToken();
1027
1028 // Parse the feature-list.
1029 do {
1030 if (!Tok.is(MMToken::Identifier)) {
1031 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1032 HadError = true;
1033 return;
1034 }
1035
1036 // Consume the feature name.
1037 std::string Feature = Tok.getString();
1038 consumeToken();
1039
1040 // Add this feature.
Douglas Gregordc58aa72012-01-30 06:01:29 +00001041 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor51f564f2011-12-31 04:05:44 +00001042
1043 if (!Tok.is(MMToken::Comma))
1044 break;
1045
1046 // Consume the comma.
1047 consumeToken();
1048 } while (true);
1049}
1050
Douglas Gregord620a842011-12-06 17:16:41 +00001051/// \brief Append to \p Paths the set of paths needed to get to the
1052/// subframework in which the given module lives.
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001053static void appendSubframeworkPaths(Module *Mod,
1054 llvm::SmallVectorImpl<char> &Path) {
Douglas Gregord620a842011-12-06 17:16:41 +00001055 // Collect the framework names from the given module to the top-level module.
1056 llvm::SmallVector<StringRef, 2> Paths;
1057 for (; Mod; Mod = Mod->Parent) {
1058 if (Mod->IsFramework)
1059 Paths.push_back(Mod->Name);
1060 }
1061
1062 if (Paths.empty())
1063 return;
1064
1065 // Add Frameworks/Name.framework for each subframework.
1066 for (unsigned I = Paths.size() - 1; I != 0; --I) {
1067 llvm::sys::path::append(Path, "Frameworks");
1068 llvm::sys::path::append(Path, Paths[I-1] + ".framework");
1069 }
1070}
1071
Douglas Gregor2f04f182012-02-02 18:42:48 +00001072/// \brief Determine whether the given file name is the name of a builtin
1073/// header, supplied by Clang to replace, override, or augment existing system
1074/// headers.
1075static bool isBuiltinHeader(StringRef FileName) {
1076 return llvm::StringSwitch<bool>(FileName)
1077 .Case("float.h", true)
1078 .Case("iso646.h", true)
1079 .Case("limits.h", true)
1080 .Case("stdalign.h", true)
1081 .Case("stdarg.h", true)
1082 .Case("stdbool.h", true)
1083 .Case("stddef.h", true)
1084 .Case("stdint.h", true)
1085 .Case("tgmath.h", true)
1086 .Case("unwind.h", true)
1087 .Default(false);
1088}
1089
Douglas Gregora30cfe52011-11-11 19:10:28 +00001090/// \brief Parse a header declaration.
1091///
1092/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +00001093/// 'umbrella'[opt] 'header' string-literal
1094void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001095 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +00001096 consumeToken();
1097
Douglas Gregor489ad432011-12-08 18:00:48 +00001098 bool Umbrella = UmbrellaLoc.isValid();
1099
Douglas Gregora30cfe52011-11-11 19:10:28 +00001100 // Parse the header name.
1101 if (!Tok.is(MMToken::StringLiteral)) {
1102 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1103 << "header";
1104 HadError = true;
1105 return;
1106 }
Douglas Gregor587986e2011-12-07 02:23:45 +00001107 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +00001108 SourceLocation FileNameLoc = consumeToken();
1109
Douglas Gregor77d029f2011-12-08 19:11:24 +00001110 // Check whether we already have an umbrella.
1111 if (Umbrella && ActiveModule->Umbrella) {
1112 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1113 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001114 HadError = true;
1115 return;
1116 }
1117
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001118 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +00001119 const FileEntry *File = 0;
Douglas Gregor2f04f182012-02-02 18:42:48 +00001120 const FileEntry *BuiltinFile = 0;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001121 SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +00001122 if (llvm::sys::path::is_absolute(FileName)) {
1123 PathName = FileName;
1124 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +00001125 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1126 PathName = Dir->getName();
1127 llvm::sys::path::append(PathName, FileName);
1128 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001129 } else {
1130 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +00001131 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +00001132 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +00001133
Douglas Gregord620a842011-12-06 17:16:41 +00001134 if (ActiveModule->isPartOfFramework()) {
1135 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001136
1137 // Check whether this file is in the public headers.
Douglas Gregor18ee5472011-11-29 21:59:16 +00001138 llvm::sys::path::append(PathName, "Headers");
Douglas Gregor587986e2011-12-07 02:23:45 +00001139 llvm::sys::path::append(PathName, FileName);
1140 File = SourceMgr.getFileManager().getFile(PathName);
1141
1142 if (!File) {
1143 // Check whether this file is in the private headers.
1144 PathName.resize(PathLength);
1145 llvm::sys::path::append(PathName, "PrivateHeaders");
1146 llvm::sys::path::append(PathName, FileName);
1147 File = SourceMgr.getFileManager().getFile(PathName);
1148 }
1149 } else {
1150 // Lookup for normal headers.
1151 llvm::sys::path::append(PathName, FileName);
1152 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001153
1154 // If this is a system module with a top-level header, this header
1155 // may have a counterpart (or replacement) in the set of headers
1156 // supplied by Clang. Find that builtin header.
1157 if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
1158 BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001159 SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
Douglas Gregor2f04f182012-02-02 18:42:48 +00001160 llvm::sys::path::append(BuiltinPathName, FileName);
1161 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1162
1163 // If Clang supplies this header but the underlying system does not,
1164 // just silently swap in our builtin version. Otherwise, we'll end
1165 // up adding both (later).
1166 if (!File && BuiltinFile) {
1167 File = BuiltinFile;
1168 BuiltinFile = 0;
1169 }
1170 }
Douglas Gregord620a842011-12-06 17:16:41 +00001171 }
Douglas Gregor18ee5472011-11-29 21:59:16 +00001172 }
Douglas Gregora8654052011-11-17 22:09:43 +00001173
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001174 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1175 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001176 if (File) {
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001177 if (const Module *OwningModule = Map.Headers[File]) {
1178 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
1179 << FileName << OwningModule->getFullModuleName();
1180 HadError = true;
Douglas Gregor489ad432011-12-08 18:00:48 +00001181 } else if (Umbrella) {
1182 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor489ad432011-12-08 18:00:48 +00001183 if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
1184 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1185 << OwningModule->getFullModuleName();
1186 HadError = true;
1187 } else {
1188 // Record this umbrella header.
1189 Map.setUmbrellaHeader(ActiveModule, File);
1190 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001191 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001192 // Record this header.
Douglas Gregore209e502011-12-06 01:10:29 +00001193 Map.addHeader(ActiveModule, File);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001194
1195 // If there is a builtin counterpart to this file, add it now.
1196 if (BuiltinFile)
1197 Map.addHeader(ActiveModule, BuiltinFile);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001198 }
1199 } else {
1200 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Douglas Gregor77d029f2011-12-08 19:11:24 +00001201 << Umbrella << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001202 HadError = true;
1203 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001204}
1205
Douglas Gregor77d029f2011-12-08 19:11:24 +00001206/// \brief Parse an umbrella directory declaration.
1207///
1208/// umbrella-dir-declaration:
1209/// umbrella string-literal
1210void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1211 // Parse the directory name.
1212 if (!Tok.is(MMToken::StringLiteral)) {
1213 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1214 << "umbrella";
1215 HadError = true;
1216 return;
1217 }
1218
1219 std::string DirName = Tok.getString();
1220 SourceLocation DirNameLoc = consumeToken();
1221
1222 // Check whether we already have an umbrella.
1223 if (ActiveModule->Umbrella) {
1224 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1225 << ActiveModule->getFullModuleName();
1226 HadError = true;
1227 return;
1228 }
1229
1230 // Look for this file.
1231 const DirectoryEntry *Dir = 0;
1232 if (llvm::sys::path::is_absolute(DirName))
1233 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1234 else {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001235 SmallString<128> PathName;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001236 PathName = Directory->getName();
1237 llvm::sys::path::append(PathName, DirName);
1238 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1239 }
1240
1241 if (!Dir) {
1242 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1243 << DirName;
1244 HadError = true;
1245 return;
1246 }
1247
1248 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1249 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1250 << OwningModule->getFullModuleName();
1251 HadError = true;
1252 return;
1253 }
1254
1255 // Record this umbrella directory.
1256 Map.setUmbrellaDir(ActiveModule, Dir);
1257}
1258
Douglas Gregor90db2602011-12-02 01:47:07 +00001259/// \brief Parse a module export declaration.
1260///
1261/// export-declaration:
1262/// 'export' wildcard-module-id
1263///
1264/// wildcard-module-id:
1265/// identifier
1266/// '*'
1267/// identifier '.' wildcard-module-id
1268void ModuleMapParser::parseExportDecl() {
1269 assert(Tok.is(MMToken::ExportKeyword));
1270 SourceLocation ExportLoc = consumeToken();
1271
1272 // Parse the module-id with an optional wildcard at the end.
1273 ModuleId ParsedModuleId;
1274 bool Wildcard = false;
1275 do {
1276 if (Tok.is(MMToken::Identifier)) {
1277 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1278 Tok.getLocation()));
1279 consumeToken();
1280
1281 if (Tok.is(MMToken::Period)) {
1282 consumeToken();
1283 continue;
1284 }
1285
1286 break;
1287 }
1288
1289 if(Tok.is(MMToken::Star)) {
1290 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001291 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001292 break;
1293 }
1294
1295 Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id);
1296 HadError = true;
1297 return;
1298 } while (true);
1299
1300 Module::UnresolvedExportDecl Unresolved = {
1301 ExportLoc, ParsedModuleId, Wildcard
1302 };
1303 ActiveModule->UnresolvedExports.push_back(Unresolved);
1304}
1305
Douglas Gregor1e123682011-12-05 22:27:44 +00001306void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
1307 assert(Tok.is(MMToken::Star));
1308 SourceLocation StarLoc = consumeToken();
1309 bool Failed = false;
1310
1311 // Inferred modules must be submodules.
1312 if (!ActiveModule) {
1313 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1314 Failed = true;
1315 }
1316
Douglas Gregor77d029f2011-12-08 19:11:24 +00001317 // Inferred modules must have umbrella directories.
1318 if (!Failed && !ActiveModule->getUmbrellaDir()) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001319 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1320 Failed = true;
1321 }
1322
1323 // Check for redefinition of an inferred module.
Douglas Gregoref85b562011-12-06 17:34:58 +00001324 if (!Failed && ActiveModule->InferSubmodules) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001325 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
Douglas Gregoref85b562011-12-06 17:34:58 +00001326 if (ActiveModule->InferredSubmoduleLoc.isValid())
1327 Diags.Report(ActiveModule->InferredSubmoduleLoc,
Douglas Gregor1e123682011-12-05 22:27:44 +00001328 diag::note_mmap_prev_definition);
1329 Failed = true;
1330 }
1331
1332 // If there were any problems with this inferred submodule, skip its body.
1333 if (Failed) {
1334 if (Tok.is(MMToken::LBrace)) {
1335 consumeToken();
1336 skipUntil(MMToken::RBrace);
1337 if (Tok.is(MMToken::RBrace))
1338 consumeToken();
1339 }
1340 HadError = true;
1341 return;
1342 }
1343
1344 // Note that we have an inferred submodule.
Douglas Gregoref85b562011-12-06 17:34:58 +00001345 ActiveModule->InferSubmodules = true;
1346 ActiveModule->InferredSubmoduleLoc = StarLoc;
1347 ActiveModule->InferExplicitSubmodules = Explicit;
Douglas Gregor1e123682011-12-05 22:27:44 +00001348
1349 // Parse the opening brace.
1350 if (!Tok.is(MMToken::LBrace)) {
1351 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1352 HadError = true;
1353 return;
1354 }
1355 SourceLocation LBraceLoc = consumeToken();
1356
1357 // Parse the body of the inferred submodule.
1358 bool Done = false;
1359 do {
1360 switch (Tok.Kind) {
1361 case MMToken::EndOfFile:
1362 case MMToken::RBrace:
1363 Done = true;
1364 break;
1365
1366 case MMToken::ExportKeyword: {
1367 consumeToken();
1368 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001369 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001370 else
1371 Diags.Report(Tok.getLocation(),
1372 diag::err_mmap_expected_export_wildcard);
1373 consumeToken();
1374 break;
1375 }
1376
1377 case MMToken::ExplicitKeyword:
1378 case MMToken::ModuleKeyword:
1379 case MMToken::HeaderKeyword:
1380 case MMToken::UmbrellaKeyword:
1381 default:
1382 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member);
1383 consumeToken();
1384 break;
1385 }
1386 } while (!Done);
1387
1388 if (Tok.is(MMToken::RBrace))
1389 consumeToken();
1390 else {
1391 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1392 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1393 HadError = true;
1394 }
1395}
1396
Douglas Gregor6a1db482011-12-09 02:04:43 +00001397/// \brief If there is a specific header search directory due the presence
1398/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
1399const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
1400 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
1401 // If we have an umbrella directory, use that.
1402 if (Mod->hasUmbrellaDir())
1403 return Mod->getUmbrellaDir();
1404
1405 // If we have a framework directory, stop looking.
1406 if (Mod->IsFramework)
1407 return 0;
1408 }
1409
1410 return 0;
1411}
1412
Douglas Gregora30cfe52011-11-11 19:10:28 +00001413/// \brief Parse a module map file.
1414///
1415/// module-map-file:
1416/// module-declaration*
1417bool ModuleMapParser::parseModuleMapFile() {
1418 do {
1419 switch (Tok.Kind) {
1420 case MMToken::EndOfFile:
1421 return HadError;
1422
Douglas Gregor587986e2011-12-07 02:23:45 +00001423 case MMToken::ExplicitKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001424 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00001425 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001426 parseModuleDecl();
1427 break;
1428
Douglas Gregor51f564f2011-12-31 04:05:44 +00001429 case MMToken::Comma:
Douglas Gregor90db2602011-12-02 01:47:07 +00001430 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001431 case MMToken::HeaderKeyword:
1432 case MMToken::Identifier:
1433 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001434 case MMToken::LSquare:
Douglas Gregor90db2602011-12-02 01:47:07 +00001435 case MMToken::Period:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001436 case MMToken::RBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001437 case MMToken::RSquare:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001438 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00001439 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001440 case MMToken::StringLiteral:
1441 case MMToken::UmbrellaKeyword:
1442 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1443 HadError = true;
1444 consumeToken();
1445 break;
1446 }
1447 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001448}
1449
1450bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
Douglas Gregordc58aa72012-01-30 06:01:29 +00001451 assert(Target != 0 && "Missing target information");
Douglas Gregora30cfe52011-11-11 19:10:28 +00001452 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
1453 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
1454 if (!Buffer)
1455 return true;
1456
1457 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00001458 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
1459 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001460 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir(),
1461 BuiltinIncludeDir);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001462 bool Result = Parser.parseModuleMapFile();
1463 Diags->getClient()->EndSourceFile();
1464
1465 return Result;
1466}