LLDB  mainline
ClangModulesDeclVendor.cpp
Go to the documentation of this file.
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"
25 
27 #include "lldb/Core/ModuleList.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Host/HostInfo.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Utility/FileSpec.h"
35 #include "lldb/Utility/Log.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 
130 StoringDiagnosticConsumer::StoringDiagnosticConsumer() {
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 
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 
150 void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); }
151 
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 
165 void StoringDiagnosticConsumer::BeginSourceFile(
166  const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) {
167  m_diag_printer->BeginSourceFile(LangOpts, PP);
168 }
169 
170 void StoringDiagnosticConsumer::EndSourceFile() {
171  m_diag_printer->EndSourceFile();
172 }
173 
175  : ClangDeclVendor(eClangModuleDeclVendor) {}
176 
178 
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 
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 
212 void ClangModulesDeclVendorImpl::ReportModuleExports(
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 
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 
354  lldb::LanguageType language) {
355  switch (language) {
356  default:
357  return false;
368  return true;
369  }
370 }
371 
372 bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
373  CompileUnit &cu, ClangModulesDeclVendor::ModuleVector &exported_modules,
374  Stream &error_stream) {
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
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 
421 void ClangModulesDeclVendorImpl::ForEachMacro(
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
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 
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 
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 }
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
FileSpec GetClangResourceDir()
Definition: ClangHost.cpp:155
A class that represents a running process on the host machine.
const ArchSpec & GetArchitecture() const
Definition: Target.h:942
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:223
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
#define lldbassert(x)
Definition: LLDBAssert.h:15
std::vector< ConstString > path
Something like "Module.Submodule".
Definition: SourceModule.h:20
A file utility class.
Definition: FileSpec.h:56
An architecture specification class.
Definition: ArchSpec.h:33
lldb::LanguageType GetLanguage()
static ClangModulesDeclVendor * Create(Target &target)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:242
static FileSystem & Instance()
const std::vector< SourceModule > & GetImportedModules()
Get the compile unit&#39;s imported module list.
A class that describes a compilation unit.
Definition: CompileUnit.h:37
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:434
virtual bool AddModule(const SourceModule &module, ModuleVector *exported_modules, Stream &error_stream)=0
Add a module to the list of modules to search.
LanguageType
Programming language type.
static ModuleListProperties & GetGlobalModuleListProperties()
Definition: ModuleList.cpp:713
static llvm::raw_ostream & error(Stream &strm)
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:232
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
static Reproducer & Instance()
Definition: Reproducer.cpp:30
size_t PutChar(char ch)
Definition: Stream.cpp:104
lldb::PlatformSP GetPlatform()
Definition: Target.h:1228
A uniqued constant string class.
Definition: ConstString.h:40
The generator is responsible for the logic needed to generate a reproducer.
Definition: Reproducer.h:225
Non-standardized C, such as K&R.
static const char * ModuleImportBufferName
FileSpecList GetClangModuleSearchPaths()
Definition: Target.cpp:3690
#define LIBLLDB_LOG_EXPRESSIONS
Definition: Logging.h:22
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:348
std::shared_ptr< llvm::FileCollector > GetFileCollector()
Definition: Reproducer.h:98
static bool LanguageSupportsClangModules(lldb::LanguageType language)
Query whether Clang supports modules for a particular language.
Information needed to import a source-language module.
Definition: SourceModule.h:18