blob: 25d68ace0f199871a262a5ad03ec4f477bc5b2b7 [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"
Jordan Rose3f6f51e2013-02-08 22:30:41 +000015#include "clang/Basic/CharInfo.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000016#include "clang/Basic/Diagnostic.h"
Douglas Gregor02c23eb2012-10-23 22:26:28 +000017#include "clang/Basic/DiagnosticOptions.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000018#include "clang/Basic/FileManager.h"
19#include "clang/Basic/TargetInfo.h"
20#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +000021#include "clang/Lex/HeaderSearch.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000022#include "clang/Lex/LexDiagnostic.h"
23#include "clang/Lex/Lexer.h"
24#include "clang/Lex/LiteralSupport.h"
25#include "llvm/ADT/StringRef.h"
26#include "llvm/ADT/StringSwitch.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000027#include "llvm/Support/Allocator.h"
Douglas Gregorac252a32011-12-06 19:39:29 +000028#include "llvm/Support/FileSystem.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000029#include "llvm/Support/Host.h"
Rafael Espindola8229d222013-06-11 22:15:02 +000030#include "llvm/Support/Path.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000031#include "llvm/Support/raw_ostream.h"
Douglas Gregor98cfcbf2012-09-27 14:50:15 +000032#include <stdlib.h>
Douglas Gregor3cc62772013-01-22 23:49:45 +000033#if defined(LLVM_ON_UNIX)
Dmitri Gribenkoadeb7822013-01-26 16:29:36 +000034#include <limits.h>
Douglas Gregor3cc62772013-01-22 23:49:45 +000035#endif
Douglas Gregora30cfe52011-11-11 19:10:28 +000036using namespace clang;
37
Douglas Gregor90db2602011-12-02 01:47:07 +000038Module::ExportDecl
39ModuleMap::resolveExport(Module *Mod,
40 const Module::UnresolvedExportDecl &Unresolved,
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +000041 bool Complain) const {
Douglas Gregor0adaa882011-12-05 17:28:06 +000042 // We may have just a wildcard.
43 if (Unresolved.Id.empty()) {
44 assert(Unresolved.Wildcard && "Invalid unresolved export");
45 return Module::ExportDecl(0, true);
46 }
47
Douglas Gregor906d66a2013-03-20 21:10:35 +000048 // Resolve the module-id.
49 Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
50 if (!Context)
51 return Module::ExportDecl();
52
53 return Module::ExportDecl(Context, Unresolved.Wildcard);
54}
55
56Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
57 bool Complain) const {
Douglas Gregor90db2602011-12-02 01:47:07 +000058 // Find the starting module.
Douglas Gregor906d66a2013-03-20 21:10:35 +000059 Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
Douglas Gregor90db2602011-12-02 01:47:07 +000060 if (!Context) {
61 if (Complain)
Douglas Gregor906d66a2013-03-20 21:10:35 +000062 Diags->Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
63 << Id[0].first << Mod->getFullModuleName();
64
65 return 0;
Douglas Gregor90db2602011-12-02 01:47:07 +000066 }
67
68 // Dig into the module path.
Douglas Gregor906d66a2013-03-20 21:10:35 +000069 for (unsigned I = 1, N = Id.size(); I != N; ++I) {
70 Module *Sub = lookupModuleQualified(Id[I].first, Context);
Douglas Gregor90db2602011-12-02 01:47:07 +000071 if (!Sub) {
72 if (Complain)
Douglas Gregor906d66a2013-03-20 21:10:35 +000073 Diags->Report(Id[I].second, diag::err_mmap_missing_module_qualified)
74 << Id[I].first << Context->getFullModuleName()
75 << SourceRange(Id[0].second, Id[I-1].second);
76
77 return 0;
Douglas Gregor90db2602011-12-02 01:47:07 +000078 }
Douglas Gregor906d66a2013-03-20 21:10:35 +000079
Douglas Gregor90db2602011-12-02 01:47:07 +000080 Context = Sub;
81 }
Douglas Gregor906d66a2013-03-20 21:10:35 +000082
83 return Context;
Douglas Gregor90db2602011-12-02 01:47:07 +000084}
85
Douglas Gregora4a90ca2013-05-03 22:58:43 +000086ModuleMap::ModuleMap(FileManager &FileMgr, DiagnosticConsumer &DC,
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +000087 const LangOptions &LangOpts, const TargetInfo *Target,
88 HeaderSearch &HeaderInfo)
89 : LangOpts(LangOpts), Target(Target), HeaderInfo(HeaderInfo),
Daniel Jasper733bac22013-09-24 12:30:27 +000090 BuiltinIncludeDir(0), CompilingModule(0), SourceModule(0)
Douglas Gregor51f564f2011-12-31 04:05:44 +000091{
Dylan Noblesmithc93dc782012-02-20 14:00:23 +000092 IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
93 Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
Douglas Gregor02c23eb2012-10-23 22:26:28 +000094 new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
Douglas Gregora4a90ca2013-05-03 22:58:43 +000095 Diags->setClient(new ForwardingDiagnosticConsumer(DC),
96 /*ShouldOwnClient=*/true);
Douglas Gregora30cfe52011-11-11 19:10:28 +000097 SourceMgr = new SourceManager(*Diags, FileMgr);
98}
99
100ModuleMap::~ModuleMap() {
Douglas Gregor09fe1bb2011-11-17 02:05:44 +0000101 for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
102 IEnd = Modules.end();
103 I != IEnd; ++I) {
104 delete I->getValue();
105 }
106
Douglas Gregora30cfe52011-11-11 19:10:28 +0000107 delete SourceMgr;
108}
109
Douglas Gregordc58aa72012-01-30 06:01:29 +0000110void ModuleMap::setTarget(const TargetInfo &Target) {
111 assert((!this->Target || this->Target == &Target) &&
112 "Improper target override");
113 this->Target = &Target;
114}
115
Douglas Gregor8b48e082012-10-12 21:15:50 +0000116/// \brief "Sanitize" a filename so that it can be used as an identifier.
117static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
118 SmallVectorImpl<char> &Buffer) {
119 if (Name.empty())
120 return Name;
121
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000122 if (!isValidIdentifier(Name)) {
Douglas Gregor8b48e082012-10-12 21:15:50 +0000123 // If we don't already have something with the form of an identifier,
124 // create a buffer with the sanitized name.
125 Buffer.clear();
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000126 if (isDigit(Name[0]))
Douglas Gregor8b48e082012-10-12 21:15:50 +0000127 Buffer.push_back('_');
128 Buffer.reserve(Buffer.size() + Name.size());
129 for (unsigned I = 0, N = Name.size(); I != N; ++I) {
Jordan Rose3f6f51e2013-02-08 22:30:41 +0000130 if (isIdentifierBody(Name[I]))
Douglas Gregor8b48e082012-10-12 21:15:50 +0000131 Buffer.push_back(Name[I]);
132 else
133 Buffer.push_back('_');
134 }
135
136 Name = StringRef(Buffer.data(), Buffer.size());
137 }
138
139 while (llvm::StringSwitch<bool>(Name)
140#define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
141#define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
142#include "clang/Basic/TokenKinds.def"
143 .Default(false)) {
144 if (Name.data() != Buffer.data())
145 Buffer.append(Name.begin(), Name.end());
146 Buffer.push_back('_');
147 Name = StringRef(Buffer.data(), Buffer.size());
148 }
149
150 return Name;
151}
152
Douglas Gregordb3910b2013-05-02 17:58:30 +0000153/// \brief Determine whether the given file name is the name of a builtin
154/// header, supplied by Clang to replace, override, or augment existing system
155/// headers.
156static bool isBuiltinHeader(StringRef FileName) {
157 return llvm::StringSwitch<bool>(FileName)
158 .Case("float.h", true)
159 .Case("iso646.h", true)
160 .Case("limits.h", true)
161 .Case("stdalign.h", true)
162 .Case("stdarg.h", true)
163 .Case("stdbool.h", true)
164 .Case("stddef.h", true)
165 .Case("stdint.h", true)
166 .Case("tgmath.h", true)
167 .Case("unwind.h", true)
168 .Default(false);
169}
170
Daniel Jasperc6417092013-10-22 08:09:47 +0000171ModuleMap::KnownHeader
172ModuleMap::findModuleForHeader(const FileEntry *File,
173 Module *RequestingModule) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000174 HeadersMap::iterator Known = Headers.find(File);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000175 if (Known != Headers.end()) {
Daniel Jasperc6417092013-10-22 08:09:47 +0000176 ModuleMap::KnownHeader Result = KnownHeader();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000177
Daniel Jasperc6417092013-10-22 08:09:47 +0000178 // Iterate over all modules that 'File' is part of to find the best fit.
179 for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(),
180 E = Known->second.end();
181 I != E; ++I) {
182 // Cannot use a module if the header is excluded or unavailable in it.
183 if (I->getRole() == ModuleMap::ExcludedHeader ||
184 !I->getModule()->isAvailable())
185 continue;
186
187 // If 'File' is part of 'RequestingModule', 'RequestingModule' is the
188 // module we are looking for.
189 if (I->getModule() == RequestingModule)
190 return *I;
191
192 // If uses need to be specified explicitly, we are only allowed to return
193 // modules that are explicitly used by the requesting module.
194 if (RequestingModule && LangOpts.ModulesDeclUse &&
195 std::find(RequestingModule->DirectUses.begin(),
196 RequestingModule->DirectUses.end(),
197 I->getModule()) == RequestingModule->DirectUses.end())
198 continue;
199 Result = *I;
200 // If 'File' is a public header of this module, this is as good as we
201 // are going to get.
202 if (I->getRole() == ModuleMap::NormalHeader)
203 break;
204 }
205 return Result;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000206 }
Douglas Gregordb3910b2013-05-02 17:58:30 +0000207
208 // If we've found a builtin header within Clang's builtin include directory,
209 // load all of the module maps to see if it will get associated with a
210 // specific module (e.g., in /usr/include).
211 if (File->getDir() == BuiltinIncludeDir &&
212 isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
Douglas Gregor30a16f12013-05-10 22:52:27 +0000213 HeaderInfo.loadTopLevelSystemModules();
Douglas Gregordb3910b2013-05-02 17:58:30 +0000214
215 // Check again.
Daniel Jasperc6417092013-10-22 08:09:47 +0000216 if (Headers.find(File) != Headers.end())
217 return findModuleForHeader(File, RequestingModule);
Douglas Gregordb3910b2013-05-02 17:58:30 +0000218 }
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000219
Douglas Gregoradb97992011-11-16 23:02:25 +0000220 const DirectoryEntry *Dir = File->getDir();
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000221 SmallVector<const DirectoryEntry *, 2> SkippedDirs;
Douglas Gregor713b7c02013-01-26 00:55:12 +0000222
Douglas Gregoraa60f9c2013-01-04 19:44:26 +0000223 // Note: as an egregious but useful hack we use the real path here, because
224 // frameworks moving from top-level frameworks to embedded frameworks tend
225 // to be symlinked from the top-level location to the embedded location,
226 // and we need to resolve lookups as if we had found the embedded location.
Douglas Gregor713b7c02013-01-26 00:55:12 +0000227 StringRef DirName = SourceMgr->getFileManager().getCanonicalName(Dir);
Douglas Gregore209e502011-12-06 01:10:29 +0000228
229 // Keep walking up the directory hierarchy, looking for a directory with
230 // an umbrella header.
231 do {
232 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
233 = UmbrellaDirs.find(Dir);
234 if (KnownDir != UmbrellaDirs.end()) {
235 Module *Result = KnownDir->second;
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000236
237 // Search up the module stack until we find a module with an umbrella
Douglas Gregor10694ce2011-12-08 17:39:04 +0000238 // directory.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000239 Module *UmbrellaModule = Result;
Douglas Gregor10694ce2011-12-08 17:39:04 +0000240 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000241 UmbrellaModule = UmbrellaModule->Parent;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000242
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000243 if (UmbrellaModule->InferSubmodules) {
Douglas Gregore209e502011-12-06 01:10:29 +0000244 // Infer submodules for each of the directories we found between
245 // the directory of the umbrella header and the directory where
246 // the actual header is located.
Douglas Gregor23af6d52011-12-07 22:05:21 +0000247 bool Explicit = UmbrellaModule->InferExplicitSubmodules;
Douglas Gregore209e502011-12-06 01:10:29 +0000248
Douglas Gregor6a1db482011-12-09 02:04:43 +0000249 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
Douglas Gregore209e502011-12-06 01:10:29 +0000250 // Find or create the module that corresponds to this directory name.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000251 SmallString<32> NameBuf;
252 StringRef Name = sanitizeFilenameAsIdentifier(
253 llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
254 NameBuf);
Douglas Gregore209e502011-12-06 01:10:29 +0000255 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000256 Explicit).first;
Douglas Gregore209e502011-12-06 01:10:29 +0000257
258 // Associate the module and the directory.
259 UmbrellaDirs[SkippedDirs[I-1]] = Result;
260
261 // If inferred submodules export everything they import, add a
262 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000263 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000264 Result->Exports.push_back(Module::ExportDecl(0, true));
265 }
266
267 // Infer a submodule with the same name as this header file.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000268 SmallString<32> NameBuf;
269 StringRef Name = sanitizeFilenameAsIdentifier(
270 llvm::sys::path::stem(File->getName()), NameBuf);
Douglas Gregore209e502011-12-06 01:10:29 +0000271 Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
Douglas Gregor23af6d52011-12-07 22:05:21 +0000272 Explicit).first;
Argyrios Kyrtzidisc1d22392013-03-13 21:13:43 +0000273 Result->addTopHeader(File);
Douglas Gregore209e502011-12-06 01:10:29 +0000274
275 // If inferred submodules export everything they import, add a
276 // wildcard to the set of exports.
Douglas Gregor9f74f4f2011-12-06 16:17:15 +0000277 if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
Douglas Gregore209e502011-12-06 01:10:29 +0000278 Result->Exports.push_back(Module::ExportDecl(0, true));
279 } else {
280 // Record each of the directories we stepped through as being part of
281 // the module we found, since the umbrella header covers them all.
282 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
283 UmbrellaDirs[SkippedDirs[I]] = Result;
284 }
285
Daniel Jasperc6417092013-10-22 08:09:47 +0000286 Headers[File].push_back(KnownHeader(Result, NormalHeader));
Douglas Gregor51f564f2011-12-31 04:05:44 +0000287
288 // If a header corresponds to an unavailable module, don't report
289 // that it maps to anything.
290 if (!Result->isAvailable())
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000291 return KnownHeader();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000292
Daniel Jasperc6417092013-10-22 08:09:47 +0000293 return Headers[File].back();
Douglas Gregore209e502011-12-06 01:10:29 +0000294 }
295
296 SkippedDirs.push_back(Dir);
297
Douglas Gregoradb97992011-11-16 23:02:25 +0000298 // Retrieve our parent path.
299 DirName = llvm::sys::path::parent_path(DirName);
300 if (DirName.empty())
301 break;
302
303 // Resolve the parent path to a directory entry.
304 Dir = SourceMgr->getFileManager().getDirectory(DirName);
Douglas Gregore209e502011-12-06 01:10:29 +0000305 } while (Dir);
Douglas Gregoradb97992011-11-16 23:02:25 +0000306
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000307 return KnownHeader();
Douglas Gregor65f3b5e2011-11-11 22:18:48 +0000308}
309
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000310bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
311 HeadersMap::const_iterator Known = Headers.find(Header);
Daniel Jasperc6417092013-10-22 08:09:47 +0000312 if (Known != Headers.end()) {
313 for (SmallVectorImpl<KnownHeader>::const_iterator
314 I = Known->second.begin(),
315 E = Known->second.end();
316 I != E; ++I) {
317 if (I->isAvailable())
318 return false;
319 }
320 return true;
321 }
Douglas Gregor51f564f2011-12-31 04:05:44 +0000322
323 const DirectoryEntry *Dir = Header->getDir();
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000324 SmallVector<const DirectoryEntry *, 2> SkippedDirs;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000325 StringRef DirName = Dir->getName();
326
327 // Keep walking up the directory hierarchy, looking for a directory with
328 // an umbrella header.
329 do {
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000330 llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
Douglas Gregor51f564f2011-12-31 04:05:44 +0000331 = UmbrellaDirs.find(Dir);
332 if (KnownDir != UmbrellaDirs.end()) {
333 Module *Found = KnownDir->second;
334 if (!Found->isAvailable())
335 return true;
336
337 // Search up the module stack until we find a module with an umbrella
338 // directory.
339 Module *UmbrellaModule = Found;
340 while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
341 UmbrellaModule = UmbrellaModule->Parent;
342
343 if (UmbrellaModule->InferSubmodules) {
344 for (unsigned I = SkippedDirs.size(); I != 0; --I) {
345 // Find or create the module that corresponds to this directory name.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000346 SmallString<32> NameBuf;
347 StringRef Name = sanitizeFilenameAsIdentifier(
348 llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
349 NameBuf);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000350 Found = lookupModuleQualified(Name, Found);
351 if (!Found)
352 return false;
353 if (!Found->isAvailable())
354 return true;
355 }
356
357 // Infer a submodule with the same name as this header file.
Douglas Gregor8b48e082012-10-12 21:15:50 +0000358 SmallString<32> NameBuf;
359 StringRef Name = sanitizeFilenameAsIdentifier(
360 llvm::sys::path::stem(Header->getName()),
361 NameBuf);
Douglas Gregor51f564f2011-12-31 04:05:44 +0000362 Found = lookupModuleQualified(Name, Found);
363 if (!Found)
364 return false;
365 }
366
367 return !Found->isAvailable();
368 }
369
370 SkippedDirs.push_back(Dir);
371
372 // Retrieve our parent path.
373 DirName = llvm::sys::path::parent_path(DirName);
374 if (DirName.empty())
375 break;
376
377 // Resolve the parent path to a directory entry.
378 Dir = SourceMgr->getFileManager().getDirectory(DirName);
379 } while (Dir);
380
381 return false;
382}
383
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000384Module *ModuleMap::findModule(StringRef Name) const {
385 llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
Douglas Gregor484535e2011-11-11 23:20:24 +0000386 if (Known != Modules.end())
387 return Known->getValue();
388
389 return 0;
390}
391
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000392Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
393 Module *Context) const {
Douglas Gregor90db2602011-12-02 01:47:07 +0000394 for(; Context; Context = Context->Parent) {
395 if (Module *Sub = lookupModuleQualified(Name, Context))
396 return Sub;
397 }
398
399 return findModule(Name);
400}
401
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000402Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
Douglas Gregor90db2602011-12-02 01:47:07 +0000403 if (!Context)
404 return findModule(Name);
405
Douglas Gregorb7a78192012-01-04 23:32:19 +0000406 return Context->findSubmodule(Name);
Douglas Gregor90db2602011-12-02 01:47:07 +0000407}
408
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000409std::pair<Module *, bool>
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000410ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
411 bool IsExplicit) {
412 // Try to find an existing module with this name.
Douglas Gregorb7a78192012-01-04 23:32:19 +0000413 if (Module *Sub = lookupModuleQualified(Name, Parent))
414 return std::make_pair(Sub, false);
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000415
416 // Create a new module with this name.
417 Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
418 IsExplicit);
Daniel Jasperddd2dfc2013-09-24 09:14:14 +0000419 if (LangOpts.CurrentModule == Name) {
420 SourceModule = Result;
421 SourceModuleName = Name;
422 }
Argyrios Kyrtzidisd3220db2013-05-08 23:46:46 +0000423 if (!Parent) {
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000424 Modules[Name] = Result;
Argyrios Kyrtzidisd3220db2013-05-08 23:46:46 +0000425 if (!LangOpts.CurrentModule.empty() && !CompilingModule &&
426 Name == LangOpts.CurrentModule) {
427 CompilingModule = Result;
428 }
429 }
Douglas Gregor392ed2b2011-11-30 17:33:56 +0000430 return std::make_pair(Result, true);
431}
432
Douglas Gregor82e52372012-11-06 19:39:40 +0000433bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir,
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000434 StringRef Name, bool &IsSystem) const {
Douglas Gregor82e52372012-11-06 19:39:40 +0000435 // Check whether we have already looked into the parent directory
436 // for a module map.
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000437 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
Douglas Gregor82e52372012-11-06 19:39:40 +0000438 inferred = InferredDirectories.find(ParentDir);
439 if (inferred == InferredDirectories.end())
440 return false;
441
442 if (!inferred->second.InferModules)
443 return false;
444
445 // We're allowed to infer for this directory, but make sure it's okay
446 // to infer this particular module.
447 bool canInfer = std::find(inferred->second.ExcludedModules.begin(),
448 inferred->second.ExcludedModules.end(),
449 Name) == inferred->second.ExcludedModules.end();
450
451 if (canInfer && inferred->second.InferSystemModules)
452 IsSystem = true;
453
454 return canInfer;
455}
456
Douglas Gregor8767dc22013-01-14 17:57:51 +0000457/// \brief For a framework module, infer the framework against which we
458/// should link.
459static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
460 FileManager &FileMgr) {
461 assert(Mod->IsFramework && "Can only infer linking for framework modules");
462 assert(!Mod->isSubFramework() &&
463 "Can only infer linking for top-level frameworks");
464
465 SmallString<128> LibName;
466 LibName += FrameworkDir->getName();
467 llvm::sys::path::append(LibName, Mod->Name);
468 if (FileMgr.getFile(LibName)) {
469 Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
470 /*IsFramework=*/true));
471 }
472}
473
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000474Module *
Douglas Gregor82e52372012-11-06 19:39:40 +0000475ModuleMap::inferFrameworkModule(StringRef ModuleName,
Douglas Gregorac252a32011-12-06 19:39:29 +0000476 const DirectoryEntry *FrameworkDir,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000477 bool IsSystem,
Douglas Gregorac252a32011-12-06 19:39:29 +0000478 Module *Parent) {
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000479 // Check whether we've already found this module.
Douglas Gregorac252a32011-12-06 19:39:29 +0000480 if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
481 return Mod;
482
483 FileManager &FileMgr = SourceMgr->getFileManager();
Douglas Gregor82e52372012-11-06 19:39:40 +0000484
485 // If the framework has a parent path from which we're allowed to infer
486 // a framework module, do so.
487 if (!Parent) {
Douglas Gregor7005b902013-01-10 01:43:00 +0000488 // Determine whether we're allowed to infer a module map.
Douglas Gregor713b7c02013-01-26 00:55:12 +0000489
Douglas Gregor7005b902013-01-10 01:43:00 +0000490 // Note: as an egregious but useful hack we use the real path here, because
491 // we might be looking at an embedded framework that symlinks out to a
492 // top-level framework, and we need to infer as if we were naming the
493 // top-level framework.
Douglas Gregor713b7c02013-01-26 00:55:12 +0000494 StringRef FrameworkDirName
495 = SourceMgr->getFileManager().getCanonicalName(FrameworkDir);
Douglas Gregor7005b902013-01-10 01:43:00 +0000496
Douglas Gregor82e52372012-11-06 19:39:40 +0000497 bool canInfer = false;
Douglas Gregor7005b902013-01-10 01:43:00 +0000498 if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
Douglas Gregor82e52372012-11-06 19:39:40 +0000499 // Figure out the parent path.
Douglas Gregor7005b902013-01-10 01:43:00 +0000500 StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
Douglas Gregor82e52372012-11-06 19:39:40 +0000501 if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
502 // Check whether we have already looked into the parent directory
503 // for a module map.
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000504 llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
Douglas Gregor82e52372012-11-06 19:39:40 +0000505 inferred = InferredDirectories.find(ParentDir);
506 if (inferred == InferredDirectories.end()) {
507 // We haven't looked here before. Load a module map, if there is
508 // one.
509 SmallString<128> ModMapPath = Parent;
510 llvm::sys::path::append(ModMapPath, "module.map");
511 if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) {
Douglas Gregor8f5d7d12013-06-21 16:28:10 +0000512 parseModuleMapFile(ModMapFile, IsSystem);
Douglas Gregor82e52372012-11-06 19:39:40 +0000513 inferred = InferredDirectories.find(ParentDir);
514 }
515
516 if (inferred == InferredDirectories.end())
517 inferred = InferredDirectories.insert(
518 std::make_pair(ParentDir, InferredDirectory())).first;
519 }
520
521 if (inferred->second.InferModules) {
522 // We're allowed to infer for this directory, but make sure it's okay
523 // to infer this particular module.
Douglas Gregor7005b902013-01-10 01:43:00 +0000524 StringRef Name = llvm::sys::path::stem(FrameworkDirName);
Douglas Gregor82e52372012-11-06 19:39:40 +0000525 canInfer = std::find(inferred->second.ExcludedModules.begin(),
526 inferred->second.ExcludedModules.end(),
527 Name) == inferred->second.ExcludedModules.end();
528
529 if (inferred->second.InferSystemModules)
530 IsSystem = true;
531 }
532 }
533 }
534
535 // If we're not allowed to infer a framework module, don't.
536 if (!canInfer)
537 return 0;
538 }
539
540
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000541 // Look for an umbrella header.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000542 SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
Benjamin Kramerceb6dc82013-06-28 16:25:46 +0000543 llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
Douglas Gregorac252a32011-12-06 19:39:29 +0000544 const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000545
546 // FIXME: If there's no umbrella header, we could probably scan the
547 // framework to load *everything*. But, it's not clear that this is a good
548 // idea.
549 if (!UmbrellaHeader)
550 return 0;
551
Douglas Gregorac252a32011-12-06 19:39:29 +0000552 Module *Result = new Module(ModuleName, SourceLocation(), Parent,
553 /*IsFramework=*/true, /*IsExplicit=*/false);
Daniel Jasperddd2dfc2013-09-24 09:14:14 +0000554 if (LangOpts.CurrentModule == ModuleName) {
555 SourceModule = Result;
556 SourceModuleName = ModuleName;
557 }
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000558 if (IsSystem)
559 Result->IsSystem = IsSystem;
560
Douglas Gregorb7a78192012-01-04 23:32:19 +0000561 if (!Parent)
Douglas Gregorac252a32011-12-06 19:39:29 +0000562 Modules[ModuleName] = Result;
Douglas Gregorb7a78192012-01-04 23:32:19 +0000563
Douglas Gregor489ad432011-12-08 18:00:48 +0000564 // umbrella header "umbrella-header-name"
Douglas Gregor10694ce2011-12-08 17:39:04 +0000565 Result->Umbrella = UmbrellaHeader;
Daniel Jasperc6417092013-10-22 08:09:47 +0000566 Headers[UmbrellaHeader].push_back(KnownHeader(Result, NormalHeader));
Douglas Gregor3cee31e2011-12-12 23:55:05 +0000567 UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
Douglas Gregor209977c2011-12-05 17:40:25 +0000568
569 // export *
570 Result->Exports.push_back(Module::ExportDecl(0, true));
571
Douglas Gregore209e502011-12-06 01:10:29 +0000572 // module * { export * }
573 Result->InferSubmodules = true;
574 Result->InferExportWildcard = true;
575
Douglas Gregorac252a32011-12-06 19:39:29 +0000576 // Look for subframeworks.
577 llvm::error_code EC;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000578 SmallString<128> SubframeworksDirName
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000579 = StringRef(FrameworkDir->getName());
Douglas Gregorac252a32011-12-06 19:39:29 +0000580 llvm::sys::path::append(SubframeworksDirName, "Frameworks");
Benjamin Kramer0f599ac2013-09-11 11:23:15 +0000581 llvm::sys::path::native(SubframeworksDirName);
Douglas Gregor52b1ed32011-12-08 16:13:24 +0000582 for (llvm::sys::fs::directory_iterator
Benjamin Kramer0f599ac2013-09-11 11:23:15 +0000583 Dir(SubframeworksDirName.str(), EC), DirEnd;
Douglas Gregorac252a32011-12-06 19:39:29 +0000584 Dir != DirEnd && !EC; Dir.increment(EC)) {
585 if (!StringRef(Dir->path()).endswith(".framework"))
586 continue;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000587
Douglas Gregorac252a32011-12-06 19:39:29 +0000588 if (const DirectoryEntry *SubframeworkDir
589 = FileMgr.getDirectory(Dir->path())) {
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000590 // Note: as an egregious but useful hack, we use the real path here and
591 // check whether it is actually a subdirectory of the parent directory.
592 // This will not be the case if the 'subframework' is actually a symlink
593 // out to a top-level framework.
Douglas Gregor713b7c02013-01-26 00:55:12 +0000594 StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
595 bool FoundParent = false;
596 do {
597 // Get the parent directory name.
598 SubframeworkDirName
599 = llvm::sys::path::parent_path(SubframeworkDirName);
600 if (SubframeworkDirName.empty())
601 break;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000602
Douglas Gregor713b7c02013-01-26 00:55:12 +0000603 if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
604 FoundParent = true;
605 break;
606 }
607 } while (true);
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000608
Douglas Gregor713b7c02013-01-26 00:55:12 +0000609 if (!FoundParent)
610 continue;
Douglas Gregor98cfcbf2012-09-27 14:50:15 +0000611
Douglas Gregorac252a32011-12-06 19:39:29 +0000612 // FIXME: Do we want to warn about subframeworks without umbrella headers?
Douglas Gregor8b48e082012-10-12 21:15:50 +0000613 SmallString<32> NameBuf;
614 inferFrameworkModule(sanitizeFilenameAsIdentifier(
615 llvm::sys::path::stem(Dir->path()), NameBuf),
616 SubframeworkDir, IsSystem, Result);
Douglas Gregorac252a32011-12-06 19:39:29 +0000617 }
618 }
Douglas Gregor3a110f72012-01-13 16:54:27 +0000619
Douglas Gregor8767dc22013-01-14 17:57:51 +0000620 // If the module is a top-level framework, automatically link against the
621 // framework.
622 if (!Result->isSubFramework()) {
623 inferFrameworkLink(Result, FrameworkDir, FileMgr);
624 }
625
Douglas Gregor2821c7f2011-11-17 01:41:17 +0000626 return Result;
627}
628
Douglas Gregore209e502011-12-06 01:10:29 +0000629void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
Daniel Jasperc6417092013-10-22 08:09:47 +0000630 Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
Douglas Gregor10694ce2011-12-08 17:39:04 +0000631 Mod->Umbrella = UmbrellaHeader;
Douglas Gregor6a1db482011-12-09 02:04:43 +0000632 UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
Douglas Gregore209e502011-12-06 01:10:29 +0000633}
634
Douglas Gregor77d029f2011-12-08 19:11:24 +0000635void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
636 Mod->Umbrella = UmbrellaDir;
637 UmbrellaDirs[UmbrellaDir] = Mod;
638}
639
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000640void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000641 ModuleHeaderRole Role) {
642 if (Role == ExcludedHeader) {
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000643 Mod->ExcludedHeaders.push_back(Header);
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +0000644 } else {
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000645 if (Role == PrivateHeader)
646 Mod->PrivateHeaders.push_back(Header);
647 else
648 Mod->NormalHeaders.push_back(Header);
Argyrios Kyrtzidisd3220db2013-05-08 23:46:46 +0000649 bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000650 HeaderInfo.MarkFileModuleHeader(Header, Role, isCompilingModuleHeader);
Argyrios Kyrtzidis55ea75b2013-03-13 21:13:51 +0000651 }
Daniel Jasperc6417092013-10-22 08:09:47 +0000652 Headers[Header].push_back(KnownHeader(Mod, Role));
Douglas Gregore209e502011-12-06 01:10:29 +0000653}
654
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000655const FileEntry *
Argyrios Kyrtzidis0be5e562013-02-19 19:58:45 +0000656ModuleMap::getContainingModuleMapFile(Module *Module) const {
Douglas Gregorf9e357d2011-11-29 19:06:37 +0000657 if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
658 return 0;
659
660 return SourceMgr->getFileEntryForID(
661 SourceMgr->getFileID(Module->DefinitionLoc));
662}
663
Douglas Gregora30cfe52011-11-11 19:10:28 +0000664void ModuleMap::dump() {
665 llvm::errs() << "Modules:";
666 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
667 MEnd = Modules.end();
668 M != MEnd; ++M)
Douglas Gregor804c3bf2011-11-29 18:17:59 +0000669 M->getValue()->print(llvm::errs(), 2);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000670
671 llvm::errs() << "Headers:";
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000672 for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
Douglas Gregora30cfe52011-11-11 19:10:28 +0000673 H != HEnd; ++H) {
Daniel Jasperc6417092013-10-22 08:09:47 +0000674 llvm::errs() << " \"" << H->first->getName() << "\" -> ";
675 for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
676 E = H->second.end();
677 I != E; ++I) {
678 if (I != H->second.begin())
679 llvm::errs() << ",";
680 llvm::errs() << I->getModule()->getFullModuleName();
681 }
682 llvm::errs() << "\n";
Douglas Gregora30cfe52011-11-11 19:10:28 +0000683 }
684}
685
Douglas Gregor90db2602011-12-02 01:47:07 +0000686bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
687 bool HadError = false;
688 for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
689 Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
690 Complain);
Douglas Gregor0adaa882011-12-05 17:28:06 +0000691 if (Export.getPointer() || Export.getInt())
Douglas Gregor90db2602011-12-02 01:47:07 +0000692 Mod->Exports.push_back(Export);
693 else
694 HadError = true;
695 }
696 Mod->UnresolvedExports.clear();
697 return HadError;
698}
699
Daniel Jasperddd2dfc2013-09-24 09:14:14 +0000700bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
701 bool HadError = false;
702 for (unsigned I = 0, N = Mod->UnresolvedDirectUses.size(); I != N; ++I) {
703 Module *DirectUse =
704 resolveModuleId(Mod->UnresolvedDirectUses[I], Mod, Complain);
705 if (DirectUse)
706 Mod->DirectUses.push_back(DirectUse);
707 else
708 HadError = true;
709 }
710 Mod->UnresolvedDirectUses.clear();
711 return HadError;
712}
713
Douglas Gregor906d66a2013-03-20 21:10:35 +0000714bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
715 bool HadError = false;
716 for (unsigned I = 0, N = Mod->UnresolvedConflicts.size(); I != N; ++I) {
717 Module *OtherMod = resolveModuleId(Mod->UnresolvedConflicts[I].Id,
718 Mod, Complain);
719 if (!OtherMod) {
720 HadError = true;
721 continue;
722 }
723
724 Module::Conflict Conflict;
725 Conflict.Other = OtherMod;
726 Conflict.Message = Mod->UnresolvedConflicts[I].Message;
727 Mod->Conflicts.push_back(Conflict);
728 }
729 Mod->UnresolvedConflicts.clear();
730 return HadError;
731}
732
Douglas Gregor55988682011-12-05 16:33:54 +0000733Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
734 if (Loc.isInvalid())
735 return 0;
736
737 // Use the expansion location to determine which module we're in.
738 FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
739 if (!ExpansionLoc.isFileID())
740 return 0;
741
742
743 const SourceManager &SrcMgr = Loc.getManager();
744 FileID ExpansionFileID = ExpansionLoc.getFileID();
Douglas Gregor55988682011-12-05 16:33:54 +0000745
Douglas Gregor303aae92012-01-06 17:19:32 +0000746 while (const FileEntry *ExpansionFile
747 = SrcMgr.getFileEntryForID(ExpansionFileID)) {
748 // Find the module that owns this header (if any).
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000749 if (Module *Mod = findModuleForHeader(ExpansionFile).getModule())
Douglas Gregor303aae92012-01-06 17:19:32 +0000750 return Mod;
751
752 // No module owns this header, so look up the inclusion chain to see if
753 // any included header has an associated module.
754 SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
755 if (IncludeLoc.isInvalid())
756 return 0;
757
758 ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
759 }
760
761 return 0;
Douglas Gregor55988682011-12-05 16:33:54 +0000762}
763
Douglas Gregora30cfe52011-11-11 19:10:28 +0000764//----------------------------------------------------------------------------//
765// Module map file parser
766//----------------------------------------------------------------------------//
767
768namespace clang {
769 /// \brief A token in a module map file.
770 struct MMToken {
771 enum TokenKind {
Douglas Gregor51f564f2011-12-31 04:05:44 +0000772 Comma,
Douglas Gregor63a72682013-03-20 00:22:05 +0000773 ConfigMacros,
Douglas Gregor906d66a2013-03-20 21:10:35 +0000774 Conflict,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000775 EndOfFile,
776 HeaderKeyword,
777 Identifier,
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000778 ExcludeKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000779 ExplicitKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000780 ExportKeyword,
Daniel Jasper5f0a3522013-09-11 07:20:44 +0000781 ExternKeyword,
Douglas Gregora8654052011-11-17 22:09:43 +0000782 FrameworkKeyword,
Douglas Gregorb6cbe512013-01-14 17:21:00 +0000783 LinkKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000784 ModuleKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000785 Period,
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000786 PrivateKeyword,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000787 UmbrellaKeyword,
Daniel Jasperddd2dfc2013-09-24 09:14:14 +0000788 UseKeyword,
Douglas Gregor51f564f2011-12-31 04:05:44 +0000789 RequiresKeyword,
Douglas Gregor90db2602011-12-02 01:47:07 +0000790 Star,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000791 StringLiteral,
792 LBrace,
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000793 RBrace,
794 LSquare,
795 RSquare
Douglas Gregora30cfe52011-11-11 19:10:28 +0000796 } Kind;
797
798 unsigned Location;
799 unsigned StringLength;
800 const char *StringData;
801
802 void clear() {
803 Kind = EndOfFile;
804 Location = 0;
805 StringLength = 0;
806 StringData = 0;
807 }
808
809 bool is(TokenKind K) const { return Kind == K; }
810
811 SourceLocation getLocation() const {
812 return SourceLocation::getFromRawEncoding(Location);
813 }
814
815 StringRef getString() const {
816 return StringRef(StringData, StringLength);
817 }
818 };
Douglas Gregor82e52372012-11-06 19:39:40 +0000819
820 /// \brief The set of attributes that can be attached to a module.
Bill Wendlingad017fa2012-12-20 19:22:21 +0000821 struct Attributes {
Douglas Gregor63a72682013-03-20 00:22:05 +0000822 Attributes() : IsSystem(), IsExhaustive() { }
Douglas Gregor82e52372012-11-06 19:39:40 +0000823
824 /// \brief Whether this is a system module.
825 unsigned IsSystem : 1;
Douglas Gregor63a72682013-03-20 00:22:05 +0000826
827 /// \brief Whether this is an exhaustive set of configuration macros.
828 unsigned IsExhaustive : 1;
Douglas Gregor82e52372012-11-06 19:39:40 +0000829 };
Douglas Gregora30cfe52011-11-11 19:10:28 +0000830
Douglas Gregor82e52372012-11-06 19:39:40 +0000831
Douglas Gregora30cfe52011-11-11 19:10:28 +0000832 class ModuleMapParser {
833 Lexer &L;
834 SourceManager &SourceMgr;
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000835
836 /// \brief Default target information, used only for string literal
837 /// parsing.
838 const TargetInfo *Target;
839
Douglas Gregora30cfe52011-11-11 19:10:28 +0000840 DiagnosticsEngine &Diags;
841 ModuleMap &Map;
842
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000843 /// \brief The directory that this module map resides in.
844 const DirectoryEntry *Directory;
Douglas Gregor2f04f182012-02-02 18:42:48 +0000845
846 /// \brief The directory containing Clang-supplied headers.
847 const DirectoryEntry *BuiltinIncludeDir;
848
Douglas Gregor8f5d7d12013-06-21 16:28:10 +0000849 /// \brief Whether this module map is in a system header directory.
850 bool IsSystem;
851
Douglas Gregora30cfe52011-11-11 19:10:28 +0000852 /// \brief Whether an error occurred.
853 bool HadError;
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000854
Douglas Gregora30cfe52011-11-11 19:10:28 +0000855 /// \brief Stores string data for the various string literals referenced
856 /// during parsing.
857 llvm::BumpPtrAllocator StringData;
858
859 /// \brief The current token.
860 MMToken Tok;
861
862 /// \brief The active module.
Douglas Gregor1a4761e2011-11-30 23:21:26 +0000863 Module *ActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +0000864
865 /// \brief Consume the current token and return its location.
866 SourceLocation consumeToken();
867
868 /// \brief Skip tokens until we reach the a token with the given kind
869 /// (or the end of the file).
870 void skipUntil(MMToken::TokenKind K);
Douglas Gregor587986e2011-12-07 02:23:45 +0000871
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000872 typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
Douglas Gregor587986e2011-12-07 02:23:45 +0000873 bool parseModuleId(ModuleId &Id);
Douglas Gregora30cfe52011-11-11 19:10:28 +0000874 void parseModuleDecl();
Daniel Jasper5f0a3522013-09-11 07:20:44 +0000875 void parseExternModuleDecl();
Douglas Gregor51f564f2011-12-31 04:05:44 +0000876 void parseRequiresDecl();
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000877 void parseHeaderDecl(clang::MMToken::TokenKind,
878 SourceLocation LeadingLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +0000879 void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
Douglas Gregor90db2602011-12-02 01:47:07 +0000880 void parseExportDecl();
Daniel Jasperddd2dfc2013-09-24 09:14:14 +0000881 void parseUseDecl();
Douglas Gregorb6cbe512013-01-14 17:21:00 +0000882 void parseLinkDecl();
Douglas Gregor63a72682013-03-20 00:22:05 +0000883 void parseConfigMacros();
Douglas Gregor906d66a2013-03-20 21:10:35 +0000884 void parseConflict();
Douglas Gregor82e52372012-11-06 19:39:40 +0000885 void parseInferredModuleDecl(bool Framework, bool Explicit);
Bill Wendlingad017fa2012-12-20 19:22:21 +0000886 bool parseOptionalAttributes(Attributes &Attrs);
Douglas Gregor82e52372012-11-06 19:39:40 +0000887
Douglas Gregor6a1db482011-12-09 02:04:43 +0000888 const DirectoryEntry *getOverriddenHeaderSearchDir();
889
Douglas Gregora30cfe52011-11-11 19:10:28 +0000890 public:
Douglas Gregora30cfe52011-11-11 19:10:28 +0000891 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000892 const TargetInfo *Target,
Douglas Gregora30cfe52011-11-11 19:10:28 +0000893 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000894 ModuleMap &Map,
Douglas Gregor2f04f182012-02-02 18:42:48 +0000895 const DirectoryEntry *Directory,
Douglas Gregor8f5d7d12013-06-21 16:28:10 +0000896 const DirectoryEntry *BuiltinIncludeDir,
897 bool IsSystem)
Douglas Gregor9a022bb2012-10-15 16:45:32 +0000898 : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
Douglas Gregor8f5d7d12013-06-21 16:28:10 +0000899 Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir),
900 IsSystem(IsSystem), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000901 {
Douglas Gregora30cfe52011-11-11 19:10:28 +0000902 Tok.clear();
903 consumeToken();
904 }
905
906 bool parseModuleMapFile();
907 };
908}
909
910SourceLocation ModuleMapParser::consumeToken() {
911retry:
912 SourceLocation Result = Tok.getLocation();
913 Tok.clear();
914
915 Token LToken;
916 L.LexFromRawLexer(LToken);
917 Tok.Location = LToken.getLocation().getRawEncoding();
918 switch (LToken.getKind()) {
919 case tok::raw_identifier:
920 Tok.StringData = LToken.getRawIdentifierData();
921 Tok.StringLength = LToken.getLength();
922 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
Douglas Gregor63a72682013-03-20 00:22:05 +0000923 .Case("config_macros", MMToken::ConfigMacros)
Douglas Gregor906d66a2013-03-20 21:10:35 +0000924 .Case("conflict", MMToken::Conflict)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +0000925 .Case("exclude", MMToken::ExcludeKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000926 .Case("explicit", MMToken::ExplicitKeyword)
Douglas Gregor90db2602011-12-02 01:47:07 +0000927 .Case("export", MMToken::ExportKeyword)
Daniel Jasper5f0a3522013-09-11 07:20:44 +0000928 .Case("extern", MMToken::ExternKeyword)
Douglas Gregora8654052011-11-17 22:09:43 +0000929 .Case("framework", MMToken::FrameworkKeyword)
Douglas Gregor63a72682013-03-20 00:22:05 +0000930 .Case("header", MMToken::HeaderKeyword)
Douglas Gregorb6cbe512013-01-14 17:21:00 +0000931 .Case("link", MMToken::LinkKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000932 .Case("module", MMToken::ModuleKeyword)
Lawrence Crowlbc3f6282013-06-20 21:14:14 +0000933 .Case("private", MMToken::PrivateKeyword)
Douglas Gregor51f564f2011-12-31 04:05:44 +0000934 .Case("requires", MMToken::RequiresKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000935 .Case("umbrella", MMToken::UmbrellaKeyword)
Daniel Jasperddd2dfc2013-09-24 09:14:14 +0000936 .Case("use", MMToken::UseKeyword)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000937 .Default(MMToken::Identifier);
938 break;
Douglas Gregor51f564f2011-12-31 04:05:44 +0000939
940 case tok::comma:
941 Tok.Kind = MMToken::Comma;
942 break;
943
Douglas Gregora30cfe52011-11-11 19:10:28 +0000944 case tok::eof:
945 Tok.Kind = MMToken::EndOfFile;
946 break;
947
948 case tok::l_brace:
949 Tok.Kind = MMToken::LBrace;
950 break;
951
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000952 case tok::l_square:
953 Tok.Kind = MMToken::LSquare;
954 break;
955
Douglas Gregor90db2602011-12-02 01:47:07 +0000956 case tok::period:
957 Tok.Kind = MMToken::Period;
958 break;
959
Douglas Gregora30cfe52011-11-11 19:10:28 +0000960 case tok::r_brace:
961 Tok.Kind = MMToken::RBrace;
962 break;
963
Douglas Gregora1f1fad2012-01-27 19:52:33 +0000964 case tok::r_square:
965 Tok.Kind = MMToken::RSquare;
966 break;
967
Douglas Gregor90db2602011-12-02 01:47:07 +0000968 case tok::star:
969 Tok.Kind = MMToken::Star;
970 break;
971
Douglas Gregora30cfe52011-11-11 19:10:28 +0000972 case tok::string_literal: {
Richard Smith99831e42012-03-06 03:21:47 +0000973 if (LToken.hasUDSuffix()) {
974 Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
975 HadError = true;
976 goto retry;
977 }
978
Douglas Gregora30cfe52011-11-11 19:10:28 +0000979 // Parse the string literal.
980 LangOptions LangOpts;
981 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
982 if (StringLiteral.hadError)
983 goto retry;
984
985 // Copy the string literal into our string data allocator.
986 unsigned Length = StringLiteral.GetStringLength();
987 char *Saved = StringData.Allocate<char>(Length + 1);
988 memcpy(Saved, StringLiteral.GetString().data(), Length);
989 Saved[Length] = 0;
990
991 // Form the token.
992 Tok.Kind = MMToken::StringLiteral;
993 Tok.StringData = Saved;
994 Tok.StringLength = Length;
995 break;
996 }
997
998 case tok::comment:
999 goto retry;
1000
1001 default:
1002 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
1003 HadError = true;
1004 goto retry;
1005 }
1006
1007 return Result;
1008}
1009
1010void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1011 unsigned braceDepth = 0;
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001012 unsigned squareDepth = 0;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001013 do {
1014 switch (Tok.Kind) {
1015 case MMToken::EndOfFile:
1016 return;
1017
1018 case MMToken::LBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001019 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
Douglas Gregora30cfe52011-11-11 19:10:28 +00001020 return;
1021
1022 ++braceDepth;
1023 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001024
1025 case MMToken::LSquare:
1026 if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1027 return;
1028
1029 ++squareDepth;
1030 break;
1031
Douglas Gregora30cfe52011-11-11 19:10:28 +00001032 case MMToken::RBrace:
1033 if (braceDepth > 0)
1034 --braceDepth;
1035 else if (Tok.is(K))
1036 return;
1037 break;
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001038
1039 case MMToken::RSquare:
1040 if (squareDepth > 0)
1041 --squareDepth;
1042 else if (Tok.is(K))
1043 return;
1044 break;
1045
Douglas Gregora30cfe52011-11-11 19:10:28 +00001046 default:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001047 if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
Douglas Gregora30cfe52011-11-11 19:10:28 +00001048 return;
1049 break;
1050 }
1051
1052 consumeToken();
1053 } while (true);
1054}
1055
Douglas Gregor587986e2011-12-07 02:23:45 +00001056/// \brief Parse a module-id.
1057///
1058/// module-id:
1059/// identifier
1060/// identifier '.' module-id
1061///
1062/// \returns true if an error occurred, false otherwise.
1063bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1064 Id.clear();
1065 do {
1066 if (Tok.is(MMToken::Identifier)) {
1067 Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1068 consumeToken();
1069 } else {
1070 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1071 return true;
1072 }
1073
1074 if (!Tok.is(MMToken::Period))
1075 break;
1076
1077 consumeToken();
1078 } while (true);
1079
1080 return false;
1081}
1082
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001083namespace {
1084 /// \brief Enumerates the known attributes.
1085 enum AttributeKind {
1086 /// \brief An unknown attribute.
1087 AT_unknown,
1088 /// \brief The 'system' attribute.
Douglas Gregor63a72682013-03-20 00:22:05 +00001089 AT_system,
1090 /// \brief The 'exhaustive' attribute.
1091 AT_exhaustive
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001092 };
1093}
1094
Douglas Gregora30cfe52011-11-11 19:10:28 +00001095/// \brief Parse a module declaration.
1096///
1097/// module-declaration:
Daniel Jasper5f0a3522013-09-11 07:20:44 +00001098/// 'extern' 'module' module-id string-literal
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001099/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1100/// { module-member* }
1101///
Douglas Gregora30cfe52011-11-11 19:10:28 +00001102/// module-member:
Douglas Gregor51f564f2011-12-31 04:05:44 +00001103/// requires-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +00001104/// header-declaration
Douglas Gregor587986e2011-12-07 02:23:45 +00001105/// submodule-declaration
Douglas Gregor90db2602011-12-02 01:47:07 +00001106/// export-declaration
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001107/// link-declaration
Douglas Gregor1e123682011-12-05 22:27:44 +00001108///
1109/// submodule-declaration:
1110/// module-declaration
1111/// inferred-submodule-declaration
Douglas Gregora30cfe52011-11-11 19:10:28 +00001112void ModuleMapParser::parseModuleDecl() {
Douglas Gregora8654052011-11-17 22:09:43 +00001113 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
Daniel Jasper5f0a3522013-09-11 07:20:44 +00001114 Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
1115 if (Tok.is(MMToken::ExternKeyword)) {
1116 parseExternModuleDecl();
1117 return;
1118 }
1119
Douglas Gregord620a842011-12-06 17:16:41 +00001120 // Parse 'explicit' or 'framework' keyword, if present.
Douglas Gregor587986e2011-12-07 02:23:45 +00001121 SourceLocation ExplicitLoc;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001122 bool Explicit = false;
Douglas Gregord620a842011-12-06 17:16:41 +00001123 bool Framework = false;
Douglas Gregora8654052011-11-17 22:09:43 +00001124
Douglas Gregord620a842011-12-06 17:16:41 +00001125 // Parse 'explicit' keyword, if present.
1126 if (Tok.is(MMToken::ExplicitKeyword)) {
Douglas Gregor587986e2011-12-07 02:23:45 +00001127 ExplicitLoc = consumeToken();
Douglas Gregord620a842011-12-06 17:16:41 +00001128 Explicit = true;
1129 }
1130
1131 // Parse 'framework' keyword, if present.
Douglas Gregora8654052011-11-17 22:09:43 +00001132 if (Tok.is(MMToken::FrameworkKeyword)) {
1133 consumeToken();
1134 Framework = true;
1135 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001136
1137 // Parse 'module' keyword.
1138 if (!Tok.is(MMToken::ModuleKeyword)) {
Douglas Gregore6fb9872011-12-06 19:57:48 +00001139 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001140 consumeToken();
1141 HadError = true;
1142 return;
1143 }
1144 consumeToken(); // 'module' keyword
Douglas Gregor1e123682011-12-05 22:27:44 +00001145
1146 // If we have a wildcard for the module name, this is an inferred submodule.
1147 // Parse it.
1148 if (Tok.is(MMToken::Star))
Douglas Gregor82e52372012-11-06 19:39:40 +00001149 return parseInferredModuleDecl(Framework, Explicit);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001150
1151 // Parse the module name.
Douglas Gregor587986e2011-12-07 02:23:45 +00001152 ModuleId Id;
1153 if (parseModuleId(Id)) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001154 HadError = true;
Douglas Gregor587986e2011-12-07 02:23:45 +00001155 return;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001156 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001157
Douglas Gregor587986e2011-12-07 02:23:45 +00001158 if (ActiveModule) {
1159 if (Id.size() > 1) {
1160 Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1161 << SourceRange(Id.front().second, Id.back().second);
1162
1163 HadError = true;
1164 return;
1165 }
1166 } else if (Id.size() == 1 && Explicit) {
1167 // Top-level modules can't be explicit.
1168 Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1169 Explicit = false;
1170 ExplicitLoc = SourceLocation();
1171 HadError = true;
1172 }
1173
1174 Module *PreviousActiveModule = ActiveModule;
1175 if (Id.size() > 1) {
1176 // This module map defines a submodule. Go find the module of which it
1177 // is a submodule.
1178 ActiveModule = 0;
1179 for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1180 if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1181 ActiveModule = Next;
1182 continue;
1183 }
1184
1185 if (ActiveModule) {
1186 Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1187 << Id[I].first << ActiveModule->getTopLevelModule();
1188 } else {
1189 Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1190 }
1191 HadError = true;
1192 return;
1193 }
1194 }
1195
1196 StringRef ModuleName = Id.back().first;
1197 SourceLocation ModuleNameLoc = Id.back().second;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001198
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001199 // Parse the optional attribute list.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001200 Attributes Attrs;
Douglas Gregor82e52372012-11-06 19:39:40 +00001201 parseOptionalAttributes(Attrs);
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001202
Douglas Gregora30cfe52011-11-11 19:10:28 +00001203 // Parse the opening brace.
1204 if (!Tok.is(MMToken::LBrace)) {
1205 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1206 << ModuleName;
1207 HadError = true;
1208 return;
1209 }
1210 SourceLocation LBraceLoc = consumeToken();
1211
1212 // Determine whether this (sub)module has already been defined.
Douglas Gregorb7a78192012-01-04 23:32:19 +00001213 if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
Douglas Gregorc634f502012-01-05 00:12:00 +00001214 if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1215 // Skip the module definition.
1216 skipUntil(MMToken::RBrace);
1217 if (Tok.is(MMToken::RBrace))
1218 consumeToken();
1219 else {
1220 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1221 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1222 HadError = true;
1223 }
1224 return;
1225 }
1226
Douglas Gregora30cfe52011-11-11 19:10:28 +00001227 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1228 << ModuleName;
Douglas Gregorb7a78192012-01-04 23:32:19 +00001229 Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001230
1231 // Skip the module definition.
1232 skipUntil(MMToken::RBrace);
1233 if (Tok.is(MMToken::RBrace))
1234 consumeToken();
1235
1236 HadError = true;
1237 return;
1238 }
1239
1240 // Start defining this module.
Douglas Gregorb7a78192012-01-04 23:32:19 +00001241 ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1242 Explicit).first;
1243 ActiveModule->DefinitionLoc = ModuleNameLoc;
Douglas Gregor8f5d7d12013-06-21 16:28:10 +00001244 if (Attrs.IsSystem || IsSystem)
Douglas Gregora1f1fad2012-01-27 19:52:33 +00001245 ActiveModule->IsSystem = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001246
1247 bool Done = false;
1248 do {
1249 switch (Tok.Kind) {
1250 case MMToken::EndOfFile:
1251 case MMToken::RBrace:
1252 Done = true;
1253 break;
Douglas Gregor63a72682013-03-20 00:22:05 +00001254
1255 case MMToken::ConfigMacros:
1256 parseConfigMacros();
1257 break;
1258
Douglas Gregor906d66a2013-03-20 21:10:35 +00001259 case MMToken::Conflict:
1260 parseConflict();
1261 break;
1262
Douglas Gregora30cfe52011-11-11 19:10:28 +00001263 case MMToken::ExplicitKeyword:
Daniel Jasper5f0a3522013-09-11 07:20:44 +00001264 case MMToken::ExternKeyword:
Douglas Gregord620a842011-12-06 17:16:41 +00001265 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00001266 case MMToken::ModuleKeyword:
1267 parseModuleDecl();
1268 break;
Daniel Jasper5f0a3522013-09-11 07:20:44 +00001269
Douglas Gregor90db2602011-12-02 01:47:07 +00001270 case MMToken::ExportKeyword:
1271 parseExportDecl();
1272 break;
Daniel Jasperddd2dfc2013-09-24 09:14:14 +00001273
1274 case MMToken::UseKeyword:
1275 parseUseDecl();
1276 break;
Douglas Gregor90db2602011-12-02 01:47:07 +00001277
Douglas Gregor51f564f2011-12-31 04:05:44 +00001278 case MMToken::RequiresKeyword:
1279 parseRequiresDecl();
1280 break;
1281
Douglas Gregor77d029f2011-12-08 19:11:24 +00001282 case MMToken::UmbrellaKeyword: {
1283 SourceLocation UmbrellaLoc = consumeToken();
1284 if (Tok.is(MMToken::HeaderKeyword))
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001285 parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
Douglas Gregor77d029f2011-12-08 19:11:24 +00001286 else
1287 parseUmbrellaDirDecl(UmbrellaLoc);
Douglas Gregora30cfe52011-11-11 19:10:28 +00001288 break;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001289 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001290
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001291 case MMToken::ExcludeKeyword: {
1292 SourceLocation ExcludeLoc = consumeToken();
1293 if (Tok.is(MMToken::HeaderKeyword)) {
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001294 parseHeaderDecl(MMToken::ExcludeKeyword, ExcludeLoc);
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001295 } else {
1296 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1297 << "exclude";
1298 }
1299 break;
1300 }
1301
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001302 case MMToken::PrivateKeyword: {
1303 SourceLocation PrivateLoc = consumeToken();
1304 if (Tok.is(MMToken::HeaderKeyword)) {
1305 parseHeaderDecl(MMToken::PrivateKeyword, PrivateLoc);
1306 } else {
1307 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1308 << "private";
1309 }
1310 break;
1311 }
1312
Douglas Gregor489ad432011-12-08 18:00:48 +00001313 case MMToken::HeaderKeyword:
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001314 parseHeaderDecl(MMToken::HeaderKeyword, SourceLocation());
Douglas Gregora30cfe52011-11-11 19:10:28 +00001315 break;
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001316
1317 case MMToken::LinkKeyword:
1318 parseLinkDecl();
1319 break;
1320
Douglas Gregora30cfe52011-11-11 19:10:28 +00001321 default:
1322 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1323 consumeToken();
1324 break;
1325 }
1326 } while (!Done);
1327
1328 if (Tok.is(MMToken::RBrace))
1329 consumeToken();
1330 else {
1331 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1332 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1333 HadError = true;
1334 }
1335
Douglas Gregor8767dc22013-01-14 17:57:51 +00001336 // If the active module is a top-level framework, and there are no link
1337 // libraries, automatically link against the framework.
1338 if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
1339 ActiveModule->LinkLibraries.empty()) {
1340 inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
1341 }
1342
Douglas Gregor587986e2011-12-07 02:23:45 +00001343 // We're done parsing this module. Pop back to the previous module.
1344 ActiveModule = PreviousActiveModule;
Douglas Gregora30cfe52011-11-11 19:10:28 +00001345}
Douglas Gregord620a842011-12-06 17:16:41 +00001346
Daniel Jasper5f0a3522013-09-11 07:20:44 +00001347/// \brief Parse an extern module declaration.
1348///
1349/// extern module-declaration:
1350/// 'extern' 'module' module-id string-literal
1351void ModuleMapParser::parseExternModuleDecl() {
1352 assert(Tok.is(MMToken::ExternKeyword));
1353 consumeToken(); // 'extern' keyword
1354
1355 // Parse 'module' keyword.
1356 if (!Tok.is(MMToken::ModuleKeyword)) {
1357 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1358 consumeToken();
1359 HadError = true;
1360 return;
1361 }
1362 consumeToken(); // 'module' keyword
1363
1364 // Parse the module name.
1365 ModuleId Id;
1366 if (parseModuleId(Id)) {
1367 HadError = true;
1368 return;
1369 }
1370
1371 // Parse the referenced module map file name.
1372 if (!Tok.is(MMToken::StringLiteral)) {
1373 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
1374 HadError = true;
1375 return;
1376 }
1377 std::string FileName = Tok.getString();
1378 consumeToken(); // filename
1379
1380 StringRef FileNameRef = FileName;
1381 SmallString<128> ModuleMapFileName;
1382 if (llvm::sys::path::is_relative(FileNameRef)) {
1383 ModuleMapFileName += Directory->getName();
1384 llvm::sys::path::append(ModuleMapFileName, FileName);
1385 FileNameRef = ModuleMapFileName.str();
1386 }
1387 if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
1388 Map.parseModuleMapFile(File, /*IsSystem=*/false);
1389}
1390
Douglas Gregor51f564f2011-12-31 04:05:44 +00001391/// \brief Parse a requires declaration.
1392///
1393/// requires-declaration:
1394/// 'requires' feature-list
1395///
1396/// feature-list:
1397/// identifier ',' feature-list
1398/// identifier
1399void ModuleMapParser::parseRequiresDecl() {
1400 assert(Tok.is(MMToken::RequiresKeyword));
1401
1402 // Parse 'requires' keyword.
1403 consumeToken();
1404
1405 // Parse the feature-list.
1406 do {
1407 if (!Tok.is(MMToken::Identifier)) {
1408 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1409 HadError = true;
1410 return;
1411 }
1412
1413 // Consume the feature name.
1414 std::string Feature = Tok.getString();
1415 consumeToken();
1416
1417 // Add this feature.
Douglas Gregordc58aa72012-01-30 06:01:29 +00001418 ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target);
Douglas Gregor51f564f2011-12-31 04:05:44 +00001419
1420 if (!Tok.is(MMToken::Comma))
1421 break;
1422
1423 // Consume the comma.
1424 consumeToken();
1425 } while (true);
1426}
1427
Douglas Gregord620a842011-12-06 17:16:41 +00001428/// \brief Append to \p Paths the set of paths needed to get to the
1429/// subframework in which the given module lives.
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001430static void appendSubframeworkPaths(Module *Mod,
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00001431 SmallVectorImpl<char> &Path) {
Douglas Gregord620a842011-12-06 17:16:41 +00001432 // Collect the framework names from the given module to the top-level module.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00001433 SmallVector<StringRef, 2> Paths;
Douglas Gregord620a842011-12-06 17:16:41 +00001434 for (; Mod; Mod = Mod->Parent) {
1435 if (Mod->IsFramework)
1436 Paths.push_back(Mod->Name);
1437 }
1438
1439 if (Paths.empty())
1440 return;
1441
1442 // Add Frameworks/Name.framework for each subframework.
Benjamin Kramerceb6dc82013-06-28 16:25:46 +00001443 for (unsigned I = Paths.size() - 1; I != 0; --I)
1444 llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
Douglas Gregord620a842011-12-06 17:16:41 +00001445}
1446
Douglas Gregora30cfe52011-11-11 19:10:28 +00001447/// \brief Parse a header declaration.
1448///
1449/// header-declaration:
Douglas Gregor489ad432011-12-08 18:00:48 +00001450/// 'umbrella'[opt] 'header' string-literal
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001451/// 'exclude'[opt] 'header' string-literal
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001452void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
1453 SourceLocation LeadingLoc) {
Douglas Gregora30cfe52011-11-11 19:10:28 +00001454 assert(Tok.is(MMToken::HeaderKeyword));
Benjamin Kramerc96c7212011-11-13 16:52:09 +00001455 consumeToken();
1456
Douglas Gregora30cfe52011-11-11 19:10:28 +00001457 // Parse the header name.
1458 if (!Tok.is(MMToken::StringLiteral)) {
1459 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1460 << "header";
1461 HadError = true;
1462 return;
1463 }
Douglas Gregor587986e2011-12-07 02:23:45 +00001464 std::string FileName = Tok.getString();
Douglas Gregora30cfe52011-11-11 19:10:28 +00001465 SourceLocation FileNameLoc = consumeToken();
1466
Douglas Gregor77d029f2011-12-08 19:11:24 +00001467 // Check whether we already have an umbrella.
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001468 if (LeadingToken == MMToken::UmbrellaKeyword && ActiveModule->Umbrella) {
Douglas Gregor77d029f2011-12-08 19:11:24 +00001469 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
1470 << ActiveModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001471 HadError = true;
1472 return;
1473 }
1474
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001475 // Look for this file.
Douglas Gregor587986e2011-12-07 02:23:45 +00001476 const FileEntry *File = 0;
Douglas Gregor2f04f182012-02-02 18:42:48 +00001477 const FileEntry *BuiltinFile = 0;
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001478 SmallString<128> PathName;
Douglas Gregor587986e2011-12-07 02:23:45 +00001479 if (llvm::sys::path::is_absolute(FileName)) {
1480 PathName = FileName;
1481 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor6a1db482011-12-09 02:04:43 +00001482 } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
1483 PathName = Dir->getName();
1484 llvm::sys::path::append(PathName, FileName);
1485 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001486 } else {
1487 // Search for the header file within the search directory.
Douglas Gregor6a1db482011-12-09 02:04:43 +00001488 PathName = Directory->getName();
Douglas Gregor587986e2011-12-07 02:23:45 +00001489 unsigned PathLength = PathName.size();
Douglas Gregor18ee5472011-11-29 21:59:16 +00001490
Douglas Gregord620a842011-12-06 17:16:41 +00001491 if (ActiveModule->isPartOfFramework()) {
1492 appendSubframeworkPaths(ActiveModule, PathName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001493
1494 // Check whether this file is in the public headers.
Benjamin Kramerceb6dc82013-06-28 16:25:46 +00001495 llvm::sys::path::append(PathName, "Headers", FileName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001496 File = SourceMgr.getFileManager().getFile(PathName);
1497
1498 if (!File) {
1499 // Check whether this file is in the private headers.
1500 PathName.resize(PathLength);
Benjamin Kramerceb6dc82013-06-28 16:25:46 +00001501 llvm::sys::path::append(PathName, "PrivateHeaders", FileName);
Douglas Gregor587986e2011-12-07 02:23:45 +00001502 File = SourceMgr.getFileManager().getFile(PathName);
1503 }
1504 } else {
1505 // Lookup for normal headers.
1506 llvm::sys::path::append(PathName, FileName);
1507 File = SourceMgr.getFileManager().getFile(PathName);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001508
1509 // If this is a system module with a top-level header, this header
1510 // may have a counterpart (or replacement) in the set of headers
1511 // supplied by Clang. Find that builtin header.
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001512 if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword &&
1513 BuiltinIncludeDir && BuiltinIncludeDir != Directory &&
1514 isBuiltinHeader(FileName)) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001515 SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
Douglas Gregor2f04f182012-02-02 18:42:48 +00001516 llvm::sys::path::append(BuiltinPathName, FileName);
1517 BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1518
1519 // If Clang supplies this header but the underlying system does not,
1520 // just silently swap in our builtin version. Otherwise, we'll end
1521 // up adding both (later).
1522 if (!File && BuiltinFile) {
1523 File = BuiltinFile;
1524 BuiltinFile = 0;
1525 }
1526 }
Douglas Gregord620a842011-12-06 17:16:41 +00001527 }
Douglas Gregor18ee5472011-11-29 21:59:16 +00001528 }
Douglas Gregora8654052011-11-17 22:09:43 +00001529
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001530 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1531 // Come up with a lazy way to do this.
Douglas Gregor587986e2011-12-07 02:23:45 +00001532 if (File) {
Daniel Jasperc6417092013-10-22 08:09:47 +00001533 if (LeadingToken == MMToken::UmbrellaKeyword) {
Douglas Gregor489ad432011-12-08 18:00:48 +00001534 const DirectoryEntry *UmbrellaDir = File->getDir();
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001535 if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001536 Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash)
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00001537 << UmbrellaModule->getFullModuleName();
Douglas Gregor489ad432011-12-08 18:00:48 +00001538 HadError = true;
1539 } else {
1540 // Record this umbrella header.
1541 Map.setUmbrellaHeader(ActiveModule, File);
1542 }
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001543 } else {
Douglas Gregor489ad432011-12-08 18:00:48 +00001544 // Record this header.
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001545 ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
1546 if (LeadingToken == MMToken::ExcludeKeyword)
1547 Role = ModuleMap::ExcludedHeader;
1548 else if (LeadingToken == MMToken::PrivateKeyword)
1549 Role = ModuleMap::PrivateHeader;
1550 else
1551 assert(LeadingToken == MMToken::HeaderKeyword);
1552
1553 Map.addHeader(ActiveModule, File, Role);
Douglas Gregor2f04f182012-02-02 18:42:48 +00001554
1555 // If there is a builtin counterpart to this file, add it now.
1556 if (BuiltinFile)
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001557 Map.addHeader(ActiveModule, BuiltinFile, Role);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001558 }
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001559 } else if (LeadingToken != MMToken::ExcludeKeyword) {
Douglas Gregor71f49f52012-11-15 19:47:16 +00001560 // Ignore excluded header files. They're optional anyway.
1561
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001562 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001563 << (LeadingToken == MMToken::UmbrellaKeyword) << FileName;
Douglas Gregor8b6d3de2011-11-11 21:55:48 +00001564 HadError = true;
1565 }
Douglas Gregora30cfe52011-11-11 19:10:28 +00001566}
1567
Douglas Gregor77d029f2011-12-08 19:11:24 +00001568/// \brief Parse an umbrella directory declaration.
1569///
1570/// umbrella-dir-declaration:
1571/// umbrella string-literal
1572void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1573 // Parse the directory name.
1574 if (!Tok.is(MMToken::StringLiteral)) {
1575 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1576 << "umbrella";
1577 HadError = true;
1578 return;
1579 }
1580
1581 std::string DirName = Tok.getString();
1582 SourceLocation DirNameLoc = consumeToken();
1583
1584 // Check whether we already have an umbrella.
1585 if (ActiveModule->Umbrella) {
1586 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1587 << ActiveModule->getFullModuleName();
1588 HadError = true;
1589 return;
1590 }
1591
1592 // Look for this file.
1593 const DirectoryEntry *Dir = 0;
1594 if (llvm::sys::path::is_absolute(DirName))
1595 Dir = SourceMgr.getFileManager().getDirectory(DirName);
1596 else {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00001597 SmallString<128> PathName;
Douglas Gregor77d029f2011-12-08 19:11:24 +00001598 PathName = Directory->getName();
1599 llvm::sys::path::append(PathName, DirName);
1600 Dir = SourceMgr.getFileManager().getDirectory(PathName);
1601 }
1602
1603 if (!Dir) {
1604 Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1605 << DirName;
1606 HadError = true;
1607 return;
1608 }
1609
1610 if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1611 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1612 << OwningModule->getFullModuleName();
1613 HadError = true;
1614 return;
1615 }
1616
1617 // Record this umbrella directory.
1618 Map.setUmbrellaDir(ActiveModule, Dir);
1619}
1620
Douglas Gregor90db2602011-12-02 01:47:07 +00001621/// \brief Parse a module export declaration.
1622///
1623/// export-declaration:
1624/// 'export' wildcard-module-id
1625///
1626/// wildcard-module-id:
1627/// identifier
1628/// '*'
1629/// identifier '.' wildcard-module-id
1630void ModuleMapParser::parseExportDecl() {
1631 assert(Tok.is(MMToken::ExportKeyword));
1632 SourceLocation ExportLoc = consumeToken();
1633
1634 // Parse the module-id with an optional wildcard at the end.
1635 ModuleId ParsedModuleId;
1636 bool Wildcard = false;
1637 do {
1638 if (Tok.is(MMToken::Identifier)) {
1639 ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1640 Tok.getLocation()));
1641 consumeToken();
1642
1643 if (Tok.is(MMToken::Period)) {
1644 consumeToken();
1645 continue;
1646 }
1647
1648 break;
1649 }
1650
1651 if(Tok.is(MMToken::Star)) {
1652 Wildcard = true;
Douglas Gregor0adaa882011-12-05 17:28:06 +00001653 consumeToken();
Douglas Gregor90db2602011-12-02 01:47:07 +00001654 break;
1655 }
1656
Daniel Jasperddd2dfc2013-09-24 09:14:14 +00001657 Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
Douglas Gregor90db2602011-12-02 01:47:07 +00001658 HadError = true;
1659 return;
1660 } while (true);
1661
1662 Module::UnresolvedExportDecl Unresolved = {
1663 ExportLoc, ParsedModuleId, Wildcard
1664 };
1665 ActiveModule->UnresolvedExports.push_back(Unresolved);
1666}
1667
Daniel Jasperddd2dfc2013-09-24 09:14:14 +00001668/// \brief Parse a module uses declaration.
1669///
1670/// uses-declaration:
1671/// 'uses' wildcard-module-id
1672void ModuleMapParser::parseUseDecl() {
1673 assert(Tok.is(MMToken::UseKeyword));
1674 consumeToken();
1675 // Parse the module-id.
1676 ModuleId ParsedModuleId;
1677
1678 do {
1679 if (Tok.is(MMToken::Identifier)) {
1680 ParsedModuleId.push_back(
1681 std::make_pair(Tok.getString(), Tok.getLocation()));
1682 consumeToken();
1683
1684 if (Tok.is(MMToken::Period)) {
1685 consumeToken();
1686 continue;
1687 }
1688
1689 break;
1690 }
1691
1692 Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
1693 HadError = true;
1694 return;
1695 } while (true);
1696
1697 ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
1698}
1699
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001700/// \brief Parse a link declaration.
1701///
1702/// module-declaration:
1703/// 'link' 'framework'[opt] string-literal
1704void ModuleMapParser::parseLinkDecl() {
1705 assert(Tok.is(MMToken::LinkKeyword));
1706 SourceLocation LinkLoc = consumeToken();
1707
1708 // Parse the optional 'framework' keyword.
1709 bool IsFramework = false;
1710 if (Tok.is(MMToken::FrameworkKeyword)) {
1711 consumeToken();
1712 IsFramework = true;
1713 }
1714
1715 // Parse the library name
1716 if (!Tok.is(MMToken::StringLiteral)) {
1717 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
1718 << IsFramework << SourceRange(LinkLoc);
1719 HadError = true;
1720 return;
1721 }
1722
1723 std::string LibraryName = Tok.getString();
1724 consumeToken();
1725 ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
1726 IsFramework));
1727}
1728
Douglas Gregor63a72682013-03-20 00:22:05 +00001729/// \brief Parse a configuration macro declaration.
1730///
1731/// module-declaration:
1732/// 'config_macros' attributes[opt] config-macro-list?
1733///
1734/// config-macro-list:
1735/// identifier (',' identifier)?
1736void ModuleMapParser::parseConfigMacros() {
1737 assert(Tok.is(MMToken::ConfigMacros));
1738 SourceLocation ConfigMacrosLoc = consumeToken();
1739
1740 // Only top-level modules can have configuration macros.
1741 if (ActiveModule->Parent) {
1742 Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
1743 }
1744
1745 // Parse the optional attributes.
1746 Attributes Attrs;
1747 parseOptionalAttributes(Attrs);
1748 if (Attrs.IsExhaustive && !ActiveModule->Parent) {
1749 ActiveModule->ConfigMacrosExhaustive = true;
1750 }
1751
1752 // If we don't have an identifier, we're done.
1753 if (!Tok.is(MMToken::Identifier))
1754 return;
1755
1756 // Consume the first identifier.
1757 if (!ActiveModule->Parent) {
1758 ActiveModule->ConfigMacros.push_back(Tok.getString().str());
1759 }
1760 consumeToken();
1761
1762 do {
1763 // If there's a comma, consume it.
1764 if (!Tok.is(MMToken::Comma))
1765 break;
1766 consumeToken();
1767
1768 // We expect to see a macro name here.
1769 if (!Tok.is(MMToken::Identifier)) {
1770 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
1771 break;
1772 }
1773
1774 // Consume the macro name.
1775 if (!ActiveModule->Parent) {
1776 ActiveModule->ConfigMacros.push_back(Tok.getString().str());
1777 }
1778 consumeToken();
1779 } while (true);
1780}
1781
Douglas Gregor906d66a2013-03-20 21:10:35 +00001782/// \brief Format a module-id into a string.
1783static std::string formatModuleId(const ModuleId &Id) {
1784 std::string result;
1785 {
1786 llvm::raw_string_ostream OS(result);
1787
1788 for (unsigned I = 0, N = Id.size(); I != N; ++I) {
1789 if (I)
1790 OS << ".";
1791 OS << Id[I].first;
1792 }
1793 }
1794
1795 return result;
1796}
1797
1798/// \brief Parse a conflict declaration.
1799///
1800/// module-declaration:
1801/// 'conflict' module-id ',' string-literal
1802void ModuleMapParser::parseConflict() {
1803 assert(Tok.is(MMToken::Conflict));
1804 SourceLocation ConflictLoc = consumeToken();
1805 Module::UnresolvedConflict Conflict;
1806
1807 // Parse the module-id.
1808 if (parseModuleId(Conflict.Id))
1809 return;
1810
1811 // Parse the ','.
1812 if (!Tok.is(MMToken::Comma)) {
1813 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
1814 << SourceRange(ConflictLoc);
1815 return;
1816 }
1817 consumeToken();
1818
1819 // Parse the message.
1820 if (!Tok.is(MMToken::StringLiteral)) {
1821 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
1822 << formatModuleId(Conflict.Id);
1823 return;
1824 }
1825 Conflict.Message = Tok.getString().str();
1826 consumeToken();
1827
1828 // Add this unresolved conflict.
1829 ActiveModule->UnresolvedConflicts.push_back(Conflict);
1830}
1831
Douglas Gregorb6cbe512013-01-14 17:21:00 +00001832/// \brief Parse an inferred module declaration (wildcard modules).
Douglas Gregor82e52372012-11-06 19:39:40 +00001833///
1834/// module-declaration:
1835/// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
1836/// { inferred-module-member* }
1837///
1838/// inferred-module-member:
1839/// 'export' '*'
1840/// 'exclude' identifier
1841void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001842 assert(Tok.is(MMToken::Star));
1843 SourceLocation StarLoc = consumeToken();
1844 bool Failed = false;
Douglas Gregor82e52372012-11-06 19:39:40 +00001845
Douglas Gregor1e123682011-12-05 22:27:44 +00001846 // Inferred modules must be submodules.
Douglas Gregor82e52372012-11-06 19:39:40 +00001847 if (!ActiveModule && !Framework) {
Douglas Gregor1e123682011-12-05 22:27:44 +00001848 Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
1849 Failed = true;
1850 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001851
1852 if (ActiveModule) {
1853 // Inferred modules must have umbrella directories.
1854 if (!Failed && !ActiveModule->getUmbrellaDir()) {
1855 Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
1856 Failed = true;
1857 }
1858
1859 // Check for redefinition of an inferred module.
1860 if (!Failed && ActiveModule->InferSubmodules) {
1861 Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
1862 if (ActiveModule->InferredSubmoduleLoc.isValid())
1863 Diags.Report(ActiveModule->InferredSubmoduleLoc,
1864 diag::note_mmap_prev_definition);
1865 Failed = true;
1866 }
1867
1868 // Check for the 'framework' keyword, which is not permitted here.
1869 if (Framework) {
1870 Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
1871 Framework = false;
1872 }
1873 } else if (Explicit) {
1874 Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
1875 Explicit = false;
Douglas Gregor1e123682011-12-05 22:27:44 +00001876 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001877
Douglas Gregor1e123682011-12-05 22:27:44 +00001878 // If there were any problems with this inferred submodule, skip its body.
1879 if (Failed) {
1880 if (Tok.is(MMToken::LBrace)) {
1881 consumeToken();
1882 skipUntil(MMToken::RBrace);
1883 if (Tok.is(MMToken::RBrace))
1884 consumeToken();
1885 }
1886 HadError = true;
1887 return;
1888 }
Douglas Gregor82e52372012-11-06 19:39:40 +00001889
1890 // Parse optional attributes.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001891 Attributes Attrs;
Douglas Gregor82e52372012-11-06 19:39:40 +00001892 parseOptionalAttributes(Attrs);
1893
1894 if (ActiveModule) {
1895 // Note that we have an inferred submodule.
1896 ActiveModule->InferSubmodules = true;
1897 ActiveModule->InferredSubmoduleLoc = StarLoc;
1898 ActiveModule->InferExplicitSubmodules = Explicit;
1899 } else {
1900 // We'll be inferring framework modules for this directory.
1901 Map.InferredDirectories[Directory].InferModules = true;
1902 Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem;
1903 }
1904
Douglas Gregor1e123682011-12-05 22:27:44 +00001905 // Parse the opening brace.
1906 if (!Tok.is(MMToken::LBrace)) {
1907 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
1908 HadError = true;
1909 return;
1910 }
1911 SourceLocation LBraceLoc = consumeToken();
1912
1913 // Parse the body of the inferred submodule.
1914 bool Done = false;
1915 do {
1916 switch (Tok.Kind) {
1917 case MMToken::EndOfFile:
1918 case MMToken::RBrace:
1919 Done = true;
1920 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001921
1922 case MMToken::ExcludeKeyword: {
1923 if (ActiveModule) {
1924 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001925 << (ActiveModule != 0);
Douglas Gregor82e52372012-11-06 19:39:40 +00001926 consumeToken();
1927 break;
1928 }
1929
1930 consumeToken();
1931 if (!Tok.is(MMToken::Identifier)) {
1932 Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
1933 break;
1934 }
1935
1936 Map.InferredDirectories[Directory].ExcludedModules
1937 .push_back(Tok.getString());
1938 consumeToken();
1939 break;
1940 }
1941
1942 case MMToken::ExportKeyword:
1943 if (!ActiveModule) {
1944 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001945 << (ActiveModule != 0);
Douglas Gregor82e52372012-11-06 19:39:40 +00001946 consumeToken();
1947 break;
1948 }
1949
Douglas Gregor1e123682011-12-05 22:27:44 +00001950 consumeToken();
1951 if (Tok.is(MMToken::Star))
Douglas Gregoref85b562011-12-06 17:34:58 +00001952 ActiveModule->InferExportWildcard = true;
Douglas Gregor1e123682011-12-05 22:27:44 +00001953 else
1954 Diags.Report(Tok.getLocation(),
1955 diag::err_mmap_expected_export_wildcard);
1956 consumeToken();
1957 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00001958
Douglas Gregor1e123682011-12-05 22:27:44 +00001959 case MMToken::ExplicitKeyword:
1960 case MMToken::ModuleKeyword:
1961 case MMToken::HeaderKeyword:
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00001962 case MMToken::PrivateKeyword:
Douglas Gregor1e123682011-12-05 22:27:44 +00001963 case MMToken::UmbrellaKeyword:
1964 default:
Douglas Gregor82e52372012-11-06 19:39:40 +00001965 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
Douglas Gregorb7ac5ac2012-11-06 19:41:11 +00001966 << (ActiveModule != 0);
Douglas Gregor1e123682011-12-05 22:27:44 +00001967 consumeToken();
1968 break;
1969 }
1970 } while (!Done);
1971
1972 if (Tok.is(MMToken::RBrace))
1973 consumeToken();
1974 else {
1975 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1976 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1977 HadError = true;
1978 }
1979}
1980
Douglas Gregor82e52372012-11-06 19:39:40 +00001981/// \brief Parse optional attributes.
1982///
1983/// attributes:
1984/// attribute attributes
1985/// attribute
1986///
1987/// attribute:
1988/// [ identifier ]
1989///
1990/// \param Attrs Will be filled in with the parsed attributes.
1991///
1992/// \returns true if an error occurred, false otherwise.
Bill Wendlingad017fa2012-12-20 19:22:21 +00001993bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
Douglas Gregor82e52372012-11-06 19:39:40 +00001994 bool HadError = false;
1995
1996 while (Tok.is(MMToken::LSquare)) {
1997 // Consume the '['.
1998 SourceLocation LSquareLoc = consumeToken();
1999
2000 // Check whether we have an attribute name here.
2001 if (!Tok.is(MMToken::Identifier)) {
2002 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
2003 skipUntil(MMToken::RSquare);
2004 if (Tok.is(MMToken::RSquare))
2005 consumeToken();
2006 HadError = true;
2007 }
2008
2009 // Decode the attribute name.
2010 AttributeKind Attribute
2011 = llvm::StringSwitch<AttributeKind>(Tok.getString())
Douglas Gregor63a72682013-03-20 00:22:05 +00002012 .Case("exhaustive", AT_exhaustive)
Douglas Gregor82e52372012-11-06 19:39:40 +00002013 .Case("system", AT_system)
2014 .Default(AT_unknown);
2015 switch (Attribute) {
2016 case AT_unknown:
2017 Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
2018 << Tok.getString();
2019 break;
2020
2021 case AT_system:
2022 Attrs.IsSystem = true;
2023 break;
Douglas Gregor63a72682013-03-20 00:22:05 +00002024
2025 case AT_exhaustive:
2026 Attrs.IsExhaustive = true;
2027 break;
Douglas Gregor82e52372012-11-06 19:39:40 +00002028 }
2029 consumeToken();
2030
2031 // Consume the ']'.
2032 if (!Tok.is(MMToken::RSquare)) {
2033 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
2034 Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
2035 skipUntil(MMToken::RSquare);
2036 HadError = true;
2037 }
2038
2039 if (Tok.is(MMToken::RSquare))
2040 consumeToken();
2041 }
2042
2043 return HadError;
2044}
2045
Douglas Gregor6a1db482011-12-09 02:04:43 +00002046/// \brief If there is a specific header search directory due the presence
2047/// of an umbrella directory, retrieve that directory. Otherwise, returns null.
2048const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() {
2049 for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) {
2050 // If we have an umbrella directory, use that.
2051 if (Mod->hasUmbrellaDir())
2052 return Mod->getUmbrellaDir();
2053
2054 // If we have a framework directory, stop looking.
2055 if (Mod->IsFramework)
2056 return 0;
2057 }
2058
2059 return 0;
2060}
2061
Douglas Gregora30cfe52011-11-11 19:10:28 +00002062/// \brief Parse a module map file.
2063///
2064/// module-map-file:
2065/// module-declaration*
2066bool ModuleMapParser::parseModuleMapFile() {
2067 do {
2068 switch (Tok.Kind) {
2069 case MMToken::EndOfFile:
2070 return HadError;
2071
Douglas Gregor587986e2011-12-07 02:23:45 +00002072 case MMToken::ExplicitKeyword:
Daniel Jasper5f0a3522013-09-11 07:20:44 +00002073 case MMToken::ExternKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00002074 case MMToken::ModuleKeyword:
Douglas Gregora8654052011-11-17 22:09:43 +00002075 case MMToken::FrameworkKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00002076 parseModuleDecl();
2077 break;
Douglas Gregorb6cbe512013-01-14 17:21:00 +00002078
Douglas Gregor51f564f2011-12-31 04:05:44 +00002079 case MMToken::Comma:
Douglas Gregor63a72682013-03-20 00:22:05 +00002080 case MMToken::ConfigMacros:
Douglas Gregor906d66a2013-03-20 21:10:35 +00002081 case MMToken::Conflict:
Douglas Gregor2b49d1f2012-10-15 06:28:11 +00002082 case MMToken::ExcludeKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00002083 case MMToken::ExportKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00002084 case MMToken::HeaderKeyword:
2085 case MMToken::Identifier:
2086 case MMToken::LBrace:
Douglas Gregorb6cbe512013-01-14 17:21:00 +00002087 case MMToken::LinkKeyword:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00002088 case MMToken::LSquare:
Douglas Gregor90db2602011-12-02 01:47:07 +00002089 case MMToken::Period:
Lawrence Crowlbc3f6282013-06-20 21:14:14 +00002090 case MMToken::PrivateKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00002091 case MMToken::RBrace:
Douglas Gregora1f1fad2012-01-27 19:52:33 +00002092 case MMToken::RSquare:
Douglas Gregor51f564f2011-12-31 04:05:44 +00002093 case MMToken::RequiresKeyword:
Douglas Gregor90db2602011-12-02 01:47:07 +00002094 case MMToken::Star:
Douglas Gregora30cfe52011-11-11 19:10:28 +00002095 case MMToken::StringLiteral:
2096 case MMToken::UmbrellaKeyword:
Daniel Jasperddd2dfc2013-09-24 09:14:14 +00002097 case MMToken::UseKeyword:
Douglas Gregora30cfe52011-11-11 19:10:28 +00002098 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2099 HadError = true;
2100 consumeToken();
2101 break;
2102 }
2103 } while (true);
Douglas Gregora30cfe52011-11-11 19:10:28 +00002104}
2105
Douglas Gregor8f5d7d12013-06-21 16:28:10 +00002106bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) {
Douglas Gregor7005b902013-01-10 01:43:00 +00002107 llvm::DenseMap<const FileEntry *, bool>::iterator Known
2108 = ParsedModuleMap.find(File);
2109 if (Known != ParsedModuleMap.end())
2110 return Known->second;
2111
Douglas Gregordc58aa72012-01-30 06:01:29 +00002112 assert(Target != 0 && "Missing target information");
Douglas Gregora30cfe52011-11-11 19:10:28 +00002113 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
2114 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
2115 if (!Buffer)
Douglas Gregor7005b902013-01-10 01:43:00 +00002116 return ParsedModuleMap[File] = true;
Douglas Gregora30cfe52011-11-11 19:10:28 +00002117
2118 // Parse this module map file.
Douglas Gregor51f564f2011-12-31 04:05:44 +00002119 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts);
2120 Diags->getClient()->BeginSourceFile(MMapLangOpts);
Douglas Gregor9a022bb2012-10-15 16:45:32 +00002121 ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(),
Douglas Gregor8f5d7d12013-06-21 16:28:10 +00002122 BuiltinIncludeDir, IsSystem);
Douglas Gregora30cfe52011-11-11 19:10:28 +00002123 bool Result = Parser.parseModuleMapFile();
2124 Diags->getClient()->EndSourceFile();
Douglas Gregor7005b902013-01-10 01:43:00 +00002125 ParsedModuleMap[File] = Result;
Douglas Gregora30cfe52011-11-11 19:10:28 +00002126 return Result;
2127}