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