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