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