1*718292f2SDouglas Gregor //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2*718292f2SDouglas Gregor //
3*718292f2SDouglas Gregor //                     The LLVM Compiler Infrastructure
4*718292f2SDouglas Gregor //
5*718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source
6*718292f2SDouglas Gregor // License. See LICENSE.TXT for details.
7*718292f2SDouglas Gregor //
8*718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
9*718292f2SDouglas Gregor //
10*718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout
11*718292f2SDouglas Gregor // of a module as it relates to headers.
12*718292f2SDouglas Gregor //
13*718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
14*718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
15*718292f2SDouglas Gregor #include "clang/Lex/Lexer.h"
16*718292f2SDouglas Gregor #include "clang/Lex/LiteralSupport.h"
17*718292f2SDouglas Gregor #include "clang/Lex/LexDiagnostic.h"
18*718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
19*718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
20*718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
21*718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h"
22*718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
23*718292f2SDouglas Gregor #include "llvm/Support/Host.h"
24*718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
25*718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h"
26*718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h"
27*718292f2SDouglas Gregor using namespace clang;
28*718292f2SDouglas Gregor 
29*718292f2SDouglas Gregor //----------------------------------------------------------------------------//
30*718292f2SDouglas Gregor // Module
31*718292f2SDouglas Gregor //----------------------------------------------------------------------------//
32*718292f2SDouglas Gregor 
33*718292f2SDouglas Gregor std::string ModuleMap::Module::getFullModuleName() const {
34*718292f2SDouglas Gregor   llvm::SmallVector<StringRef, 2> Names;
35*718292f2SDouglas Gregor 
36*718292f2SDouglas Gregor   // Build up the set of module names (from innermost to outermost).
37*718292f2SDouglas Gregor   for (const Module *M = this; M; M = M->Parent)
38*718292f2SDouglas Gregor     Names.push_back(M->Name);
39*718292f2SDouglas Gregor 
40*718292f2SDouglas Gregor   std::string Result;
41*718292f2SDouglas Gregor   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
42*718292f2SDouglas Gregor                                                       IEnd = Names.rend();
43*718292f2SDouglas Gregor        I != IEnd; ++I) {
44*718292f2SDouglas Gregor     if (!Result.empty())
45*718292f2SDouglas Gregor       Result += '.';
46*718292f2SDouglas Gregor 
47*718292f2SDouglas Gregor     Result += *I;
48*718292f2SDouglas Gregor   }
49*718292f2SDouglas Gregor 
50*718292f2SDouglas Gregor   return Result;
51*718292f2SDouglas Gregor }
52*718292f2SDouglas Gregor 
53*718292f2SDouglas Gregor //----------------------------------------------------------------------------//
54*718292f2SDouglas Gregor // Module map
55*718292f2SDouglas Gregor //----------------------------------------------------------------------------//
56*718292f2SDouglas Gregor 
57*718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
58*718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
59*718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
60*718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
61*718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
62*718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
63*718292f2SDouglas Gregor }
64*718292f2SDouglas Gregor 
65*718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
66*718292f2SDouglas Gregor   delete SourceMgr;
67*718292f2SDouglas Gregor }
68*718292f2SDouglas Gregor 
69*718292f2SDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
70*718292f2SDouglas Gregor   OS << std::string(' ', Spaces);
71*718292f2SDouglas Gregor }
72*718292f2SDouglas Gregor 
73*718292f2SDouglas Gregor static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M,
74*718292f2SDouglas Gregor                        unsigned Indent) {
75*718292f2SDouglas Gregor   indent(OS, Indent);
76*718292f2SDouglas Gregor   if (M->IsExplicit)
77*718292f2SDouglas Gregor     OS << "explicit ";
78*718292f2SDouglas Gregor   OS << M->Name << " {\n";
79*718292f2SDouglas Gregor 
80*718292f2SDouglas Gregor   if (M->UmbrellaHeader) {
81*718292f2SDouglas Gregor     indent(OS, Indent + 2);
82*718292f2SDouglas Gregor     OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n";
83*718292f2SDouglas Gregor   }
84*718292f2SDouglas Gregor 
85*718292f2SDouglas Gregor   for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) {
86*718292f2SDouglas Gregor     indent(OS, Indent + 2);
87*718292f2SDouglas Gregor     OS << "header \"" << M->Headers[I]->getName() << "\"\n";
88*718292f2SDouglas Gregor   }
89*718292f2SDouglas Gregor 
90*718292f2SDouglas Gregor   for (llvm::StringMap<ModuleMap::Module *>::iterator
91*718292f2SDouglas Gregor             MI = M->SubModules.begin(),
92*718292f2SDouglas Gregor          MIEnd = M->SubModules.end();
93*718292f2SDouglas Gregor        MI != MIEnd; ++MI)
94*718292f2SDouglas Gregor     dumpModule(llvm::errs(), MI->getValue(), Indent + 2);
95*718292f2SDouglas Gregor 
96*718292f2SDouglas Gregor   indent(OS, Indent);
97*718292f2SDouglas Gregor   OS << "}\n";
98*718292f2SDouglas Gregor }
99*718292f2SDouglas Gregor 
100*718292f2SDouglas Gregor void ModuleMap::dump() {
101*718292f2SDouglas Gregor   llvm::errs() << "Modules:";
102*718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
103*718292f2SDouglas Gregor                                         MEnd = Modules.end();
104*718292f2SDouglas Gregor        M != MEnd; ++M)
105*718292f2SDouglas Gregor     dumpModule(llvm::errs(), M->getValue(), 2);
106*718292f2SDouglas Gregor 
107*718292f2SDouglas Gregor   llvm::errs() << "Headers:";
108*718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
109*718292f2SDouglas Gregor             H = Headers.begin(),
110*718292f2SDouglas Gregor          HEnd = Headers.end();
111*718292f2SDouglas Gregor        H != HEnd; ++H) {
112*718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
113*718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
114*718292f2SDouglas Gregor   }
115*718292f2SDouglas Gregor }
116*718292f2SDouglas Gregor 
117*718292f2SDouglas Gregor //----------------------------------------------------------------------------//
118*718292f2SDouglas Gregor // Module map file parser
119*718292f2SDouglas Gregor //----------------------------------------------------------------------------//
120*718292f2SDouglas Gregor 
121*718292f2SDouglas Gregor namespace clang {
122*718292f2SDouglas Gregor   /// \brief A token in a module map file.
123*718292f2SDouglas Gregor   struct MMToken {
124*718292f2SDouglas Gregor     enum TokenKind {
125*718292f2SDouglas Gregor       EndOfFile,
126*718292f2SDouglas Gregor       HeaderKeyword,
127*718292f2SDouglas Gregor       Identifier,
128*718292f2SDouglas Gregor       ExplicitKeyword,
129*718292f2SDouglas Gregor       ModuleKeyword,
130*718292f2SDouglas Gregor       UmbrellaKeyword,
131*718292f2SDouglas Gregor       StringLiteral,
132*718292f2SDouglas Gregor       LBrace,
133*718292f2SDouglas Gregor       RBrace
134*718292f2SDouglas Gregor     } Kind;
135*718292f2SDouglas Gregor 
136*718292f2SDouglas Gregor     unsigned Location;
137*718292f2SDouglas Gregor     unsigned StringLength;
138*718292f2SDouglas Gregor     const char *StringData;
139*718292f2SDouglas Gregor 
140*718292f2SDouglas Gregor     void clear() {
141*718292f2SDouglas Gregor       Kind = EndOfFile;
142*718292f2SDouglas Gregor       Location = 0;
143*718292f2SDouglas Gregor       StringLength = 0;
144*718292f2SDouglas Gregor       StringData = 0;
145*718292f2SDouglas Gregor     }
146*718292f2SDouglas Gregor 
147*718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
148*718292f2SDouglas Gregor 
149*718292f2SDouglas Gregor     SourceLocation getLocation() const {
150*718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
151*718292f2SDouglas Gregor     }
152*718292f2SDouglas Gregor 
153*718292f2SDouglas Gregor     StringRef getString() const {
154*718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
155*718292f2SDouglas Gregor     }
156*718292f2SDouglas Gregor   };
157*718292f2SDouglas Gregor 
158*718292f2SDouglas Gregor   class ModuleMapParser {
159*718292f2SDouglas Gregor     Lexer &L;
160*718292f2SDouglas Gregor     SourceManager &SourceMgr;
161*718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
162*718292f2SDouglas Gregor     ModuleMap &Map;
163*718292f2SDouglas Gregor 
164*718292f2SDouglas Gregor     /// \brief Whether an error occurred.
165*718292f2SDouglas Gregor     bool HadError;
166*718292f2SDouglas Gregor 
167*718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
168*718292f2SDouglas Gregor     /// parsing.
169*718292f2SDouglas Gregor     TargetInfo *Target;
170*718292f2SDouglas Gregor 
171*718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
172*718292f2SDouglas Gregor     /// during parsing.
173*718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
174*718292f2SDouglas Gregor 
175*718292f2SDouglas Gregor     /// \brief The current token.
176*718292f2SDouglas Gregor     MMToken Tok;
177*718292f2SDouglas Gregor 
178*718292f2SDouglas Gregor     /// \brief The active module.
179*718292f2SDouglas Gregor     ModuleMap::Module *ActiveModule;
180*718292f2SDouglas Gregor 
181*718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
182*718292f2SDouglas Gregor     SourceLocation consumeToken();
183*718292f2SDouglas Gregor 
184*718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
185*718292f2SDouglas Gregor     /// (or the end of the file).
186*718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
187*718292f2SDouglas Gregor 
188*718292f2SDouglas Gregor     void parseModuleDecl();
189*718292f2SDouglas Gregor     void parseUmbrellaDecl();
190*718292f2SDouglas Gregor     void parseHeaderDecl();
191*718292f2SDouglas Gregor 
192*718292f2SDouglas Gregor   public:
193*718292f2SDouglas Gregor     typedef ModuleMap::Module Module;
194*718292f2SDouglas Gregor 
195*718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
196*718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
197*718292f2SDouglas Gregor                              ModuleMap &Map)
198*718292f2SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), HadError(false),
199*718292f2SDouglas Gregor         ActiveModule(0)
200*718292f2SDouglas Gregor     {
201*718292f2SDouglas Gregor       TargetOptions TargetOpts;
202*718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
203*718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
204*718292f2SDouglas Gregor 
205*718292f2SDouglas Gregor       Tok.clear();
206*718292f2SDouglas Gregor       consumeToken();
207*718292f2SDouglas Gregor     }
208*718292f2SDouglas Gregor 
209*718292f2SDouglas Gregor     bool parseModuleMapFile();
210*718292f2SDouglas Gregor   };
211*718292f2SDouglas Gregor }
212*718292f2SDouglas Gregor 
213*718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
214*718292f2SDouglas Gregor retry:
215*718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
216*718292f2SDouglas Gregor   Tok.clear();
217*718292f2SDouglas Gregor 
218*718292f2SDouglas Gregor   Token LToken;
219*718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
220*718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
221*718292f2SDouglas Gregor   switch (LToken.getKind()) {
222*718292f2SDouglas Gregor   case tok::raw_identifier:
223*718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
224*718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
225*718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
226*718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
227*718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
228*718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
229*718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
230*718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
231*718292f2SDouglas Gregor     break;
232*718292f2SDouglas Gregor 
233*718292f2SDouglas Gregor   case tok::eof:
234*718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
235*718292f2SDouglas Gregor     break;
236*718292f2SDouglas Gregor 
237*718292f2SDouglas Gregor   case tok::l_brace:
238*718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
239*718292f2SDouglas Gregor     break;
240*718292f2SDouglas Gregor 
241*718292f2SDouglas Gregor   case tok::r_brace:
242*718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
243*718292f2SDouglas Gregor     break;
244*718292f2SDouglas Gregor 
245*718292f2SDouglas Gregor   case tok::string_literal: {
246*718292f2SDouglas Gregor     // Parse the string literal.
247*718292f2SDouglas Gregor     LangOptions LangOpts;
248*718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
249*718292f2SDouglas Gregor     if (StringLiteral.hadError)
250*718292f2SDouglas Gregor       goto retry;
251*718292f2SDouglas Gregor 
252*718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
253*718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
254*718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
255*718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
256*718292f2SDouglas Gregor     Saved[Length] = 0;
257*718292f2SDouglas Gregor 
258*718292f2SDouglas Gregor     // Form the token.
259*718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
260*718292f2SDouglas Gregor     Tok.StringData = Saved;
261*718292f2SDouglas Gregor     Tok.StringLength = Length;
262*718292f2SDouglas Gregor     break;
263*718292f2SDouglas Gregor   }
264*718292f2SDouglas Gregor 
265*718292f2SDouglas Gregor   case tok::comment:
266*718292f2SDouglas Gregor     goto retry;
267*718292f2SDouglas Gregor 
268*718292f2SDouglas Gregor   default:
269*718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
270*718292f2SDouglas Gregor     HadError = true;
271*718292f2SDouglas Gregor     goto retry;
272*718292f2SDouglas Gregor   }
273*718292f2SDouglas Gregor 
274*718292f2SDouglas Gregor   return Result;
275*718292f2SDouglas Gregor }
276*718292f2SDouglas Gregor 
277*718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
278*718292f2SDouglas Gregor   unsigned braceDepth = 0;
279*718292f2SDouglas Gregor   do {
280*718292f2SDouglas Gregor     switch (Tok.Kind) {
281*718292f2SDouglas Gregor     case MMToken::EndOfFile:
282*718292f2SDouglas Gregor       return;
283*718292f2SDouglas Gregor 
284*718292f2SDouglas Gregor     case MMToken::LBrace:
285*718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
286*718292f2SDouglas Gregor         return;
287*718292f2SDouglas Gregor 
288*718292f2SDouglas Gregor       ++braceDepth;
289*718292f2SDouglas Gregor       break;
290*718292f2SDouglas Gregor 
291*718292f2SDouglas Gregor     case MMToken::RBrace:
292*718292f2SDouglas Gregor       if (braceDepth > 0)
293*718292f2SDouglas Gregor         --braceDepth;
294*718292f2SDouglas Gregor       else if (Tok.is(K))
295*718292f2SDouglas Gregor         return;
296*718292f2SDouglas Gregor       break;
297*718292f2SDouglas Gregor 
298*718292f2SDouglas Gregor     default:
299*718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
300*718292f2SDouglas Gregor         return;
301*718292f2SDouglas Gregor       break;
302*718292f2SDouglas Gregor     }
303*718292f2SDouglas Gregor 
304*718292f2SDouglas Gregor    consumeToken();
305*718292f2SDouglas Gregor   } while (true);
306*718292f2SDouglas Gregor }
307*718292f2SDouglas Gregor 
308*718292f2SDouglas Gregor /// \brief Parse a module declaration.
309*718292f2SDouglas Gregor ///
310*718292f2SDouglas Gregor ///   module-declaration:
311*718292f2SDouglas Gregor ///     'module' identifier { module-member* }
312*718292f2SDouglas Gregor ///
313*718292f2SDouglas Gregor ///   module-member:
314*718292f2SDouglas Gregor ///     umbrella-declaration
315*718292f2SDouglas Gregor ///     header-declaration
316*718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
317*718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
318*718292f2SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword));
319*718292f2SDouglas Gregor 
320*718292f2SDouglas Gregor   // Parse 'explicit' keyword, if present.
321*718292f2SDouglas Gregor   bool Explicit = false;
322*718292f2SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
323*718292f2SDouglas Gregor     consumeToken();
324*718292f2SDouglas Gregor     Explicit = true;
325*718292f2SDouglas Gregor   }
326*718292f2SDouglas Gregor 
327*718292f2SDouglas Gregor   // Parse 'module' keyword.
328*718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
329*718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
330*718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
331*718292f2SDouglas Gregor     consumeToken();
332*718292f2SDouglas Gregor     HadError = true;
333*718292f2SDouglas Gregor     return;
334*718292f2SDouglas Gregor   }
335*718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
336*718292f2SDouglas Gregor 
337*718292f2SDouglas Gregor   // Parse the module name.
338*718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
339*718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
340*718292f2SDouglas Gregor     HadError = true;
341*718292f2SDouglas Gregor     return;
342*718292f2SDouglas Gregor   }
343*718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
344*718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
345*718292f2SDouglas Gregor 
346*718292f2SDouglas Gregor   // Parse the opening brace.
347*718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
348*718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
349*718292f2SDouglas Gregor       << ModuleName;
350*718292f2SDouglas Gregor     HadError = true;
351*718292f2SDouglas Gregor     return;
352*718292f2SDouglas Gregor   }
353*718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
354*718292f2SDouglas Gregor 
355*718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
356*718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
357*718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
358*718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
359*718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
360*718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
361*718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
362*718292f2SDouglas Gregor       << ModuleName;
363*718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
364*718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
365*718292f2SDouglas Gregor 
366*718292f2SDouglas Gregor     // Skip the module definition.
367*718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
368*718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
369*718292f2SDouglas Gregor       consumeToken();
370*718292f2SDouglas Gregor 
371*718292f2SDouglas Gregor     HadError = true;
372*718292f2SDouglas Gregor     return;
373*718292f2SDouglas Gregor   }
374*718292f2SDouglas Gregor 
375*718292f2SDouglas Gregor   // Start defining this module.
376*718292f2SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit);
377*718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
378*718292f2SDouglas Gregor 
379*718292f2SDouglas Gregor   bool Done = false;
380*718292f2SDouglas Gregor   do {
381*718292f2SDouglas Gregor     switch (Tok.Kind) {
382*718292f2SDouglas Gregor     case MMToken::EndOfFile:
383*718292f2SDouglas Gregor     case MMToken::RBrace:
384*718292f2SDouglas Gregor       Done = true;
385*718292f2SDouglas Gregor       break;
386*718292f2SDouglas Gregor 
387*718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
388*718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
389*718292f2SDouglas Gregor       parseModuleDecl();
390*718292f2SDouglas Gregor       break;
391*718292f2SDouglas Gregor 
392*718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
393*718292f2SDouglas Gregor       parseHeaderDecl();
394*718292f2SDouglas Gregor       break;
395*718292f2SDouglas Gregor 
396*718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
397*718292f2SDouglas Gregor       parseUmbrellaDecl();
398*718292f2SDouglas Gregor       break;
399*718292f2SDouglas Gregor 
400*718292f2SDouglas Gregor     default:
401*718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
402*718292f2SDouglas Gregor       consumeToken();
403*718292f2SDouglas Gregor       break;
404*718292f2SDouglas Gregor     }
405*718292f2SDouglas Gregor   } while (!Done);
406*718292f2SDouglas Gregor 
407*718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
408*718292f2SDouglas Gregor     consumeToken();
409*718292f2SDouglas Gregor   else {
410*718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
411*718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
412*718292f2SDouglas Gregor     HadError = true;
413*718292f2SDouglas Gregor   }
414*718292f2SDouglas Gregor 
415*718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
416*718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
417*718292f2SDouglas Gregor }
418*718292f2SDouglas Gregor 
419*718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
420*718292f2SDouglas Gregor ///
421*718292f2SDouglas Gregor ///   umbrella-declaration:
422*718292f2SDouglas Gregor ///     'umbrella' string-literal
423*718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
424*718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
425*718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
426*718292f2SDouglas Gregor 
427*718292f2SDouglas Gregor   // Parse the header name.
428*718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
429*718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
430*718292f2SDouglas Gregor       << "umbrella";
431*718292f2SDouglas Gregor     HadError = true;
432*718292f2SDouglas Gregor     return;
433*718292f2SDouglas Gregor   }
434*718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
435*718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
436*718292f2SDouglas Gregor 
437*718292f2SDouglas Gregor   // FIXME: Record the umbrella header.
438*718292f2SDouglas Gregor }
439*718292f2SDouglas Gregor 
440*718292f2SDouglas Gregor /// \brief Parse a header declaration.
441*718292f2SDouglas Gregor ///
442*718292f2SDouglas Gregor ///   header-declaration:
443*718292f2SDouglas Gregor ///     'header' string-literal
444*718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
445*718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
446*718292f2SDouglas Gregor   SourceLocation HeaderLoc = consumeToken();
447*718292f2SDouglas Gregor 
448*718292f2SDouglas Gregor   // Parse the header name.
449*718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
450*718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
451*718292f2SDouglas Gregor       << "header";
452*718292f2SDouglas Gregor     HadError = true;
453*718292f2SDouglas Gregor     return;
454*718292f2SDouglas Gregor   }
455*718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
456*718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
457*718292f2SDouglas Gregor 
458*718292f2SDouglas Gregor   // FIXME: Record the header.
459*718292f2SDouglas Gregor }
460*718292f2SDouglas Gregor 
461*718292f2SDouglas Gregor /// \brief Parse a module map file.
462*718292f2SDouglas Gregor ///
463*718292f2SDouglas Gregor ///   module-map-file:
464*718292f2SDouglas Gregor ///     module-declaration*
465*718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
466*718292f2SDouglas Gregor   do {
467*718292f2SDouglas Gregor     switch (Tok.Kind) {
468*718292f2SDouglas Gregor     case MMToken::EndOfFile:
469*718292f2SDouglas Gregor       return HadError;
470*718292f2SDouglas Gregor 
471*718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
472*718292f2SDouglas Gregor       parseModuleDecl();
473*718292f2SDouglas Gregor       break;
474*718292f2SDouglas Gregor 
475*718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
476*718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
477*718292f2SDouglas Gregor     case MMToken::Identifier:
478*718292f2SDouglas Gregor     case MMToken::LBrace:
479*718292f2SDouglas Gregor     case MMToken::RBrace:
480*718292f2SDouglas Gregor     case MMToken::StringLiteral:
481*718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
482*718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
483*718292f2SDouglas Gregor       HadError = true;
484*718292f2SDouglas Gregor       consumeToken();
485*718292f2SDouglas Gregor       break;
486*718292f2SDouglas Gregor     }
487*718292f2SDouglas Gregor   } while (true);
488*718292f2SDouglas Gregor 
489*718292f2SDouglas Gregor   return HadError;
490*718292f2SDouglas Gregor }
491*718292f2SDouglas Gregor 
492*718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
493*718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
494*718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
495*718292f2SDouglas Gregor   if (!Buffer)
496*718292f2SDouglas Gregor     return true;
497*718292f2SDouglas Gregor 
498*718292f2SDouglas Gregor   // Parse this module map file.
499*718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
500*718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
501*718292f2SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this);
502*718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
503*718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
504*718292f2SDouglas Gregor 
505*718292f2SDouglas Gregor   return Result;
506*718292f2SDouglas Gregor }
507