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 
71d28d1b8dSDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
72d28d1b8dSDouglas Gregor   OS << std::string(' ', Spaces);
73d28d1b8dSDouglas Gregor }
74d28d1b8dSDouglas Gregor 
75d28d1b8dSDouglas Gregor void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
76d28d1b8dSDouglas Gregor   indent(OS, Indent);
77d28d1b8dSDouglas Gregor   if (IsFramework)
78d28d1b8dSDouglas Gregor     OS << "framework ";
79d28d1b8dSDouglas Gregor   if (IsExplicit)
80d28d1b8dSDouglas Gregor     OS << "explicit ";
81d28d1b8dSDouglas Gregor   OS << Name << " {\n";
82d28d1b8dSDouglas Gregor 
83d28d1b8dSDouglas Gregor   if (UmbrellaHeader) {
84d28d1b8dSDouglas Gregor     indent(OS, Indent + 2);
85d28d1b8dSDouglas Gregor     OS << "umbrella \"" << UmbrellaHeader->getName() << "\"\n";
86d28d1b8dSDouglas Gregor   }
87d28d1b8dSDouglas Gregor 
88d28d1b8dSDouglas Gregor   for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
89d28d1b8dSDouglas Gregor     indent(OS, Indent + 2);
90d28d1b8dSDouglas Gregor     OS << "header \"" << Headers[I]->getName() << "\"\n";
91d28d1b8dSDouglas Gregor   }
92d28d1b8dSDouglas Gregor 
93d28d1b8dSDouglas Gregor   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
94d28d1b8dSDouglas Gregor                                               MIEnd = SubModules.end();
95d28d1b8dSDouglas Gregor        MI != MIEnd; ++MI)
96d28d1b8dSDouglas Gregor     MI->getValue()->print(OS, Indent + 2);
97d28d1b8dSDouglas Gregor 
98d28d1b8dSDouglas Gregor   indent(OS, Indent);
99d28d1b8dSDouglas Gregor   OS << "}\n";
100d28d1b8dSDouglas Gregor }
101d28d1b8dSDouglas Gregor 
102d28d1b8dSDouglas Gregor void ModuleMap::Module::dump() const {
103d28d1b8dSDouglas Gregor   print(llvm::errs());
104d28d1b8dSDouglas Gregor }
105d28d1b8dSDouglas 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 
209*514b636aSDouglas Gregor const FileEntry *
210*514b636aSDouglas Gregor ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) {
211*514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
212*514b636aSDouglas Gregor     return 0;
213*514b636aSDouglas Gregor 
214*514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
215*514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
216*514b636aSDouglas Gregor }
217*514b636aSDouglas Gregor 
218718292f2SDouglas Gregor void ModuleMap::dump() {
219718292f2SDouglas Gregor   llvm::errs() << "Modules:";
220718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
221718292f2SDouglas Gregor                                         MEnd = Modules.end();
222718292f2SDouglas Gregor        M != MEnd; ++M)
223d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
224718292f2SDouglas Gregor 
225718292f2SDouglas Gregor   llvm::errs() << "Headers:";
226718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
227718292f2SDouglas Gregor             H = Headers.begin(),
228718292f2SDouglas Gregor          HEnd = Headers.end();
229718292f2SDouglas Gregor        H != HEnd; ++H) {
230718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
231718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
232718292f2SDouglas Gregor   }
233718292f2SDouglas Gregor }
234718292f2SDouglas Gregor 
235718292f2SDouglas Gregor //----------------------------------------------------------------------------//
236718292f2SDouglas Gregor // Module map file parser
237718292f2SDouglas Gregor //----------------------------------------------------------------------------//
238718292f2SDouglas Gregor 
239718292f2SDouglas Gregor namespace clang {
240718292f2SDouglas Gregor   /// \brief A token in a module map file.
241718292f2SDouglas Gregor   struct MMToken {
242718292f2SDouglas Gregor     enum TokenKind {
243718292f2SDouglas Gregor       EndOfFile,
244718292f2SDouglas Gregor       HeaderKeyword,
245718292f2SDouglas Gregor       Identifier,
246718292f2SDouglas Gregor       ExplicitKeyword,
247755b2055SDouglas Gregor       FrameworkKeyword,
248718292f2SDouglas Gregor       ModuleKeyword,
249718292f2SDouglas Gregor       UmbrellaKeyword,
250718292f2SDouglas Gregor       StringLiteral,
251718292f2SDouglas Gregor       LBrace,
252718292f2SDouglas Gregor       RBrace
253718292f2SDouglas Gregor     } Kind;
254718292f2SDouglas Gregor 
255718292f2SDouglas Gregor     unsigned Location;
256718292f2SDouglas Gregor     unsigned StringLength;
257718292f2SDouglas Gregor     const char *StringData;
258718292f2SDouglas Gregor 
259718292f2SDouglas Gregor     void clear() {
260718292f2SDouglas Gregor       Kind = EndOfFile;
261718292f2SDouglas Gregor       Location = 0;
262718292f2SDouglas Gregor       StringLength = 0;
263718292f2SDouglas Gregor       StringData = 0;
264718292f2SDouglas Gregor     }
265718292f2SDouglas Gregor 
266718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
267718292f2SDouglas Gregor 
268718292f2SDouglas Gregor     SourceLocation getLocation() const {
269718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
270718292f2SDouglas Gregor     }
271718292f2SDouglas Gregor 
272718292f2SDouglas Gregor     StringRef getString() const {
273718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
274718292f2SDouglas Gregor     }
275718292f2SDouglas Gregor   };
276718292f2SDouglas Gregor 
277718292f2SDouglas Gregor   class ModuleMapParser {
278718292f2SDouglas Gregor     Lexer &L;
279718292f2SDouglas Gregor     SourceManager &SourceMgr;
280718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
281718292f2SDouglas Gregor     ModuleMap &Map;
282718292f2SDouglas Gregor 
2835257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
2845257fc63SDouglas Gregor     const DirectoryEntry *Directory;
2855257fc63SDouglas Gregor 
286718292f2SDouglas Gregor     /// \brief Whether an error occurred.
287718292f2SDouglas Gregor     bool HadError;
288718292f2SDouglas Gregor 
289718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
290718292f2SDouglas Gregor     /// parsing.
291718292f2SDouglas Gregor     TargetInfo *Target;
292718292f2SDouglas Gregor 
293718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
294718292f2SDouglas Gregor     /// during parsing.
295718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
296718292f2SDouglas Gregor 
297718292f2SDouglas Gregor     /// \brief The current token.
298718292f2SDouglas Gregor     MMToken Tok;
299718292f2SDouglas Gregor 
300718292f2SDouglas Gregor     /// \brief The active module.
301718292f2SDouglas Gregor     ModuleMap::Module *ActiveModule;
302718292f2SDouglas Gregor 
303718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
304718292f2SDouglas Gregor     SourceLocation consumeToken();
305718292f2SDouglas Gregor 
306718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
307718292f2SDouglas Gregor     /// (or the end of the file).
308718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
309718292f2SDouglas Gregor 
310718292f2SDouglas Gregor     void parseModuleDecl();
311718292f2SDouglas Gregor     void parseUmbrellaDecl();
312718292f2SDouglas Gregor     void parseHeaderDecl();
313718292f2SDouglas Gregor 
314718292f2SDouglas Gregor   public:
315718292f2SDouglas Gregor     typedef ModuleMap::Module Module;
316718292f2SDouglas Gregor 
317718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
318718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
3195257fc63SDouglas Gregor                              ModuleMap &Map,
3205257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
3215257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
3225257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
323718292f2SDouglas Gregor     {
324718292f2SDouglas Gregor       TargetOptions TargetOpts;
325718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
326718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
327718292f2SDouglas Gregor 
328718292f2SDouglas Gregor       Tok.clear();
329718292f2SDouglas Gregor       consumeToken();
330718292f2SDouglas Gregor     }
331718292f2SDouglas Gregor 
332718292f2SDouglas Gregor     bool parseModuleMapFile();
333718292f2SDouglas Gregor   };
334718292f2SDouglas Gregor }
335718292f2SDouglas Gregor 
336718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
337718292f2SDouglas Gregor retry:
338718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
339718292f2SDouglas Gregor   Tok.clear();
340718292f2SDouglas Gregor 
341718292f2SDouglas Gregor   Token LToken;
342718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
343718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
344718292f2SDouglas Gregor   switch (LToken.getKind()) {
345718292f2SDouglas Gregor   case tok::raw_identifier:
346718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
347718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
348718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
349718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
350718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
351755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
352718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
353718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
354718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
355718292f2SDouglas Gregor     break;
356718292f2SDouglas Gregor 
357718292f2SDouglas Gregor   case tok::eof:
358718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
359718292f2SDouglas Gregor     break;
360718292f2SDouglas Gregor 
361718292f2SDouglas Gregor   case tok::l_brace:
362718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
363718292f2SDouglas Gregor     break;
364718292f2SDouglas Gregor 
365718292f2SDouglas Gregor   case tok::r_brace:
366718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
367718292f2SDouglas Gregor     break;
368718292f2SDouglas Gregor 
369718292f2SDouglas Gregor   case tok::string_literal: {
370718292f2SDouglas Gregor     // Parse the string literal.
371718292f2SDouglas Gregor     LangOptions LangOpts;
372718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
373718292f2SDouglas Gregor     if (StringLiteral.hadError)
374718292f2SDouglas Gregor       goto retry;
375718292f2SDouglas Gregor 
376718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
377718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
378718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
379718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
380718292f2SDouglas Gregor     Saved[Length] = 0;
381718292f2SDouglas Gregor 
382718292f2SDouglas Gregor     // Form the token.
383718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
384718292f2SDouglas Gregor     Tok.StringData = Saved;
385718292f2SDouglas Gregor     Tok.StringLength = Length;
386718292f2SDouglas Gregor     break;
387718292f2SDouglas Gregor   }
388718292f2SDouglas Gregor 
389718292f2SDouglas Gregor   case tok::comment:
390718292f2SDouglas Gregor     goto retry;
391718292f2SDouglas Gregor 
392718292f2SDouglas Gregor   default:
393718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
394718292f2SDouglas Gregor     HadError = true;
395718292f2SDouglas Gregor     goto retry;
396718292f2SDouglas Gregor   }
397718292f2SDouglas Gregor 
398718292f2SDouglas Gregor   return Result;
399718292f2SDouglas Gregor }
400718292f2SDouglas Gregor 
401718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
402718292f2SDouglas Gregor   unsigned braceDepth = 0;
403718292f2SDouglas Gregor   do {
404718292f2SDouglas Gregor     switch (Tok.Kind) {
405718292f2SDouglas Gregor     case MMToken::EndOfFile:
406718292f2SDouglas Gregor       return;
407718292f2SDouglas Gregor 
408718292f2SDouglas Gregor     case MMToken::LBrace:
409718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
410718292f2SDouglas Gregor         return;
411718292f2SDouglas Gregor 
412718292f2SDouglas Gregor       ++braceDepth;
413718292f2SDouglas Gregor       break;
414718292f2SDouglas Gregor 
415718292f2SDouglas Gregor     case MMToken::RBrace:
416718292f2SDouglas Gregor       if (braceDepth > 0)
417718292f2SDouglas Gregor         --braceDepth;
418718292f2SDouglas Gregor       else if (Tok.is(K))
419718292f2SDouglas Gregor         return;
420718292f2SDouglas Gregor       break;
421718292f2SDouglas Gregor 
422718292f2SDouglas Gregor     default:
423718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
424718292f2SDouglas Gregor         return;
425718292f2SDouglas Gregor       break;
426718292f2SDouglas Gregor     }
427718292f2SDouglas Gregor 
428718292f2SDouglas Gregor    consumeToken();
429718292f2SDouglas Gregor   } while (true);
430718292f2SDouglas Gregor }
431718292f2SDouglas Gregor 
432718292f2SDouglas Gregor /// \brief Parse a module declaration.
433718292f2SDouglas Gregor ///
434718292f2SDouglas Gregor ///   module-declaration:
435755b2055SDouglas Gregor ///     'framework'[opt] 'module' identifier { module-member* }
436718292f2SDouglas Gregor ///
437718292f2SDouglas Gregor ///   module-member:
438718292f2SDouglas Gregor ///     umbrella-declaration
439718292f2SDouglas Gregor ///     header-declaration
440718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
441718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
442755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
443755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
444718292f2SDouglas Gregor 
445755b2055SDouglas Gregor   // Parse 'framework' or 'explicit' keyword, if present.
446755b2055SDouglas Gregor   bool Framework = false;
447718292f2SDouglas Gregor   bool Explicit = false;
448755b2055SDouglas Gregor 
449755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
450755b2055SDouglas Gregor     consumeToken();
451755b2055SDouglas Gregor     Framework = true;
452755b2055SDouglas Gregor   }
453755b2055SDouglas Gregor   // Parse 'explicit' keyword, if present.
454755b2055SDouglas Gregor   else if (Tok.is(MMToken::ExplicitKeyword)) {
455718292f2SDouglas Gregor     consumeToken();
456718292f2SDouglas Gregor     Explicit = true;
457718292f2SDouglas Gregor   }
458718292f2SDouglas Gregor 
459718292f2SDouglas Gregor   // Parse 'module' keyword.
460718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
461718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
462718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
463718292f2SDouglas Gregor     consumeToken();
464718292f2SDouglas Gregor     HadError = true;
465718292f2SDouglas Gregor     return;
466718292f2SDouglas Gregor   }
467718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
468718292f2SDouglas Gregor 
469718292f2SDouglas Gregor   // Parse the module name.
470718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
471718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
472718292f2SDouglas Gregor     HadError = true;
473718292f2SDouglas Gregor     return;
474718292f2SDouglas Gregor   }
475718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
476718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
477718292f2SDouglas Gregor 
478718292f2SDouglas Gregor   // Parse the opening brace.
479718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
480718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
481718292f2SDouglas Gregor       << ModuleName;
482718292f2SDouglas Gregor     HadError = true;
483718292f2SDouglas Gregor     return;
484718292f2SDouglas Gregor   }
485718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
486718292f2SDouglas Gregor 
487718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
488718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
489718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
490718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
491718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
492718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
493718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
494718292f2SDouglas Gregor       << ModuleName;
495718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
496718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
497718292f2SDouglas Gregor 
498718292f2SDouglas Gregor     // Skip the module definition.
499718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
500718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
501718292f2SDouglas Gregor       consumeToken();
502718292f2SDouglas Gregor 
503718292f2SDouglas Gregor     HadError = true;
504718292f2SDouglas Gregor     return;
505718292f2SDouglas Gregor   }
506718292f2SDouglas Gregor 
507718292f2SDouglas Gregor   // Start defining this module.
508755b2055SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
509755b2055SDouglas Gregor                             Explicit);
510718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
511718292f2SDouglas Gregor 
512718292f2SDouglas Gregor   bool Done = false;
513718292f2SDouglas Gregor   do {
514718292f2SDouglas Gregor     switch (Tok.Kind) {
515718292f2SDouglas Gregor     case MMToken::EndOfFile:
516718292f2SDouglas Gregor     case MMToken::RBrace:
517718292f2SDouglas Gregor       Done = true;
518718292f2SDouglas Gregor       break;
519718292f2SDouglas Gregor 
520718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
521718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
522718292f2SDouglas Gregor       parseModuleDecl();
523718292f2SDouglas Gregor       break;
524718292f2SDouglas Gregor 
525718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
526718292f2SDouglas Gregor       parseHeaderDecl();
527718292f2SDouglas Gregor       break;
528718292f2SDouglas Gregor 
529718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
530718292f2SDouglas Gregor       parseUmbrellaDecl();
531718292f2SDouglas Gregor       break;
532718292f2SDouglas Gregor 
533718292f2SDouglas Gregor     default:
534718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
535718292f2SDouglas Gregor       consumeToken();
536718292f2SDouglas Gregor       break;
537718292f2SDouglas Gregor     }
538718292f2SDouglas Gregor   } while (!Done);
539718292f2SDouglas Gregor 
540718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
541718292f2SDouglas Gregor     consumeToken();
542718292f2SDouglas Gregor   else {
543718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
544718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
545718292f2SDouglas Gregor     HadError = true;
546718292f2SDouglas Gregor   }
547718292f2SDouglas Gregor 
548718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
549718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
550718292f2SDouglas Gregor }
551718292f2SDouglas Gregor 
552718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
553718292f2SDouglas Gregor ///
554718292f2SDouglas Gregor ///   umbrella-declaration:
555718292f2SDouglas Gregor ///     'umbrella' string-literal
556718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
557718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
558718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
559718292f2SDouglas Gregor 
560718292f2SDouglas Gregor   // Parse the header name.
561718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
562718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
563718292f2SDouglas Gregor       << "umbrella";
564718292f2SDouglas Gregor     HadError = true;
565718292f2SDouglas Gregor     return;
566718292f2SDouglas Gregor   }
567718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
568718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
569718292f2SDouglas Gregor 
5705257fc63SDouglas Gregor   // Check whether we already have an umbrella header.
5715257fc63SDouglas Gregor   if (ActiveModule->UmbrellaHeader) {
5725257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
5735257fc63SDouglas Gregor       << ActiveModule->getFullModuleName()
5745257fc63SDouglas Gregor       << ActiveModule->UmbrellaHeader->getName();
5755257fc63SDouglas Gregor     HadError = true;
5765257fc63SDouglas Gregor     return;
5775257fc63SDouglas Gregor   }
5785257fc63SDouglas Gregor 
5795257fc63SDouglas Gregor   // Only top-level modules can have umbrella headers.
5805257fc63SDouglas Gregor   if (ActiveModule->Parent) {
5815257fc63SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
5825257fc63SDouglas Gregor       << ActiveModule->getFullModuleName();
5835257fc63SDouglas Gregor     HadError = true;
5845257fc63SDouglas Gregor     return;
5855257fc63SDouglas Gregor   }
5865257fc63SDouglas Gregor 
5875257fc63SDouglas Gregor   // Look for this file.
5885257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
5895257fc63SDouglas Gregor   PathName += Directory->getName();
590755b2055SDouglas Gregor   unsigned PathLength = PathName.size();
591755b2055SDouglas Gregor   const FileEntry *File = 0;
592755b2055SDouglas Gregor   if (ActiveModule->isPartOfFramework()) {
593755b2055SDouglas Gregor     // Check whether this file is in the public headers.
594755b2055SDouglas Gregor     llvm::sys::path::append(PathName, "Headers");
5955257fc63SDouglas Gregor     llvm::sys::path::append(PathName, FileName);
596755b2055SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
597755b2055SDouglas Gregor 
598755b2055SDouglas Gregor     if (!File) {
599755b2055SDouglas Gregor       // Check whether this file is in the private headers.
600755b2055SDouglas Gregor       PathName.resize(PathLength);
601755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "PrivateHeaders");
602755b2055SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
603755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
604755b2055SDouglas Gregor     }
605755b2055SDouglas Gregor 
606755b2055SDouglas Gregor     // FIXME: Deal with subframeworks.
607755b2055SDouglas Gregor   } else {
608755b2055SDouglas Gregor     // Lookup for normal headers.
609755b2055SDouglas Gregor     llvm::sys::path::append(PathName, FileName);
610755b2055SDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
611755b2055SDouglas Gregor   }
6125257fc63SDouglas Gregor 
6135257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6145257fc63SDouglas Gregor   // Come up with a lazy way to do this.
615755b2055SDouglas Gregor   if (File) {
6165257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6175257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6185257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6195257fc63SDouglas Gregor       HadError = true;
620b65dbfffSDouglas Gregor     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
621b65dbfffSDouglas Gregor       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
622b65dbfffSDouglas Gregor         << OwningModule->getFullModuleName();
623b65dbfffSDouglas Gregor       HadError = true;
6245257fc63SDouglas Gregor     } else {
6255257fc63SDouglas Gregor       // Record this umbrella header.
6265257fc63SDouglas Gregor       ActiveModule->UmbrellaHeader = File;
6275257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
628b65dbfffSDouglas Gregor       Map.UmbrellaDirs[Directory] = ActiveModule;
6295257fc63SDouglas Gregor     }
6305257fc63SDouglas Gregor   } else {
6315257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6325257fc63SDouglas Gregor       << true << FileName;
6335257fc63SDouglas Gregor     HadError = true;
6345257fc63SDouglas Gregor   }
635718292f2SDouglas Gregor }
636718292f2SDouglas Gregor 
637718292f2SDouglas Gregor /// \brief Parse a header declaration.
638718292f2SDouglas Gregor ///
639718292f2SDouglas Gregor ///   header-declaration:
640718292f2SDouglas Gregor ///     'header' string-literal
641718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
642718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
6431871ed3dSBenjamin Kramer   consumeToken();
644718292f2SDouglas Gregor 
645718292f2SDouglas Gregor   // Parse the header name.
646718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
647718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
648718292f2SDouglas Gregor       << "header";
649718292f2SDouglas Gregor     HadError = true;
650718292f2SDouglas Gregor     return;
651718292f2SDouglas Gregor   }
652718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
653718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
654718292f2SDouglas Gregor 
6555257fc63SDouglas Gregor   // Look for this file.
6565257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
6575257fc63SDouglas Gregor   PathName += Directory->getName();
658755b2055SDouglas Gregor 
659755b2055SDouglas Gregor   if (ActiveModule->isPartOfFramework())
660755b2055SDouglas Gregor     llvm::sys::path::append(PathName, "Headers");
661755b2055SDouglas Gregor 
6625257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
6635257fc63SDouglas Gregor 
6645257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6655257fc63SDouglas Gregor   // Come up with a lazy way to do this.
6665257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
6675257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6685257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6695257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6705257fc63SDouglas Gregor       HadError = true;
6715257fc63SDouglas Gregor     } else {
6725257fc63SDouglas Gregor       // Record this file.
6735257fc63SDouglas Gregor       ActiveModule->Headers.push_back(File);
6745257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
6755257fc63SDouglas Gregor     }
6765257fc63SDouglas Gregor   } else {
6775257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6785257fc63SDouglas Gregor       << false << FileName;
6795257fc63SDouglas Gregor     HadError = true;
6805257fc63SDouglas Gregor   }
681718292f2SDouglas Gregor }
682718292f2SDouglas Gregor 
683718292f2SDouglas Gregor /// \brief Parse a module map file.
684718292f2SDouglas Gregor ///
685718292f2SDouglas Gregor ///   module-map-file:
686718292f2SDouglas Gregor ///     module-declaration*
687718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
688718292f2SDouglas Gregor   do {
689718292f2SDouglas Gregor     switch (Tok.Kind) {
690718292f2SDouglas Gregor     case MMToken::EndOfFile:
691718292f2SDouglas Gregor       return HadError;
692718292f2SDouglas Gregor 
693718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
694755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
695718292f2SDouglas Gregor       parseModuleDecl();
696718292f2SDouglas Gregor       break;
697718292f2SDouglas Gregor 
698718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
699718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
700718292f2SDouglas Gregor     case MMToken::Identifier:
701718292f2SDouglas Gregor     case MMToken::LBrace:
702718292f2SDouglas Gregor     case MMToken::RBrace:
703718292f2SDouglas Gregor     case MMToken::StringLiteral:
704718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
705718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
706718292f2SDouglas Gregor       HadError = true;
707718292f2SDouglas Gregor       consumeToken();
708718292f2SDouglas Gregor       break;
709718292f2SDouglas Gregor     }
710718292f2SDouglas Gregor   } while (true);
711718292f2SDouglas Gregor 
712718292f2SDouglas Gregor   return HadError;
713718292f2SDouglas Gregor }
714718292f2SDouglas Gregor 
715718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
716718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
717718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
718718292f2SDouglas Gregor   if (!Buffer)
719718292f2SDouglas Gregor     return true;
720718292f2SDouglas Gregor 
721718292f2SDouglas Gregor   // Parse this module map file.
722718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
723718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
7245257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
725718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
726718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
727718292f2SDouglas Gregor 
728718292f2SDouglas Gregor   return Result;
729718292f2SDouglas Gregor }
730