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