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"
29#include "ModuleDependencyCollector.h"
30
31#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
32#include "lldb/Core/ModuleList.h"
33#include "lldb/Core/Progress.h"
34#include "lldb/Host/Host.h"
35#include "lldb/Host/HostInfo.h"
36#include "lldb/Symbol/CompileUnit.h"
37#include "lldb/Symbol/SourceModule.h"
38#include "lldb/Target/Target.h"
39#include "lldb/Utility/FileSpec.h"
40#include "lldb/Utility/LLDBAssert.h"
41#include "lldb/Utility/LLDBLog.h"
42#include "lldb/Utility/Log.h"
43#include "lldb/Utility/StreamString.h"
44
45#include <memory>
46#include <mutex>
47
48using namespace lldb_private;
49
50namespace {
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.
54class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
55public:
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
69private:
70  bool HandleModuleRemark(const clang::Diagnostic &info);
71  void SetCurrentModuleProgress(std::string 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.
91class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
92public:
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
114private:
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
144StoringDiagnosticConsumer::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
153void 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
167void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); }
168
169void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) {
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
182void StoringDiagnosticConsumer::BeginSourceFile(
183    const clang::LangOptions &LangOpts, const clang::Preprocessor *PP) {
184  m_diag_printer->BeginSourceFile(LangOpts, PP);
185}
186
187void StoringDiagnosticConsumer::EndSourceFile() {
188  m_current_progress_up = nullptr;
189  m_diag_printer->EndSourceFile();
190}
191
192bool StoringDiagnosticConsumer::HandleModuleRemark(
193    const clang::Diagnostic &info) {
194  Log *log = GetLog(LLDBLog::Expressions);
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      // When the just completed module began building, a module that depends on
212      // it ("module A") was effectively paused. Update the progress to re-show
213      // "module A" as continuing to be built.
214      const auto &resumed_module_name = m_module_build_stack.back();
215      SetCurrentModuleProgress(resumed_module_name);
216    }
217
218    const auto &module_name = info.getArgStdStr(0);
219    LLDB_LOG(log, "Finished building Clang module {0}", module_name);
220    return true;
221  }
222  default:
223    return false;
224  }
225}
226
227void StoringDiagnosticConsumer::SetCurrentModuleProgress(
228    std::string module_name) {
229  if (!m_current_progress_up)
230    m_current_progress_up =
231        std::make_unique<Progress>("Building Clang modules");
232
233  m_current_progress_up->Increment(1, std::move(module_name));
234}
235
236ClangModulesDeclVendor::ClangModulesDeclVendor()
237    : ClangDeclVendor(eClangModuleDeclVendor) {}
238
239ClangModulesDeclVendor::~ClangModulesDeclVendor() = default;
240
241ClangModulesDeclVendorImpl::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
257void 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
272void 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
282bool 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 = HS.getFileMgr().getOptionalDirectoryRef(
333          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
409bool ClangModulesDeclVendor::LanguageSupportsClangModules(
410    lldb::LanguageType language) {
411  switch (language) {
412  default:
413    return false;
414  case lldb::LanguageType::eLanguageTypeC:
415  case lldb::LanguageType::eLanguageTypeC11:
416  case lldb::LanguageType::eLanguageTypeC89:
417  case lldb::LanguageType::eLanguageTypeC99:
418  case lldb::LanguageType::eLanguageTypeC_plus_plus:
419  case lldb::LanguageType::eLanguageTypeC_plus_plus_03:
420  case lldb::LanguageType::eLanguageTypeC_plus_plus_11:
421  case lldb::LanguageType::eLanguageTypeC_plus_plus_14:
422  case lldb::LanguageType::eLanguageTypeObjC:
423  case lldb::LanguageType::eLanguageTypeObjC_plus_plus:
424    return true;
425  }
426}
427
428bool 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
441uint32_t
442ClangModulesDeclVendorImpl::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
476void ClangModulesDeclVendorImpl::ForEachMacro(
477    const ClangModulesDeclVendor::ModuleVector &modules,
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
636clang::ModuleLoadResult
637ClangModulesDeclVendorImpl::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
648static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
649
650lldb_private::ClangModulesDeclVendor *
651ClangModulesDeclVendor::Create(Target &target) {
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
724  Log *log = GetLog(LLDBLog::Expressions);
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));",
741          ModuleImportBufferName);
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}
788