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 
34*5acdf59eSDouglas Gregor ModuleMap::Module::~Module() {
35*5acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
36*5acdf59eSDouglas Gregor                                         IEnd = SubModules.end();
37*5acdf59eSDouglas Gregor        I != IEnd; ++I) {
38*5acdf59eSDouglas Gregor     delete I->getValue();
39*5acdf59eSDouglas Gregor   }
40*5acdf59eSDouglas Gregor 
41*5acdf59eSDouglas Gregor }
42*5acdf59eSDouglas Gregor 
43718292f2SDouglas Gregor std::string ModuleMap::Module::getFullModuleName() const {
44718292f2SDouglas Gregor   llvm::SmallVector<StringRef, 2> Names;
45718292f2SDouglas Gregor 
46718292f2SDouglas Gregor   // Build up the set of module names (from innermost to outermost).
47718292f2SDouglas Gregor   for (const Module *M = this; M; M = M->Parent)
48718292f2SDouglas Gregor     Names.push_back(M->Name);
49718292f2SDouglas Gregor 
50718292f2SDouglas Gregor   std::string Result;
51718292f2SDouglas Gregor   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
52718292f2SDouglas Gregor                                                       IEnd = Names.rend();
53718292f2SDouglas Gregor        I != IEnd; ++I) {
54718292f2SDouglas Gregor     if (!Result.empty())
55718292f2SDouglas Gregor       Result += '.';
56718292f2SDouglas Gregor 
57718292f2SDouglas Gregor     Result += *I;
58718292f2SDouglas Gregor   }
59718292f2SDouglas Gregor 
60718292f2SDouglas Gregor   return Result;
61718292f2SDouglas Gregor }
62718292f2SDouglas Gregor 
63ab0c8a84SDouglas Gregor StringRef ModuleMap::Module::getTopLevelModuleName() const {
64ab0c8a84SDouglas Gregor   const Module *Top = this;
65ab0c8a84SDouglas Gregor   while (Top->Parent)
66ab0c8a84SDouglas Gregor     Top = Top->Parent;
67ab0c8a84SDouglas Gregor 
68ab0c8a84SDouglas Gregor   return Top->Name;
69ab0c8a84SDouglas Gregor }
70ab0c8a84SDouglas Gregor 
71718292f2SDouglas Gregor //----------------------------------------------------------------------------//
72718292f2SDouglas Gregor // Module map
73718292f2SDouglas Gregor //----------------------------------------------------------------------------//
74718292f2SDouglas Gregor 
75718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
76718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
77718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
78718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
79718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
80718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
81718292f2SDouglas Gregor }
82718292f2SDouglas Gregor 
83718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
84*5acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
85*5acdf59eSDouglas Gregor                                         IEnd = Modules.end();
86*5acdf59eSDouglas Gregor        I != IEnd; ++I) {
87*5acdf59eSDouglas Gregor     delete I->getValue();
88*5acdf59eSDouglas Gregor   }
89*5acdf59eSDouglas Gregor 
90718292f2SDouglas Gregor   delete SourceMgr;
91718292f2SDouglas Gregor }
92718292f2SDouglas Gregor 
93ab0c8a84SDouglas Gregor ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
94ab0c8a84SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
95ab0c8a84SDouglas Gregor     = Headers.find(File);
96ab0c8a84SDouglas Gregor   if (Known != Headers.end())
97ab0c8a84SDouglas Gregor     return Known->second;
98ab0c8a84SDouglas Gregor 
99b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
100b65dbfffSDouglas Gregor   llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
101b65dbfffSDouglas Gregor     = UmbrellaDirs.find(Dir);
102b65dbfffSDouglas Gregor   if (KnownDir != UmbrellaDirs.end())
103b65dbfffSDouglas Gregor     return KnownDir->second;
104b65dbfffSDouglas Gregor 
105b65dbfffSDouglas Gregor   // Walk up the directory hierarchy looking for umbrella headers.
106b65dbfffSDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
107b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
108b65dbfffSDouglas Gregor   do {
109b65dbfffSDouglas Gregor     // Retrieve our parent path.
110b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
111b65dbfffSDouglas Gregor     if (DirName.empty())
112b65dbfffSDouglas Gregor       break;
113b65dbfffSDouglas Gregor 
114b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
115b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
116b65dbfffSDouglas Gregor     if (!Dir)
117b65dbfffSDouglas Gregor       break;
118b65dbfffSDouglas Gregor 
119b65dbfffSDouglas Gregor     KnownDir = UmbrellaDirs.find(Dir);
120b65dbfffSDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
121b65dbfffSDouglas Gregor       Module *Result = KnownDir->second;
122b65dbfffSDouglas Gregor 
123b65dbfffSDouglas Gregor       // Record each of the directories we stepped through as being part of
124b65dbfffSDouglas Gregor       // the module we found, since the umbrella header covers them all.
125b65dbfffSDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
126b65dbfffSDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
127b65dbfffSDouglas Gregor 
128b65dbfffSDouglas Gregor       return Result;
129b65dbfffSDouglas Gregor     }
130b65dbfffSDouglas Gregor 
131b65dbfffSDouglas Gregor     SkippedDirs.push_back(Dir);
132b65dbfffSDouglas Gregor   } while (true);
133b65dbfffSDouglas Gregor 
134ab0c8a84SDouglas Gregor   return 0;
135ab0c8a84SDouglas Gregor }
136ab0c8a84SDouglas Gregor 
13788bdfb0eSDouglas Gregor ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
13888bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
13988bdfb0eSDouglas Gregor   if (Known != Modules.end())
14088bdfb0eSDouglas Gregor     return Known->getValue();
14188bdfb0eSDouglas Gregor 
14288bdfb0eSDouglas Gregor   return 0;
14388bdfb0eSDouglas Gregor }
14488bdfb0eSDouglas Gregor 
14556c64013SDouglas Gregor ModuleMap::Module *
14656c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
14756c64013SDouglas Gregor                                 const DirectoryEntry *FrameworkDir) {
14856c64013SDouglas Gregor   // Check whether we've already found this module.
14956c64013SDouglas Gregor   if (Module *Module = findModule(ModuleName))
15056c64013SDouglas Gregor     return Module;
15156c64013SDouglas Gregor 
15256c64013SDouglas Gregor   // Look for an umbrella header.
15356c64013SDouglas Gregor   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
15456c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
15556c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
15656c64013SDouglas Gregor   const FileEntry *UmbrellaHeader
15756c64013SDouglas Gregor     = SourceMgr->getFileManager().getFile(UmbrellaName);
15856c64013SDouglas Gregor 
15956c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
16056c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
16156c64013SDouglas Gregor   // idea.
16256c64013SDouglas Gregor   if (!UmbrellaHeader)
16356c64013SDouglas Gregor     return 0;
16456c64013SDouglas Gregor 
16556c64013SDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation());
16656c64013SDouglas Gregor   Result->UmbrellaHeader = UmbrellaHeader;
16756c64013SDouglas Gregor   Headers[UmbrellaHeader] = Result;
16856c64013SDouglas Gregor   UmbrellaDirs[FrameworkDir] = Result;
16956c64013SDouglas Gregor   Modules[ModuleName] = Result;
17056c64013SDouglas Gregor   return Result;
17156c64013SDouglas Gregor }
17256c64013SDouglas Gregor 
173718292f2SDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
174718292f2SDouglas Gregor   OS << std::string(' ', Spaces);
175718292f2SDouglas Gregor }
176718292f2SDouglas Gregor 
177718292f2SDouglas Gregor static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M,
178718292f2SDouglas Gregor                        unsigned Indent) {
179718292f2SDouglas Gregor   indent(OS, Indent);
180718292f2SDouglas Gregor   if (M->IsExplicit)
181718292f2SDouglas Gregor     OS << "explicit ";
182718292f2SDouglas Gregor   OS << M->Name << " {\n";
183718292f2SDouglas Gregor 
184718292f2SDouglas Gregor   if (M->UmbrellaHeader) {
185718292f2SDouglas Gregor     indent(OS, Indent + 2);
186718292f2SDouglas Gregor     OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n";
187718292f2SDouglas Gregor   }
188718292f2SDouglas Gregor 
189718292f2SDouglas Gregor   for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) {
190718292f2SDouglas Gregor     indent(OS, Indent + 2);
191718292f2SDouglas Gregor     OS << "header \"" << M->Headers[I]->getName() << "\"\n";
192718292f2SDouglas Gregor   }
193718292f2SDouglas Gregor 
194718292f2SDouglas Gregor   for (llvm::StringMap<ModuleMap::Module *>::iterator
195718292f2SDouglas Gregor             MI = M->SubModules.begin(),
196718292f2SDouglas Gregor          MIEnd = M->SubModules.end();
197718292f2SDouglas Gregor        MI != MIEnd; ++MI)
198718292f2SDouglas Gregor     dumpModule(llvm::errs(), MI->getValue(), Indent + 2);
199718292f2SDouglas Gregor 
200718292f2SDouglas Gregor   indent(OS, Indent);
201718292f2SDouglas Gregor   OS << "}\n";
202718292f2SDouglas Gregor }
203718292f2SDouglas Gregor 
204718292f2SDouglas Gregor void ModuleMap::dump() {
205718292f2SDouglas Gregor   llvm::errs() << "Modules:";
206718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
207718292f2SDouglas Gregor                                         MEnd = Modules.end();
208718292f2SDouglas Gregor        M != MEnd; ++M)
209718292f2SDouglas Gregor     dumpModule(llvm::errs(), M->getValue(), 2);
210718292f2SDouglas Gregor 
211718292f2SDouglas Gregor   llvm::errs() << "Headers:";
212718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
213718292f2SDouglas Gregor             H = Headers.begin(),
214718292f2SDouglas Gregor          HEnd = Headers.end();
215718292f2SDouglas Gregor        H != HEnd; ++H) {
216718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
217718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
218718292f2SDouglas Gregor   }
219718292f2SDouglas Gregor }
220718292f2SDouglas Gregor 
221718292f2SDouglas Gregor //----------------------------------------------------------------------------//
222718292f2SDouglas Gregor // Module map file parser
223718292f2SDouglas Gregor //----------------------------------------------------------------------------//
224718292f2SDouglas Gregor 
225718292f2SDouglas Gregor namespace clang {
226718292f2SDouglas Gregor   /// \brief A token in a module map file.
227718292f2SDouglas Gregor   struct MMToken {
228718292f2SDouglas Gregor     enum TokenKind {
229718292f2SDouglas Gregor       EndOfFile,
230718292f2SDouglas Gregor       HeaderKeyword,
231718292f2SDouglas Gregor       Identifier,
232718292f2SDouglas Gregor       ExplicitKeyword,
233718292f2SDouglas Gregor       ModuleKeyword,
234718292f2SDouglas Gregor       UmbrellaKeyword,
235718292f2SDouglas Gregor       StringLiteral,
236718292f2SDouglas Gregor       LBrace,
237718292f2SDouglas Gregor       RBrace
238718292f2SDouglas Gregor     } Kind;
239718292f2SDouglas Gregor 
240718292f2SDouglas Gregor     unsigned Location;
241718292f2SDouglas Gregor     unsigned StringLength;
242718292f2SDouglas Gregor     const char *StringData;
243718292f2SDouglas Gregor 
244718292f2SDouglas Gregor     void clear() {
245718292f2SDouglas Gregor       Kind = EndOfFile;
246718292f2SDouglas Gregor       Location = 0;
247718292f2SDouglas Gregor       StringLength = 0;
248718292f2SDouglas Gregor       StringData = 0;
249718292f2SDouglas Gregor     }
250718292f2SDouglas Gregor 
251718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
252718292f2SDouglas Gregor 
253718292f2SDouglas Gregor     SourceLocation getLocation() const {
254718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
255718292f2SDouglas Gregor     }
256718292f2SDouglas Gregor 
257718292f2SDouglas Gregor     StringRef getString() const {
258718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
259718292f2SDouglas Gregor     }
260718292f2SDouglas Gregor   };
261718292f2SDouglas Gregor 
262718292f2SDouglas Gregor   class ModuleMapParser {
263718292f2SDouglas Gregor     Lexer &L;
264718292f2SDouglas Gregor     SourceManager &SourceMgr;
265718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
266718292f2SDouglas Gregor     ModuleMap &Map;
267718292f2SDouglas Gregor 
2685257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
2695257fc63SDouglas Gregor     const DirectoryEntry *Directory;
2705257fc63SDouglas Gregor 
271718292f2SDouglas Gregor     /// \brief Whether an error occurred.
272718292f2SDouglas Gregor     bool HadError;
273718292f2SDouglas Gregor 
274718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
275718292f2SDouglas Gregor     /// parsing.
276718292f2SDouglas Gregor     TargetInfo *Target;
277718292f2SDouglas Gregor 
278718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
279718292f2SDouglas Gregor     /// during parsing.
280718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
281718292f2SDouglas Gregor 
282718292f2SDouglas Gregor     /// \brief The current token.
283718292f2SDouglas Gregor     MMToken Tok;
284718292f2SDouglas Gregor 
285718292f2SDouglas Gregor     /// \brief The active module.
286718292f2SDouglas Gregor     ModuleMap::Module *ActiveModule;
287718292f2SDouglas Gregor 
288718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
289718292f2SDouglas Gregor     SourceLocation consumeToken();
290718292f2SDouglas Gregor 
291718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
292718292f2SDouglas Gregor     /// (or the end of the file).
293718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
294718292f2SDouglas Gregor 
295718292f2SDouglas Gregor     void parseModuleDecl();
296718292f2SDouglas Gregor     void parseUmbrellaDecl();
297718292f2SDouglas Gregor     void parseHeaderDecl();
298718292f2SDouglas Gregor 
299718292f2SDouglas Gregor   public:
300718292f2SDouglas Gregor     typedef ModuleMap::Module Module;
301718292f2SDouglas Gregor 
302718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
303718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
3045257fc63SDouglas Gregor                              ModuleMap &Map,
3055257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
3065257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
3075257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
308718292f2SDouglas Gregor     {
309718292f2SDouglas Gregor       TargetOptions TargetOpts;
310718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
311718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
312718292f2SDouglas Gregor 
313718292f2SDouglas Gregor       Tok.clear();
314718292f2SDouglas Gregor       consumeToken();
315718292f2SDouglas Gregor     }
316718292f2SDouglas Gregor 
317718292f2SDouglas Gregor     bool parseModuleMapFile();
318718292f2SDouglas Gregor   };
319718292f2SDouglas Gregor }
320718292f2SDouglas Gregor 
321718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
322718292f2SDouglas Gregor retry:
323718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
324718292f2SDouglas Gregor   Tok.clear();
325718292f2SDouglas Gregor 
326718292f2SDouglas Gregor   Token LToken;
327718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
328718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
329718292f2SDouglas Gregor   switch (LToken.getKind()) {
330718292f2SDouglas Gregor   case tok::raw_identifier:
331718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
332718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
333718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
334718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
335718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
336718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
337718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
338718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
339718292f2SDouglas Gregor     break;
340718292f2SDouglas Gregor 
341718292f2SDouglas Gregor   case tok::eof:
342718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
343718292f2SDouglas Gregor     break;
344718292f2SDouglas Gregor 
345718292f2SDouglas Gregor   case tok::l_brace:
346718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
347718292f2SDouglas Gregor     break;
348718292f2SDouglas Gregor 
349718292f2SDouglas Gregor   case tok::r_brace:
350718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
351718292f2SDouglas Gregor     break;
352718292f2SDouglas Gregor 
353718292f2SDouglas Gregor   case tok::string_literal: {
354718292f2SDouglas Gregor     // Parse the string literal.
355718292f2SDouglas Gregor     LangOptions LangOpts;
356718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
357718292f2SDouglas Gregor     if (StringLiteral.hadError)
358718292f2SDouglas Gregor       goto retry;
359718292f2SDouglas Gregor 
360718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
361718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
362718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
363718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
364718292f2SDouglas Gregor     Saved[Length] = 0;
365718292f2SDouglas Gregor 
366718292f2SDouglas Gregor     // Form the token.
367718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
368718292f2SDouglas Gregor     Tok.StringData = Saved;
369718292f2SDouglas Gregor     Tok.StringLength = Length;
370718292f2SDouglas Gregor     break;
371718292f2SDouglas Gregor   }
372718292f2SDouglas Gregor 
373718292f2SDouglas Gregor   case tok::comment:
374718292f2SDouglas Gregor     goto retry;
375718292f2SDouglas Gregor 
376718292f2SDouglas Gregor   default:
377718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
378718292f2SDouglas Gregor     HadError = true;
379718292f2SDouglas Gregor     goto retry;
380718292f2SDouglas Gregor   }
381718292f2SDouglas Gregor 
382718292f2SDouglas Gregor   return Result;
383718292f2SDouglas Gregor }
384718292f2SDouglas Gregor 
385718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
386718292f2SDouglas Gregor   unsigned braceDepth = 0;
387718292f2SDouglas Gregor   do {
388718292f2SDouglas Gregor     switch (Tok.Kind) {
389718292f2SDouglas Gregor     case MMToken::EndOfFile:
390718292f2SDouglas Gregor       return;
391718292f2SDouglas Gregor 
392718292f2SDouglas Gregor     case MMToken::LBrace:
393718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
394718292f2SDouglas Gregor         return;
395718292f2SDouglas Gregor 
396718292f2SDouglas Gregor       ++braceDepth;
397718292f2SDouglas Gregor       break;
398718292f2SDouglas Gregor 
399718292f2SDouglas Gregor     case MMToken::RBrace:
400718292f2SDouglas Gregor       if (braceDepth > 0)
401718292f2SDouglas Gregor         --braceDepth;
402718292f2SDouglas Gregor       else if (Tok.is(K))
403718292f2SDouglas Gregor         return;
404718292f2SDouglas Gregor       break;
405718292f2SDouglas Gregor 
406718292f2SDouglas Gregor     default:
407718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
408718292f2SDouglas Gregor         return;
409718292f2SDouglas Gregor       break;
410718292f2SDouglas Gregor     }
411718292f2SDouglas Gregor 
412718292f2SDouglas Gregor    consumeToken();
413718292f2SDouglas Gregor   } while (true);
414718292f2SDouglas Gregor }
415718292f2SDouglas Gregor 
416718292f2SDouglas Gregor /// \brief Parse a module declaration.
417718292f2SDouglas Gregor ///
418718292f2SDouglas Gregor ///   module-declaration:
419718292f2SDouglas Gregor ///     'module' identifier { module-member* }
420718292f2SDouglas Gregor ///
421718292f2SDouglas Gregor ///   module-member:
422718292f2SDouglas Gregor ///     umbrella-declaration
423718292f2SDouglas Gregor ///     header-declaration
424718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
425718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
426718292f2SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword));
427718292f2SDouglas Gregor 
428718292f2SDouglas Gregor   // Parse 'explicit' keyword, if present.
429718292f2SDouglas Gregor   bool Explicit = false;
430718292f2SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
431718292f2SDouglas Gregor     consumeToken();
432718292f2SDouglas Gregor     Explicit = true;
433718292f2SDouglas Gregor   }
434718292f2SDouglas Gregor 
435718292f2SDouglas Gregor   // Parse 'module' keyword.
436718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
437718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
438718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
439718292f2SDouglas Gregor     consumeToken();
440718292f2SDouglas Gregor     HadError = true;
441718292f2SDouglas Gregor     return;
442718292f2SDouglas Gregor   }
443718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
444718292f2SDouglas Gregor 
445718292f2SDouglas Gregor   // Parse the module name.
446718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
447718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
448718292f2SDouglas Gregor     HadError = true;
449718292f2SDouglas Gregor     return;
450718292f2SDouglas Gregor   }
451718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
452718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
453718292f2SDouglas Gregor 
454718292f2SDouglas Gregor   // Parse the opening brace.
455718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
456718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
457718292f2SDouglas Gregor       << ModuleName;
458718292f2SDouglas Gregor     HadError = true;
459718292f2SDouglas Gregor     return;
460718292f2SDouglas Gregor   }
461718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
462718292f2SDouglas Gregor 
463718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
464718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
465718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
466718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
467718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
468718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
469718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
470718292f2SDouglas Gregor       << ModuleName;
471718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
472718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
473718292f2SDouglas Gregor 
474718292f2SDouglas Gregor     // Skip the module definition.
475718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
476718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
477718292f2SDouglas Gregor       consumeToken();
478718292f2SDouglas Gregor 
479718292f2SDouglas Gregor     HadError = true;
480718292f2SDouglas Gregor     return;
481718292f2SDouglas Gregor   }
482718292f2SDouglas Gregor 
483718292f2SDouglas Gregor   // Start defining this module.
484718292f2SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit);
485718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
486718292f2SDouglas Gregor 
487718292f2SDouglas Gregor   bool Done = false;
488718292f2SDouglas Gregor   do {
489718292f2SDouglas Gregor     switch (Tok.Kind) {
490718292f2SDouglas Gregor     case MMToken::EndOfFile:
491718292f2SDouglas Gregor     case MMToken::RBrace:
492718292f2SDouglas Gregor       Done = true;
493718292f2SDouglas Gregor       break;
494718292f2SDouglas Gregor 
495718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
496718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
497718292f2SDouglas Gregor       parseModuleDecl();
498718292f2SDouglas Gregor       break;
499718292f2SDouglas Gregor 
500718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
501718292f2SDouglas Gregor       parseHeaderDecl();
502718292f2SDouglas Gregor       break;
503718292f2SDouglas Gregor 
504718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
505718292f2SDouglas Gregor       parseUmbrellaDecl();
506718292f2SDouglas Gregor       break;
507718292f2SDouglas Gregor 
508718292f2SDouglas Gregor     default:
509718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
510718292f2SDouglas Gregor       consumeToken();
511718292f2SDouglas Gregor       break;
512718292f2SDouglas Gregor     }
513718292f2SDouglas Gregor   } while (!Done);
514718292f2SDouglas Gregor 
515718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
516718292f2SDouglas Gregor     consumeToken();
517718292f2SDouglas Gregor   else {
518718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
519718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
520718292f2SDouglas Gregor     HadError = true;
521718292f2SDouglas Gregor   }
522718292f2SDouglas Gregor 
523718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
524718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
525718292f2SDouglas Gregor }
526718292f2SDouglas Gregor 
527718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
528718292f2SDouglas Gregor ///
529718292f2SDouglas Gregor ///   umbrella-declaration:
530718292f2SDouglas Gregor ///     'umbrella' string-literal
531718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
532718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
533718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
534718292f2SDouglas Gregor 
535718292f2SDouglas Gregor   // Parse the header name.
536718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
537718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
538718292f2SDouglas Gregor       << "umbrella";
539718292f2SDouglas Gregor     HadError = true;
540718292f2SDouglas Gregor     return;
541718292f2SDouglas Gregor   }
542718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
543718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
544718292f2SDouglas Gregor 
5455257fc63SDouglas Gregor   // Check whether we already have an umbrella header.
5465257fc63SDouglas Gregor   if (ActiveModule->UmbrellaHeader) {
5475257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
5485257fc63SDouglas Gregor       << ActiveModule->getFullModuleName()
5495257fc63SDouglas Gregor       << ActiveModule->UmbrellaHeader->getName();
5505257fc63SDouglas Gregor     HadError = true;
5515257fc63SDouglas Gregor     return;
5525257fc63SDouglas Gregor   }
5535257fc63SDouglas Gregor 
5545257fc63SDouglas Gregor   // Only top-level modules can have umbrella headers.
5555257fc63SDouglas Gregor   if (ActiveModule->Parent) {
5565257fc63SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
5575257fc63SDouglas Gregor       << ActiveModule->getFullModuleName();
5585257fc63SDouglas Gregor     HadError = true;
5595257fc63SDouglas Gregor     return;
5605257fc63SDouglas Gregor   }
5615257fc63SDouglas Gregor 
5625257fc63SDouglas Gregor   // Look for this file.
5635257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
5645257fc63SDouglas Gregor   PathName += Directory->getName();
5655257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
5665257fc63SDouglas Gregor 
5675257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
5685257fc63SDouglas Gregor   // Come up with a lazy way to do this.
5695257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
5705257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
5715257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
5725257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
5735257fc63SDouglas Gregor       HadError = true;
574b65dbfffSDouglas Gregor     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
575b65dbfffSDouglas Gregor       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
576b65dbfffSDouglas Gregor         << OwningModule->getFullModuleName();
577b65dbfffSDouglas Gregor       HadError = true;
5785257fc63SDouglas Gregor     } else {
5795257fc63SDouglas Gregor       // Record this umbrella header.
5805257fc63SDouglas Gregor       ActiveModule->UmbrellaHeader = File;
5815257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
582b65dbfffSDouglas Gregor       Map.UmbrellaDirs[Directory] = ActiveModule;
5835257fc63SDouglas Gregor     }
5845257fc63SDouglas Gregor   } else {
5855257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
5865257fc63SDouglas Gregor       << true << FileName;
5875257fc63SDouglas Gregor     HadError = true;
5885257fc63SDouglas Gregor   }
589718292f2SDouglas Gregor }
590718292f2SDouglas Gregor 
591718292f2SDouglas Gregor /// \brief Parse a header declaration.
592718292f2SDouglas Gregor ///
593718292f2SDouglas Gregor ///   header-declaration:
594718292f2SDouglas Gregor ///     'header' string-literal
595718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
596718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
5971871ed3dSBenjamin Kramer   consumeToken();
598718292f2SDouglas Gregor 
599718292f2SDouglas Gregor   // Parse the header name.
600718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
601718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
602718292f2SDouglas Gregor       << "header";
603718292f2SDouglas Gregor     HadError = true;
604718292f2SDouglas Gregor     return;
605718292f2SDouglas Gregor   }
606718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
607718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
608718292f2SDouglas Gregor 
6095257fc63SDouglas Gregor   // Look for this file.
6105257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
6115257fc63SDouglas Gregor   PathName += Directory->getName();
6125257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
6135257fc63SDouglas Gregor 
6145257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6155257fc63SDouglas Gregor   // Come up with a lazy way to do this.
6165257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
6175257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6185257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6195257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6205257fc63SDouglas Gregor       HadError = true;
6215257fc63SDouglas Gregor     } else {
6225257fc63SDouglas Gregor       // Record this file.
6235257fc63SDouglas Gregor       ActiveModule->Headers.push_back(File);
6245257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
6255257fc63SDouglas Gregor     }
6265257fc63SDouglas Gregor   } else {
6275257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6285257fc63SDouglas Gregor       << false << FileName;
6295257fc63SDouglas Gregor     HadError = true;
6305257fc63SDouglas Gregor   }
631718292f2SDouglas Gregor }
632718292f2SDouglas Gregor 
633718292f2SDouglas Gregor /// \brief Parse a module map file.
634718292f2SDouglas Gregor ///
635718292f2SDouglas Gregor ///   module-map-file:
636718292f2SDouglas Gregor ///     module-declaration*
637718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
638718292f2SDouglas Gregor   do {
639718292f2SDouglas Gregor     switch (Tok.Kind) {
640718292f2SDouglas Gregor     case MMToken::EndOfFile:
641718292f2SDouglas Gregor       return HadError;
642718292f2SDouglas Gregor 
643718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
644718292f2SDouglas Gregor       parseModuleDecl();
645718292f2SDouglas Gregor       break;
646718292f2SDouglas Gregor 
647718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
648718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
649718292f2SDouglas Gregor     case MMToken::Identifier:
650718292f2SDouglas Gregor     case MMToken::LBrace:
651718292f2SDouglas Gregor     case MMToken::RBrace:
652718292f2SDouglas Gregor     case MMToken::StringLiteral:
653718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
654718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
655718292f2SDouglas Gregor       HadError = true;
656718292f2SDouglas Gregor       consumeToken();
657718292f2SDouglas Gregor       break;
658718292f2SDouglas Gregor     }
659718292f2SDouglas Gregor   } while (true);
660718292f2SDouglas Gregor 
661718292f2SDouglas Gregor   return HadError;
662718292f2SDouglas Gregor }
663718292f2SDouglas Gregor 
664718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
665718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
666718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
667718292f2SDouglas Gregor   if (!Buffer)
668718292f2SDouglas Gregor     return true;
669718292f2SDouglas Gregor 
670718292f2SDouglas Gregor   // Parse this module map file.
671718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
672718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
6735257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
674718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
675718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
676718292f2SDouglas Gregor 
677718292f2SDouglas Gregor   return Result;
678718292f2SDouglas Gregor }
679