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