1 //===-- ClangModulesDeclVendor.cpp ----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Basic/Diagnostic.h"
10 #include "clang/Basic/DiagnosticFrontend.h"
11 #include "clang/Basic/DiagnosticSerialization.h"
12 #include "clang/Basic/TargetInfo.h"
13 #include "clang/Frontend/CompilerInstance.h"
14 #include "clang/Frontend/FrontendActions.h"
15 #include "clang/Frontend/TextDiagnosticPrinter.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "clang/Lex/PreprocessorOptions.h"
18 #include "clang/Parse/Parser.h"
19 #include "clang/Sema/Lookup.h"
20 #include "clang/Serialization/ASTReader.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/FormatVariadic.h"
24 #include "llvm/Support/Path.h"
25 #include "llvm/Support/Threading.h"
26 
27 #include "ClangHost.h"
28 #include "ClangModulesDeclVendor.h"
29 #include "ModuleDependencyCollector.h"
30 
31 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
32 #include "lldb/Core/ModuleList.h"
33 #include "lldb/Core/Progress.h"
34 #include "lldb/Host/Host.h"
35 #include "lldb/Host/HostInfo.h"
36 #include "lldb/Symbol/CompileUnit.h"
37 #include "lldb/Symbol/SourceModule.h"
38 #include "lldb/Target/Target.h"
39 #include "lldb/Utility/FileSpec.h"
40 #include "lldb/Utility/LLDBAssert.h"
41 #include "lldb/Utility/LLDBLog.h"
42 #include "lldb/Utility/Log.h"
43 #include "lldb/Utility/StreamString.h"
44 
45 #include <memory>
46 #include <mutex>
47 
48 using namespace lldb_private;
49 
50 namespace {
51 /// Any Clang compiler requires a consumer for diagnostics.  This one stores
52 /// them as strings so we can provide them to the user in case a module failed
53 /// to load.
54 class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
55 public:
56   StoringDiagnosticConsumer();
57 
58   void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
59                         const clang::Diagnostic &info) override;
60 
61   void ClearDiagnostics();
62 
63   void DumpDiagnostics(Stream &error_stream);
64 
65   void BeginSourceFile(const clang::LangOptions &LangOpts,
66                        const clang::Preprocessor *PP = nullptr) override;
67   void EndSourceFile() override;
68 
69 private:
70   bool HandleModuleRemark(const clang::Diagnostic &info);
71   void SetCurrentModuleProgress(std::string module_name);
72 
73   typedef std::pair<clang::DiagnosticsEngine::Level, std::string>
74       IDAndDiagnostic;
75   std::vector<IDAndDiagnostic> m_diagnostics;
76   /// The DiagnosticPrinter used for creating the full diagnostic messages
77   /// that are stored in m_diagnostics.
78   std::shared_ptr<clang::TextDiagnosticPrinter> m_diag_printer;
79   /// Output stream of m_diag_printer.
80   std::shared_ptr<llvm::raw_string_ostream> m_os;
81   /// Output string filled by m_os. Will be reused for different diagnostics.
82   std::string m_output;
83   Log *m_log;
84   /// A Progress with explicitly managed lifetime.
85   std::unique_ptr<Progress> m_current_progress_up;
86   std::vector<std::string> m_module_build_stack;
87 };
88 
89 /// The private implementation of our ClangModulesDeclVendor.  Contains all the
90 /// Clang state required to load modules.
91 class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
92 public:
93   ClangModulesDeclVendorImpl(
94       llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
95       std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
96       std::unique_ptr<clang::CompilerInstance> compiler_instance,
97       std::unique_ptr<clang::Parser> parser);
98 
99   ~ClangModulesDeclVendorImpl() override = default;
100 
101   bool AddModule(const SourceModule &module, ModuleVector *exported_modules,
102                  Stream &error_stream) override;
103 
104   bool AddModulesForCompileUnit(CompileUnit &cu, ModuleVector &exported_modules,
105                                 Stream &error_stream) override;
106 
107   uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
108                      std::vector<CompilerDecl> &decls) override;
109 
110   void ForEachMacro(
111       const ModuleVector &modules,
112       std::function<bool(llvm::StringRef, llvm::StringRef)> handler) override;
113 
114 private:
115   typedef llvm::DenseSet<ModuleID> ExportedModuleSet;
116   void ReportModuleExportsHelper(ExportedModuleSet &exports,
117                                  clang::Module *module);
118 
119   void ReportModuleExports(ModuleVector &exports, clang::Module *module);
120 
121   clang::ModuleLoadResult DoGetModule(clang::ModuleIdPath path,
122                                       bool make_visible);
123 
124   bool m_enabled = false;
125 
126   llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
127   std::shared_ptr<clang::CompilerInvocation> m_compiler_invocation;
128   std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
129   std::unique_ptr<clang::Parser> m_parser;
130   size_t m_source_location_index =
131       0; // used to give name components fake SourceLocations
132 
133   typedef std::vector<ConstString> ImportedModule;
134   typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
135   typedef llvm::DenseSet<ModuleID> ImportedModuleSet;
136   ImportedModuleMap m_imported_modules;
137   ImportedModuleSet m_user_imported_modules;
138   // We assume that every ASTContext has an TypeSystemClang, so we also store
139   // a custom TypeSystemClang for our internal ASTContext.
140   std::shared_ptr<TypeSystemClang> m_ast_context;
141 };
142 } // anonymous namespace
143 
144 StoringDiagnosticConsumer::StoringDiagnosticConsumer() {
145   m_log = GetLog(LLDBLog::Expressions);
146 
147   clang::DiagnosticOptions *m_options = new clang::DiagnosticOptions();
148   m_os = std::make_shared<llvm::raw_string_ostream>(m_output);
149   m_diag_printer =
150       std::make_shared<clang::TextDiagnosticPrinter>(*m_os, m_options);
151 }
152 
153 void StoringDiagnosticConsumer::HandleDiagnostic(
154     clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) {
155   if (HandleModuleRemark(info))
156     return;
157 
158   // Print the diagnostic to m_output.
159   m_output.clear();
160   m_diag_printer->HandleDiagnostic(DiagLevel, info);
161   m_os->flush();
162 
163   // Store the diagnostic for later.
164   m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, m_output));
165 }
166 
167 void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); }
168 
169 void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) {
170   for (IDAndDiagnostic &diag : m_diagnostics) {
171     switch (diag.first) {
172     default:
173       error_stream.PutCString(diag.second);
174       error_stream.PutChar('\n');
175       break;
176     case clang::DiagnosticsEngine::Level::Ignored:
177       break;
178     }
179   }
180 }
181 
182 void StoringDiagnosticConsumer::BeginSourceFile(
183     const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) {
184   m_diag_printer->BeginSourceFile(LangOpts, PP);
185 }
186 
187 void StoringDiagnosticConsumer::EndSourceFile() {
188   m_current_progress_up = nullptr;
189   m_diag_printer->EndSourceFile();
190 }
191 
192 bool StoringDiagnosticConsumer::HandleModuleRemark(
193     const clang::Diagnostic &info) {
194   Log *log = GetLog(LLDBLog::Expressions);
195   switch (info.getID()) {
196   case clang::diag::remark_module_build: {
197     const auto &module_name = info.getArgStdStr(0);
198     SetCurrentModuleProgress(module_name);
199     m_module_build_stack.push_back(module_name);
200 
201     const auto &module_path = info.getArgStdStr(1);
202     LLDB_LOG(log, "Building Clang module {0} as {1}", module_name, module_path);
203     return true;
204   }
205   case clang::diag::remark_module_build_done: {
206     // The current module is done.
207     m_module_build_stack.pop_back();
208     if (m_module_build_stack.empty()) {
209       m_current_progress_up = nullptr;
210     } else {
211       // When the just completed module began building, a module that depends on
212       // it ("module A") was effectively paused. Update the progress to re-show
213       // "module A" as continuing to be built.
214       const auto &resumed_module_name = m_module_build_stack.back();
215       SetCurrentModuleProgress(resumed_module_name);
216     }
217 
218     const auto &module_name = info.getArgStdStr(0);
219     LLDB_LOG(log, "Finished building Clang module {0}", module_name);
220     return true;
221   }
222   default:
223     return false;
224   }
225 }
226 
227 void StoringDiagnosticConsumer::SetCurrentModuleProgress(
228     std::string module_name) {
229   if (!m_current_progress_up)
230     m_current_progress_up =
231         std::make_unique<Progress>("Building Clang modules");
232 
233   m_current_progress_up->Increment(1, std::move(module_name));
234 }
235 
236 ClangModulesDeclVendor::ClangModulesDeclVendor()
237     : ClangDeclVendor(eClangModuleDeclVendor) {}
238 
239 ClangModulesDeclVendor::~ClangModulesDeclVendor() = default;
240 
241 ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
242     llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
243     std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
244     std::unique_ptr<clang::CompilerInstance> compiler_instance,
245     std::unique_ptr<clang::Parser> parser)
246     : m_diagnostics_engine(std::move(diagnostics_engine)),
247       m_compiler_invocation(std::move(compiler_invocation)),
248       m_compiler_instance(std::move(compiler_instance)),
249       m_parser(std::move(parser)) {
250 
251   // Initialize our TypeSystemClang.
252   m_ast_context =
253       std::make_shared<TypeSystemClang>("ClangModulesDeclVendor ASTContext",
254                                         m_compiler_instance->getASTContext());
255 }
256 
257 void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
258     ExportedModuleSet &exports, clang::Module *module) {
259   if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
260     return;
261 
262   exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module));
263 
264   llvm::SmallVector<clang::Module *, 2> sub_exports;
265 
266   module->getExportedModules(sub_exports);
267 
268   for (clang::Module *module : sub_exports)
269     ReportModuleExportsHelper(exports, module);
270 }
271 
272 void ClangModulesDeclVendorImpl::ReportModuleExports(
273     ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) {
274   ExportedModuleSet exports_set;
275 
276   ReportModuleExportsHelper(exports_set, module);
277 
278   for (ModuleID module : exports_set)
279     exports.push_back(module);
280 }
281 
282 bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module,
283                                            ModuleVector *exported_modules,
284                                            Stream &error_stream) {
285   // Fail early.
286 
287   if (m_compiler_instance->hadModuleLoaderFatalFailure()) {
288     error_stream.PutCString("error: Couldn't load a module because the module "
289                             "loader is in a fatal state.\n");
290     return false;
291   }
292 
293   // Check if we've already imported this module.
294 
295   std::vector<ConstString> imported_module;
296 
297   for (ConstString path_component : module.path)
298     imported_module.push_back(path_component);
299 
300   {
301     ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
302 
303     if (mi != m_imported_modules.end()) {
304       if (exported_modules)
305         ReportModuleExports(*exported_modules, mi->second);
306       return true;
307     }
308   }
309 
310   clang::HeaderSearch &HS =
311     m_compiler_instance->getPreprocessor().getHeaderSearchInfo();
312 
313   if (module.search_path) {
314     auto path_begin = llvm::sys::path::begin(module.search_path.GetStringRef());
315     auto path_end = llvm::sys::path::end(module.search_path.GetStringRef());
316     auto sysroot_begin = llvm::sys::path::begin(module.sysroot.GetStringRef());
317     auto sysroot_end = llvm::sys::path::end(module.sysroot.GetStringRef());
318     // FIXME: Use C++14 std::equal(it, it, it, it) variant once it's available.
319     bool is_system_module = (std::distance(path_begin, path_end) >=
320                              std::distance(sysroot_begin, sysroot_end)) &&
321                             std::equal(sysroot_begin, sysroot_end, path_begin);
322     // No need to inject search paths to modules in the sysroot.
323     if (!is_system_module) {
324       auto error = [&]() {
325         error_stream.Printf("error: No module map file in %s\n",
326                             module.search_path.AsCString());
327         return false;
328       };
329 
330       bool is_system = true;
331       bool is_framework = false;
332       auto dir = HS.getFileMgr().getOptionalDirectoryRef(
333           module.search_path.GetStringRef());
334       if (!dir)
335         return error();
336       auto file = HS.lookupModuleMapFile(*dir, is_framework);
337       if (!file)
338         return error();
339       if (!HS.loadModuleMapFile(*file, is_system))
340         return error();
341     }
342   }
343   if (!HS.lookupModule(module.path.front().GetStringRef())) {
344     error_stream.Printf("error: Header search couldn't locate module %s\n",
345                         module.path.front().AsCString());
346     return false;
347   }
348 
349   llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>,
350                     4>
351       clang_path;
352 
353   {
354     clang::SourceManager &source_manager =
355         m_compiler_instance->getASTContext().getSourceManager();
356 
357     for (ConstString path_component : module.path) {
358       clang_path.push_back(std::make_pair(
359           &m_compiler_instance->getASTContext().Idents.get(
360               path_component.GetStringRef()),
361           source_manager.getLocForStartOfFile(source_manager.getMainFileID())
362               .getLocWithOffset(m_source_location_index++)));
363     }
364   }
365 
366   StoringDiagnosticConsumer *diagnostic_consumer =
367       static_cast<StoringDiagnosticConsumer *>(
368           m_compiler_instance->getDiagnostics().getClient());
369 
370   diagnostic_consumer->ClearDiagnostics();
371 
372   clang::Module *top_level_module = DoGetModule(clang_path.front(), false);
373 
374   if (!top_level_module) {
375     diagnostic_consumer->DumpDiagnostics(error_stream);
376     error_stream.Printf("error: Couldn't load top-level module %s\n",
377                         module.path.front().AsCString());
378     return false;
379   }
380 
381   clang::Module *submodule = top_level_module;
382 
383   for (auto &component : llvm::ArrayRef<ConstString>(module.path).drop_front()) {
384     submodule = submodule->findSubmodule(component.GetStringRef());
385     if (!submodule) {
386       diagnostic_consumer->DumpDiagnostics(error_stream);
387       error_stream.Printf("error: Couldn't load submodule %s\n",
388                           component.GetCString());
389       return false;
390     }
391   }
392 
393   clang::Module *requested_module = DoGetModule(clang_path, true);
394 
395   if (requested_module != nullptr) {
396     if (exported_modules)
397       ReportModuleExports(*exported_modules, requested_module);
398 
399     m_imported_modules[imported_module] = requested_module;
400 
401     m_enabled = true;
402 
403     return true;
404   }
405 
406   return false;
407 }
408 
409 bool ClangModulesDeclVendor::LanguageSupportsClangModules(
410     lldb::LanguageType language) {
411   switch (language) {
412   default:
413     return false;
414   case lldb::LanguageType::eLanguageTypeC:
415   case lldb::LanguageType::eLanguageTypeC11:
416   case lldb::LanguageType::eLanguageTypeC89:
417   case lldb::LanguageType::eLanguageTypeC99:
418   case lldb::LanguageType::eLanguageTypeC_plus_plus:
419   case lldb::LanguageType::eLanguageTypeC_plus_plus_03:
420   case lldb::LanguageType::eLanguageTypeC_plus_plus_11:
421   case lldb::LanguageType::eLanguageTypeC_plus_plus_14:
422   case lldb::LanguageType::eLanguageTypeObjC:
423   case lldb::LanguageType::eLanguageTypeObjC_plus_plus:
424     return true;
425   }
426 }
427 
428 bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
429     CompileUnit &cu, ClangModulesDeclVendor::ModuleVector &exported_modules,
430     Stream &error_stream) {
431   if (LanguageSupportsClangModules(cu.GetLanguage())) {
432     for (auto &imported_module : cu.GetImportedModules())
433       if (!AddModule(imported_module, &exported_modules, error_stream))
434         return false;
435   }
436   return true;
437 }
438 
439 // ClangImporter::lookupValue
440 
441 uint32_t
442 ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
443                                       uint32_t max_matches,
444                                       std::vector<CompilerDecl> &decls) {
445   if (!m_enabled)
446     return 0;
447 
448   if (!append)
449     decls.clear();
450 
451   clang::IdentifierInfo &ident =
452       m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());
453 
454   clang::LookupResult lookup_result(
455       m_compiler_instance->getSema(), clang::DeclarationName(&ident),
456       clang::SourceLocation(), clang::Sema::LookupOrdinaryName);
457 
458   m_compiler_instance->getSema().LookupName(
459       lookup_result,
460       m_compiler_instance->getSema().getScopeForContext(
461           m_compiler_instance->getASTContext().getTranslationUnitDecl()));
462 
463   uint32_t num_matches = 0;
464 
465   for (clang::NamedDecl *named_decl : lookup_result) {
466     if (num_matches >= max_matches)
467       return num_matches;
468 
469     decls.push_back(m_ast_context->GetCompilerDecl(named_decl));
470     ++num_matches;
471   }
472 
473   return num_matches;
474 }
475 
476 void ClangModulesDeclVendorImpl::ForEachMacro(
477     const ClangModulesDeclVendor::ModuleVector &modules,
478     std::function<bool(llvm::StringRef, llvm::StringRef)> handler) {
479   if (!m_enabled)
480     return;
481 
482   typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
483   ModulePriorityMap module_priorities;
484 
485   ssize_t priority = 0;
486 
487   for (ModuleID module : modules)
488     module_priorities[module] = priority++;
489 
490   if (m_compiler_instance->getPreprocessor().getExternalSource()) {
491     m_compiler_instance->getPreprocessor()
492         .getExternalSource()
493         ->ReadDefinedMacros();
494   }
495 
496   for (clang::Preprocessor::macro_iterator
497            mi = m_compiler_instance->getPreprocessor().macro_begin(),
498            me = m_compiler_instance->getPreprocessor().macro_end();
499        mi != me; ++mi) {
500     const clang::IdentifierInfo *ii = nullptr;
501 
502     {
503       if (clang::IdentifierInfoLookup *lookup =
504               m_compiler_instance->getPreprocessor()
505                   .getIdentifierTable()
506                   .getExternalIdentifierLookup()) {
507         lookup->get(mi->first->getName());
508       }
509       if (!ii)
510         ii = mi->first;
511     }
512 
513     ssize_t found_priority = -1;
514     clang::MacroInfo *macro_info = nullptr;
515 
516     for (clang::ModuleMacro *module_macro :
517          m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) {
518       clang::Module *module = module_macro->getOwningModule();
519 
520       {
521         ModulePriorityMap::iterator pi =
522             module_priorities.find(reinterpret_cast<ModuleID>(module));
523 
524         if (pi != module_priorities.end() && pi->second > found_priority) {
525           macro_info = module_macro->getMacroInfo();
526           found_priority = pi->second;
527         }
528       }
529 
530       clang::Module *top_level_module = module->getTopLevelModule();
531 
532       if (top_level_module != module) {
533         ModulePriorityMap::iterator pi = module_priorities.find(
534             reinterpret_cast<ModuleID>(top_level_module));
535 
536         if ((pi != module_priorities.end()) && pi->second > found_priority) {
537           macro_info = module_macro->getMacroInfo();
538           found_priority = pi->second;
539         }
540       }
541     }
542 
543     if (macro_info) {
544       std::string macro_expansion = "#define ";
545       llvm::StringRef macro_identifier = mi->first->getName();
546       macro_expansion.append(macro_identifier.str());
547 
548       {
549         if (macro_info->isFunctionLike()) {
550           macro_expansion.append("(");
551 
552           bool first_arg = true;
553 
554           for (auto pi = macro_info->param_begin(),
555                     pe = macro_info->param_end();
556                pi != pe; ++pi) {
557             if (!first_arg)
558               macro_expansion.append(", ");
559             else
560               first_arg = false;
561 
562             macro_expansion.append((*pi)->getName().str());
563           }
564 
565           if (macro_info->isC99Varargs()) {
566             if (first_arg)
567               macro_expansion.append("...");
568             else
569               macro_expansion.append(", ...");
570           } else if (macro_info->isGNUVarargs())
571             macro_expansion.append("...");
572 
573           macro_expansion.append(")");
574         }
575 
576         macro_expansion.append(" ");
577 
578         bool first_token = true;
579 
580         for (clang::MacroInfo::const_tokens_iterator
581                  ti = macro_info->tokens_begin(),
582                  te = macro_info->tokens_end();
583              ti != te; ++ti) {
584           if (!first_token)
585             macro_expansion.append(" ");
586           else
587             first_token = false;
588 
589           if (ti->isLiteral()) {
590             if (const char *literal_data = ti->getLiteralData()) {
591               std::string token_str(literal_data, ti->getLength());
592               macro_expansion.append(token_str);
593             } else {
594               bool invalid = false;
595               const char *literal_source =
596                   m_compiler_instance->getSourceManager().getCharacterData(
597                       ti->getLocation(), &invalid);
598 
599               if (invalid) {
600                 lldbassert(0 && "Unhandled token kind");
601                 macro_expansion.append("<unknown literal value>");
602               } else {
603                 macro_expansion.append(
604                     std::string(literal_source, ti->getLength()));
605               }
606             }
607           } else if (const char *punctuator_spelling =
608                          clang::tok::getPunctuatorSpelling(ti->getKind())) {
609             macro_expansion.append(punctuator_spelling);
610           } else if (const char *keyword_spelling =
611                          clang::tok::getKeywordSpelling(ti->getKind())) {
612             macro_expansion.append(keyword_spelling);
613           } else {
614             switch (ti->getKind()) {
615             case clang::tok::TokenKind::identifier:
616               macro_expansion.append(ti->getIdentifierInfo()->getName().str());
617               break;
618             case clang::tok::TokenKind::raw_identifier:
619               macro_expansion.append(ti->getRawIdentifier().str());
620               break;
621             default:
622               macro_expansion.append(ti->getName());
623               break;
624             }
625           }
626         }
627 
628         if (handler(macro_identifier, macro_expansion)) {
629           return;
630         }
631       }
632     }
633   }
634 }
635 
636 clang::ModuleLoadResult
637 ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
638                                         bool make_visible) {
639   clang::Module::NameVisibilityKind visibility =
640       make_visible ? clang::Module::AllVisible : clang::Module::Hidden;
641 
642   const bool is_inclusion_directive = false;
643 
644   return m_compiler_instance->loadModule(path.front().second, path, visibility,
645                                          is_inclusion_directive);
646 }
647 
648 static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
649 
650 lldb_private::ClangModulesDeclVendor *
651 ClangModulesDeclVendor::Create(Target &target) {
652   // FIXME we should insure programmatically that the expression parser's
653   // compiler and the modules runtime's
654   // compiler are both initialized in the same way – preferably by the same
655   // code.
656 
657   if (!target.GetPlatform()->SupportsModules())
658     return nullptr;
659 
660   const ArchSpec &arch = target.GetArchitecture();
661 
662   std::vector<std::string> compiler_invocation_arguments = {
663       "clang",
664       "-fmodules",
665       "-fimplicit-module-maps",
666       "-fcxx-modules",
667       "-fsyntax-only",
668       "-femit-all-decls",
669       "-target",
670       arch.GetTriple().str(),
671       "-fmodules-validate-system-headers",
672       "-Werror=non-modular-include-in-framework-module",
673       "-Xclang=-fincremental-extensions",
674       "-Rmodule-build"};
675 
676   target.GetPlatform()->AddClangModuleCompilationOptions(
677       &target, compiler_invocation_arguments);
678 
679   compiler_invocation_arguments.push_back(ModuleImportBufferName);
680 
681   // Add additional search paths with { "-I", path } or { "-F", path } here.
682 
683   {
684     llvm::SmallString<128> path;
685     const auto &props = ModuleList::GetGlobalModuleListProperties();
686     props.GetClangModulesCachePath().GetPath(path);
687     std::string module_cache_argument("-fmodules-cache-path=");
688     module_cache_argument.append(std::string(path.str()));
689     compiler_invocation_arguments.push_back(module_cache_argument);
690   }
691 
692   FileSpecList module_search_paths = target.GetClangModuleSearchPaths();
693 
694   for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) {
695     const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi);
696 
697     std::string search_path_argument = "-I";
698     search_path_argument.append(search_path.GetPath());
699 
700     compiler_invocation_arguments.push_back(search_path_argument);
701   }
702 
703   {
704     FileSpec clang_resource_dir = GetClangResourceDir();
705 
706     if (FileSystem::Instance().IsDirectory(clang_resource_dir.GetPath())) {
707       compiler_invocation_arguments.push_back("-resource-dir");
708       compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
709     }
710   }
711 
712   std::vector<const char *> compiler_invocation_argument_cstrs;
713   compiler_invocation_argument_cstrs.reserve(
714       compiler_invocation_arguments.size());
715   for (const std::string &arg : compiler_invocation_arguments)
716     compiler_invocation_argument_cstrs.push_back(arg.c_str());
717 
718   auto diag_options_up =
719       clang::CreateAndPopulateDiagOpts(compiler_invocation_argument_cstrs);
720   llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine =
721       clang::CompilerInstance::createDiagnostics(diag_options_up.release(),
722                                                  new StoringDiagnosticConsumer);
723 
724   Log *log = GetLog(LLDBLog::Expressions);
725   LLDB_LOG(log, "ClangModulesDeclVendor's compiler flags {0:$[ ]}",
726            llvm::make_range(compiler_invocation_arguments.begin(),
727                             compiler_invocation_arguments.end()));
728 
729   clang::CreateInvocationOptions CIOpts;
730   CIOpts.Diags = diagnostics_engine;
731   std::shared_ptr<clang::CompilerInvocation> invocation =
732       clang::createInvocation(compiler_invocation_argument_cstrs,
733                               std::move(CIOpts));
734 
735   if (!invocation)
736     return nullptr;
737 
738   std::unique_ptr<llvm::MemoryBuffer> source_buffer =
739       llvm::MemoryBuffer::getMemBuffer(
740           "extern int __lldb __attribute__((unavailable));",
741           ModuleImportBufferName);
742 
743   invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName,
744                                                     source_buffer.release());
745 
746   std::unique_ptr<clang::CompilerInstance> instance(
747       new clang::CompilerInstance);
748 
749   // Make sure clang uses the same VFS as LLDB.
750   instance->createFileManager(FileSystem::Instance().GetVirtualFileSystem());
751   instance->setDiagnostics(diagnostics_engine.get());
752   instance->setInvocation(invocation);
753 
754   std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
755 
756   instance->setTarget(clang::TargetInfo::CreateTargetInfo(
757       *diagnostics_engine, instance->getInvocation().TargetOpts));
758 
759   if (!instance->hasTarget())
760     return nullptr;
761 
762   instance->getTarget().adjust(*diagnostics_engine, instance->getLangOpts());
763 
764   if (!action->BeginSourceFile(*instance,
765                                instance->getFrontendOpts().Inputs[0]))
766     return nullptr;
767 
768   instance->createASTReader();
769 
770   instance->createSema(action->getTranslationUnitKind(), nullptr);
771 
772   const bool skipFunctionBodies = false;
773   std::unique_ptr<clang::Parser> parser(new clang::Parser(
774       instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));
775 
776   instance->getPreprocessor().EnterMainSourceFile();
777   parser->Initialize();
778 
779   clang::Parser::DeclGroupPtrTy parsed;
780   auto ImportState = clang::Sema::ModuleImportState::NotACXX20Module;
781   while (!parser->ParseTopLevelDecl(parsed, ImportState))
782     ;
783 
784   return new ClangModulesDeclVendorImpl(std::move(diagnostics_engine),
785                                         std::move(invocation),
786                                         std::move(instance), std::move(parser));
787 }
788