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 
345acdf59eSDouglas Gregor ModuleMap::Module::~Module() {
355acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
365acdf59eSDouglas Gregor                                         IEnd = SubModules.end();
375acdf59eSDouglas Gregor        I != IEnd; ++I) {
385acdf59eSDouglas Gregor     delete I->getValue();
395acdf59eSDouglas Gregor   }
405acdf59eSDouglas Gregor 
415acdf59eSDouglas Gregor }
425acdf59eSDouglas 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 
71*d28d1b8dSDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
72*d28d1b8dSDouglas Gregor   OS << std::string(' ', Spaces);
73*d28d1b8dSDouglas Gregor }
74*d28d1b8dSDouglas Gregor 
75*d28d1b8dSDouglas Gregor void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
76*d28d1b8dSDouglas Gregor   indent(OS, Indent);
77*d28d1b8dSDouglas Gregor   if (IsFramework)
78*d28d1b8dSDouglas Gregor     OS << "framework ";
79*d28d1b8dSDouglas Gregor   if (IsExplicit)
80*d28d1b8dSDouglas Gregor     OS << "explicit ";
81*d28d1b8dSDouglas Gregor   OS << Name << " {\n";
82*d28d1b8dSDouglas Gregor 
83*d28d1b8dSDouglas Gregor   if (UmbrellaHeader) {
84*d28d1b8dSDouglas Gregor     indent(OS, Indent + 2);
85*d28d1b8dSDouglas Gregor     OS << "umbrella \"" << UmbrellaHeader->getName() << "\"\n";
86*d28d1b8dSDouglas Gregor   }
87*d28d1b8dSDouglas Gregor 
88*d28d1b8dSDouglas Gregor   for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
89*d28d1b8dSDouglas Gregor     indent(OS, Indent + 2);
90*d28d1b8dSDouglas Gregor     OS << "header \"" << Headers[I]->getName() << "\"\n";
91*d28d1b8dSDouglas Gregor   }
92*d28d1b8dSDouglas Gregor 
93*d28d1b8dSDouglas Gregor   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
94*d28d1b8dSDouglas Gregor                                               MIEnd = SubModules.end();
95*d28d1b8dSDouglas Gregor        MI != MIEnd; ++MI)
96*d28d1b8dSDouglas Gregor     MI->getValue()->print(OS, Indent + 2);
97*d28d1b8dSDouglas Gregor 
98*d28d1b8dSDouglas Gregor   indent(OS, Indent);
99*d28d1b8dSDouglas Gregor   OS << "}\n";
100*d28d1b8dSDouglas Gregor }
101*d28d1b8dSDouglas Gregor 
102*d28d1b8dSDouglas Gregor void ModuleMap::Module::dump() const {
103*d28d1b8dSDouglas Gregor   print(llvm::errs());
104*d28d1b8dSDouglas Gregor }
105*d28d1b8dSDouglas Gregor 
106718292f2SDouglas Gregor //----------------------------------------------------------------------------//
107718292f2SDouglas Gregor // Module map
108718292f2SDouglas Gregor //----------------------------------------------------------------------------//
109718292f2SDouglas Gregor 
110718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
111718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
112718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
113718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
114718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
115718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
116718292f2SDouglas Gregor }
117718292f2SDouglas Gregor 
118718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
1195acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
1205acdf59eSDouglas Gregor                                         IEnd = Modules.end();
1215acdf59eSDouglas Gregor        I != IEnd; ++I) {
1225acdf59eSDouglas Gregor     delete I->getValue();
1235acdf59eSDouglas Gregor   }
1245acdf59eSDouglas Gregor 
125718292f2SDouglas Gregor   delete SourceMgr;
126718292f2SDouglas Gregor }
127718292f2SDouglas Gregor 
128ab0c8a84SDouglas Gregor ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
129ab0c8a84SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
130ab0c8a84SDouglas Gregor     = Headers.find(File);
131ab0c8a84SDouglas Gregor   if (Known != Headers.end())
132ab0c8a84SDouglas Gregor     return Known->second;
133ab0c8a84SDouglas Gregor 
134b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
135b65dbfffSDouglas Gregor   llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
136b65dbfffSDouglas Gregor     = UmbrellaDirs.find(Dir);
137b65dbfffSDouglas Gregor   if (KnownDir != UmbrellaDirs.end())
138b65dbfffSDouglas Gregor     return KnownDir->second;
139b65dbfffSDouglas Gregor 
140b65dbfffSDouglas Gregor   // Walk up the directory hierarchy looking for umbrella headers.
141b65dbfffSDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
142b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
143b65dbfffSDouglas Gregor   do {
144b65dbfffSDouglas Gregor     // Retrieve our parent path.
145b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
146b65dbfffSDouglas Gregor     if (DirName.empty())
147b65dbfffSDouglas Gregor       break;
148b65dbfffSDouglas Gregor 
149b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
150b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
151b65dbfffSDouglas Gregor     if (!Dir)
152b65dbfffSDouglas Gregor       break;
153b65dbfffSDouglas Gregor 
154b65dbfffSDouglas Gregor     KnownDir = UmbrellaDirs.find(Dir);
155b65dbfffSDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
156b65dbfffSDouglas Gregor       Module *Result = KnownDir->second;
157b65dbfffSDouglas Gregor 
158b65dbfffSDouglas Gregor       // Record each of the directories we stepped through as being part of
159b65dbfffSDouglas Gregor       // the module we found, since the umbrella header covers them all.
160b65dbfffSDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
161b65dbfffSDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
162b65dbfffSDouglas Gregor 
163b65dbfffSDouglas Gregor       return Result;
164b65dbfffSDouglas Gregor     }
165b65dbfffSDouglas Gregor 
166b65dbfffSDouglas Gregor     SkippedDirs.push_back(Dir);
167b65dbfffSDouglas Gregor   } while (true);
168b65dbfffSDouglas Gregor 
169ab0c8a84SDouglas Gregor   return 0;
170ab0c8a84SDouglas Gregor }
171ab0c8a84SDouglas Gregor 
17288bdfb0eSDouglas Gregor ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
17388bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
17488bdfb0eSDouglas Gregor   if (Known != Modules.end())
17588bdfb0eSDouglas Gregor     return Known->getValue();
17688bdfb0eSDouglas Gregor 
17788bdfb0eSDouglas Gregor   return 0;
17888bdfb0eSDouglas Gregor }
17988bdfb0eSDouglas Gregor 
18056c64013SDouglas Gregor ModuleMap::Module *
18156c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
18256c64013SDouglas Gregor                                 const DirectoryEntry *FrameworkDir) {
18356c64013SDouglas Gregor   // Check whether we've already found this module.
18456c64013SDouglas Gregor   if (Module *Module = findModule(ModuleName))
18556c64013SDouglas Gregor     return Module;
18656c64013SDouglas Gregor 
18756c64013SDouglas Gregor   // Look for an umbrella header.
18856c64013SDouglas Gregor   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
18956c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
19056c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
19156c64013SDouglas Gregor   const FileEntry *UmbrellaHeader
19256c64013SDouglas Gregor     = SourceMgr->getFileManager().getFile(UmbrellaName);
19356c64013SDouglas Gregor 
19456c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
19556c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
19656c64013SDouglas Gregor   // idea.
19756c64013SDouglas Gregor   if (!UmbrellaHeader)
19856c64013SDouglas Gregor     return 0;
19956c64013SDouglas Gregor 
200755b2055SDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(),
201755b2055SDouglas Gregor                               /*IsFramework=*/true);
20256c64013SDouglas Gregor   Result->UmbrellaHeader = UmbrellaHeader;
20356c64013SDouglas Gregor   Headers[UmbrellaHeader] = Result;
20456c64013SDouglas Gregor   UmbrellaDirs[FrameworkDir] = Result;
20556c64013SDouglas Gregor   Modules[ModuleName] = Result;
20656c64013SDouglas Gregor   return Result;
20756c64013SDouglas Gregor }
20856c64013SDouglas Gregor 
209718292f2SDouglas Gregor void ModuleMap::dump() {
210718292f2SDouglas Gregor   llvm::errs() << "Modules:";
211718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
212718292f2SDouglas Gregor                                         MEnd = Modules.end();
213718292f2SDouglas Gregor        M != MEnd; ++M)
214*d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
215718292f2SDouglas Gregor 
216718292f2SDouglas Gregor   llvm::errs() << "Headers:";
217718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
218718292f2SDouglas Gregor             H = Headers.begin(),
219718292f2SDouglas Gregor          HEnd = Headers.end();
220718292f2SDouglas Gregor        H != HEnd; ++H) {
221718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
222718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
223718292f2SDouglas Gregor   }
224718292f2SDouglas Gregor }
225718292f2SDouglas Gregor 
226718292f2SDouglas Gregor //----------------------------------------------------------------------------//
227718292f2SDouglas Gregor // Module map file parser
228718292f2SDouglas Gregor //----------------------------------------------------------------------------//
229718292f2SDouglas Gregor 
230718292f2SDouglas Gregor namespace clang {
231718292f2SDouglas Gregor   /// \brief A token in a module map file.
232718292f2SDouglas Gregor   struct MMToken {
233718292f2SDouglas Gregor     enum TokenKind {
234718292f2SDouglas Gregor       EndOfFile,
235718292f2SDouglas Gregor       HeaderKeyword,
236718292f2SDouglas Gregor       Identifier,
237718292f2SDouglas Gregor       ExplicitKeyword,
238755b2055SDouglas Gregor       FrameworkKeyword,
239718292f2SDouglas Gregor       ModuleKeyword,
240718292f2SDouglas Gregor       UmbrellaKeyword,
241718292f2SDouglas Gregor       StringLiteral,
242718292f2SDouglas Gregor       LBrace,
243718292f2SDouglas Gregor       RBrace
244718292f2SDouglas Gregor     } Kind;
245718292f2SDouglas Gregor 
246718292f2SDouglas Gregor     unsigned Location;
247718292f2SDouglas Gregor     unsigned StringLength;
248718292f2SDouglas Gregor     const char *StringData;
249718292f2SDouglas Gregor 
250718292f2SDouglas Gregor     void clear() {
251718292f2SDouglas Gregor       Kind = EndOfFile;
252718292f2SDouglas Gregor       Location = 0;
253718292f2SDouglas Gregor       StringLength = 0;
254718292f2SDouglas Gregor       StringData = 0;
255718292f2SDouglas Gregor     }
256718292f2SDouglas Gregor 
257718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
258718292f2SDouglas Gregor 
259718292f2SDouglas Gregor     SourceLocation getLocation() const {
260718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
261718292f2SDouglas Gregor     }
262718292f2SDouglas Gregor 
263718292f2SDouglas Gregor     StringRef getString() const {
264718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
265718292f2SDouglas Gregor     }
266718292f2SDouglas Gregor   };
267718292f2SDouglas Gregor 
268718292f2SDouglas Gregor   class ModuleMapParser {
269718292f2SDouglas Gregor     Lexer &L;
270718292f2SDouglas Gregor     SourceManager &SourceMgr;
271718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
272718292f2SDouglas Gregor     ModuleMap &Map;
273718292f2SDouglas Gregor 
2745257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
2755257fc63SDouglas Gregor     const DirectoryEntry *Directory;
2765257fc63SDouglas Gregor 
277718292f2SDouglas Gregor     /// \brief Whether an error occurred.
278718292f2SDouglas Gregor     bool HadError;
279718292f2SDouglas Gregor 
280718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
281718292f2SDouglas Gregor     /// parsing.
282718292f2SDouglas Gregor     TargetInfo *Target;
283718292f2SDouglas Gregor 
284718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
285718292f2SDouglas Gregor     /// during parsing.
286718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
287718292f2SDouglas Gregor 
288718292f2SDouglas Gregor     /// \brief The current token.
289718292f2SDouglas Gregor     MMToken Tok;
290718292f2SDouglas Gregor 
291718292f2SDouglas Gregor     /// \brief The active module.
292718292f2SDouglas Gregor     ModuleMap::Module *ActiveModule;
293718292f2SDouglas Gregor 
294718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
295718292f2SDouglas Gregor     SourceLocation consumeToken();
296718292f2SDouglas Gregor 
297718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
298718292f2SDouglas Gregor     /// (or the end of the file).
299718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
300718292f2SDouglas Gregor 
301718292f2SDouglas Gregor     void parseModuleDecl();
302718292f2SDouglas Gregor     void parseUmbrellaDecl();
303718292f2SDouglas Gregor     void parseHeaderDecl();
304718292f2SDouglas Gregor 
305718292f2SDouglas Gregor   public:
306718292f2SDouglas Gregor     typedef ModuleMap::Module Module;
307718292f2SDouglas Gregor 
308718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
309718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
3105257fc63SDouglas Gregor                              ModuleMap &Map,
3115257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
3125257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
3135257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
314718292f2SDouglas Gregor     {
315718292f2SDouglas Gregor       TargetOptions TargetOpts;
316718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
317718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
318718292f2SDouglas Gregor 
319718292f2SDouglas Gregor       Tok.clear();
320718292f2SDouglas Gregor       consumeToken();
321718292f2SDouglas Gregor     }
322718292f2SDouglas Gregor 
323718292f2SDouglas Gregor     bool parseModuleMapFile();
324718292f2SDouglas Gregor   };
325718292f2SDouglas Gregor }
326718292f2SDouglas Gregor 
327718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
328718292f2SDouglas Gregor retry:
329718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
330718292f2SDouglas Gregor   Tok.clear();
331718292f2SDouglas Gregor 
332718292f2SDouglas Gregor   Token LToken;
333718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
334718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
335718292f2SDouglas Gregor   switch (LToken.getKind()) {
336718292f2SDouglas Gregor   case tok::raw_identifier:
337718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
338718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
339718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
340718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
341718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
342755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
343718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
344718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
345718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
346718292f2SDouglas Gregor     break;
347718292f2SDouglas Gregor 
348718292f2SDouglas Gregor   case tok::eof:
349718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
350718292f2SDouglas Gregor     break;
351718292f2SDouglas Gregor 
352718292f2SDouglas Gregor   case tok::l_brace:
353718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
354718292f2SDouglas Gregor     break;
355718292f2SDouglas Gregor 
356718292f2SDouglas Gregor   case tok::r_brace:
357718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
358718292f2SDouglas Gregor     break;
359718292f2SDouglas Gregor 
360718292f2SDouglas Gregor   case tok::string_literal: {
361718292f2SDouglas Gregor     // Parse the string literal.
362718292f2SDouglas Gregor     LangOptions LangOpts;
363718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
364718292f2SDouglas Gregor     if (StringLiteral.hadError)
365718292f2SDouglas Gregor       goto retry;
366718292f2SDouglas Gregor 
367718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
368718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
369718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
370718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
371718292f2SDouglas Gregor     Saved[Length] = 0;
372718292f2SDouglas Gregor 
373718292f2SDouglas Gregor     // Form the token.
374718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
375718292f2SDouglas Gregor     Tok.StringData = Saved;
376718292f2SDouglas Gregor     Tok.StringLength = Length;
377718292f2SDouglas Gregor     break;
378718292f2SDouglas Gregor   }
379718292f2SDouglas Gregor 
380718292f2SDouglas Gregor   case tok::comment:
381718292f2SDouglas Gregor     goto retry;
382718292f2SDouglas Gregor 
383718292f2SDouglas Gregor   default:
384718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
385718292f2SDouglas Gregor     HadError = true;
386718292f2SDouglas Gregor     goto retry;
387718292f2SDouglas Gregor   }
388718292f2SDouglas Gregor 
389718292f2SDouglas Gregor   return Result;
390718292f2SDouglas Gregor }
391718292f2SDouglas Gregor 
392718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
393718292f2SDouglas Gregor   unsigned braceDepth = 0;
394718292f2SDouglas Gregor   do {
395718292f2SDouglas Gregor     switch (Tok.Kind) {
396718292f2SDouglas Gregor     case MMToken::EndOfFile:
397718292f2SDouglas Gregor       return;
398718292f2SDouglas Gregor 
399718292f2SDouglas Gregor     case MMToken::LBrace:
400718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
401718292f2SDouglas Gregor         return;
402718292f2SDouglas Gregor 
403718292f2SDouglas Gregor       ++braceDepth;
404718292f2SDouglas Gregor       break;
405718292f2SDouglas Gregor 
406718292f2SDouglas Gregor     case MMToken::RBrace:
407718292f2SDouglas Gregor       if (braceDepth > 0)
408718292f2SDouglas Gregor         --braceDepth;
409718292f2SDouglas Gregor       else if (Tok.is(K))
410718292f2SDouglas Gregor         return;
411718292f2SDouglas Gregor       break;
412718292f2SDouglas Gregor 
413718292f2SDouglas Gregor     default:
414718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
415718292f2SDouglas Gregor         return;
416718292f2SDouglas Gregor       break;
417718292f2SDouglas Gregor     }
418718292f2SDouglas Gregor 
419718292f2SDouglas Gregor    consumeToken();
420718292f2SDouglas Gregor   } while (true);
421718292f2SDouglas Gregor }
422718292f2SDouglas Gregor 
423718292f2SDouglas Gregor /// \brief Parse a module declaration.
424718292f2SDouglas Gregor ///
425718292f2SDouglas Gregor ///   module-declaration:
426755b2055SDouglas Gregor ///     'framework'[opt] 'module' identifier { module-member* }
427718292f2SDouglas Gregor ///
428718292f2SDouglas Gregor ///   module-member:
429718292f2SDouglas Gregor ///     umbrella-declaration
430718292f2SDouglas Gregor ///     header-declaration
431718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
432718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
433755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
434755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
435718292f2SDouglas Gregor 
436755b2055SDouglas Gregor   // Parse 'framework' or 'explicit' keyword, if present.
437755b2055SDouglas Gregor   bool Framework = false;
438718292f2SDouglas Gregor   bool Explicit = false;
439755b2055SDouglas Gregor 
440755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
441755b2055SDouglas Gregor     consumeToken();
442755b2055SDouglas Gregor     Framework = true;
443755b2055SDouglas Gregor   }
444755b2055SDouglas Gregor   // Parse 'explicit' keyword, if present.
445755b2055SDouglas Gregor   else if (Tok.is(MMToken::ExplicitKeyword)) {
446718292f2SDouglas Gregor     consumeToken();
447718292f2SDouglas Gregor     Explicit = true;
448718292f2SDouglas Gregor   }
449718292f2SDouglas Gregor 
450718292f2SDouglas Gregor   // Parse 'module' keyword.
451718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
452718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
453718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
454718292f2SDouglas Gregor     consumeToken();
455718292f2SDouglas Gregor     HadError = true;
456718292f2SDouglas Gregor     return;
457718292f2SDouglas Gregor   }
458718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
459718292f2SDouglas Gregor 
460718292f2SDouglas Gregor   // Parse the module name.
461718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
462718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
463718292f2SDouglas Gregor     HadError = true;
464718292f2SDouglas Gregor     return;
465718292f2SDouglas Gregor   }
466718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
467718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
468718292f2SDouglas Gregor 
469718292f2SDouglas Gregor   // Parse the opening brace.
470718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
471718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
472718292f2SDouglas Gregor       << ModuleName;
473718292f2SDouglas Gregor     HadError = true;
474718292f2SDouglas Gregor     return;
475718292f2SDouglas Gregor   }
476718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
477718292f2SDouglas Gregor 
478718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
479718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
480718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
481718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
482718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
483718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
484718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
485718292f2SDouglas Gregor       << ModuleName;
486718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
487718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
488718292f2SDouglas Gregor 
489718292f2SDouglas Gregor     // Skip the module definition.
490718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
491718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
492718292f2SDouglas Gregor       consumeToken();
493718292f2SDouglas Gregor 
494718292f2SDouglas Gregor     HadError = true;
495718292f2SDouglas Gregor     return;
496718292f2SDouglas Gregor   }
497718292f2SDouglas Gregor 
498718292f2SDouglas Gregor   // Start defining this module.
499755b2055SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
500755b2055SDouglas Gregor                             Explicit);
501718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
502718292f2SDouglas Gregor 
503718292f2SDouglas Gregor   bool Done = false;
504718292f2SDouglas Gregor   do {
505718292f2SDouglas Gregor     switch (Tok.Kind) {
506718292f2SDouglas Gregor     case MMToken::EndOfFile:
507718292f2SDouglas Gregor     case MMToken::RBrace:
508718292f2SDouglas Gregor       Done = true;
509718292f2SDouglas Gregor       break;
510718292f2SDouglas Gregor 
511718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
512718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
513718292f2SDouglas Gregor       parseModuleDecl();
514718292f2SDouglas Gregor       break;
515718292f2SDouglas Gregor 
516718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
517718292f2SDouglas Gregor       parseHeaderDecl();
518718292f2SDouglas Gregor       break;
519718292f2SDouglas Gregor 
520718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
521718292f2SDouglas Gregor       parseUmbrellaDecl();
522718292f2SDouglas Gregor       break;
523718292f2SDouglas Gregor 
524718292f2SDouglas Gregor     default:
525718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
526718292f2SDouglas Gregor       consumeToken();
527718292f2SDouglas Gregor       break;
528718292f2SDouglas Gregor     }
529718292f2SDouglas Gregor   } while (!Done);
530718292f2SDouglas Gregor 
531718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
532718292f2SDouglas Gregor     consumeToken();
533718292f2SDouglas Gregor   else {
534718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
535718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
536718292f2SDouglas Gregor     HadError = true;
537718292f2SDouglas Gregor   }
538718292f2SDouglas Gregor 
539718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
540718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
541718292f2SDouglas Gregor }
542718292f2SDouglas Gregor 
543718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
544718292f2SDouglas Gregor ///
545718292f2SDouglas Gregor ///   umbrella-declaration:
546718292f2SDouglas Gregor ///     'umbrella' string-literal
547718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
548718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
549718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
550718292f2SDouglas Gregor 
551718292f2SDouglas Gregor   // Parse the header name.
552718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
553718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
554718292f2SDouglas Gregor       << "umbrella";
555718292f2SDouglas Gregor     HadError = true;
556718292f2SDouglas Gregor     return;
557718292f2SDouglas Gregor   }
558718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
559718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
560718292f2SDouglas Gregor 
5615257fc63SDouglas Gregor   // Check whether we already have an umbrella header.
5625257fc63SDouglas Gregor   if (ActiveModule->UmbrellaHeader) {
5635257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
5645257fc63SDouglas Gregor       << ActiveModule->getFullModuleName()
5655257fc63SDouglas Gregor       << ActiveModule->UmbrellaHeader->getName();
5665257fc63SDouglas Gregor     HadError = true;
5675257fc63SDouglas Gregor     return;
5685257fc63SDouglas Gregor   }
5695257fc63SDouglas Gregor 
5705257fc63SDouglas Gregor   // Only top-level modules can have umbrella headers.
5715257fc63SDouglas Gregor   if (ActiveModule->Parent) {
5725257fc63SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
5735257fc63SDouglas Gregor       << ActiveModule->getFullModuleName();
5745257fc63SDouglas Gregor     HadError = true;
5755257fc63SDouglas Gregor     return;
5765257fc63SDouglas Gregor   }
5775257fc63SDouglas Gregor 
5785257fc63SDouglas Gregor   // Look for this file.
5795257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
5805257fc63SDouglas Gregor   PathName += Directory->getName();
581755b2055SDouglas Gregor   unsigned PathLength = PathName.size();
582755b2055SDouglas Gregor   const FileEntry *File = 0;
583755b2055SDouglas Gregor   if (ActiveModule->isPartOfFramework()) {
584755b2055SDouglas Gregor     // Check whether this file is in the public headers.
585755b2055SDouglas Gregor     llvm::sys::path::append(PathName, "Headers");
5865257fc63SDouglas Gregor     llvm::sys::path::append(PathName, FileName);
587755b2055SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
588755b2055SDouglas Gregor 
589755b2055SDouglas Gregor     if (!File) {
590755b2055SDouglas Gregor       // Check whether this file is in the private headers.
591755b2055SDouglas Gregor       PathName.resize(PathLength);
592755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "PrivateHeaders");
593755b2055SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
594755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
595755b2055SDouglas Gregor     }
596755b2055SDouglas Gregor 
597755b2055SDouglas Gregor     // FIXME: Deal with subframeworks.
598755b2055SDouglas Gregor   } else {
599755b2055SDouglas Gregor     // Lookup for normal headers.
600755b2055SDouglas Gregor     llvm::sys::path::append(PathName, FileName);
601755b2055SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
602755b2055SDouglas Gregor   }
6035257fc63SDouglas Gregor 
6045257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6055257fc63SDouglas Gregor   // Come up with a lazy way to do this.
606755b2055SDouglas Gregor   if (File) {
6075257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6085257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6095257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6105257fc63SDouglas Gregor       HadError = true;
611b65dbfffSDouglas Gregor     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
612b65dbfffSDouglas Gregor       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
613b65dbfffSDouglas Gregor         << OwningModule->getFullModuleName();
614b65dbfffSDouglas Gregor       HadError = true;
6155257fc63SDouglas Gregor     } else {
6165257fc63SDouglas Gregor       // Record this umbrella header.
6175257fc63SDouglas Gregor       ActiveModule->UmbrellaHeader = File;
6185257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
619b65dbfffSDouglas Gregor       Map.UmbrellaDirs[Directory] = ActiveModule;
6205257fc63SDouglas Gregor     }
6215257fc63SDouglas Gregor   } else {
6225257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6235257fc63SDouglas Gregor       << true << FileName;
6245257fc63SDouglas Gregor     HadError = true;
6255257fc63SDouglas Gregor   }
626718292f2SDouglas Gregor }
627718292f2SDouglas Gregor 
628718292f2SDouglas Gregor /// \brief Parse a header declaration.
629718292f2SDouglas Gregor ///
630718292f2SDouglas Gregor ///   header-declaration:
631718292f2SDouglas Gregor ///     'header' string-literal
632718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
633718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
6341871ed3dSBenjamin Kramer   consumeToken();
635718292f2SDouglas Gregor 
636718292f2SDouglas Gregor   // Parse the header name.
637718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
638718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
639718292f2SDouglas Gregor       << "header";
640718292f2SDouglas Gregor     HadError = true;
641718292f2SDouglas Gregor     return;
642718292f2SDouglas Gregor   }
643718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
644718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
645718292f2SDouglas Gregor 
6465257fc63SDouglas Gregor   // Look for this file.
6475257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
6485257fc63SDouglas Gregor   PathName += Directory->getName();
649755b2055SDouglas Gregor 
650755b2055SDouglas Gregor   if (ActiveModule->isPartOfFramework())
651755b2055SDouglas Gregor     llvm::sys::path::append(PathName, "Headers");
652755b2055SDouglas Gregor 
6535257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
6545257fc63SDouglas Gregor 
6555257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6565257fc63SDouglas Gregor   // Come up with a lazy way to do this.
6575257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
6585257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6595257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6605257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6615257fc63SDouglas Gregor       HadError = true;
6625257fc63SDouglas Gregor     } else {
6635257fc63SDouglas Gregor       // Record this file.
6645257fc63SDouglas Gregor       ActiveModule->Headers.push_back(File);
6655257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
6665257fc63SDouglas Gregor     }
6675257fc63SDouglas Gregor   } else {
6685257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6695257fc63SDouglas Gregor       << false << FileName;
6705257fc63SDouglas Gregor     HadError = true;
6715257fc63SDouglas Gregor   }
672718292f2SDouglas Gregor }
673718292f2SDouglas Gregor 
674718292f2SDouglas Gregor /// \brief Parse a module map file.
675718292f2SDouglas Gregor ///
676718292f2SDouglas Gregor ///   module-map-file:
677718292f2SDouglas Gregor ///     module-declaration*
678718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
679718292f2SDouglas Gregor   do {
680718292f2SDouglas Gregor     switch (Tok.Kind) {
681718292f2SDouglas Gregor     case MMToken::EndOfFile:
682718292f2SDouglas Gregor       return HadError;
683718292f2SDouglas Gregor 
684718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
685755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
686718292f2SDouglas Gregor       parseModuleDecl();
687718292f2SDouglas Gregor       break;
688718292f2SDouglas Gregor 
689718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
690718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
691718292f2SDouglas Gregor     case MMToken::Identifier:
692718292f2SDouglas Gregor     case MMToken::LBrace:
693718292f2SDouglas Gregor     case MMToken::RBrace:
694718292f2SDouglas Gregor     case MMToken::StringLiteral:
695718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
696718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
697718292f2SDouglas Gregor       HadError = true;
698718292f2SDouglas Gregor       consumeToken();
699718292f2SDouglas Gregor       break;
700718292f2SDouglas Gregor     }
701718292f2SDouglas Gregor   } while (true);
702718292f2SDouglas Gregor 
703718292f2SDouglas Gregor   return HadError;
704718292f2SDouglas Gregor }
705718292f2SDouglas Gregor 
706718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
707718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
708718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
709718292f2SDouglas Gregor   if (!Buffer)
710718292f2SDouglas Gregor     return true;
711718292f2SDouglas Gregor 
712718292f2SDouglas Gregor   // Parse this module map file.
713718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
714718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
7155257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
716718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
717718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
718718292f2SDouglas Gregor 
719718292f2SDouglas Gregor   return Result;
720718292f2SDouglas Gregor }
721