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