xref: /llvm-project/clang/lib/Lex/ModuleMap.cpp (revision 56c64013064b646c50f703615d5597ec5c8d4f72)
1 //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the ModuleMap implementation, which describes the layout
11 // of a module as it relates to headers.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "clang/Lex/ModuleMap.h"
15 #include "clang/Lex/Lexer.h"
16 #include "clang/Lex/LiteralSupport.h"
17 #include "clang/Lex/LexDiagnostic.h"
18 #include "clang/Basic/Diagnostic.h"
19 #include "clang/Basic/FileManager.h"
20 #include "clang/Basic/TargetInfo.h"
21 #include "clang/Basic/TargetOptions.h"
22 #include "llvm/Support/Allocator.h"
23 #include "llvm/Support/Host.h"
24 #include "llvm/Support/PathV2.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/ADT/StringRef.h"
27 #include "llvm/ADT/StringSwitch.h"
28 using namespace clang;
29 
30 //----------------------------------------------------------------------------//
31 // Module
32 //----------------------------------------------------------------------------//
33 
34 std::string ModuleMap::Module::getFullModuleName() const {
35   llvm::SmallVector<StringRef, 2> Names;
36 
37   // Build up the set of module names (from innermost to outermost).
38   for (const Module *M = this; M; M = M->Parent)
39     Names.push_back(M->Name);
40 
41   std::string Result;
42   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
43                                                       IEnd = Names.rend();
44        I != IEnd; ++I) {
45     if (!Result.empty())
46       Result += '.';
47 
48     Result += *I;
49   }
50 
51   return Result;
52 }
53 
54 StringRef ModuleMap::Module::getTopLevelModuleName() const {
55   const Module *Top = this;
56   while (Top->Parent)
57     Top = Top->Parent;
58 
59   return Top->Name;
60 }
61 
62 //----------------------------------------------------------------------------//
63 // Module map
64 //----------------------------------------------------------------------------//
65 
66 ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) {
67   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
68   Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>(
69             new DiagnosticsEngine(DiagIDs));
70   Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true);
71   SourceMgr = new SourceManager(*Diags, FileMgr);
72 }
73 
74 ModuleMap::~ModuleMap() {
75   delete SourceMgr;
76 }
77 
78 ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
79   llvm::DenseMap<const FileEntry *, Module *>::iterator Known
80     = Headers.find(File);
81   if (Known != Headers.end())
82     return Known->second;
83 
84   const DirectoryEntry *Dir = File->getDir();
85   llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir
86     = UmbrellaDirs.find(Dir);
87   if (KnownDir != UmbrellaDirs.end())
88     return KnownDir->second;
89 
90   // Walk up the directory hierarchy looking for umbrella headers.
91   llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
92   StringRef DirName = Dir->getName();
93   do {
94     // Retrieve our parent path.
95     DirName = llvm::sys::path::parent_path(DirName);
96     if (DirName.empty())
97       break;
98 
99     // Resolve the parent path to a directory entry.
100     Dir = SourceMgr->getFileManager().getDirectory(DirName);
101     if (!Dir)
102       break;
103 
104     KnownDir = UmbrellaDirs.find(Dir);
105     if (KnownDir != UmbrellaDirs.end()) {
106       Module *Result = KnownDir->second;
107 
108       // Record each of the directories we stepped through as being part of
109       // the module we found, since the umbrella header covers them all.
110       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
111         UmbrellaDirs[SkippedDirs[I]] = Result;
112 
113       return Result;
114     }
115 
116     SkippedDirs.push_back(Dir);
117   } while (true);
118 
119   return 0;
120 }
121 
122 ModuleMap::Module *ModuleMap::findModule(StringRef Name) {
123   llvm::StringMap<Module *>::iterator Known = Modules.find(Name);
124   if (Known != Modules.end())
125     return Known->getValue();
126 
127   return 0;
128 }
129 
130 ModuleMap::Module *
131 ModuleMap::inferFrameworkModule(StringRef ModuleName,
132                                 const DirectoryEntry *FrameworkDir) {
133   // Check whether we've already found this module.
134   if (Module *Module = findModule(ModuleName))
135     return Module;
136 
137   // Look for an umbrella header.
138   llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
139   llvm::sys::path::append(UmbrellaName, "Headers");
140   llvm::sys::path::append(UmbrellaName, ModuleName + ".h");
141   const FileEntry *UmbrellaHeader
142     = SourceMgr->getFileManager().getFile(UmbrellaName);
143 
144   // FIXME: If there's no umbrella header, we could probably scan the
145   // framework to load *everything*. But, it's not clear that this is a good
146   // idea.
147   if (!UmbrellaHeader)
148     return 0;
149 
150   Module *Result = new Module(ModuleName, SourceLocation());
151   Result->UmbrellaHeader = UmbrellaHeader;
152   Headers[UmbrellaHeader] = Result;
153   UmbrellaDirs[FrameworkDir] = Result;
154   Modules[ModuleName] = Result;
155   return Result;
156 }
157 
158 static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
159   OS << std::string(' ', Spaces);
160 }
161 
162 static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M,
163                        unsigned Indent) {
164   indent(OS, Indent);
165   if (M->IsExplicit)
166     OS << "explicit ";
167   OS << M->Name << " {\n";
168 
169   if (M->UmbrellaHeader) {
170     indent(OS, Indent + 2);
171     OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n";
172   }
173 
174   for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) {
175     indent(OS, Indent + 2);
176     OS << "header \"" << M->Headers[I]->getName() << "\"\n";
177   }
178 
179   for (llvm::StringMap<ModuleMap::Module *>::iterator
180             MI = M->SubModules.begin(),
181          MIEnd = M->SubModules.end();
182        MI != MIEnd; ++MI)
183     dumpModule(llvm::errs(), MI->getValue(), Indent + 2);
184 
185   indent(OS, Indent);
186   OS << "}\n";
187 }
188 
189 void ModuleMap::dump() {
190   llvm::errs() << "Modules:";
191   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
192                                         MEnd = Modules.end();
193        M != MEnd; ++M)
194     dumpModule(llvm::errs(), M->getValue(), 2);
195 
196   llvm::errs() << "Headers:";
197   for (llvm::DenseMap<const FileEntry *, Module *>::iterator
198             H = Headers.begin(),
199          HEnd = Headers.end();
200        H != HEnd; ++H) {
201     llvm::errs() << "  \"" << H->first->getName() << "\" -> "
202                  << H->second->getFullModuleName() << "\n";
203   }
204 }
205 
206 //----------------------------------------------------------------------------//
207 // Module map file parser
208 //----------------------------------------------------------------------------//
209 
210 namespace clang {
211   /// \brief A token in a module map file.
212   struct MMToken {
213     enum TokenKind {
214       EndOfFile,
215       HeaderKeyword,
216       Identifier,
217       ExplicitKeyword,
218       ModuleKeyword,
219       UmbrellaKeyword,
220       StringLiteral,
221       LBrace,
222       RBrace
223     } Kind;
224 
225     unsigned Location;
226     unsigned StringLength;
227     const char *StringData;
228 
229     void clear() {
230       Kind = EndOfFile;
231       Location = 0;
232       StringLength = 0;
233       StringData = 0;
234     }
235 
236     bool is(TokenKind K) const { return Kind == K; }
237 
238     SourceLocation getLocation() const {
239       return SourceLocation::getFromRawEncoding(Location);
240     }
241 
242     StringRef getString() const {
243       return StringRef(StringData, StringLength);
244     }
245   };
246 
247   class ModuleMapParser {
248     Lexer &L;
249     SourceManager &SourceMgr;
250     DiagnosticsEngine &Diags;
251     ModuleMap &Map;
252 
253     /// \brief The directory that this module map resides in.
254     const DirectoryEntry *Directory;
255 
256     /// \brief Whether an error occurred.
257     bool HadError;
258 
259     /// \brief Default target information, used only for string literal
260     /// parsing.
261     TargetInfo *Target;
262 
263     /// \brief Stores string data for the various string literals referenced
264     /// during parsing.
265     llvm::BumpPtrAllocator StringData;
266 
267     /// \brief The current token.
268     MMToken Tok;
269 
270     /// \brief The active module.
271     ModuleMap::Module *ActiveModule;
272 
273     /// \brief Consume the current token and return its location.
274     SourceLocation consumeToken();
275 
276     /// \brief Skip tokens until we reach the a token with the given kind
277     /// (or the end of the file).
278     void skipUntil(MMToken::TokenKind K);
279 
280     void parseModuleDecl();
281     void parseUmbrellaDecl();
282     void parseHeaderDecl();
283 
284   public:
285     typedef ModuleMap::Module Module;
286 
287     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
288                              DiagnosticsEngine &Diags,
289                              ModuleMap &Map,
290                              const DirectoryEntry *Directory)
291       : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map),
292         Directory(Directory), HadError(false), ActiveModule(0)
293     {
294       TargetOptions TargetOpts;
295       TargetOpts.Triple = llvm::sys::getDefaultTargetTriple();
296       Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
297 
298       Tok.clear();
299       consumeToken();
300     }
301 
302     bool parseModuleMapFile();
303   };
304 }
305 
306 SourceLocation ModuleMapParser::consumeToken() {
307 retry:
308   SourceLocation Result = Tok.getLocation();
309   Tok.clear();
310 
311   Token LToken;
312   L.LexFromRawLexer(LToken);
313   Tok.Location = LToken.getLocation().getRawEncoding();
314   switch (LToken.getKind()) {
315   case tok::raw_identifier:
316     Tok.StringData = LToken.getRawIdentifierData();
317     Tok.StringLength = LToken.getLength();
318     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
319                  .Case("header", MMToken::HeaderKeyword)
320                  .Case("explicit", MMToken::ExplicitKeyword)
321                  .Case("module", MMToken::ModuleKeyword)
322                  .Case("umbrella", MMToken::UmbrellaKeyword)
323                  .Default(MMToken::Identifier);
324     break;
325 
326   case tok::eof:
327     Tok.Kind = MMToken::EndOfFile;
328     break;
329 
330   case tok::l_brace:
331     Tok.Kind = MMToken::LBrace;
332     break;
333 
334   case tok::r_brace:
335     Tok.Kind = MMToken::RBrace;
336     break;
337 
338   case tok::string_literal: {
339     // Parse the string literal.
340     LangOptions LangOpts;
341     StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
342     if (StringLiteral.hadError)
343       goto retry;
344 
345     // Copy the string literal into our string data allocator.
346     unsigned Length = StringLiteral.GetStringLength();
347     char *Saved = StringData.Allocate<char>(Length + 1);
348     memcpy(Saved, StringLiteral.GetString().data(), Length);
349     Saved[Length] = 0;
350 
351     // Form the token.
352     Tok.Kind = MMToken::StringLiteral;
353     Tok.StringData = Saved;
354     Tok.StringLength = Length;
355     break;
356   }
357 
358   case tok::comment:
359     goto retry;
360 
361   default:
362     Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
363     HadError = true;
364     goto retry;
365   }
366 
367   return Result;
368 }
369 
370 void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
371   unsigned braceDepth = 0;
372   do {
373     switch (Tok.Kind) {
374     case MMToken::EndOfFile:
375       return;
376 
377     case MMToken::LBrace:
378       if (Tok.is(K) && braceDepth == 0)
379         return;
380 
381       ++braceDepth;
382       break;
383 
384     case MMToken::RBrace:
385       if (braceDepth > 0)
386         --braceDepth;
387       else if (Tok.is(K))
388         return;
389       break;
390 
391     default:
392       if (braceDepth == 0 && Tok.is(K))
393         return;
394       break;
395     }
396 
397    consumeToken();
398   } while (true);
399 }
400 
401 /// \brief Parse a module declaration.
402 ///
403 ///   module-declaration:
404 ///     'module' identifier { module-member* }
405 ///
406 ///   module-member:
407 ///     umbrella-declaration
408 ///     header-declaration
409 ///     'explicit'[opt] module-declaration
410 void ModuleMapParser::parseModuleDecl() {
411   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword));
412 
413   // Parse 'explicit' keyword, if present.
414   bool Explicit = false;
415   if (Tok.is(MMToken::ExplicitKeyword)) {
416     consumeToken();
417     Explicit = true;
418   }
419 
420   // Parse 'module' keyword.
421   if (!Tok.is(MMToken::ModuleKeyword)) {
422     Diags.Report(Tok.getLocation(),
423                  diag::err_mmap_expected_module_after_explicit);
424     consumeToken();
425     HadError = true;
426     return;
427   }
428   consumeToken(); // 'module' keyword
429 
430   // Parse the module name.
431   if (!Tok.is(MMToken::Identifier)) {
432     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
433     HadError = true;
434     return;
435   }
436   StringRef ModuleName = Tok.getString();
437   SourceLocation ModuleNameLoc = consumeToken();
438 
439   // Parse the opening brace.
440   if (!Tok.is(MMToken::LBrace)) {
441     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
442       << ModuleName;
443     HadError = true;
444     return;
445   }
446   SourceLocation LBraceLoc = consumeToken();
447 
448   // Determine whether this (sub)module has already been defined.
449   llvm::StringMap<Module *> &ModuleSpace
450     = ActiveModule? ActiveModule->SubModules : Map.Modules;
451   llvm::StringMap<Module *>::iterator ExistingModule
452     = ModuleSpace.find(ModuleName);
453   if (ExistingModule != ModuleSpace.end()) {
454     Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
455       << ModuleName;
456     Diags.Report(ExistingModule->getValue()->DefinitionLoc,
457                  diag::note_mmap_prev_definition);
458 
459     // Skip the module definition.
460     skipUntil(MMToken::RBrace);
461     if (Tok.is(MMToken::RBrace))
462       consumeToken();
463 
464     HadError = true;
465     return;
466   }
467 
468   // Start defining this module.
469   ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit);
470   ModuleSpace[ModuleName] = ActiveModule;
471 
472   bool Done = false;
473   do {
474     switch (Tok.Kind) {
475     case MMToken::EndOfFile:
476     case MMToken::RBrace:
477       Done = true;
478       break;
479 
480     case MMToken::ExplicitKeyword:
481     case MMToken::ModuleKeyword:
482       parseModuleDecl();
483       break;
484 
485     case MMToken::HeaderKeyword:
486       parseHeaderDecl();
487       break;
488 
489     case MMToken::UmbrellaKeyword:
490       parseUmbrellaDecl();
491       break;
492 
493     default:
494       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
495       consumeToken();
496       break;
497     }
498   } while (!Done);
499 
500   if (Tok.is(MMToken::RBrace))
501     consumeToken();
502   else {
503     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
504     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
505     HadError = true;
506   }
507 
508   // We're done parsing this module. Pop back to our parent scope.
509   ActiveModule = ActiveModule->Parent;
510 }
511 
512 /// \brief Parse an umbrella header declaration.
513 ///
514 ///   umbrella-declaration:
515 ///     'umbrella' string-literal
516 void ModuleMapParser::parseUmbrellaDecl() {
517   assert(Tok.is(MMToken::UmbrellaKeyword));
518   SourceLocation UmbrellaLoc = consumeToken();
519 
520   // Parse the header name.
521   if (!Tok.is(MMToken::StringLiteral)) {
522     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
523       << "umbrella";
524     HadError = true;
525     return;
526   }
527   StringRef FileName = Tok.getString();
528   SourceLocation FileNameLoc = consumeToken();
529 
530   // Check whether we already have an umbrella header.
531   if (ActiveModule->UmbrellaHeader) {
532     Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
533       << ActiveModule->getFullModuleName()
534       << ActiveModule->UmbrellaHeader->getName();
535     HadError = true;
536     return;
537   }
538 
539   // Only top-level modules can have umbrella headers.
540   if (ActiveModule->Parent) {
541     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule)
542       << ActiveModule->getFullModuleName();
543     HadError = true;
544     return;
545   }
546 
547   // Look for this file.
548   llvm::SmallString<128> PathName;
549   PathName += Directory->getName();
550   llvm::sys::path::append(PathName, FileName);
551 
552   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
553   // Come up with a lazy way to do this.
554   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
555     if (const Module *OwningModule = Map.Headers[File]) {
556       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
557         << FileName << OwningModule->getFullModuleName();
558       HadError = true;
559     } else if ((OwningModule = Map.UmbrellaDirs[Directory])) {
560       Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
561         << OwningModule->getFullModuleName();
562       HadError = true;
563     } else {
564       // Record this umbrella header.
565       ActiveModule->UmbrellaHeader = File;
566       Map.Headers[File] = ActiveModule;
567       Map.UmbrellaDirs[Directory] = ActiveModule;
568     }
569   } else {
570     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
571       << true << FileName;
572     HadError = true;
573   }
574 }
575 
576 /// \brief Parse a header declaration.
577 ///
578 ///   header-declaration:
579 ///     'header' string-literal
580 void ModuleMapParser::parseHeaderDecl() {
581   assert(Tok.is(MMToken::HeaderKeyword));
582   consumeToken();
583 
584   // Parse the header name.
585   if (!Tok.is(MMToken::StringLiteral)) {
586     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
587       << "header";
588     HadError = true;
589     return;
590   }
591   StringRef FileName = Tok.getString();
592   SourceLocation FileNameLoc = consumeToken();
593 
594   // Look for this file.
595   llvm::SmallString<128> PathName;
596   PathName += Directory->getName();
597   llvm::sys::path::append(PathName, FileName);
598 
599   // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
600   // Come up with a lazy way to do this.
601   if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
602     if (const Module *OwningModule = Map.Headers[File]) {
603       Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
604         << FileName << OwningModule->getFullModuleName();
605       HadError = true;
606     } else {
607       // Record this file.
608       ActiveModule->Headers.push_back(File);
609       Map.Headers[File] = ActiveModule;
610     }
611   } else {
612     Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
613       << false << FileName;
614     HadError = true;
615   }
616 }
617 
618 /// \brief Parse a module map file.
619 ///
620 ///   module-map-file:
621 ///     module-declaration*
622 bool ModuleMapParser::parseModuleMapFile() {
623   do {
624     switch (Tok.Kind) {
625     case MMToken::EndOfFile:
626       return HadError;
627 
628     case MMToken::ModuleKeyword:
629       parseModuleDecl();
630       break;
631 
632     case MMToken::ExplicitKeyword:
633     case MMToken::HeaderKeyword:
634     case MMToken::Identifier:
635     case MMToken::LBrace:
636     case MMToken::RBrace:
637     case MMToken::StringLiteral:
638     case MMToken::UmbrellaKeyword:
639       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
640       HadError = true;
641       consumeToken();
642       break;
643     }
644   } while (true);
645 
646   return HadError;
647 }
648 
649 bool ModuleMap::parseModuleMapFile(const FileEntry *File) {
650   FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User);
651   const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID);
652   if (!Buffer)
653     return true;
654 
655   // Parse this module map file.
656   Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts);
657   Diags->getClient()->BeginSourceFile(LangOpts);
658   ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir());
659   bool Result = Parser.parseModuleMapFile();
660   Diags->getClient()->EndSourceFile();
661 
662   return Result;
663 }
664