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