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