ModuleMap.cpp revision 484535e45b4d301847a157e943c7823da5d40884
1//===--- 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"
24#include "llvm/Support/PathV2.h"
25#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
54StringRef ModuleMap::Module::getTopLevelModuleName() const {
55  const Module *Top = this;
56  while (Top->Parent)
57    Top = Top->Parent;
58
59  return Top->Name;
60}
61
62//----------------------------------------------------------------------------//
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
78ModuleMap::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
87ModuleMap::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
95static 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
190    /// \brief The directory that this module map resides in.
191    const DirectoryEntry *Directory;
192
193    /// \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,
226                             ModuleMap &Map,
227                             const DirectoryEntry *Directory)
228      : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
229        Directory(Directory), HadError(false), ActiveModule(0)
230    {
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
467  // 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  }
506}
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
526  // 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  }
548}
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);
590  ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
591  bool Result = Parser.parseModuleMapFile();
592  Diags->getClient()->EndSourceFile();
593
594  return Result;
595}
596