ModuleMap.cpp revision 09fe1bb696847e6f1b482e5ac40029d53a2402df
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
34ModuleMap::Module::~Module() {
35  for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
36                                        IEnd = SubModules.end();
37       I != IEnd; ++I) {
38    delete I->getValue();
39  }
40
41}
42
43std::string ModuleMap::Module::getFullModuleName() const {
44  llvm::SmallVector<StringRef, 2> Names;
45
46  // Build up the set of module names (from innermost to outermost).
47  for (const Module *M = this; M; M = M->Parent)
48    Names.push_back(M->Name);
49
50  std::string Result;
51  for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
52                                                      IEnd = Names.rend();
53       I != IEnd; ++I) {
54    if (!Result.empty())
55      Result += '.';
56
57    Result += *I;
58  }
59
60  return Result;
61}
62
63StringRef ModuleMap::Module::getTopLevelModuleName() const {
64  const Module *Top = this;
65  while (Top->Parent)
66    Top = Top->Parent;
67
68  return Top->Name;
69}
70
71//----------------------------------------------------------------------------//
72// Module map
73//----------------------------------------------------------------------------//
74
75ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
76  llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
77  Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
78            new DiagnosticsEngine(DiagIDs));
79  Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
80  SourceMgr = new SourceManager(*Diags, FileMgr);
81}
82
83ModuleMap::~ModuleMap() {
84  for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
85                                        IEnd = Modules.end();
86       I != IEnd; ++I) {
87    delete I->getValue();
88  }
89
90  delete SourceMgr;
91}
92
93ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
94  llvm::DenseMap<const FileEntry *, Module *>::iterator Known
95    = Headers.find(File);
96  if (Known != Headers.end())
97    return Known->second;
98
99  const DirectoryEntry *Dir = File->getDir();
100  llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
101    = UmbrellaDirs.find(Dir);
102  if (KnownDir != UmbrellaDirs.end())
103    return KnownDir->second;
104
105  // Walk up the directory hierarchy looking for umbrella headers.
106  llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
107  StringRef DirName = Dir->getName();
108  do {
109    // Retrieve our parent path.
110    DirName = llvm::sys::path::parent_path(DirName);
111    if (DirName.empty())
112      break;
113
114    // Resolve the parent path to a directory entry.
115    Dir = SourceMgr->getFileManager().getDirectory(DirName);
116    if (!Dir)
117      break;
118
119    KnownDir = UmbrellaDirs.find(Dir);
120    if (KnownDir != UmbrellaDirs.end()) {
121      Module *Result = KnownDir->second;
122
123      // Record each of the directories we stepped through as being part of
124      // the module we found, since the umbrella header covers them all.
125      for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
126        UmbrellaDirs[SkippedDirs[I]] = Result;
127
128      return Result;
129    }
130
131    SkippedDirs.push_back(Dir);
132  } while (true);
133
134  return 0;
135}
136
137ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
138  llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
139  if (Known != Modules.end())
140    return Known->getValue();
141
142  return 0;
143}
144
145ModuleMap::Module *
146ModuleMap::inferFrameworkModule(StringRef ModuleName,
147                                const DirectoryEntry *FrameworkDir) {
148  // Check whether we've already found this module.
149  if (Module *Module = findModule(ModuleName))
150    return Module;
151
152  // Look for an umbrella header.
153  llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
154  llvm::sys::path::append(UmbrellaName, "Headers");
155  llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
156  const FileEntry *UmbrellaHeader
157    = SourceMgr->getFileManager().getFile(UmbrellaName);
158
159  // FIXME: If there's no umbrella header, we could probably scan the
160  // framework to load *everything*. But, it's not clear that this is a good
161  // idea.
162  if (!UmbrellaHeader)
163    return 0;
164
165  Module *Result = new Module(ModuleName, SourceLocation());
166  Result->UmbrellaHeader = UmbrellaHeader;
167  Headers[UmbrellaHeader] = Result;
168  UmbrellaDirs[FrameworkDir] = Result;
169  Modules[ModuleName] = Result;
170  return Result;
171}
172
173static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
174  OS << std::string(' ', Spaces);
175}
176
177static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M,
178                       unsigned Indent) {
179  indent(OS, Indent);
180  if (M->IsExplicit)
181    OS << "explicit ";
182  OS << M->Name << " {\n";
183
184  if (M->UmbrellaHeader) {
185    indent(OS, Indent + 2);
186    OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n";
187  }
188
189  for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) {
190    indent(OS, Indent + 2);
191    OS << "header \"" << M->Headers[I]->getName() << "\"\n";
192  }
193
194  for (llvm::StringMap<ModuleMap::Module *>::iterator
195            MI = M->SubModules.begin(),
196         MIEnd = M->SubModules.end();
197       MI != MIEnd; ++MI)
198    dumpModule(llvm::errs(), MI->getValue(), Indent + 2);
199
200  indent(OS, Indent);
201  OS << "}\n";
202}
203
204void ModuleMap::dump() {
205  llvm::errs() << "Modules:";
206  for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
207                                        MEnd = Modules.end();
208       M != MEnd; ++M)
209    dumpModule(llvm::errs(), M->getValue(), 2);
210
211  llvm::errs() << "Headers:";
212  for (llvm::DenseMap<const FileEntry *, Module *>::iterator
213            H = Headers.begin(),
214         HEnd = Headers.end();
215       H != HEnd; ++H) {
216    llvm::errs() << "  \"" << H->first->getName() << "\" -> "
217                 << H->second->getFullModuleName() << "\n";
218  }
219}
220
221//----------------------------------------------------------------------------//
222// Module map file parser
223//----------------------------------------------------------------------------//
224
225namespace clang {
226  /// \brief A token in a module map file.
227  struct MMToken {
228    enum TokenKind {
229      EndOfFile,
230      HeaderKeyword,
231      Identifier,
232      ExplicitKeyword,
233      ModuleKeyword,
234      UmbrellaKeyword,
235      StringLiteral,
236      LBrace,
237      RBrace
238    } Kind;
239
240    unsigned Location;
241    unsigned StringLength;
242    const char *StringData;
243
244    void clear() {
245      Kind = EndOfFile;
246      Location = 0;
247      StringLength = 0;
248      StringData = 0;
249    }
250
251    bool is(TokenKind K) const { return Kind == K; }
252
253    SourceLocation getLocation() const {
254      return SourceLocation::getFromRawEncoding(Location);
255    }
256
257    StringRef getString() const {
258      return StringRef(StringData, StringLength);
259    }
260  };
261
262  class ModuleMapParser {
263    Lexer &L;
264    SourceManager &SourceMgr;
265    DiagnosticsEngine &Diags;
266    ModuleMap &Map;
267
268    /// \brief The directory that this module map resides in.
269    const DirectoryEntry *Directory;
270
271    /// \brief Whether an error occurred.
272    bool HadError;
273
274    /// \brief Default target information, used only for string literal
275    /// parsing.
276    TargetInfo *Target;
277
278    /// \brief Stores string data for the various string literals referenced
279    /// during parsing.
280    llvm::BumpPtrAllocator StringData;
281
282    /// \brief The current token.
283    MMToken Tok;
284
285    /// \brief The active module.
286    ModuleMap::Module *ActiveModule;
287
288    /// \brief Consume the current token and return its location.
289    SourceLocation consumeToken();
290
291    /// \brief Skip tokens until we reach the a token with the given kind
292    /// (or the end of the file).
293    void skipUntil(MMToken::TokenKind K);
294
295    void parseModuleDecl();
296    void parseUmbrellaDecl();
297    void parseHeaderDecl();
298
299  public:
300    typedef ModuleMap::Module Module;
301
302    explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
303                             DiagnosticsEngine &Diags,
304                             ModuleMap &Map,
305                             const DirectoryEntry *Directory)
306      : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
307        Directory(Directory), HadError(false), ActiveModule(0)
308    {
309      TargetOptions TargetOpts;
310      TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
311      Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
312
313      Tok.clear();
314      consumeToken();
315    }
316
317    bool parseModuleMapFile();
318  };
319}
320
321SourceLocation ModuleMapParser::consumeToken() {
322retry:
323  SourceLocation Result = Tok.getLocation();
324  Tok.clear();
325
326  Token LToken;
327  L.LexFromRawLexer(LToken);
328  Tok.Location = LToken.getLocation().getRawEncoding();
329  switch (LToken.getKind()) {
330  case tok::raw_identifier:
331    Tok.StringData = LToken.getRawIdentifierData();
332    Tok.StringLength = LToken.getLength();
333    Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
334                 .Case("header", MMToken::HeaderKeyword)
335                 .Case("explicit", MMToken::ExplicitKeyword)
336                 .Case("module", MMToken::ModuleKeyword)
337                 .Case("umbrella", MMToken::UmbrellaKeyword)
338                 .Default(MMToken::Identifier);
339    break;
340
341  case tok::eof:
342    Tok.Kind = MMToken::EndOfFile;
343    break;
344
345  case tok::l_brace:
346    Tok.Kind = MMToken::LBrace;
347    break;
348
349  case tok::r_brace:
350    Tok.Kind = MMToken::RBrace;
351    break;
352
353  case tok::string_literal: {
354    // Parse the string literal.
355    LangOptions LangOpts;
356    StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
357    if (StringLiteral.hadError)
358      goto retry;
359
360    // Copy the string literal into our string data allocator.
361    unsigned Length = StringLiteral.GetStringLength();
362    char *Saved = StringData.Allocate<char>(Length + 1);
363    memcpy(Saved, StringLiteral.GetString().data(), Length);
364    Saved[Length] = 0;
365
366    // Form the token.
367    Tok.Kind = MMToken::StringLiteral;
368    Tok.StringData = Saved;
369    Tok.StringLength = Length;
370    break;
371  }
372
373  case tok::comment:
374    goto retry;
375
376  default:
377    Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
378    HadError = true;
379    goto retry;
380  }
381
382  return Result;
383}
384
385void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
386  unsigned braceDepth = 0;
387  do {
388    switch (Tok.Kind) {
389    case MMToken::EndOfFile:
390      return;
391
392    case MMToken::LBrace:
393      if (Tok.is(K) && braceDepth == 0)
394        return;
395
396      ++braceDepth;
397      break;
398
399    case MMToken::RBrace:
400      if (braceDepth > 0)
401        --braceDepth;
402      else if (Tok.is(K))
403        return;
404      break;
405
406    default:
407      if (braceDepth == 0 && Tok.is(K))
408        return;
409      break;
410    }
411
412   consumeToken();
413  } while (true);
414}
415
416/// \brief Parse a module declaration.
417///
418///   module-declaration:
419///     'module' identifier { module-member* }
420///
421///   module-member:
422///     umbrella-declaration
423///     header-declaration
424///     'explicit'[opt] module-declaration
425void ModuleMapParser::parseModuleDecl() {
426  assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword));
427
428  // Parse 'explicit' keyword, if present.
429  bool Explicit = false;
430  if (Tok.is(MMToken::ExplicitKeyword)) {
431    consumeToken();
432    Explicit = true;
433  }
434
435  // Parse 'module' keyword.
436  if (!Tok.is(MMToken::ModuleKeyword)) {
437    Diags.Report(Tok.getLocation(),
438                 diag::err_mmap_expected_module_after_explicit);
439    consumeToken();
440    HadError = true;
441    return;
442  }
443  consumeToken(); // 'module' keyword
444
445  // Parse the module name.
446  if (!Tok.is(MMToken::Identifier)) {
447    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
448    HadError = true;
449    return;
450  }
451  StringRef ModuleName = Tok.getString();
452  SourceLocation ModuleNameLoc = consumeToken();
453
454  // Parse the opening brace.
455  if (!Tok.is(MMToken::LBrace)) {
456    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
457      << ModuleName;
458    HadError = true;
459    return;
460  }
461  SourceLocation LBraceLoc = consumeToken();
462
463  // Determine whether this (sub)module has already been defined.
464  llvm::StringMap<Module *> &ModuleSpace
465    = ActiveModule? ActiveModule->SubModules : Map.Modules;
466  llvm::StringMap<Module *>::iterator ExistingModule
467    = ModuleSpace.find(ModuleName);
468  if (ExistingModule != ModuleSpace.end()) {
469    Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
470      << ModuleName;
471    Diags.Report(ExistingModule->getValue()->DefinitionLoc,
472                 diag::note_mmap_prev_definition);
473
474    // Skip the module definition.
475    skipUntil(MMToken::RBrace);
476    if (Tok.is(MMToken::RBrace))
477      consumeToken();
478
479    HadError = true;
480    return;
481  }
482
483  // Start defining this module.
484  ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit);
485  ModuleSpace[ModuleName] = ActiveModule;
486
487  bool Done = false;
488  do {
489    switch (Tok.Kind) {
490    case MMToken::EndOfFile:
491    case MMToken::RBrace:
492      Done = true;
493      break;
494
495    case MMToken::ExplicitKeyword:
496    case MMToken::ModuleKeyword:
497      parseModuleDecl();
498      break;
499
500    case MMToken::HeaderKeyword:
501      parseHeaderDecl();
502      break;
503
504    case MMToken::UmbrellaKeyword:
505      parseUmbrellaDecl();
506      break;
507
508    default:
509      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
510      consumeToken();
511      break;
512    }
513  } while (!Done);
514
515  if (Tok.is(MMToken::RBrace))
516    consumeToken();
517  else {
518    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
519    Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
520    HadError = true;
521  }
522
523  // We're done parsing this module. Pop back to our parent scope.
524  ActiveModule = ActiveModule->Parent;
525}
526
527/// \brief Parse an umbrella header declaration.
528///
529///   umbrella-declaration:
530///     'umbrella' string-literal
531void ModuleMapParser::parseUmbrellaDecl() {
532  assert(Tok.is(MMToken::UmbrellaKeyword));
533  SourceLocation UmbrellaLoc = consumeToken();
534
535  // Parse the header name.
536  if (!Tok.is(MMToken::StringLiteral)) {
537    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
538      << "umbrella";
539    HadError = true;
540    return;
541  }
542  StringRef FileName = Tok.getString();
543  SourceLocation FileNameLoc = consumeToken();
544
545  // Check whether we already have an umbrella header.
546  if (ActiveModule->UmbrellaHeader) {
547    Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
548      << ActiveModule->getFullModuleName()
549      << ActiveModule->UmbrellaHeader->getName();
550    HadError = true;
551    return;
552  }
553
554  // Only top-level modules can have umbrella headers.
555  if (ActiveModule->Parent) {
556    Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
557      << ActiveModule->getFullModuleName();
558    HadError = true;
559    return;
560  }
561
562  // Look for this file.
563  llvm::SmallString<128> PathName;
564  PathName += Directory->getName();
565  llvm::sys::path::append(PathName, FileName);
566
567  // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
568  // Come up with a lazy way to do this.
569  if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
570    if (const Module *OwningModule = Map.Headers[File]) {
571      Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
572        << FileName << OwningModule->getFullModuleName();
573      HadError = true;
574    } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
575      Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
576        << OwningModule->getFullModuleName();
577      HadError = true;
578    } else {
579      // Record this umbrella header.
580      ActiveModule->UmbrellaHeader = File;
581      Map.Headers[File] = ActiveModule;
582      Map.UmbrellaDirs[Directory] = ActiveModule;
583    }
584  } else {
585    Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
586      << true << FileName;
587    HadError = true;
588  }
589}
590
591/// \brief Parse a header declaration.
592///
593///   header-declaration:
594///     'header' string-literal
595void ModuleMapParser::parseHeaderDecl() {
596  assert(Tok.is(MMToken::HeaderKeyword));
597  consumeToken();
598
599  // Parse the header name.
600  if (!Tok.is(MMToken::StringLiteral)) {
601    Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
602      << "header";
603    HadError = true;
604    return;
605  }
606  StringRef FileName = Tok.getString();
607  SourceLocation FileNameLoc = consumeToken();
608
609  // Look for this file.
610  llvm::SmallString<128> PathName;
611  PathName += Directory->getName();
612  llvm::sys::path::append(PathName, FileName);
613
614  // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
615  // Come up with a lazy way to do this.
616  if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
617    if (const Module *OwningModule = Map.Headers[File]) {
618      Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
619        << FileName << OwningModule->getFullModuleName();
620      HadError = true;
621    } else {
622      // Record this file.
623      ActiveModule->Headers.push_back(File);
624      Map.Headers[File] = ActiveModule;
625    }
626  } else {
627    Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
628      << false << FileName;
629    HadError = true;
630  }
631}
632
633/// \brief Parse a module map file.
634///
635///   module-map-file:
636///     module-declaration*
637bool ModuleMapParser::parseModuleMapFile() {
638  do {
639    switch (Tok.Kind) {
640    case MMToken::EndOfFile:
641      return HadError;
642
643    case MMToken::ModuleKeyword:
644      parseModuleDecl();
645      break;
646
647    case MMToken::ExplicitKeyword:
648    case MMToken::HeaderKeyword:
649    case MMToken::Identifier:
650    case MMToken::LBrace:
651    case MMToken::RBrace:
652    case MMToken::StringLiteral:
653    case MMToken::UmbrellaKeyword:
654      Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
655      HadError = true;
656      consumeToken();
657      break;
658    }
659  } while (true);
660
661  return HadError;
662}
663
664bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
665  FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
666  const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
667  if (!Buffer)
668    return true;
669
670  // Parse this module map file.
671  Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
672  Diags->getClient()->BeginSourceFile(LangOpts);
673  ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
674  bool Result = Parser.parseModuleMapFile();
675  Diags->getClient()->EndSourceFile();
676
677  return Result;
678}
679