blob: 7defe01a67fc04cdb5664b4f45411916757f6a0c [file] [log] [blame]
Douglas Gregora30cfe52011-11-11 19:10:28 +00001//===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the ModuleMap implementation, which describes the layout
11// of a module as it relates to headers.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/Lex/ModuleMap.h"
15#include "clang/Lex/Lexer.h"
16#include "clang/Lex/LiteralSupport.h"
17#include "clang/Lex/LexDiagnostic.h"
18#include "clang/Basic/Diagnostic.h"
19#include "clang/Basic/FileManager.h"
20#include "clang/Basic/TargetInfo.h"
21#include "clang/Basic/TargetOptions.h"
22#include "llvm/Support/Allocator.h"
23#include "llvm/Support/Host.h"
Douglas Gregor8b6d3de2011-11-11 21:55:48 +000024#include "llvm/Support/PathV2.h"
Douglas Gregora30cfe52011-11-11 19:10:28 +000025#include "llvm/Support/raw_ostream.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/ADT/StringSwitch.h"
28using namespace clang;
29
30//----------------------------------------------------------------------------//
31// Module
32//----------------------------------------------------------------------------//
33
34std::string ModuleMap::Module::getFullModuleName() const {
35 llvm::SmallVector<StringRef, 2> Names;
36
37 // Build up the set of module names (from innermost to outermost).
38 for (const Module *M = this; M; M = M->Parent)
39 Names.push_back(M->Name);
40
41 std::string Result;
42 for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
43 IEnd = Names.rend();
44 I != IEnd; ++I) {
45 if (!Result.empty())
46 Result += '.';
47
48 Result += *I;
49 }
50
51 return Result;
52}
53
Douglas Gregor65f3b5e2011-11-11 22:18:48 +000054StringRef ModuleMap::Module::getTopLevelModuleName() const {
55 const Module *Top = this;
56 while (Top->Parent)
57 Top = Top->Parent;
58
59 return Top->Name;
60}
61
Douglas Gregora30cfe52011-11-11 19:10:28 +000062//----------------------------------------------------------------------------//
63// Module map
64//----------------------------------------------------------------------------//
65
66ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
67 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
68 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
69 new DiagnosticsEngine(DiagIDs));
70 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
71 SourceMgr = new SourceManager(*Diags, FileMgr);
72}
73
74ModuleMap::~ModuleMap() {
75 delete SourceMgr;
76}
77
Douglas Gregor65f3b5e2011-11-11 22:18:48 +000078ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
79 llvm::DenseMap<const FileEntry *, Module *>::iterator Known
80 = Headers.find(File);
81 if (Known != Headers.end())
82 return Known->second;
83
84 return 0;
85}
86
Douglas Gregora30cfe52011-11-11 19:10:28 +000087static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
88 OS << std::string(' ', Spaces);
89}
90
91static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M,
92 unsigned Indent) {
93 indent(OS, Indent);
94 if (M->IsExplicit)
95 OS << "explicit ";
96 OS << M->Name << " {\n";
97
98 if (M->UmbrellaHeader) {
99 indent(OS, Indent + 2);
100 OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n";
101 }
102
103 for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) {
104 indent(OS, Indent + 2);
105 OS << "header \"" << M->Headers[I]->getName() << "\"\n";
106 }
107
108 for (llvm::StringMap<ModuleMap::Module *>::iterator
109 MI = M->SubModules.begin(),
110 MIEnd = M->SubModules.end();
111 MI != MIEnd; ++MI)
112 dumpModule(llvm::errs(), MI->getValue(), Indent + 2);
113
114 indent(OS, Indent);
115 OS << "}\n";
116}
117
118void ModuleMap::dump() {
119 llvm::errs() << "Modules:";
120 for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
121 MEnd = Modules.end();
122 M != MEnd; ++M)
123 dumpModule(llvm::errs(), M->getValue(), 2);
124
125 llvm::errs() << "Headers:";
126 for (llvm::DenseMap<const FileEntry *, Module *>::iterator
127 H = Headers.begin(),
128 HEnd = Headers.end();
129 H != HEnd; ++H) {
130 llvm::errs() << " \"" << H->first->getName() << "\" -> "
131 << H->second->getFullModuleName() << "\n";
132 }
133}
134
135//----------------------------------------------------------------------------//
136// Module map file parser
137//----------------------------------------------------------------------------//
138
139namespace clang {
140 /// \brief A token in a module map file.
141 struct MMToken {
142 enum TokenKind {
143 EndOfFile,
144 HeaderKeyword,
145 Identifier,
146 ExplicitKeyword,
147 ModuleKeyword,
148 UmbrellaKeyword,
149 StringLiteral,
150 LBrace,
151 RBrace
152 } Kind;
153
154 unsigned Location;
155 unsigned StringLength;
156 const char *StringData;
157
158 void clear() {
159 Kind = EndOfFile;
160 Location = 0;
161 StringLength = 0;
162 StringData = 0;
163 }
164
165 bool is(TokenKind K) const { return Kind == K; }
166
167 SourceLocation getLocation() const {
168 return SourceLocation::getFromRawEncoding(Location);
169 }
170
171 StringRef getString() const {
172 return StringRef(StringData, StringLength);
173 }
174 };
175
176 class ModuleMapParser {
177 Lexer &L;
178 SourceManager &SourceMgr;
179 DiagnosticsEngine &Diags;
180 ModuleMap &Map;
181
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000182 /// \brief The directory that this module map resides in.
183 const DirectoryEntry *Directory;
184
Douglas Gregora30cfe52011-11-11 19:10:28 +0000185 /// \brief Whether an error occurred.
186 bool HadError;
187
188 /// \brief Default target information, used only for string literal
189 /// parsing.
190 TargetInfo *Target;
191
192 /// \brief Stores string data for the various string literals referenced
193 /// during parsing.
194 llvm::BumpPtrAllocator StringData;
195
196 /// \brief The current token.
197 MMToken Tok;
198
199 /// \brief The active module.
200 ModuleMap::Module *ActiveModule;
201
202 /// \brief Consume the current token and return its location.
203 SourceLocation consumeToken();
204
205 /// \brief Skip tokens until we reach the a token with the given kind
206 /// (or the end of the file).
207 void skipUntil(MMToken::TokenKind K);
208
209 void parseModuleDecl();
210 void parseUmbrellaDecl();
211 void parseHeaderDecl();
212
213 public:
214 typedef ModuleMap::Module Module;
215
216 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
217 DiagnosticsEngine &Diags,
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000218 ModuleMap &Map,
219 const DirectoryEntry *Directory)
220 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
221 Directory(Directory), HadError(false), ActiveModule(0)
Douglas Gregora30cfe52011-11-11 19:10:28 +0000222 {
223 TargetOptions TargetOpts;
224 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
225 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
226
227 Tok.clear();
228 consumeToken();
229 }
230
231 bool parseModuleMapFile();
232 };
233}
234
235SourceLocation ModuleMapParser::consumeToken() {
236retry:
237 SourceLocation Result = Tok.getLocation();
238 Tok.clear();
239
240 Token LToken;
241 L.LexFromRawLexer(LToken);
242 Tok.Location = LToken.getLocation().getRawEncoding();
243 switch (LToken.getKind()) {
244 case tok::raw_identifier:
245 Tok.StringData = LToken.getRawIdentifierData();
246 Tok.StringLength = LToken.getLength();
247 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
248 .Case("header", MMToken::HeaderKeyword)
249 .Case("explicit", MMToken::ExplicitKeyword)
250 .Case("module", MMToken::ModuleKeyword)
251 .Case("umbrella", MMToken::UmbrellaKeyword)
252 .Default(MMToken::Identifier);
253 break;
254
255 case tok::eof:
256 Tok.Kind = MMToken::EndOfFile;
257 break;
258
259 case tok::l_brace:
260 Tok.Kind = MMToken::LBrace;
261 break;
262
263 case tok::r_brace:
264 Tok.Kind = MMToken::RBrace;
265 break;
266
267 case tok::string_literal: {
268 // Parse the string literal.
269 LangOptions LangOpts;
270 StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
271 if (StringLiteral.hadError)
272 goto retry;
273
274 // Copy the string literal into our string data allocator.
275 unsigned Length = StringLiteral.GetStringLength();
276 char *Saved = StringData.Allocate<char>(Length + 1);
277 memcpy(Saved, StringLiteral.GetString().data(), Length);
278 Saved[Length] = 0;
279
280 // Form the token.
281 Tok.Kind = MMToken::StringLiteral;
282 Tok.StringData = Saved;
283 Tok.StringLength = Length;
284 break;
285 }
286
287 case tok::comment:
288 goto retry;
289
290 default:
291 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
292 HadError = true;
293 goto retry;
294 }
295
296 return Result;
297}
298
299void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
300 unsigned braceDepth = 0;
301 do {
302 switch (Tok.Kind) {
303 case MMToken::EndOfFile:
304 return;
305
306 case MMToken::LBrace:
307 if (Tok.is(K) && braceDepth == 0)
308 return;
309
310 ++braceDepth;
311 break;
312
313 case MMToken::RBrace:
314 if (braceDepth > 0)
315 --braceDepth;
316 else if (Tok.is(K))
317 return;
318 break;
319
320 default:
321 if (braceDepth == 0 && Tok.is(K))
322 return;
323 break;
324 }
325
326 consumeToken();
327 } while (true);
328}
329
330/// \brief Parse a module declaration.
331///
332/// module-declaration:
333/// 'module' identifier { module-member* }
334///
335/// module-member:
336/// umbrella-declaration
337/// header-declaration
338/// 'explicit'[opt] module-declaration
339void ModuleMapParser::parseModuleDecl() {
340 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword));
341
342 // Parse 'explicit' keyword, if present.
343 bool Explicit = false;
344 if (Tok.is(MMToken::ExplicitKeyword)) {
345 consumeToken();
346 Explicit = true;
347 }
348
349 // Parse 'module' keyword.
350 if (!Tok.is(MMToken::ModuleKeyword)) {
351 Diags.Report(Tok.getLocation(),
352 diag::err_mmap_expected_module_after_explicit);
353 consumeToken();
354 HadError = true;
355 return;
356 }
357 consumeToken(); // 'module' keyword
358
359 // Parse the module name.
360 if (!Tok.is(MMToken::Identifier)) {
361 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
362 HadError = true;
363 return;
364 }
365 StringRef ModuleName = Tok.getString();
366 SourceLocation ModuleNameLoc = consumeToken();
367
368 // Parse the opening brace.
369 if (!Tok.is(MMToken::LBrace)) {
370 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
371 << ModuleName;
372 HadError = true;
373 return;
374 }
375 SourceLocation LBraceLoc = consumeToken();
376
377 // Determine whether this (sub)module has already been defined.
378 llvm::StringMap<Module *> &ModuleSpace
379 = ActiveModule? ActiveModule->SubModules : Map.Modules;
380 llvm::StringMap<Module *>::iterator ExistingModule
381 = ModuleSpace.find(ModuleName);
382 if (ExistingModule != ModuleSpace.end()) {
383 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
384 << ModuleName;
385 Diags.Report(ExistingModule->getValue()->DefinitionLoc,
386 diag::note_mmap_prev_definition);
387
388 // Skip the module definition.
389 skipUntil(MMToken::RBrace);
390 if (Tok.is(MMToken::RBrace))
391 consumeToken();
392
393 HadError = true;
394 return;
395 }
396
397 // Start defining this module.
398 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit);
399 ModuleSpace[ModuleName] = ActiveModule;
400
401 bool Done = false;
402 do {
403 switch (Tok.Kind) {
404 case MMToken::EndOfFile:
405 case MMToken::RBrace:
406 Done = true;
407 break;
408
409 case MMToken::ExplicitKeyword:
410 case MMToken::ModuleKeyword:
411 parseModuleDecl();
412 break;
413
414 case MMToken::HeaderKeyword:
415 parseHeaderDecl();
416 break;
417
418 case MMToken::UmbrellaKeyword:
419 parseUmbrellaDecl();
420 break;
421
422 default:
423 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
424 consumeToken();
425 break;
426 }
427 } while (!Done);
428
429 if (Tok.is(MMToken::RBrace))
430 consumeToken();
431 else {
432 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
433 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
434 HadError = true;
435 }
436
437 // We're done parsing this module. Pop back to our parent scope.
438 ActiveModule = ActiveModule->Parent;
439}
440
441/// \brief Parse an umbrella header declaration.
442///
443/// umbrella-declaration:
444/// 'umbrella' string-literal
445void ModuleMapParser::parseUmbrellaDecl() {
446 assert(Tok.is(MMToken::UmbrellaKeyword));
447 SourceLocation UmbrellaLoc = consumeToken();
448
449 // Parse the header name.
450 if (!Tok.is(MMToken::StringLiteral)) {
451 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
452 << "umbrella";
453 HadError = true;
454 return;
455 }
456 StringRef FileName = Tok.getString();
457 SourceLocation FileNameLoc = consumeToken();
458
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000459 // Check whether we already have an umbrella header.
460 if (ActiveModule->UmbrellaHeader) {
461 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
462 << ActiveModule->getFullModuleName()
463 << ActiveModule->UmbrellaHeader->getName();
464 HadError = true;
465 return;
466 }
467
468 // Only top-level modules can have umbrella headers.
469 if (ActiveModule->Parent) {
470 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
471 << ActiveModule->getFullModuleName();
472 HadError = true;
473 return;
474 }
475
476 // Look for this file.
477 llvm::SmallString<128> PathName;
478 PathName += Directory->getName();
479 llvm::sys::path::append(PathName, FileName);
480
481 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
482 // Come up with a lazy way to do this.
483 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
484 if (const Module *OwningModule = Map.Headers[File]) {
485 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
486 << FileName << OwningModule->getFullModuleName();
487 HadError = true;
488 } else {
489 // Record this umbrella header.
490 ActiveModule->UmbrellaHeader = File;
491 Map.Headers[File] = ActiveModule;
492 }
493 } else {
494 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
495 << true << FileName;
496 HadError = true;
497 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000498}
499
500/// \brief Parse a header declaration.
501///
502/// header-declaration:
503/// 'header' string-literal
504void ModuleMapParser::parseHeaderDecl() {
505 assert(Tok.is(MMToken::HeaderKeyword));
506 SourceLocation HeaderLoc = consumeToken();
507
508 // Parse the header name.
509 if (!Tok.is(MMToken::StringLiteral)) {
510 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
511 << "header";
512 HadError = true;
513 return;
514 }
515 StringRef FileName = Tok.getString();
516 SourceLocation FileNameLoc = consumeToken();
517
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000518 // Look for this file.
519 llvm::SmallString<128> PathName;
520 PathName += Directory->getName();
521 llvm::sys::path::append(PathName, FileName);
522
523 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
524 // Come up with a lazy way to do this.
525 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
526 if (const Module *OwningModule = Map.Headers[File]) {
527 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
528 << FileName << OwningModule->getFullModuleName();
529 HadError = true;
530 } else {
531 // Record this file.
532 ActiveModule->Headers.push_back(File);
533 Map.Headers[File] = ActiveModule;
534 }
535 } else {
536 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
537 << false << FileName;
538 HadError = true;
539 }
Douglas Gregora30cfe52011-11-11 19:10:28 +0000540}
541
542/// \brief Parse a module map file.
543///
544/// module-map-file:
545/// module-declaration*
546bool ModuleMapParser::parseModuleMapFile() {
547 do {
548 switch (Tok.Kind) {
549 case MMToken::EndOfFile:
550 return HadError;
551
552 case MMToken::ModuleKeyword:
553 parseModuleDecl();
554 break;
555
556 case MMToken::ExplicitKeyword:
557 case MMToken::HeaderKeyword:
558 case MMToken::Identifier:
559 case MMToken::LBrace:
560 case MMToken::RBrace:
561 case MMToken::StringLiteral:
562 case MMToken::UmbrellaKeyword:
563 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
564 HadError = true;
565 consumeToken();
566 break;
567 }
568 } while (true);
569
570 return HadError;
571}
572
573bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
574 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
575 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
576 if (!Buffer)
577 return true;
578
579 // Parse this module map file.
580 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
581 Diags->getClient()->BeginSourceFile(LangOpts);
Douglas Gregor8b6d3de2011-11-11 21:55:48 +0000582 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
Douglas Gregora30cfe52011-11-11 19:10:28 +0000583 bool Result = Parser.parseModuleMapFile();
584 Diags->getClient()->EndSourceFile();
585
586 return Result;
587}