1718292f2SDouglas Gregor //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2718292f2SDouglas Gregor //
3718292f2SDouglas Gregor //                     The LLVM Compiler Infrastructure
4718292f2SDouglas Gregor //
5718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source
6718292f2SDouglas Gregor // License. See LICENSE.TXT for details.
7718292f2SDouglas Gregor //
8718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
9718292f2SDouglas Gregor //
10718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout
11718292f2SDouglas Gregor // of a module as it relates to headers.
12718292f2SDouglas Gregor //
13718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
15718292f2SDouglas Gregor #include "clang/Lex/Lexer.h"
16718292f2SDouglas Gregor #include "clang/Lex/LiteralSupport.h"
17718292f2SDouglas Gregor #include "clang/Lex/LexDiagnostic.h"
18718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
19718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
20718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
21718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h"
22718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
23718292f2SDouglas Gregor #include "llvm/Support/Host.h"
245257fc63SDouglas Gregor #include "llvm/Support/PathV2.h"
25718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
26718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h"
27718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h"
28718292f2SDouglas Gregor using namespace clang;
29718292f2SDouglas Gregor 
30718292f2SDouglas Gregor //----------------------------------------------------------------------------//
31718292f2SDouglas Gregor // Module
32718292f2SDouglas Gregor //----------------------------------------------------------------------------//
33718292f2SDouglas Gregor 
34718292f2SDouglas Gregor std::string ModuleMap::Module::getFullModuleName() const {
35718292f2SDouglas Gregor   llvm::SmallVector<StringRef, 2> Names;
36718292f2SDouglas Gregor 
37718292f2SDouglas Gregor   // Build up the set of module names (from innermost to outermost).
38718292f2SDouglas Gregor   for (const Module *M = this; M; M = M->Parent)
39718292f2SDouglas Gregor     Names.push_back(M->Name);
40718292f2SDouglas Gregor 
41718292f2SDouglas Gregor   std::string Result;
42718292f2SDouglas Gregor   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
43718292f2SDouglas Gregor                                                       IEnd = Names.rend();
44718292f2SDouglas Gregor        I != IEnd; ++I) {
45718292f2SDouglas Gregor     if (!Result.empty())
46718292f2SDouglas Gregor       Result += '.';
47718292f2SDouglas Gregor 
48718292f2SDouglas Gregor     Result += *I;
49718292f2SDouglas Gregor   }
50718292f2SDouglas Gregor 
51718292f2SDouglas Gregor   return Result;
52718292f2SDouglas Gregor }
53718292f2SDouglas Gregor 
54*ab0c8a84SDouglas Gregor StringRef ModuleMap::Module::getTopLevelModuleName() const {
55*ab0c8a84SDouglas Gregor   const Module *Top = this;
56*ab0c8a84SDouglas Gregor   while (Top->Parent)
57*ab0c8a84SDouglas Gregor     Top = Top->Parent;
58*ab0c8a84SDouglas Gregor 
59*ab0c8a84SDouglas Gregor   return Top->Name;
60*ab0c8a84SDouglas Gregor }
61*ab0c8a84SDouglas Gregor 
62718292f2SDouglas Gregor //----------------------------------------------------------------------------//
63718292f2SDouglas Gregor // Module map
64718292f2SDouglas Gregor //----------------------------------------------------------------------------//
65718292f2SDouglas Gregor 
66718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
67718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
68718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
69718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
70718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
71718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
72718292f2SDouglas Gregor }
73718292f2SDouglas Gregor 
74718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
75718292f2SDouglas Gregor   delete SourceMgr;
76718292f2SDouglas Gregor }
77718292f2SDouglas Gregor 
78*ab0c8a84SDouglas Gregor ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
79*ab0c8a84SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
80*ab0c8a84SDouglas Gregor     = Headers.find(File);
81*ab0c8a84SDouglas Gregor   if (Known != Headers.end())
82*ab0c8a84SDouglas Gregor     return Known->second;
83*ab0c8a84SDouglas Gregor 
84*ab0c8a84SDouglas Gregor   return 0;
85*ab0c8a84SDouglas Gregor }
86*ab0c8a84SDouglas Gregor 
87718292f2SDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
88718292f2SDouglas Gregor   OS << std::string(' ', Spaces);
89718292f2SDouglas Gregor }
90718292f2SDouglas Gregor 
91718292f2SDouglas Gregor static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M,
92718292f2SDouglas Gregor                        unsigned Indent) {
93718292f2SDouglas Gregor   indent(OS, Indent);
94718292f2SDouglas Gregor   if (M->IsExplicit)
95718292f2SDouglas Gregor     OS << "explicit ";
96718292f2SDouglas Gregor   OS << M->Name << " {\n";
97718292f2SDouglas Gregor 
98718292f2SDouglas Gregor   if (M->UmbrellaHeader) {
99718292f2SDouglas Gregor     indent(OS, Indent + 2);
100718292f2SDouglas Gregor     OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n";
101718292f2SDouglas Gregor   }
102718292f2SDouglas Gregor 
103718292f2SDouglas Gregor   for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) {
104718292f2SDouglas Gregor     indent(OS, Indent + 2);
105718292f2SDouglas Gregor     OS << "header \"" << M->Headers[I]->getName() << "\"\n";
106718292f2SDouglas Gregor   }
107718292f2SDouglas Gregor 
108718292f2SDouglas Gregor   for (llvm::StringMap<ModuleMap::Module *>::iterator
109718292f2SDouglas Gregor             MI = M->SubModules.begin(),
110718292f2SDouglas Gregor          MIEnd = M->SubModules.end();
111718292f2SDouglas Gregor        MI != MIEnd; ++MI)
112718292f2SDouglas Gregor     dumpModule(llvm::errs(), MI->getValue(), Indent + 2);
113718292f2SDouglas Gregor 
114718292f2SDouglas Gregor   indent(OS, Indent);
115718292f2SDouglas Gregor   OS << "}\n";
116718292f2SDouglas Gregor }
117718292f2SDouglas Gregor 
118718292f2SDouglas Gregor void ModuleMap::dump() {
119718292f2SDouglas Gregor   llvm::errs() << "Modules:";
120718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
121718292f2SDouglas Gregor                                         MEnd = Modules.end();
122718292f2SDouglas Gregor        M != MEnd; ++M)
123718292f2SDouglas Gregor     dumpModule(llvm::errs(), M->getValue(), 2);
124718292f2SDouglas Gregor 
125718292f2SDouglas Gregor   llvm::errs() << "Headers:";
126718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
127718292f2SDouglas Gregor             H = Headers.begin(),
128718292f2SDouglas Gregor          HEnd = Headers.end();
129718292f2SDouglas Gregor        H != HEnd; ++H) {
130718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
131718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
132718292f2SDouglas Gregor   }
133718292f2SDouglas Gregor }
134718292f2SDouglas Gregor 
135718292f2SDouglas Gregor //----------------------------------------------------------------------------//
136718292f2SDouglas Gregor // Module map file parser
137718292f2SDouglas Gregor //----------------------------------------------------------------------------//
138718292f2SDouglas Gregor 
139718292f2SDouglas Gregor namespace clang {
140718292f2SDouglas Gregor   /// \brief A token in a module map file.
141718292f2SDouglas Gregor   struct MMToken {
142718292f2SDouglas Gregor     enum TokenKind {
143718292f2SDouglas Gregor       EndOfFile,
144718292f2SDouglas Gregor       HeaderKeyword,
145718292f2SDouglas Gregor       Identifier,
146718292f2SDouglas Gregor       ExplicitKeyword,
147718292f2SDouglas Gregor       ModuleKeyword,
148718292f2SDouglas Gregor       UmbrellaKeyword,
149718292f2SDouglas Gregor       StringLiteral,
150718292f2SDouglas Gregor       LBrace,
151718292f2SDouglas Gregor       RBrace
152718292f2SDouglas Gregor     } Kind;
153718292f2SDouglas Gregor 
154718292f2SDouglas Gregor     unsigned Location;
155718292f2SDouglas Gregor     unsigned StringLength;
156718292f2SDouglas Gregor     const char *StringData;
157718292f2SDouglas Gregor 
158718292f2SDouglas Gregor     void clear() {
159718292f2SDouglas Gregor       Kind = EndOfFile;
160718292f2SDouglas Gregor       Location = 0;
161718292f2SDouglas Gregor       StringLength = 0;
162718292f2SDouglas Gregor       StringData = 0;
163718292f2SDouglas Gregor     }
164718292f2SDouglas Gregor 
165718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
166718292f2SDouglas Gregor 
167718292f2SDouglas Gregor     SourceLocation getLocation() const {
168718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
169718292f2SDouglas Gregor     }
170718292f2SDouglas Gregor 
171718292f2SDouglas Gregor     StringRef getString() const {
172718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
173718292f2SDouglas Gregor     }
174718292f2SDouglas Gregor   };
175718292f2SDouglas Gregor 
176718292f2SDouglas Gregor   class ModuleMapParser {
177718292f2SDouglas Gregor     Lexer &L;
178718292f2SDouglas Gregor     SourceManager &SourceMgr;
179718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
180718292f2SDouglas Gregor     ModuleMap &Map;
181718292f2SDouglas Gregor 
1825257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
1835257fc63SDouglas Gregor     const DirectoryEntry *Directory;
1845257fc63SDouglas Gregor 
185718292f2SDouglas Gregor     /// \brief Whether an error occurred.
186718292f2SDouglas Gregor     bool HadError;
187718292f2SDouglas Gregor 
188718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
189718292f2SDouglas Gregor     /// parsing.
190718292f2SDouglas Gregor     TargetInfo *Target;
191718292f2SDouglas Gregor 
192718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
193718292f2SDouglas Gregor     /// during parsing.
194718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
195718292f2SDouglas Gregor 
196718292f2SDouglas Gregor     /// \brief The current token.
197718292f2SDouglas Gregor     MMToken Tok;
198718292f2SDouglas Gregor 
199718292f2SDouglas Gregor     /// \brief The active module.
200718292f2SDouglas Gregor     ModuleMap::Module *ActiveModule;
201718292f2SDouglas Gregor 
202718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
203718292f2SDouglas Gregor     SourceLocation consumeToken();
204718292f2SDouglas Gregor 
205718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
206718292f2SDouglas Gregor     /// (or the end of the file).
207718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
208718292f2SDouglas Gregor 
209718292f2SDouglas Gregor     void parseModuleDecl();
210718292f2SDouglas Gregor     void parseUmbrellaDecl();
211718292f2SDouglas Gregor     void parseHeaderDecl();
212718292f2SDouglas Gregor 
213718292f2SDouglas Gregor   public:
214718292f2SDouglas Gregor     typedef ModuleMap::Module Module;
215718292f2SDouglas Gregor 
216718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
217718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
2185257fc63SDouglas Gregor                              ModuleMap &Map,
2195257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
2205257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
2215257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
222718292f2SDouglas Gregor     {
223718292f2SDouglas Gregor       TargetOptions TargetOpts;
224718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
225718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
226718292f2SDouglas Gregor 
227718292f2SDouglas Gregor       Tok.clear();
228718292f2SDouglas Gregor       consumeToken();
229718292f2SDouglas Gregor     }
230718292f2SDouglas Gregor 
231718292f2SDouglas Gregor     bool parseModuleMapFile();
232718292f2SDouglas Gregor   };
233718292f2SDouglas Gregor }
234718292f2SDouglas Gregor 
235718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
236718292f2SDouglas Gregor retry:
237718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
238718292f2SDouglas Gregor   Tok.clear();
239718292f2SDouglas Gregor 
240718292f2SDouglas Gregor   Token LToken;
241718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
242718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
243718292f2SDouglas Gregor   switch (LToken.getKind()) {
244718292f2SDouglas Gregor   case tok::raw_identifier:
245718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
246718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
247718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
248718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
249718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
250718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
251718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
252718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
253718292f2SDouglas Gregor     break;
254718292f2SDouglas Gregor 
255718292f2SDouglas Gregor   case tok::eof:
256718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
257718292f2SDouglas Gregor     break;
258718292f2SDouglas Gregor 
259718292f2SDouglas Gregor   case tok::l_brace:
260718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
261718292f2SDouglas Gregor     break;
262718292f2SDouglas Gregor 
263718292f2SDouglas Gregor   case tok::r_brace:
264718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
265718292f2SDouglas Gregor     break;
266718292f2SDouglas Gregor 
267718292f2SDouglas Gregor   case tok::string_literal: {
268718292f2SDouglas Gregor     // Parse the string literal.
269718292f2SDouglas Gregor     LangOptions LangOpts;
270718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
271718292f2SDouglas Gregor     if (StringLiteral.hadError)
272718292f2SDouglas Gregor       goto retry;
273718292f2SDouglas Gregor 
274718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
275718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
276718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
277718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
278718292f2SDouglas Gregor     Saved[Length] = 0;
279718292f2SDouglas Gregor 
280718292f2SDouglas Gregor     // Form the token.
281718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
282718292f2SDouglas Gregor     Tok.StringData = Saved;
283718292f2SDouglas Gregor     Tok.StringLength = Length;
284718292f2SDouglas Gregor     break;
285718292f2SDouglas Gregor   }
286718292f2SDouglas Gregor 
287718292f2SDouglas Gregor   case tok::comment:
288718292f2SDouglas Gregor     goto retry;
289718292f2SDouglas Gregor 
290718292f2SDouglas Gregor   default:
291718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
292718292f2SDouglas Gregor     HadError = true;
293718292f2SDouglas Gregor     goto retry;
294718292f2SDouglas Gregor   }
295718292f2SDouglas Gregor 
296718292f2SDouglas Gregor   return Result;
297718292f2SDouglas Gregor }
298718292f2SDouglas Gregor 
299718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
300718292f2SDouglas Gregor   unsigned braceDepth = 0;
301718292f2SDouglas Gregor   do {
302718292f2SDouglas Gregor     switch (Tok.Kind) {
303718292f2SDouglas Gregor     case MMToken::EndOfFile:
304718292f2SDouglas Gregor       return;
305718292f2SDouglas Gregor 
306718292f2SDouglas Gregor     case MMToken::LBrace:
307718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
308718292f2SDouglas Gregor         return;
309718292f2SDouglas Gregor 
310718292f2SDouglas Gregor       ++braceDepth;
311718292f2SDouglas Gregor       break;
312718292f2SDouglas Gregor 
313718292f2SDouglas Gregor     case MMToken::RBrace:
314718292f2SDouglas Gregor       if (braceDepth > 0)
315718292f2SDouglas Gregor         --braceDepth;
316718292f2SDouglas Gregor       else if (Tok.is(K))
317718292f2SDouglas Gregor         return;
318718292f2SDouglas Gregor       break;
319718292f2SDouglas Gregor 
320718292f2SDouglas Gregor     default:
321718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
322718292f2SDouglas Gregor         return;
323718292f2SDouglas Gregor       break;
324718292f2SDouglas Gregor     }
325718292f2SDouglas Gregor 
326718292f2SDouglas Gregor    consumeToken();
327718292f2SDouglas Gregor   } while (true);
328718292f2SDouglas Gregor }
329718292f2SDouglas Gregor 
330718292f2SDouglas Gregor /// \brief Parse a module declaration.
331718292f2SDouglas Gregor ///
332718292f2SDouglas Gregor ///   module-declaration:
333718292f2SDouglas Gregor ///     'module' identifier { module-member* }
334718292f2SDouglas Gregor ///
335718292f2SDouglas Gregor ///   module-member:
336718292f2SDouglas Gregor ///     umbrella-declaration
337718292f2SDouglas Gregor ///     header-declaration
338718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
339718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
340718292f2SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword));
341718292f2SDouglas Gregor 
342718292f2SDouglas Gregor   // Parse 'explicit' keyword, if present.
343718292f2SDouglas Gregor   bool Explicit = false;
344718292f2SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
345718292f2SDouglas Gregor     consumeToken();
346718292f2SDouglas Gregor     Explicit = true;
347718292f2SDouglas Gregor   }
348718292f2SDouglas Gregor 
349718292f2SDouglas Gregor   // Parse 'module' keyword.
350718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
351718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
352718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
353718292f2SDouglas Gregor     consumeToken();
354718292f2SDouglas Gregor     HadError = true;
355718292f2SDouglas Gregor     return;
356718292f2SDouglas Gregor   }
357718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
358718292f2SDouglas Gregor 
359718292f2SDouglas Gregor   // Parse the module name.
360718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
361718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
362718292f2SDouglas Gregor     HadError = true;
363718292f2SDouglas Gregor     return;
364718292f2SDouglas Gregor   }
365718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
366718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
367718292f2SDouglas Gregor 
368718292f2SDouglas Gregor   // Parse the opening brace.
369718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
370718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
371718292f2SDouglas Gregor       << ModuleName;
372718292f2SDouglas Gregor     HadError = true;
373718292f2SDouglas Gregor     return;
374718292f2SDouglas Gregor   }
375718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
376718292f2SDouglas Gregor 
377718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
378718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
379718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
380718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
381718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
382718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
383718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
384718292f2SDouglas Gregor       << ModuleName;
385718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
386718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
387718292f2SDouglas Gregor 
388718292f2SDouglas Gregor     // Skip the module definition.
389718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
390718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
391718292f2SDouglas Gregor       consumeToken();
392718292f2SDouglas Gregor 
393718292f2SDouglas Gregor     HadError = true;
394718292f2SDouglas Gregor     return;
395718292f2SDouglas Gregor   }
396718292f2SDouglas Gregor 
397718292f2SDouglas Gregor   // Start defining this module.
398718292f2SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit);
399718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
400718292f2SDouglas Gregor 
401718292f2SDouglas Gregor   bool Done = false;
402718292f2SDouglas Gregor   do {
403718292f2SDouglas Gregor     switch (Tok.Kind) {
404718292f2SDouglas Gregor     case MMToken::EndOfFile:
405718292f2SDouglas Gregor     case MMToken::RBrace:
406718292f2SDouglas Gregor       Done = true;
407718292f2SDouglas Gregor       break;
408718292f2SDouglas Gregor 
409718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
410718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
411718292f2SDouglas Gregor       parseModuleDecl();
412718292f2SDouglas Gregor       break;
413718292f2SDouglas Gregor 
414718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
415718292f2SDouglas Gregor       parseHeaderDecl();
416718292f2SDouglas Gregor       break;
417718292f2SDouglas Gregor 
418718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
419718292f2SDouglas Gregor       parseUmbrellaDecl();
420718292f2SDouglas Gregor       break;
421718292f2SDouglas Gregor 
422718292f2SDouglas Gregor     default:
423718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
424718292f2SDouglas Gregor       consumeToken();
425718292f2SDouglas Gregor       break;
426718292f2SDouglas Gregor     }
427718292f2SDouglas Gregor   } while (!Done);
428718292f2SDouglas Gregor 
429718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
430718292f2SDouglas Gregor     consumeToken();
431718292f2SDouglas Gregor   else {
432718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
433718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
434718292f2SDouglas Gregor     HadError = true;
435718292f2SDouglas Gregor   }
436718292f2SDouglas Gregor 
437718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
438718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
439718292f2SDouglas Gregor }
440718292f2SDouglas Gregor 
441718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
442718292f2SDouglas Gregor ///
443718292f2SDouglas Gregor ///   umbrella-declaration:
444718292f2SDouglas Gregor ///     'umbrella' string-literal
445718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
446718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
447718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
448718292f2SDouglas Gregor 
449718292f2SDouglas Gregor   // Parse the header name.
450718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
451718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
452718292f2SDouglas Gregor       << "umbrella";
453718292f2SDouglas Gregor     HadError = true;
454718292f2SDouglas Gregor     return;
455718292f2SDouglas Gregor   }
456718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
457718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
458718292f2SDouglas Gregor 
4595257fc63SDouglas Gregor   // Check whether we already have an umbrella header.
4605257fc63SDouglas Gregor   if (ActiveModule->UmbrellaHeader) {
4615257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
4625257fc63SDouglas Gregor       << ActiveModule->getFullModuleName()
4635257fc63SDouglas Gregor       << ActiveModule->UmbrellaHeader->getName();
4645257fc63SDouglas Gregor     HadError = true;
4655257fc63SDouglas Gregor     return;
4665257fc63SDouglas Gregor   }
4675257fc63SDouglas Gregor 
4685257fc63SDouglas Gregor   // Only top-level modules can have umbrella headers.
4695257fc63SDouglas Gregor   if (ActiveModule->Parent) {
4705257fc63SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
4715257fc63SDouglas Gregor       << ActiveModule->getFullModuleName();
4725257fc63SDouglas Gregor     HadError = true;
4735257fc63SDouglas Gregor     return;
4745257fc63SDouglas Gregor   }
4755257fc63SDouglas Gregor 
4765257fc63SDouglas Gregor   // Look for this file.
4775257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
4785257fc63SDouglas Gregor   PathName += Directory->getName();
4795257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
4805257fc63SDouglas Gregor 
4815257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
4825257fc63SDouglas Gregor   // Come up with a lazy way to do this.
4835257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
4845257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
4855257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
4865257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
4875257fc63SDouglas Gregor       HadError = true;
4885257fc63SDouglas Gregor     } else {
4895257fc63SDouglas Gregor       // Record this umbrella header.
4905257fc63SDouglas Gregor       ActiveModule->UmbrellaHeader = File;
4915257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
4925257fc63SDouglas Gregor     }
4935257fc63SDouglas Gregor   } else {
4945257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
4955257fc63SDouglas Gregor       << true << FileName;
4965257fc63SDouglas Gregor     HadError = true;
4975257fc63SDouglas Gregor   }
498718292f2SDouglas Gregor }
499718292f2SDouglas Gregor 
500718292f2SDouglas Gregor /// \brief Parse a header declaration.
501718292f2SDouglas Gregor ///
502718292f2SDouglas Gregor ///   header-declaration:
503718292f2SDouglas Gregor ///     'header' string-literal
504718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
505718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
506718292f2SDouglas Gregor   SourceLocation HeaderLoc = consumeToken();
507718292f2SDouglas Gregor 
508718292f2SDouglas Gregor   // Parse the header name.
509718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
510718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
511718292f2SDouglas Gregor       << "header";
512718292f2SDouglas Gregor     HadError = true;
513718292f2SDouglas Gregor     return;
514718292f2SDouglas Gregor   }
515718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
516718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
517718292f2SDouglas Gregor 
5185257fc63SDouglas Gregor   // Look for this file.
5195257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
5205257fc63SDouglas Gregor   PathName += Directory->getName();
5215257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
5225257fc63SDouglas Gregor 
5235257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
5245257fc63SDouglas Gregor   // Come up with a lazy way to do this.
5255257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
5265257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
5275257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
5285257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
5295257fc63SDouglas Gregor       HadError = true;
5305257fc63SDouglas Gregor     } else {
5315257fc63SDouglas Gregor       // Record this file.
5325257fc63SDouglas Gregor       ActiveModule->Headers.push_back(File);
5335257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
5345257fc63SDouglas Gregor     }
5355257fc63SDouglas Gregor   } else {
5365257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
5375257fc63SDouglas Gregor       << false << FileName;
5385257fc63SDouglas Gregor     HadError = true;
5395257fc63SDouglas Gregor   }
540718292f2SDouglas Gregor }
541718292f2SDouglas Gregor 
542718292f2SDouglas Gregor /// \brief Parse a module map file.
543718292f2SDouglas Gregor ///
544718292f2SDouglas Gregor ///   module-map-file:
545718292f2SDouglas Gregor ///     module-declaration*
546718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
547718292f2SDouglas Gregor   do {
548718292f2SDouglas Gregor     switch (Tok.Kind) {
549718292f2SDouglas Gregor     case MMToken::EndOfFile:
550718292f2SDouglas Gregor       return HadError;
551718292f2SDouglas Gregor 
552718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
553718292f2SDouglas Gregor       parseModuleDecl();
554718292f2SDouglas Gregor       break;
555718292f2SDouglas Gregor 
556718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
557718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
558718292f2SDouglas Gregor     case MMToken::Identifier:
559718292f2SDouglas Gregor     case MMToken::LBrace:
560718292f2SDouglas Gregor     case MMToken::RBrace:
561718292f2SDouglas Gregor     case MMToken::StringLiteral:
562718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
563718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
564718292f2SDouglas Gregor       HadError = true;
565718292f2SDouglas Gregor       consumeToken();
566718292f2SDouglas Gregor       break;
567718292f2SDouglas Gregor     }
568718292f2SDouglas Gregor   } while (true);
569718292f2SDouglas Gregor 
570718292f2SDouglas Gregor   return HadError;
571718292f2SDouglas Gregor }
572718292f2SDouglas Gregor 
573718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
574718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
575718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
576718292f2SDouglas Gregor   if (!Buffer)
577718292f2SDouglas Gregor     return true;
578718292f2SDouglas Gregor 
579718292f2SDouglas Gregor   // Parse this module map file.
580718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
581718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
5825257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
583718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
584718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
585718292f2SDouglas Gregor 
586718292f2SDouglas Gregor   return Result;
587718292f2SDouglas Gregor }
588