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 ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
31718292f2SDouglas Gregor   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
32718292f2SDouglas Gregor   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
33718292f2SDouglas Gregor             new DiagnosticsEngine(DiagIDs));
34718292f2SDouglas Gregor   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
35718292f2SDouglas Gregor   SourceMgr = new SourceManager(*Diags, FileMgr);
36718292f2SDouglas Gregor }
37718292f2SDouglas Gregor 
38718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
395acdf59eSDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
405acdf59eSDouglas Gregor                                         IEnd = Modules.end();
415acdf59eSDouglas Gregor        I != IEnd; ++I) {
425acdf59eSDouglas Gregor     delete I->getValue();
435acdf59eSDouglas Gregor   }
445acdf59eSDouglas Gregor 
45718292f2SDouglas Gregor   delete SourceMgr;
46718292f2SDouglas Gregor }
47718292f2SDouglas Gregor 
48*de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
49ab0c8a84SDouglas Gregor   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
50ab0c8a84SDouglas Gregor     = Headers.find(File);
51ab0c8a84SDouglas Gregor   if (Known != Headers.end())
52ab0c8a84SDouglas Gregor     return Known->second;
53ab0c8a84SDouglas Gregor 
54b65dbfffSDouglas Gregor   const DirectoryEntry *Dir = File->getDir();
55b65dbfffSDouglas Gregor   llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
56b65dbfffSDouglas Gregor     = UmbrellaDirs.find(Dir);
57b65dbfffSDouglas Gregor   if (KnownDir != UmbrellaDirs.end())
58b65dbfffSDouglas Gregor     return KnownDir->second;
59b65dbfffSDouglas Gregor 
60b65dbfffSDouglas Gregor   // Walk up the directory hierarchy looking for umbrella headers.
61b65dbfffSDouglas Gregor   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
62b65dbfffSDouglas Gregor   StringRef DirName = Dir->getName();
63b65dbfffSDouglas Gregor   do {
64b65dbfffSDouglas Gregor     // Retrieve our parent path.
65b65dbfffSDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
66b65dbfffSDouglas Gregor     if (DirName.empty())
67b65dbfffSDouglas Gregor       break;
68b65dbfffSDouglas Gregor 
69b65dbfffSDouglas Gregor     // Resolve the parent path to a directory entry.
70b65dbfffSDouglas Gregor     Dir = SourceMgr->getFileManager().getDirectory(DirName);
71b65dbfffSDouglas Gregor     if (!Dir)
72b65dbfffSDouglas Gregor       break;
73b65dbfffSDouglas Gregor 
74b65dbfffSDouglas Gregor     KnownDir = UmbrellaDirs.find(Dir);
75b65dbfffSDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
76b65dbfffSDouglas Gregor       Module *Result = KnownDir->second;
77b65dbfffSDouglas Gregor 
78b65dbfffSDouglas Gregor       // Record each of the directories we stepped through as being part of
79b65dbfffSDouglas Gregor       // the module we found, since the umbrella header covers them all.
80b65dbfffSDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
81b65dbfffSDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
82b65dbfffSDouglas Gregor 
83b65dbfffSDouglas Gregor       return Result;
84b65dbfffSDouglas Gregor     }
85b65dbfffSDouglas Gregor 
86b65dbfffSDouglas Gregor     SkippedDirs.push_back(Dir);
87b65dbfffSDouglas Gregor   } while (true);
88b65dbfffSDouglas Gregor 
89ab0c8a84SDouglas Gregor   return 0;
90ab0c8a84SDouglas Gregor }
91ab0c8a84SDouglas Gregor 
92*de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) {
9388bdfb0eSDouglas Gregor   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
9488bdfb0eSDouglas Gregor   if (Known != Modules.end())
9588bdfb0eSDouglas Gregor     return Known->getValue();
9688bdfb0eSDouglas Gregor 
9788bdfb0eSDouglas Gregor   return 0;
9888bdfb0eSDouglas Gregor }
9988bdfb0eSDouglas Gregor 
100*de3ef502SDouglas Gregor std::pair<Module *, bool>
10169021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
10269021974SDouglas Gregor                               bool IsExplicit) {
10369021974SDouglas Gregor   // Try to find an existing module with this name.
10469021974SDouglas Gregor   if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name])
10569021974SDouglas Gregor     return std::make_pair(Found, false);
10669021974SDouglas Gregor 
10769021974SDouglas Gregor   // Create a new module with this name.
10869021974SDouglas Gregor   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
10969021974SDouglas Gregor                               IsExplicit);
11069021974SDouglas Gregor   if (Parent)
11169021974SDouglas Gregor     Parent->SubModules[Name] = Result;
11269021974SDouglas Gregor   else
11369021974SDouglas Gregor     Modules[Name] = Result;
11469021974SDouglas Gregor   return std::make_pair(Result, true);
11569021974SDouglas Gregor }
11669021974SDouglas Gregor 
117*de3ef502SDouglas Gregor Module *
11856c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName,
11956c64013SDouglas Gregor                                 const DirectoryEntry *FrameworkDir) {
12056c64013SDouglas Gregor   // Check whether we've already found this module.
12156c64013SDouglas Gregor   if (Module *Module = findModule(ModuleName))
12256c64013SDouglas Gregor     return Module;
12356c64013SDouglas Gregor 
12456c64013SDouglas Gregor   // Look for an umbrella header.
12556c64013SDouglas Gregor   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
12656c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, "Headers");
12756c64013SDouglas Gregor   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
12856c64013SDouglas Gregor   const FileEntry *UmbrellaHeader
12956c64013SDouglas Gregor     = SourceMgr->getFileManager().getFile(UmbrellaName);
13056c64013SDouglas Gregor 
13156c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
13256c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
13356c64013SDouglas Gregor   // idea.
13456c64013SDouglas Gregor   if (!UmbrellaHeader)
13556c64013SDouglas Gregor     return 0;
13656c64013SDouglas Gregor 
137755b2055SDouglas Gregor   Module *Result = new Module(ModuleName, SourceLocation(),
138755b2055SDouglas Gregor                               /*IsFramework=*/true);
13956c64013SDouglas Gregor   Result->UmbrellaHeader = UmbrellaHeader;
14056c64013SDouglas Gregor   Headers[UmbrellaHeader] = Result;
14156c64013SDouglas Gregor   UmbrellaDirs[FrameworkDir] = Result;
14256c64013SDouglas Gregor   Modules[ModuleName] = Result;
14356c64013SDouglas Gregor   return Result;
14456c64013SDouglas Gregor }
14556c64013SDouglas Gregor 
146514b636aSDouglas Gregor const FileEntry *
147*de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) {
148514b636aSDouglas Gregor   if (Module->DefinitionLoc.isInvalid() || !SourceMgr)
149514b636aSDouglas Gregor     return 0;
150514b636aSDouglas Gregor 
151514b636aSDouglas Gregor   return SourceMgr->getFileEntryForID(
152514b636aSDouglas Gregor            SourceMgr->getFileID(Module->DefinitionLoc));
153514b636aSDouglas Gregor }
154514b636aSDouglas Gregor 
155718292f2SDouglas Gregor void ModuleMap::dump() {
156718292f2SDouglas Gregor   llvm::errs() << "Modules:";
157718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
158718292f2SDouglas Gregor                                         MEnd = Modules.end();
159718292f2SDouglas Gregor        M != MEnd; ++M)
160d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
161718292f2SDouglas Gregor 
162718292f2SDouglas Gregor   llvm::errs() << "Headers:";
163718292f2SDouglas Gregor   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
164718292f2SDouglas Gregor             H = Headers.begin(),
165718292f2SDouglas Gregor          HEnd = Headers.end();
166718292f2SDouglas Gregor        H != HEnd; ++H) {
167718292f2SDouglas Gregor     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
168718292f2SDouglas Gregor                  << H->second->getFullModuleName() << "\n";
169718292f2SDouglas Gregor   }
170718292f2SDouglas Gregor }
171718292f2SDouglas Gregor 
172718292f2SDouglas Gregor //----------------------------------------------------------------------------//
173718292f2SDouglas Gregor // Module map file parser
174718292f2SDouglas Gregor //----------------------------------------------------------------------------//
175718292f2SDouglas Gregor 
176718292f2SDouglas Gregor namespace clang {
177718292f2SDouglas Gregor   /// \brief A token in a module map file.
178718292f2SDouglas Gregor   struct MMToken {
179718292f2SDouglas Gregor     enum TokenKind {
180718292f2SDouglas Gregor       EndOfFile,
181718292f2SDouglas Gregor       HeaderKeyword,
182718292f2SDouglas Gregor       Identifier,
183718292f2SDouglas Gregor       ExplicitKeyword,
184755b2055SDouglas Gregor       FrameworkKeyword,
185718292f2SDouglas Gregor       ModuleKeyword,
186718292f2SDouglas Gregor       UmbrellaKeyword,
187718292f2SDouglas Gregor       StringLiteral,
188718292f2SDouglas Gregor       LBrace,
189718292f2SDouglas Gregor       RBrace
190718292f2SDouglas Gregor     } Kind;
191718292f2SDouglas Gregor 
192718292f2SDouglas Gregor     unsigned Location;
193718292f2SDouglas Gregor     unsigned StringLength;
194718292f2SDouglas Gregor     const char *StringData;
195718292f2SDouglas Gregor 
196718292f2SDouglas Gregor     void clear() {
197718292f2SDouglas Gregor       Kind = EndOfFile;
198718292f2SDouglas Gregor       Location = 0;
199718292f2SDouglas Gregor       StringLength = 0;
200718292f2SDouglas Gregor       StringData = 0;
201718292f2SDouglas Gregor     }
202718292f2SDouglas Gregor 
203718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
204718292f2SDouglas Gregor 
205718292f2SDouglas Gregor     SourceLocation getLocation() const {
206718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
207718292f2SDouglas Gregor     }
208718292f2SDouglas Gregor 
209718292f2SDouglas Gregor     StringRef getString() const {
210718292f2SDouglas Gregor       return StringRef(StringData, StringLength);
211718292f2SDouglas Gregor     }
212718292f2SDouglas Gregor   };
213718292f2SDouglas Gregor 
214718292f2SDouglas Gregor   class ModuleMapParser {
215718292f2SDouglas Gregor     Lexer &L;
216718292f2SDouglas Gregor     SourceManager &SourceMgr;
217718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
218718292f2SDouglas Gregor     ModuleMap &Map;
219718292f2SDouglas Gregor 
2205257fc63SDouglas Gregor     /// \brief The directory that this module map resides in.
2215257fc63SDouglas Gregor     const DirectoryEntry *Directory;
2225257fc63SDouglas Gregor 
223718292f2SDouglas Gregor     /// \brief Whether an error occurred.
224718292f2SDouglas Gregor     bool HadError;
225718292f2SDouglas Gregor 
226718292f2SDouglas Gregor     /// \brief Default target information, used only for string literal
227718292f2SDouglas Gregor     /// parsing.
228718292f2SDouglas Gregor     TargetInfo *Target;
229718292f2SDouglas Gregor 
230718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
231718292f2SDouglas Gregor     /// during parsing.
232718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
233718292f2SDouglas Gregor 
234718292f2SDouglas Gregor     /// \brief The current token.
235718292f2SDouglas Gregor     MMToken Tok;
236718292f2SDouglas Gregor 
237718292f2SDouglas Gregor     /// \brief The active module.
238*de3ef502SDouglas Gregor     Module *ActiveModule;
239718292f2SDouglas Gregor 
240718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
241718292f2SDouglas Gregor     SourceLocation consumeToken();
242718292f2SDouglas Gregor 
243718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
244718292f2SDouglas Gregor     /// (or the end of the file).
245718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
246718292f2SDouglas Gregor 
247718292f2SDouglas Gregor     void parseModuleDecl();
248718292f2SDouglas Gregor     void parseUmbrellaDecl();
249718292f2SDouglas Gregor     void parseHeaderDecl();
250718292f2SDouglas Gregor 
251718292f2SDouglas Gregor   public:
252*de3ef502SDouglas Gregor     typedef Module Module;
253718292f2SDouglas Gregor 
254718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
255718292f2SDouglas Gregor                              DiagnosticsEngine &Diags,
2565257fc63SDouglas Gregor                              ModuleMap &Map,
2575257fc63SDouglas Gregor                              const DirectoryEntry *Directory)
2585257fc63SDouglas Gregor       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
2595257fc63SDouglas Gregor         Directory(Directory), HadError(false), ActiveModule(0)
260718292f2SDouglas Gregor     {
261718292f2SDouglas Gregor       TargetOptions TargetOpts;
262718292f2SDouglas Gregor       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
263718292f2SDouglas Gregor       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
264718292f2SDouglas Gregor 
265718292f2SDouglas Gregor       Tok.clear();
266718292f2SDouglas Gregor       consumeToken();
267718292f2SDouglas Gregor     }
268718292f2SDouglas Gregor 
269718292f2SDouglas Gregor     bool parseModuleMapFile();
270718292f2SDouglas Gregor   };
271718292f2SDouglas Gregor }
272718292f2SDouglas Gregor 
273718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
274718292f2SDouglas Gregor retry:
275718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
276718292f2SDouglas Gregor   Tok.clear();
277718292f2SDouglas Gregor 
278718292f2SDouglas Gregor   Token LToken;
279718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
280718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
281718292f2SDouglas Gregor   switch (LToken.getKind()) {
282718292f2SDouglas Gregor   case tok::raw_identifier:
283718292f2SDouglas Gregor     Tok.StringData = LToken.getRawIdentifierData();
284718292f2SDouglas Gregor     Tok.StringLength = LToken.getLength();
285718292f2SDouglas Gregor     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
286718292f2SDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
287718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
288755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
289718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
290718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
291718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
292718292f2SDouglas Gregor     break;
293718292f2SDouglas Gregor 
294718292f2SDouglas Gregor   case tok::eof:
295718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
296718292f2SDouglas Gregor     break;
297718292f2SDouglas Gregor 
298718292f2SDouglas Gregor   case tok::l_brace:
299718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
300718292f2SDouglas Gregor     break;
301718292f2SDouglas Gregor 
302718292f2SDouglas Gregor   case tok::r_brace:
303718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
304718292f2SDouglas Gregor     break;
305718292f2SDouglas Gregor 
306718292f2SDouglas Gregor   case tok::string_literal: {
307718292f2SDouglas Gregor     // Parse the string literal.
308718292f2SDouglas Gregor     LangOptions LangOpts;
309718292f2SDouglas Gregor     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
310718292f2SDouglas Gregor     if (StringLiteral.hadError)
311718292f2SDouglas Gregor       goto retry;
312718292f2SDouglas Gregor 
313718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
314718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
315718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
316718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
317718292f2SDouglas Gregor     Saved[Length] = 0;
318718292f2SDouglas Gregor 
319718292f2SDouglas Gregor     // Form the token.
320718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
321718292f2SDouglas Gregor     Tok.StringData = Saved;
322718292f2SDouglas Gregor     Tok.StringLength = Length;
323718292f2SDouglas Gregor     break;
324718292f2SDouglas Gregor   }
325718292f2SDouglas Gregor 
326718292f2SDouglas Gregor   case tok::comment:
327718292f2SDouglas Gregor     goto retry;
328718292f2SDouglas Gregor 
329718292f2SDouglas Gregor   default:
330718292f2SDouglas Gregor     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
331718292f2SDouglas Gregor     HadError = true;
332718292f2SDouglas Gregor     goto retry;
333718292f2SDouglas Gregor   }
334718292f2SDouglas Gregor 
335718292f2SDouglas Gregor   return Result;
336718292f2SDouglas Gregor }
337718292f2SDouglas Gregor 
338718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
339718292f2SDouglas Gregor   unsigned braceDepth = 0;
340718292f2SDouglas Gregor   do {
341718292f2SDouglas Gregor     switch (Tok.Kind) {
342718292f2SDouglas Gregor     case MMToken::EndOfFile:
343718292f2SDouglas Gregor       return;
344718292f2SDouglas Gregor 
345718292f2SDouglas Gregor     case MMToken::LBrace:
346718292f2SDouglas Gregor       if (Tok.is(K) && braceDepth == 0)
347718292f2SDouglas Gregor         return;
348718292f2SDouglas Gregor 
349718292f2SDouglas Gregor       ++braceDepth;
350718292f2SDouglas Gregor       break;
351718292f2SDouglas Gregor 
352718292f2SDouglas Gregor     case MMToken::RBrace:
353718292f2SDouglas Gregor       if (braceDepth > 0)
354718292f2SDouglas Gregor         --braceDepth;
355718292f2SDouglas Gregor       else if (Tok.is(K))
356718292f2SDouglas Gregor         return;
357718292f2SDouglas Gregor       break;
358718292f2SDouglas Gregor 
359718292f2SDouglas Gregor     default:
360718292f2SDouglas Gregor       if (braceDepth == 0 && Tok.is(K))
361718292f2SDouglas Gregor         return;
362718292f2SDouglas Gregor       break;
363718292f2SDouglas Gregor     }
364718292f2SDouglas Gregor 
365718292f2SDouglas Gregor    consumeToken();
366718292f2SDouglas Gregor   } while (true);
367718292f2SDouglas Gregor }
368718292f2SDouglas Gregor 
369718292f2SDouglas Gregor /// \brief Parse a module declaration.
370718292f2SDouglas Gregor ///
371718292f2SDouglas Gregor ///   module-declaration:
372755b2055SDouglas Gregor ///     'framework'[opt] 'module' identifier { module-member* }
373718292f2SDouglas Gregor ///
374718292f2SDouglas Gregor ///   module-member:
375718292f2SDouglas Gregor ///     umbrella-declaration
376718292f2SDouglas Gregor ///     header-declaration
377718292f2SDouglas Gregor ///     'explicit'[opt] module-declaration
378718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
379755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
380755b2055SDouglas Gregor          Tok.is(MMToken::FrameworkKeyword));
381718292f2SDouglas Gregor 
382755b2055SDouglas Gregor   // Parse 'framework' or 'explicit' keyword, if present.
383755b2055SDouglas Gregor   bool Framework = false;
384718292f2SDouglas Gregor   bool Explicit = false;
385755b2055SDouglas Gregor 
386755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
387755b2055SDouglas Gregor     consumeToken();
388755b2055SDouglas Gregor     Framework = true;
389755b2055SDouglas Gregor   }
390755b2055SDouglas Gregor   // Parse 'explicit' keyword, if present.
391755b2055SDouglas Gregor   else if (Tok.is(MMToken::ExplicitKeyword)) {
392718292f2SDouglas Gregor     consumeToken();
393718292f2SDouglas Gregor     Explicit = true;
394718292f2SDouglas Gregor   }
395718292f2SDouglas Gregor 
396718292f2SDouglas Gregor   // Parse 'module' keyword.
397718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
398718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(),
399718292f2SDouglas Gregor                  diag::err_mmap_expected_module_after_explicit);
400718292f2SDouglas Gregor     consumeToken();
401718292f2SDouglas Gregor     HadError = true;
402718292f2SDouglas Gregor     return;
403718292f2SDouglas Gregor   }
404718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
405718292f2SDouglas Gregor 
406718292f2SDouglas Gregor   // Parse the module name.
407718292f2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
408718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
409718292f2SDouglas Gregor     HadError = true;
410718292f2SDouglas Gregor     return;
411718292f2SDouglas Gregor   }
412718292f2SDouglas Gregor   StringRef ModuleName = Tok.getString();
413718292f2SDouglas Gregor   SourceLocation ModuleNameLoc = consumeToken();
414718292f2SDouglas Gregor 
415718292f2SDouglas Gregor   // Parse the opening brace.
416718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
417718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
418718292f2SDouglas Gregor       << ModuleName;
419718292f2SDouglas Gregor     HadError = true;
420718292f2SDouglas Gregor     return;
421718292f2SDouglas Gregor   }
422718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
423718292f2SDouglas Gregor 
424718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
425718292f2SDouglas Gregor   llvm::StringMap<Module *> &ModuleSpace
426718292f2SDouglas Gregor     = ActiveModule? ActiveModule->SubModules : Map.Modules;
427718292f2SDouglas Gregor   llvm::StringMap<Module *>::iterator ExistingModule
428718292f2SDouglas Gregor     = ModuleSpace.find(ModuleName);
429718292f2SDouglas Gregor   if (ExistingModule != ModuleSpace.end()) {
430718292f2SDouglas Gregor     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
431718292f2SDouglas Gregor       << ModuleName;
432718292f2SDouglas Gregor     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
433718292f2SDouglas Gregor                  diag::note_mmap_prev_definition);
434718292f2SDouglas Gregor 
435718292f2SDouglas Gregor     // Skip the module definition.
436718292f2SDouglas Gregor     skipUntil(MMToken::RBrace);
437718292f2SDouglas Gregor     if (Tok.is(MMToken::RBrace))
438718292f2SDouglas Gregor       consumeToken();
439718292f2SDouglas Gregor 
440718292f2SDouglas Gregor     HadError = true;
441718292f2SDouglas Gregor     return;
442718292f2SDouglas Gregor   }
443718292f2SDouglas Gregor 
444718292f2SDouglas Gregor   // Start defining this module.
445755b2055SDouglas Gregor   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
446755b2055SDouglas Gregor                             Explicit);
447718292f2SDouglas Gregor   ModuleSpace[ModuleName] = ActiveModule;
448718292f2SDouglas Gregor 
449718292f2SDouglas Gregor   bool Done = false;
450718292f2SDouglas Gregor   do {
451718292f2SDouglas Gregor     switch (Tok.Kind) {
452718292f2SDouglas Gregor     case MMToken::EndOfFile:
453718292f2SDouglas Gregor     case MMToken::RBrace:
454718292f2SDouglas Gregor       Done = true;
455718292f2SDouglas Gregor       break;
456718292f2SDouglas Gregor 
457718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
458718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
459718292f2SDouglas Gregor       parseModuleDecl();
460718292f2SDouglas Gregor       break;
461718292f2SDouglas Gregor 
462718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
463718292f2SDouglas Gregor       parseHeaderDecl();
464718292f2SDouglas Gregor       break;
465718292f2SDouglas Gregor 
466718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
467718292f2SDouglas Gregor       parseUmbrellaDecl();
468718292f2SDouglas Gregor       break;
469718292f2SDouglas Gregor 
470718292f2SDouglas Gregor     default:
471718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
472718292f2SDouglas Gregor       consumeToken();
473718292f2SDouglas Gregor       break;
474718292f2SDouglas Gregor     }
475718292f2SDouglas Gregor   } while (!Done);
476718292f2SDouglas Gregor 
477718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
478718292f2SDouglas Gregor     consumeToken();
479718292f2SDouglas Gregor   else {
480718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
481718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
482718292f2SDouglas Gregor     HadError = true;
483718292f2SDouglas Gregor   }
484718292f2SDouglas Gregor 
485718292f2SDouglas Gregor   // We're done parsing this module. Pop back to our parent scope.
486718292f2SDouglas Gregor   ActiveModule = ActiveModule->Parent;
487718292f2SDouglas Gregor }
488718292f2SDouglas Gregor 
489718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration.
490718292f2SDouglas Gregor ///
491718292f2SDouglas Gregor ///   umbrella-declaration:
492718292f2SDouglas Gregor ///     'umbrella' string-literal
493718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() {
494718292f2SDouglas Gregor   assert(Tok.is(MMToken::UmbrellaKeyword));
495718292f2SDouglas Gregor   SourceLocation UmbrellaLoc = consumeToken();
496718292f2SDouglas Gregor 
497718292f2SDouglas Gregor   // Parse the header name.
498718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
499718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
500718292f2SDouglas Gregor       << "umbrella";
501718292f2SDouglas Gregor     HadError = true;
502718292f2SDouglas Gregor     return;
503718292f2SDouglas Gregor   }
504718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
505718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
506718292f2SDouglas Gregor 
5075257fc63SDouglas Gregor   // Check whether we already have an umbrella header.
5085257fc63SDouglas Gregor   if (ActiveModule->UmbrellaHeader) {
5095257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
5105257fc63SDouglas Gregor       << ActiveModule->getFullModuleName()
5115257fc63SDouglas Gregor       << ActiveModule->UmbrellaHeader->getName();
5125257fc63SDouglas Gregor     HadError = true;
5135257fc63SDouglas Gregor     return;
5145257fc63SDouglas Gregor   }
5155257fc63SDouglas Gregor 
5165257fc63SDouglas Gregor   // Only top-level modules can have umbrella headers.
5175257fc63SDouglas Gregor   if (ActiveModule->Parent) {
5185257fc63SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
5195257fc63SDouglas Gregor       << ActiveModule->getFullModuleName();
5205257fc63SDouglas Gregor     HadError = true;
5215257fc63SDouglas Gregor     return;
5225257fc63SDouglas Gregor   }
5235257fc63SDouglas Gregor 
5245257fc63SDouglas Gregor   // Look for this file.
5255257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
526f545f67dSDouglas Gregor   const FileEntry *File = 0;
527f545f67dSDouglas Gregor 
528f545f67dSDouglas Gregor   if (llvm::sys::path::is_absolute(FileName)) {
529f545f67dSDouglas Gregor     PathName = FileName;
530f545f67dSDouglas Gregor     File = SourceMgr.getFileManager().getFile(PathName);
531f545f67dSDouglas Gregor   } else {
532f545f67dSDouglas Gregor     // Search for the header file within the search directory.
5335257fc63SDouglas Gregor     PathName += Directory->getName();
534755b2055SDouglas Gregor     unsigned PathLength = PathName.size();
535755b2055SDouglas Gregor     if (ActiveModule->isPartOfFramework()) {
536755b2055SDouglas Gregor       // Check whether this file is in the public headers.
537755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
5385257fc63SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
539755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
540755b2055SDouglas Gregor 
541755b2055SDouglas Gregor       if (!File) {
542755b2055SDouglas Gregor         // Check whether this file is in the private headers.
543755b2055SDouglas Gregor         PathName.resize(PathLength);
544755b2055SDouglas Gregor         llvm::sys::path::append(PathName, "PrivateHeaders");
545755b2055SDouglas Gregor         llvm::sys::path::append(PathName, FileName);
546755b2055SDouglas Gregor         File = SourceMgr.getFileManager().getFile(PathName);
547755b2055SDouglas Gregor       }
548755b2055SDouglas Gregor 
549755b2055SDouglas Gregor       // FIXME: Deal with subframeworks.
550755b2055SDouglas Gregor     } else {
551755b2055SDouglas Gregor       // Lookup for normal headers.
552755b2055SDouglas Gregor       llvm::sys::path::append(PathName, FileName);
553755b2055SDouglas Gregor       File = SourceMgr.getFileManager().getFile(PathName);
554755b2055SDouglas Gregor     }
555f545f67dSDouglas Gregor   }
5565257fc63SDouglas Gregor 
5575257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
5585257fc63SDouglas Gregor   // Come up with a lazy way to do this.
559755b2055SDouglas Gregor   if (File) {
5605257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
5615257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
5625257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
5635257fc63SDouglas Gregor       HadError = true;
564b65dbfffSDouglas Gregor     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
565b65dbfffSDouglas Gregor       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
566b65dbfffSDouglas Gregor         << OwningModule->getFullModuleName();
567b65dbfffSDouglas Gregor       HadError = true;
5685257fc63SDouglas Gregor     } else {
5695257fc63SDouglas Gregor       // Record this umbrella header.
5705257fc63SDouglas Gregor       ActiveModule->UmbrellaHeader = File;
5715257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
572b65dbfffSDouglas Gregor       Map.UmbrellaDirs[Directory] = ActiveModule;
5735257fc63SDouglas Gregor     }
5745257fc63SDouglas Gregor   } else {
5755257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
5765257fc63SDouglas Gregor       << true << FileName;
5775257fc63SDouglas Gregor     HadError = true;
5785257fc63SDouglas Gregor   }
579718292f2SDouglas Gregor }
580718292f2SDouglas Gregor 
581718292f2SDouglas Gregor /// \brief Parse a header declaration.
582718292f2SDouglas Gregor ///
583718292f2SDouglas Gregor ///   header-declaration:
584718292f2SDouglas Gregor ///     'header' string-literal
585718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() {
586718292f2SDouglas Gregor   assert(Tok.is(MMToken::HeaderKeyword));
5871871ed3dSBenjamin Kramer   consumeToken();
588718292f2SDouglas Gregor 
589718292f2SDouglas Gregor   // Parse the header name.
590718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
591718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
592718292f2SDouglas Gregor       << "header";
593718292f2SDouglas Gregor     HadError = true;
594718292f2SDouglas Gregor     return;
595718292f2SDouglas Gregor   }
596718292f2SDouglas Gregor   StringRef FileName = Tok.getString();
597718292f2SDouglas Gregor   SourceLocation FileNameLoc = consumeToken();
598718292f2SDouglas Gregor 
5995257fc63SDouglas Gregor   // Look for this file.
6005257fc63SDouglas Gregor   llvm::SmallString<128> PathName;
601f545f67dSDouglas Gregor   if (llvm::sys::path::is_relative(FileName)) {
602f545f67dSDouglas Gregor     // FIXME: Change this search to also look for private headers!
6035257fc63SDouglas Gregor     PathName += Directory->getName();
604755b2055SDouglas Gregor 
605755b2055SDouglas Gregor     if (ActiveModule->isPartOfFramework())
606755b2055SDouglas Gregor       llvm::sys::path::append(PathName, "Headers");
607f545f67dSDouglas Gregor   }
608755b2055SDouglas Gregor 
6095257fc63SDouglas Gregor   llvm::sys::path::append(PathName, FileName);
6105257fc63SDouglas Gregor 
6115257fc63SDouglas Gregor   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
6125257fc63SDouglas Gregor   // Come up with a lazy way to do this.
6135257fc63SDouglas Gregor   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
6145257fc63SDouglas Gregor     if (const Module *OwningModule = Map.Headers[File]) {
6155257fc63SDouglas Gregor       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
6165257fc63SDouglas Gregor         << FileName << OwningModule->getFullModuleName();
6175257fc63SDouglas Gregor       HadError = true;
6185257fc63SDouglas Gregor     } else {
6195257fc63SDouglas Gregor       // Record this file.
6205257fc63SDouglas Gregor       ActiveModule->Headers.push_back(File);
6215257fc63SDouglas Gregor       Map.Headers[File] = ActiveModule;
6225257fc63SDouglas Gregor     }
6235257fc63SDouglas Gregor   } else {
6245257fc63SDouglas Gregor     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
6255257fc63SDouglas Gregor       << false << FileName;
6265257fc63SDouglas Gregor     HadError = true;
6275257fc63SDouglas Gregor   }
628718292f2SDouglas Gregor }
629718292f2SDouglas Gregor 
630718292f2SDouglas Gregor /// \brief Parse a module map file.
631718292f2SDouglas Gregor ///
632718292f2SDouglas Gregor ///   module-map-file:
633718292f2SDouglas Gregor ///     module-declaration*
634718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
635718292f2SDouglas Gregor   do {
636718292f2SDouglas Gregor     switch (Tok.Kind) {
637718292f2SDouglas Gregor     case MMToken::EndOfFile:
638718292f2SDouglas Gregor       return HadError;
639718292f2SDouglas Gregor 
640718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
641755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
642718292f2SDouglas Gregor       parseModuleDecl();
643718292f2SDouglas Gregor       break;
644718292f2SDouglas Gregor 
645718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
646718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
647718292f2SDouglas Gregor     case MMToken::Identifier:
648718292f2SDouglas Gregor     case MMToken::LBrace:
649718292f2SDouglas Gregor     case MMToken::RBrace:
650718292f2SDouglas Gregor     case MMToken::StringLiteral:
651718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
652718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
653718292f2SDouglas Gregor       HadError = true;
654718292f2SDouglas Gregor       consumeToken();
655718292f2SDouglas Gregor       break;
656718292f2SDouglas Gregor     }
657718292f2SDouglas Gregor   } while (true);
658718292f2SDouglas Gregor 
659718292f2SDouglas Gregor   return HadError;
660718292f2SDouglas Gregor }
661718292f2SDouglas Gregor 
662718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
663718292f2SDouglas Gregor   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
664718292f2SDouglas Gregor   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
665718292f2SDouglas Gregor   if (!Buffer)
666718292f2SDouglas Gregor     return true;
667718292f2SDouglas Gregor 
668718292f2SDouglas Gregor   // Parse this module map file.
669718292f2SDouglas Gregor   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
670718292f2SDouglas Gregor   Diags->getClient()->BeginSourceFile(LangOpts);
6715257fc63SDouglas Gregor   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
672718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
673718292f2SDouglas Gregor   Diags->getClient()->EndSourceFile();
674718292f2SDouglas Gregor 
675718292f2SDouglas Gregor   return Result;
676718292f2SDouglas Gregor }
677