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
42using namespace lldb_private;
43
44namespace {
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.
48class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
49public:
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
63private:
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.
79class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
80public:
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;
100private:
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
130StoringDiagnosticConsumer::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
139void 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
150void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); }
151
152void 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
165void StoringDiagnosticConsumer::BeginSourceFile(
166    const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) {
167  m_diag_printer->BeginSourceFile(LangOpts, PP);
168}
169
170void StoringDiagnosticConsumer::EndSourceFile() {
171  m_diag_printer->EndSourceFile();
172}
173
174ClangModulesDeclVendor::ClangModulesDeclVendor()
175    : ClangDeclVendor(eClangModuleDeclVendor) {}
176
177ClangModulesDeclVendor::~ClangModulesDeclVendor() {}
178
179ClangModulesDeclVendorImpl::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
195void 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
212void 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
223bool 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
353bool 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
372bool 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
385uint32_t
386ClangModulesDeclVendorImpl::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
421void 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
586clang::ModuleLoadResult
587ClangModulesDeclVendorImpl::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
598static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
599
600lldb_private::ClangModulesDeclVendor *
601ClangModulesDeclVendor::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