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