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