//===-- ClangExpressionParser.cpp -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Edit/Commit.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Edit/EditsReceiver.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/TextDiagnostic.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"

#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/TargetParser/Triple.h"

#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
#include "llvm/TargetParser/Host.h"

#include "ClangDiagnostic.h"
#include "ClangExpressionParser.h"
#include "ClangUserExpression.h"

#include "ASTUtils.h"
#include "ClangASTSource.h"
#include "ClangExpressionDeclMap.h"
#include "ClangExpressionHelper.h"
#include "ClangHost.h"
#include "ClangModulesDeclVendor.h"
#include "ClangPersistentVariables.h"
#include "IRDynamicChecks.h"
#include "IRForTarget.h"
#include "ModuleDependencyCollector.h"

#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/File.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"

#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
#include "Plugins/Platform/MacOSX/PlatformDarwin.h"
#include "lldb/Utility/XcodeSDK.h"
#include "lldb/lldb-enumerations.h"

#include <cctype>
#include <memory>
#include <optional>

using namespace clang;
using namespace llvm;
using namespace lldb_private;

//===----------------------------------------------------------------------===//
// Utility Methods for Clang
//===----------------------------------------------------------------------===//

class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks {
  ClangModulesDeclVendor &m_decl_vendor;
  ClangPersistentVariables &m_persistent_vars;
  clang::SourceManager &m_source_mgr;
  /// Accumulates error messages across all moduleImport calls.
  StreamString m_error_stream;
  bool m_has_errors = false;

public:
  LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor,
                            ClangPersistentVariables &persistent_vars,
                            clang::SourceManager &source_mgr)
      : m_decl_vendor(decl_vendor), m_persistent_vars(persistent_vars),
        m_source_mgr(source_mgr) {}

  void moduleImport(SourceLocation import_location, clang::ModuleIdPath path,
                    const clang::Module * /*null*/) override {
    // Ignore modules that are imported in the wrapper code as these are not
    // loaded by the user.
    llvm::StringRef filename =
        m_source_mgr.getPresumedLoc(import_location).getFilename();
    if (filename == ClangExpressionSourceCode::g_prefix_file_name)
      return;

    SourceModule module;

    for (const IdentifierLoc &component : path)
      module.path.push_back(
          ConstString(component.getIdentifierInfo()->getName()));

    ClangModulesDeclVendor::ModuleVector exported_modules;
    if (auto err = m_decl_vendor.AddModule(module, &exported_modules)) {
      m_has_errors = true;
      m_error_stream.PutCString(llvm::toString(std::move(err)));
      m_error_stream.PutChar('\n');
    }

    for (ClangModulesDeclVendor::ModuleID module : exported_modules)
      m_persistent_vars.AddHandLoadedClangModule(module);
  }

  bool hasErrors() { return m_has_errors; }

  llvm::StringRef getErrorString() { return m_error_stream.GetString(); }
};

static void AddAllFixIts(ClangDiagnostic *diag, const clang::Diagnostic &Info) {
  for (auto &fix_it : Info.getFixItHints()) {
    if (fix_it.isNull())
      continue;
    diag->AddFixitHint(fix_it);
  }
}

class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer {
public:
  ClangDiagnosticManagerAdapter(DiagnosticOptions &opts, StringRef filename)
      : m_options(opts), m_filename(filename) {
    m_options.ShowPresumedLoc = true;
    m_options.ShowLevel = false;
    m_os = std::make_unique<llvm::raw_string_ostream>(m_output);
    m_passthrough =
        std::make_unique<clang::TextDiagnosticPrinter>(*m_os, m_options);
  }

  void ResetManager(DiagnosticManager *manager = nullptr) {
    m_manager = manager;
  }

  /// Returns the last error ClangDiagnostic message that the
  /// DiagnosticManager received or a nullptr.
  ClangDiagnostic *MaybeGetLastClangDiag() const {
    if (m_manager->Diagnostics().empty())
      return nullptr;
    auto &diags = m_manager->Diagnostics();
    for (auto it = diags.rbegin(); it != diags.rend(); it++) {
      lldb_private::Diagnostic *diag = it->get();
      if (ClangDiagnostic *clang_diag = dyn_cast<ClangDiagnostic>(diag)) {
        if (clang_diag->GetSeverity() == lldb::eSeverityWarning)
          return nullptr;
        if (clang_diag->GetSeverity() == lldb::eSeverityError)
          return clang_diag;
      }
    }
    return nullptr;
  }

  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                        const clang::Diagnostic &Info) override {
    if (!m_manager) {
      // We have no DiagnosticManager before/after parsing but we still could
      // receive diagnostics (e.g., by the ASTImporter failing to copy decls
      // when we move the expression result ot the ScratchASTContext). Let's at
      // least log these diagnostics until we find a way to properly render
      // them and display them to the user.
      Log *log = GetLog(LLDBLog::Expressions);
      if (log) {
        llvm::SmallVector<char, 32> diag_str;
        Info.FormatDiagnostic(diag_str);
        diag_str.push_back('\0');
        const char *plain_diag = diag_str.data();
        LLDB_LOG(log, "Received diagnostic outside parsing: {0}", plain_diag);
      }
      return;
    }

    // Update error/warning counters.
    DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);

    // Render diagnostic message to m_output.
    m_output.clear();
    m_passthrough->HandleDiagnostic(DiagLevel, Info);

    DiagnosticDetail detail;
    switch (DiagLevel) {
    case DiagnosticsEngine::Level::Fatal:
    case DiagnosticsEngine::Level::Error:
      detail.severity = lldb::eSeverityError;
      break;
    case DiagnosticsEngine::Level::Warning:
      detail.severity = lldb::eSeverityWarning;
      break;
    case DiagnosticsEngine::Level::Remark:
    case DiagnosticsEngine::Level::Ignored:
      detail.severity = lldb::eSeverityInfo;
      break;
    case DiagnosticsEngine::Level::Note:
      // 'note:' diagnostics for errors and warnings can also contain Fix-Its.
      // We add these Fix-Its to the last error diagnostic to make sure
      // that we later have all Fix-Its related to an 'error' diagnostic when
      // we apply them to the user expression.
      auto *clang_diag = MaybeGetLastClangDiag();
      // If we don't have a previous diagnostic there is nothing to do.
      // If the previous diagnostic already has its own Fix-Its, assume that
      // the 'note:' Fix-It is just an alternative way to solve the issue and
      // ignore these Fix-Its.
      if (!clang_diag || clang_diag->HasFixIts())
        break;
      // Ignore all Fix-Its that are not associated with an error.
      if (clang_diag->GetSeverity() != lldb::eSeverityError)
        break;
      AddAllFixIts(clang_diag, Info);
      break;
    }
      // ClangDiagnostic messages are expected to have no whitespace/newlines
      // around them.
      std::string stripped_output =
          std::string(llvm::StringRef(m_output).trim());

      // Translate the source location.
      if (Info.hasSourceManager()) {
        DiagnosticDetail::SourceLocation loc;
        clang::SourceManager &sm = Info.getSourceManager();
        const clang::SourceLocation sloc = Info.getLocation();
        if (sloc.isValid()) {
          const clang::FullSourceLoc fsloc(sloc, sm);
          clang::PresumedLoc PLoc = fsloc.getPresumedLoc(true);
          StringRef filename =
              PLoc.isValid() ? PLoc.getFilename() : StringRef{};
          loc.file = FileSpec(filename);
          loc.line = fsloc.getSpellingLineNumber();
          loc.column = fsloc.getSpellingColumnNumber();
          loc.in_user_input = filename == m_filename;
          loc.hidden = filename.starts_with("<lldb wrapper ");

          // Find the range of the primary location.
          for (const auto &range : Info.getRanges()) {
            if (range.getBegin() == sloc) {
              // FIXME: This is probably not handling wide characters correctly.
              unsigned end_col = sm.getSpellingColumnNumber(range.getEnd());
              if (end_col > loc.column)
                loc.length = end_col - loc.column;
              break;
            }
          }
          detail.source_location = loc;
        }
      }
      llvm::SmallString<0> msg;
      Info.FormatDiagnostic(msg);
      detail.message = msg.str();
      detail.rendered = stripped_output;
      auto new_diagnostic =
          std::make_unique<ClangDiagnostic>(detail, Info.getID());

      // Don't store away warning fixits, since the compiler doesn't have
      // enough context in an expression for the warning to be useful.
      // FIXME: Should we try to filter out FixIts that apply to our generated
      // code, and not the user's expression?
      if (detail.severity == lldb::eSeverityError)
        AddAllFixIts(new_diagnostic.get(), Info);

      m_manager->AddDiagnostic(std::move(new_diagnostic));
  }

  void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override {
    m_passthrough->BeginSourceFile(LO, PP);
  }

  void EndSourceFile() override { m_passthrough->EndSourceFile(); }

private:
  DiagnosticManager *m_manager = nullptr;
  DiagnosticOptions m_options;
  /// Output string filled by m_os.
  std::string m_output;
  /// Output stream of m_passthrough.
  std::unique_ptr<llvm::raw_string_ostream> m_os;
  std::unique_ptr<clang::TextDiagnosticPrinter> m_passthrough;
  StringRef m_filename;
};

static void SetupModuleHeaderPaths(CompilerInstance *compiler,
                                   std::vector<std::string> include_directories,
                                   lldb::TargetSP target_sp) {
  Log *log = GetLog(LLDBLog::Expressions);

  HeaderSearchOptions &search_opts = compiler->getHeaderSearchOpts();

  for (const std::string &dir : include_directories) {
    search_opts.AddPath(dir, frontend::System, false, true);
    LLDB_LOG(log, "Added user include dir: {0}", dir);
  }

  llvm::SmallString<128> module_cache;
  const auto &props = ModuleList::GetGlobalModuleListProperties();
  props.GetClangModulesCachePath().GetPath(module_cache);
  search_opts.ModuleCachePath = std::string(module_cache.str());
  LLDB_LOG(log, "Using module cache path: {0}", module_cache.c_str());

  search_opts.ResourceDir = GetClangResourceDir().GetPath();

  search_opts.ImplicitModuleMaps = true;
}

/// Iff the given identifier is a C++ keyword, remove it from the
/// identifier table (i.e., make the token a normal identifier).
static void RemoveCppKeyword(IdentifierTable &idents, llvm::StringRef token) {
  // FIXME: 'using' is used by LLDB for local variables, so we can't remove
  // this keyword without breaking this functionality.
  if (token == "using")
    return;
  // GCC's '__null' is used by LLDB to define NULL/Nil/nil.
  if (token == "__null")
    return;

  LangOptions cpp_lang_opts;
  cpp_lang_opts.CPlusPlus = true;
  cpp_lang_opts.CPlusPlus11 = true;
  cpp_lang_opts.CPlusPlus20 = true;

  clang::IdentifierInfo &ii = idents.get(token);
  // The identifier has to be a C++-exclusive keyword. if not, then there is
  // nothing to do.
  if (!ii.isCPlusPlusKeyword(cpp_lang_opts))
    return;
  // If the token is already an identifier, then there is nothing to do.
  if (ii.getTokenID() == clang::tok::identifier)
    return;
  // Otherwise the token is a C++ keyword, so turn it back into a normal
  // identifier.
  ii.revertTokenIDToIdentifier();
}

/// Remove all C++ keywords from the given identifier table.
static void RemoveAllCppKeywords(IdentifierTable &idents) {
#define KEYWORD(NAME, FLAGS) RemoveCppKeyword(idents, llvm::StringRef(#NAME));
#include "clang/Basic/TokenKinds.def"
}

/// Configures Clang diagnostics for the expression parser.
static void SetupDefaultClangDiagnostics(CompilerInstance &compiler) {
  // List of Clang warning groups that are not useful when parsing expressions.
  const std::vector<const char *> groupsToIgnore = {
      "unused-value",
      "odr",
      "unused-getter-return-value",
  };
  for (const char *group : groupsToIgnore) {
    compiler.getDiagnostics().setSeverityForGroup(
        clang::diag::Flavor::WarningOrError, group,
        clang::diag::Severity::Ignored, SourceLocation());
  }
}

/// Returns a string representing current ABI.
///
/// \param[in] target_arch
///     The target architecture.
///
/// \return
///     A string representing target ABI for the current architecture.
static std::string GetClangTargetABI(const ArchSpec &target_arch) {
  if (target_arch.IsMIPS()) {
    switch (target_arch.GetFlags() & ArchSpec::eMIPSABI_mask) {
    case ArchSpec::eMIPSABI_N64:
      return "n64";
    case ArchSpec::eMIPSABI_N32:
      return "n32";
    case ArchSpec::eMIPSABI_O32:
      return "o32";
    default:
      return {};
    }
  }

  if (target_arch.GetTriple().isRISCV64()) {
    switch (target_arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask) {
    case ArchSpec::eRISCV_float_abi_soft:
      return "lp64";
    case ArchSpec::eRISCV_float_abi_single:
      return "lp64f";
    case ArchSpec::eRISCV_float_abi_double:
      return "lp64d";
    case ArchSpec::eRISCV_float_abi_quad:
      return "lp64q";
    default:
      return {};
    }
  }

  if (target_arch.GetTriple().isRISCV32()) {
    switch (target_arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask) {
    case ArchSpec::eRISCV_float_abi_soft:
      return "ilp32";
    case ArchSpec::eRISCV_float_abi_single:
      return "ilp32f";
    case ArchSpec::eRISCV_float_abi_double:
      return "ilp32d";
    case ArchSpec::eRISCV_float_abi_soft | ArchSpec::eRISCV_rve:
      return "ilp32e";
    default:
      return {};
    }
  }

  if (target_arch.GetTriple().isLoongArch64()) {
    switch (target_arch.GetFlags() & ArchSpec::eLoongArch_abi_mask) {
    case ArchSpec::eLoongArch_abi_soft_float:
      return "lp64s";
    case ArchSpec::eLoongArch_abi_single_float:
      return "lp64f";
    case ArchSpec::eLoongArch_abi_double_float:
      return "lp64d";
    default:
      return {};
    }
  }

  return {};
}

static void SetupTargetOpts(CompilerInstance &compiler,
                            lldb_private::Target const &target) {
  Log *log = GetLog(LLDBLog::Expressions);
  ArchSpec target_arch = target.GetArchitecture();

  const auto target_machine = target_arch.GetMachine();
  if (target_arch.IsValid()) {
    std::string triple = target_arch.GetTriple().str();
    compiler.getTargetOpts().Triple = triple;
    LLDB_LOGF(log, "Using %s as the target triple",
              compiler.getTargetOpts().Triple.c_str());
  } else {
    // If we get here we don't have a valid target and just have to guess.
    // Sometimes this will be ok to just use the host target triple (when we
    // evaluate say "2+3", but other expressions like breakpoint conditions and
    // other things that _are_ target specific really shouldn't just be using
    // the host triple. In such a case the language runtime should expose an
    // overridden options set (3), below.
    compiler.getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
    LLDB_LOGF(log, "Using default target triple of %s",
              compiler.getTargetOpts().Triple.c_str());
  }
  // Now add some special fixes for known architectures: Any arm32 iOS
  // environment, but not on arm64
  if (compiler.getTargetOpts().Triple.find("arm64") == std::string::npos &&
      compiler.getTargetOpts().Triple.find("arm") != std::string::npos &&
      compiler.getTargetOpts().Triple.find("ios") != std::string::npos) {
    compiler.getTargetOpts().ABI = "apcs-gnu";
  }
  // Supported subsets of x86
  if (target_machine == llvm::Triple::x86 ||
      target_machine == llvm::Triple::x86_64) {
    compiler.getTargetOpts().FeaturesAsWritten.push_back("+sse");
    compiler.getTargetOpts().FeaturesAsWritten.push_back("+sse2");
  }

  // Set the target CPU to generate code for. This will be empty for any CPU
  // that doesn't really need to make a special
  // CPU string.
  compiler.getTargetOpts().CPU = target_arch.GetClangTargetCPU();

  // Set the target ABI
  if (std::string abi = GetClangTargetABI(target_arch); !abi.empty())
    compiler.getTargetOpts().ABI = std::move(abi);

  if ((target_machine == llvm::Triple::riscv64 &&
       compiler.getTargetOpts().ABI == "lp64f") ||
      (target_machine == llvm::Triple::riscv32 &&
       compiler.getTargetOpts().ABI == "ilp32f"))
    compiler.getTargetOpts().FeaturesAsWritten.emplace_back("+f");

  if ((target_machine == llvm::Triple::riscv64 &&
       compiler.getTargetOpts().ABI == "lp64d") ||
      (target_machine == llvm::Triple::riscv32 &&
       compiler.getTargetOpts().ABI == "ilp32d"))
    compiler.getTargetOpts().FeaturesAsWritten.emplace_back("+d");

  if ((target_machine == llvm::Triple::loongarch64 &&
       compiler.getTargetOpts().ABI == "lp64f"))
    compiler.getTargetOpts().FeaturesAsWritten.emplace_back("+f");

  if ((target_machine == llvm::Triple::loongarch64 &&
       compiler.getTargetOpts().ABI == "lp64d"))
    compiler.getTargetOpts().FeaturesAsWritten.emplace_back("+d");
}

static void SetupLangOpts(CompilerInstance &compiler,
                          ExecutionContextScope &exe_scope,
                          const Expression &expr,
                          DiagnosticManager &diagnostic_manager) {
  Log *log = GetLog(LLDBLog::Expressions);

  // If the expression is being evaluated in the context of an existing stack
  // frame, we introspect to see if the language runtime is available.

  lldb::StackFrameSP frame_sp = exe_scope.CalculateStackFrame();
  lldb::ProcessSP process_sp = exe_scope.CalculateProcess();

  lldb::LanguageType language = expr.Language().AsLanguageType();

  if (process_sp)
    LLDB_LOG(
        log,
        "Frame has language of type {0}\nPicked {1} for expression evaluation.",
        lldb_private::Language::GetNameForLanguageType(
            frame_sp ? frame_sp->GetLanguage().AsLanguageType()
                     : lldb::eLanguageTypeUnknown),
        lldb_private::Language::GetNameForLanguageType(language));

  lldb::LanguageType language_for_note = language;
  std::string language_fallback_reason;

  LangOptions &lang_opts = compiler.getLangOpts();

  switch (language) {
  case lldb::eLanguageTypeC:
  case lldb::eLanguageTypeC89:
  case lldb::eLanguageTypeC99:
  case lldb::eLanguageTypeC11:
    // FIXME: the following language option is a temporary workaround,
    // to "ask for C, get C++."
    // For now, the expression parser must use C++ anytime the language is a C
    // family language, because the expression parser uses features of C++ to
    // capture values.
    lang_opts.CPlusPlus = true;

    language_for_note = lldb::eLanguageTypeC_plus_plus;
    language_fallback_reason =
        "Expression evaluation in pure C not supported. ";
    break;
  case lldb::eLanguageTypeObjC:
    lang_opts.ObjC = true;
    // FIXME: the following language option is a temporary workaround,
    // to "ask for ObjC, get ObjC++" (see comment above).
    lang_opts.CPlusPlus = true;

    language_for_note = lldb::eLanguageTypeObjC_plus_plus;
    language_fallback_reason =
        "Expression evaluation in pure Objective-C not supported. ";

    // Clang now sets as default C++14 as the default standard (with
    // GNU extensions), so we do the same here to avoid mismatches that
    // cause compiler error when evaluating expressions (e.g. nullptr not found
    // as it's a C++11 feature). Currently lldb evaluates C++14 as C++11 (see
    // two lines below) so we decide to be consistent with that, but this could
    // be re-evaluated in the future.
    lang_opts.CPlusPlus11 = true;
    break;
  case lldb::eLanguageTypeC_plus_plus_20:
    lang_opts.CPlusPlus20 = true;
    [[fallthrough]];
  case lldb::eLanguageTypeC_plus_plus_17:
    // FIXME: add a separate case for CPlusPlus14. Currently folded into C++17
    // because C++14 is the default standard for Clang but enabling CPlusPlus14
    // expression evaluatino doesn't pass the test-suite cleanly.
    lang_opts.CPlusPlus14 = true;
    lang_opts.CPlusPlus17 = true;
    [[fallthrough]];
  case lldb::eLanguageTypeC_plus_plus:
  case lldb::eLanguageTypeC_plus_plus_11:
  case lldb::eLanguageTypeC_plus_plus_14:
    lang_opts.CPlusPlus11 = true;
    compiler.getHeaderSearchOpts().UseLibcxx = true;
    [[fallthrough]];
  case lldb::eLanguageTypeC_plus_plus_03: {
    lang_opts.CPlusPlus = true;
    if (process_sp
        // We're stopped in a frame without debug-info. The user probably
        // intends to make global queries (which should include Objective-C).
        && !(frame_sp && frame_sp->HasDebugInformation())) {
      lang_opts.ObjC =
          process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC) != nullptr;
      if (lang_opts.ObjC) {
        language_for_note = lldb::eLanguageTypeObjC_plus_plus;
        language_fallback_reason = "Possibly stopped inside system library, so "
                                   "speculatively enabled Objective-C. ";
      }
    }
  } break;
  case lldb::eLanguageTypeObjC_plus_plus:
  case lldb::eLanguageTypeUnknown:
  default:
    lang_opts.ObjC = true;
    lang_opts.CPlusPlus = true;
    lang_opts.CPlusPlus11 = true;
    compiler.getHeaderSearchOpts().UseLibcxx = true;

    language_for_note = lldb::eLanguageTypeObjC_plus_plus;
    if (language != language_for_note) {
      if (language != lldb::eLanguageTypeUnknown)
        language_fallback_reason = llvm::formatv(
            "Expression evaluation in {0} not supported. ",
            lldb_private::Language::GetDisplayNameForLanguageType(language));

      language_fallback_reason +=
          llvm::formatv("Falling back to default language. ");
    }
    break;
  }

  diagnostic_manager.AddDiagnostic(
      llvm::formatv("{0}Ran expression as '{1}'.", language_fallback_reason,
                    lldb_private::Language::GetDisplayNameForLanguageType(
                        language_for_note))
          .str(),
      lldb::Severity::eSeverityInfo, DiagnosticOrigin::eDiagnosticOriginLLDB);

  lang_opts.Bool = true;
  lang_opts.WChar = true;
  lang_opts.Blocks = true;
  lang_opts.DebuggerSupport =
      true; // Features specifically for debugger clients
  if (expr.DesiredResultType() == Expression::eResultTypeId)
    lang_opts.DebuggerCastResultToId = true;

  lang_opts.CharIsSigned =
      ArchSpec(compiler.getTargetOpts().Triple.c_str()).CharIsSignedByDefault();

  // Spell checking is a nice feature, but it ends up completing a lot of types
  // that we didn't strictly speaking need to complete. As a result, we spend a
  // long time parsing and importing debug information.
  lang_opts.SpellChecking = false;

  if (process_sp && lang_opts.ObjC) {
    if (auto *runtime = ObjCLanguageRuntime::Get(*process_sp)) {
      switch (runtime->GetRuntimeVersion()) {
      case ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2:
        lang_opts.ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
        break;
      case ObjCLanguageRuntime::ObjCRuntimeVersions::eObjC_VersionUnknown:
      case ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V1:
        lang_opts.ObjCRuntime.set(ObjCRuntime::FragileMacOSX,
                                  VersionTuple(10, 7));
        break;
      case ObjCLanguageRuntime::ObjCRuntimeVersions::eGNUstep_libobjc2:
        lang_opts.ObjCRuntime.set(ObjCRuntime::GNUstep, VersionTuple(2, 0));
        break;
      }

      if (runtime->HasNewLiteralsAndIndexing())
        lang_opts.DebuggerObjCLiteral = true;
    }
  }

  lang_opts.ThreadsafeStatics = false;
  lang_opts.AccessControl = false; // Debuggers get universal access
  lang_opts.DollarIdents = true;   // $ indicates a persistent variable name
  // We enable all builtin functions beside the builtins from libc/libm (e.g.
  // 'fopen'). Those libc functions are already correctly handled by LLDB, and
  // additionally enabling them as expandable builtins is breaking Clang.
  lang_opts.NoBuiltin = true;
}

static void SetupImportStdModuleLangOpts(CompilerInstance &compiler,
                                         lldb_private::Target &target) {
  LangOptions &lang_opts = compiler.getLangOpts();
  lang_opts.Modules = true;
  // We want to implicitly build modules.
  lang_opts.ImplicitModules = true;
  // To automatically import all submodules when we import 'std'.
  lang_opts.ModulesLocalVisibility = false;

  // We use the @import statements, so we need this:
  // FIXME: We could use the modules-ts, but that currently doesn't work.
  lang_opts.ObjC = true;

  // Options we need to parse libc++ code successfully.
  // FIXME: We should ask the driver for the appropriate default flags.
  lang_opts.GNUMode = true;
  lang_opts.GNUKeywords = true;
  lang_opts.CPlusPlus11 = true;

  lang_opts.BuiltinHeadersInSystemModules = false;

  // The Darwin libc expects this macro to be set.
  lang_opts.GNUCVersion = 40201;
}

//===----------------------------------------------------------------------===//
// Implementation of ClangExpressionParser
//===----------------------------------------------------------------------===//

static void SetPointerAuthOptionsForArm64e(LangOptions &lang_opts) {
  lang_opts.PointerAuthIntrinsics = true;
  lang_opts.PointerAuthCalls = true;
  lang_opts.PointerAuthReturns = true;
  lang_opts.PointerAuthAuthTraps = true;
  lang_opts.PointerAuthIndirectGotos = true;
  lang_opts.PointerAuthVTPtrAddressDiscrimination = true;
  lang_opts.PointerAuthVTPtrTypeDiscrimination = true;
  lang_opts.PointerAuthObjcIsa = true;
  lang_opts.PointerAuthObjcClassROPointers = true;
  lang_opts.PointerAuthObjcInterfaceSel = true;
}

ClangExpressionParser::ClangExpressionParser(
    ExecutionContextScope *exe_scope, Expression &expr,
    bool generate_debug_info, DiagnosticManager &diagnostic_manager,
    std::vector<std::string> include_directories, std::string filename,
    bool force_disable_ptrauth_codegen)
    : ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(),
      m_pp_callbacks(nullptr),
      m_include_directories(std::move(include_directories)),
      m_filename(std::move(filename)) {
  Log *log = GetLog(LLDBLog::Expressions);

  // We can't compile expressions without a target.  So if the exe_scope is
  // null or doesn't have a target, then we just need to get out of here.  I'll
  // lldbassert and not make any of the compiler objects since
  // I can't return errors directly from the constructor.  Further calls will
  // check if the compiler was made and
  // bag out if it wasn't.

  if (!exe_scope) {
    lldbassert(exe_scope &&
               "Can't make an expression parser with a null scope.");
    return;
  }

  lldb::TargetSP target_sp;
  target_sp = exe_scope->CalculateTarget();
  if (!target_sp) {
    lldbassert(target_sp.get() &&
               "Can't make an expression parser with a null target.");
    return;
  }

  // 1. Create a new compiler instance.
  m_compiler = std::make_unique<CompilerInstance>();

  // Make sure clang uses the same VFS as LLDB.
  m_compiler->setVirtualFileSystem(
      FileSystem::Instance().GetVirtualFileSystem());

  // 2. Configure the compiler with a set of default options that are
  // appropriate for most situations.
  SetupTargetOpts(*m_compiler, *target_sp);

  // 3. Create and install the target on the compiler.
  m_compiler->createDiagnostics();
  // Limit the number of error diagnostics we emit.
  // A value of 0 means no limit for both LLDB and Clang.
  m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());

  if (auto *target_info = TargetInfo::CreateTargetInfo(
          m_compiler->getDiagnostics(),
          m_compiler->getInvocation().getTargetOpts())) {
    LLDB_LOGF(log, "Target datalayout string: '%s'",
              target_info->getDataLayoutString());
    LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str());
    LLDB_LOGF(log, "Target vector alignment: %d",
              target_info->getMaxVectorAlign());
    m_compiler->setTarget(target_info);
  } else {
    LLDB_LOGF(log, "Failed to create TargetInfo for '%s'",
              m_compiler->getTargetOpts().Triple.c_str());

    lldbassert(false && "Failed to create TargetInfo.");
  }

  // 4. Set language options.
  SetupLangOpts(*m_compiler, *exe_scope, expr, diagnostic_manager);

  const llvm::Triple triple = target_sp->GetArchitecture().GetTriple();
  const bool enable_ptrauth =
      triple.isArm64e() && !force_disable_ptrauth_codegen;
  if (enable_ptrauth)
    SetPointerAuthOptionsForArm64e(m_compiler->getLangOpts());

  auto *clang_expr = dyn_cast<ClangUserExpression>(&m_expr);
  if (clang_expr && clang_expr->DidImportCxxModules()) {
    LLDB_LOG(log, "Adding lang options for importing C++ modules");
    SetupImportStdModuleLangOpts(*m_compiler, *target_sp);
    SetupModuleHeaderPaths(m_compiler.get(), m_include_directories, target_sp);
  }

  // Set CodeGen options
  m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
  m_compiler->getCodeGenOpts().InstrumentFunctions = false;
  m_compiler->getCodeGenOpts().setFramePointer(
      CodeGenOptions::FramePointerKind::All);
  if (generate_debug_info)
    m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
  else
    m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo);

  if (enable_ptrauth) {
    PointerAuthOptions &ptrauth_opts = m_compiler->getCodeGenOpts().PointerAuth;
    clang::CompilerInvocation::setDefaultPointerAuthOptions(
        ptrauth_opts, m_compiler->getLangOpts(), triple);
  }

  // Disable some warnings.
  SetupDefaultClangDiagnostics(*m_compiler);

  // Inform the target of the language options
  //
  // FIXME: We shouldn't need to do this, the target should be immutable once
  // created. This complexity should be lifted elsewhere.
  m_compiler->getTarget().adjust(m_compiler->getDiagnostics(),
                                 m_compiler->getLangOpts(),
                                 /*AuxTarget=*/nullptr);

  // 5. Set up the diagnostic buffer for reporting errors
  auto diag_mgr = new ClangDiagnosticManagerAdapter(
      m_compiler->getDiagnostics().getDiagnosticOptions(),
      clang_expr ? clang_expr->GetFilename() : StringRef());
  m_compiler->getDiagnostics().setClient(diag_mgr);

  // 6. Set up the source management objects inside the compiler
  m_compiler->createFileManager();
  if (!m_compiler->hasSourceManager())
    m_compiler->createSourceManager();
  m_compiler->createPreprocessor(TU_Complete);

  switch (expr.Language().AsLanguageType()) {
  case lldb::eLanguageTypeC:
  case lldb::eLanguageTypeC89:
  case lldb::eLanguageTypeC99:
  case lldb::eLanguageTypeC11:
  case lldb::eLanguageTypeObjC:
    // This is not a C++ expression but we enabled C++ as explained above.
    // Remove all C++ keywords from the PP so that the user can still use
    // variables that have C++ keywords as names (e.g. 'int template;').
    RemoveAllCppKeywords(m_compiler->getPreprocessor().getIdentifierTable());
    break;
  default:
    break;
  }

  if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
          target_sp->GetPersistentExpressionStateForLanguage(
              lldb::eLanguageTypeC))) {
    if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
            clang_persistent_vars->GetClangModulesDeclVendor()) {
      std::unique_ptr<PPCallbacks> pp_callbacks(
          new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars,
                                        m_compiler->getSourceManager()));
      m_pp_callbacks =
          static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get());
      m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
    }
  }

  // 7. Most of this we get from the CompilerInstance, but we also want to give
  // the context an ExternalASTSource.

  auto &PP = m_compiler->getPreprocessor();
  auto &builtin_context = PP.getBuiltinInfo();
  builtin_context.initializeBuiltins(PP.getIdentifierTable(),
                                     m_compiler->getLangOpts());

  m_compiler->createASTContext();
  clang::ASTContext &ast_context = m_compiler->getASTContext();

  m_ast_context = std::make_shared<TypeSystemClang>(
      "Expression ASTContext for '" + m_filename + "'", ast_context);

  std::string module_name("$__lldb_module");

  m_llvm_context = std::make_unique<LLVMContext>();
  m_code_generator =
      CreateLLVMCodeGen(*m_compiler, module_name, *m_llvm_context);
}

ClangExpressionParser::~ClangExpressionParser() = default;

namespace {

/// \class CodeComplete
///
/// A code completion consumer for the clang Sema that is responsible for
/// creating the completion suggestions when a user requests completion
/// of an incomplete `expr` invocation.
class CodeComplete : public CodeCompleteConsumer {
  CodeCompletionTUInfo m_info;

  std::string m_expr;
  unsigned m_position = 0;
  /// The printing policy we use when printing declarations for our completion
  /// descriptions.
  clang::PrintingPolicy m_desc_policy;

  struct CompletionWithPriority {
    CompletionResult::Completion completion;
    /// See CodeCompletionResult::Priority;
    unsigned Priority;

    /// Establishes a deterministic order in a list of CompletionWithPriority.
    /// The order returned here is the order in which the completions are
    /// displayed to the user.
    bool operator<(const CompletionWithPriority &o) const {
      // High priority results should come first.
      if (Priority != o.Priority)
        return Priority > o.Priority;

      // Identical priority, so just make sure it's a deterministic order.
      return completion.GetUniqueKey() < o.completion.GetUniqueKey();
    }
  };

  /// The stored completions.
  /// Warning: These are in a non-deterministic order until they are sorted
  /// and returned back to the caller.
  std::vector<CompletionWithPriority> m_completions;

  /// Returns true if the given character can be used in an identifier.
  /// This also returns true for numbers because for completion we usually
  /// just iterate backwards over iterators.
  ///
  /// Note: lldb uses '$' in its internal identifiers, so we also allow this.
  static bool IsIdChar(char c) {
    return c == '_' || std::isalnum(c) || c == '$';
  }

  /// Returns true if the given character is used to separate arguments
  /// in the command line of lldb.
  static bool IsTokenSeparator(char c) { return c == ' ' || c == '\t'; }

  /// Drops all tokens in front of the expression that are unrelated for
  /// the completion of the cmd line. 'unrelated' means here that the token
  /// is not interested for the lldb completion API result.
  StringRef dropUnrelatedFrontTokens(StringRef cmd) const {
    if (cmd.empty())
      return cmd;

    // If we are at the start of a word, then all tokens are unrelated to
    // the current completion logic.
    if (IsTokenSeparator(cmd.back()))
      return StringRef();

    // Remove all previous tokens from the string as they are unrelated
    // to completing the current token.
    StringRef to_remove = cmd;
    while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
      to_remove = to_remove.drop_back();
    }
    cmd = cmd.drop_front(to_remove.size());

    return cmd;
  }

  /// Removes the last identifier token from the given cmd line.
  StringRef removeLastToken(StringRef cmd) const {
    while (!cmd.empty() && IsIdChar(cmd.back())) {
      cmd = cmd.drop_back();
    }
    return cmd;
  }

  /// Attempts to merge the given completion from the given position into the
  /// existing command. Returns the completion string that can be returned to
  /// the lldb completion API.
  std::string mergeCompletion(StringRef existing, unsigned pos,
                              StringRef completion) const {
    StringRef existing_command = existing.substr(0, pos);
    // We rewrite the last token with the completion, so let's drop that
    // token from the command.
    existing_command = removeLastToken(existing_command);
    // We also should remove all previous tokens from the command as they
    // would otherwise be added to the completion that already has the
    // completion.
    existing_command = dropUnrelatedFrontTokens(existing_command);
    return existing_command.str() + completion.str();
  }

public:
  /// Constructs a CodeComplete consumer that can be attached to a Sema.
  ///
  /// \param[out] expr
  ///    The whole expression string that we are currently parsing. This
  ///    string needs to be equal to the input the user typed, and NOT the
  ///    final code that Clang is parsing.
  /// \param[out] position
  ///    The character position of the user cursor in the `expr` parameter.
  ///
  CodeComplete(clang::LangOptions ops, std::string expr, unsigned position)
      : CodeCompleteConsumer(CodeCompleteOptions()),
        m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
        m_position(position), m_desc_policy(ops) {

    // Ensure that the printing policy is producing a description that is as
    // short as possible.
    m_desc_policy.SuppressScope = true;
    m_desc_policy.SuppressTagKeyword = true;
    m_desc_policy.FullyQualifiedName = false;
    m_desc_policy.TerseOutput = true;
    m_desc_policy.IncludeNewlines = false;
    m_desc_policy.UseVoidForZeroParams = false;
    m_desc_policy.Bool = true;
  }

  /// \name Code-completion filtering
  /// Check if the result should be filtered out.
  bool isResultFilteredOut(StringRef Filter,
                           CodeCompletionResult Result) override {
    // This code is mostly copied from CodeCompleteConsumer.
    switch (Result.Kind) {
    case CodeCompletionResult::RK_Declaration:
      return !(
          Result.Declaration->getIdentifier() &&
          Result.Declaration->getIdentifier()->getName().starts_with(Filter));
    case CodeCompletionResult::RK_Keyword:
      return !StringRef(Result.Keyword).starts_with(Filter);
    case CodeCompletionResult::RK_Macro:
      return !Result.Macro->getName().starts_with(Filter);
    case CodeCompletionResult::RK_Pattern:
      return !StringRef(Result.Pattern->getAsString()).starts_with(Filter);
    }
    // If we trigger this assert or the above switch yields a warning, then
    // CodeCompletionResult has been enhanced with more kinds of completion
    // results. Expand the switch above in this case.
    assert(false && "Unknown completion result type?");
    // If we reach this, then we should just ignore whatever kind of unknown
    // result we got back. We probably can't turn it into any kind of useful
    // completion suggestion with the existing code.
    return true;
  }

private:
  /// Generate the completion strings for the given CodeCompletionResult.
  /// Note that this function has to process results that could come in
  /// non-deterministic order, so this function should have no side effects.
  /// To make this easier to enforce, this function and all its parameters
  /// should always be const-qualified.
  /// \return Returns std::nullopt if no completion should be provided for the
  ///         given CodeCompletionResult.
  std::optional<CompletionWithPriority>
  getCompletionForResult(const CodeCompletionResult &R) const {
    std::string ToInsert;
    std::string Description;
    // Handle the different completion kinds that come from the Sema.
    switch (R.Kind) {
    case CodeCompletionResult::RK_Declaration: {
      const NamedDecl *D = R.Declaration;
      ToInsert = R.Declaration->getNameAsString();
      // If we have a function decl that has no arguments we want to
      // complete the empty parantheses for the user. If the function has
      // arguments, we at least complete the opening bracket.
      if (const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
        if (F->getNumParams() == 0)
          ToInsert += "()";
        else
          ToInsert += "(";
        raw_string_ostream OS(Description);
        F->print(OS, m_desc_policy, false);
      } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
        Description = V->getType().getAsString(m_desc_policy);
      } else if (const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
        Description = F->getType().getAsString(m_desc_policy);
      } else if (const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
        // If we try to complete a namespace, then we can directly append
        // the '::'.
        if (!N->isAnonymousNamespace())
          ToInsert += "::";
      }
      break;
    }
    case CodeCompletionResult::RK_Keyword:
      ToInsert = R.Keyword;
      break;
    case CodeCompletionResult::RK_Macro:
      ToInsert = R.Macro->getName().str();
      break;
    case CodeCompletionResult::RK_Pattern:
      ToInsert = R.Pattern->getTypedText();
      break;
    }
    // We also filter some internal lldb identifiers here. The user
    // shouldn't see these.
    if (llvm::StringRef(ToInsert).starts_with("$__lldb_"))
      return std::nullopt;
    if (ToInsert.empty())
      return std::nullopt;
    // Merge the suggested Token into the existing command line to comply
    // with the kind of result the lldb API expects.
    std::string CompletionSuggestion =
        mergeCompletion(m_expr, m_position, ToInsert);

    CompletionResult::Completion completion(CompletionSuggestion, Description,
                                            CompletionMode::Normal);
    return {{completion, R.Priority}};
  }

public:
  /// Adds the completions to the given CompletionRequest.
  void GetCompletions(CompletionRequest &request) {
    // Bring m_completions into a deterministic order and pass it on to the
    // CompletionRequest.
    llvm::sort(m_completions);

    for (const CompletionWithPriority &C : m_completions)
      request.AddCompletion(C.completion.GetCompletion(),
                            C.completion.GetDescription(),
                            C.completion.GetMode());
  }

  /// \name Code-completion callbacks
  /// Process the finalized code-completion results.
  void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
                                  CodeCompletionResult *Results,
                                  unsigned NumResults) override {

    // The Sema put the incomplete token we try to complete in here during
    // lexing, so we need to retrieve it here to know what we are completing.
    StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();

    // Iterate over all the results. Filter out results we don't want and
    // process the rest.
    for (unsigned I = 0; I != NumResults; ++I) {
      // Filter the results with the information from the Sema.
      if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
        continue;

      CodeCompletionResult &R = Results[I];
      std::optional<CompletionWithPriority> CompletionAndPriority =
          getCompletionForResult(R);
      if (!CompletionAndPriority)
        continue;
      m_completions.push_back(*CompletionAndPriority);
    }
  }

  /// \param S the semantic-analyzer object for which code-completion is being
  /// done.
  ///
  /// \param CurrentArg the index of the current argument.
  ///
  /// \param Candidates an array of overload candidates.
  ///
  /// \param NumCandidates the number of overload candidates
  void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                 OverloadCandidate *Candidates,
                                 unsigned NumCandidates,
                                 SourceLocation OpenParLoc,
                                 bool Braced) override {
    // At the moment we don't filter out any overloaded candidates.
  }

  CodeCompletionAllocator &getAllocator() override {
    return m_info.getAllocator();
  }

  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return m_info; }
};
} // namespace

bool ClangExpressionParser::Complete(CompletionRequest &request, unsigned line,
                                     unsigned pos, unsigned typed_pos) {
  DiagnosticManager mgr;
  // We need the raw user expression here because that's what the CodeComplete
  // class uses to provide completion suggestions.
  // However, the `Text` method only gives us the transformed expression here.
  // To actually get the raw user input here, we have to cast our expression to
  // the LLVMUserExpression which exposes the right API. This should never fail
  // as we always have a ClangUserExpression whenever we call this.
  ClangUserExpression *llvm_expr = cast<ClangUserExpression>(&m_expr);
  CodeComplete CC(m_compiler->getLangOpts(), llvm_expr->GetUserText(),
                  typed_pos);
  // We don't need a code generator for parsing.
  m_code_generator.reset();
  // Start parsing the expression with our custom code completion consumer.
  ParseInternal(mgr, &CC, line, pos);
  CC.GetCompletions(request);
  return true;
}

unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) {
  return ParseInternal(diagnostic_manager);
}

unsigned
ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
                                     CodeCompleteConsumer *completion_consumer,
                                     unsigned completion_line,
                                     unsigned completion_column) {
  ClangDiagnosticManagerAdapter *adapter =
      static_cast<ClangDiagnosticManagerAdapter *>(
          m_compiler->getDiagnostics().getClient());

  adapter->ResetManager(&diagnostic_manager);

  const char *expr_text = m_expr.Text();

  clang::SourceManager &source_mgr = m_compiler->getSourceManager();
  bool created_main_file = false;

  // Clang wants to do completion on a real file known by Clang's file manager,
  // so we have to create one to make this work.
  // TODO: We probably could also simulate to Clang's file manager that there
  // is a real file that contains our code.
  bool should_create_file = completion_consumer != nullptr;

  // We also want a real file on disk if we generate full debug info.
  should_create_file |= m_compiler->getCodeGenOpts().getDebugInfo() ==
                        codegenoptions::FullDebugInfo;

  if (should_create_file) {
    int temp_fd = -1;
    llvm::SmallString<128> result_path;
    if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
      tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
      std::string temp_source_path = tmpdir_file_spec.GetPath();
      llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
    } else {
      llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
    }

    if (temp_fd != -1) {
      lldb_private::NativeFile file(temp_fd, File::eOpenOptionWriteOnly, true);
      const size_t expr_text_len = strlen(expr_text);
      size_t bytes_written = expr_text_len;
      if (file.Write(expr_text, bytes_written).Success()) {
        if (bytes_written == expr_text_len) {
          file.Close();
          if (auto fileEntry = m_compiler->getFileManager().getOptionalFileRef(
                  result_path)) {
            source_mgr.setMainFileID(source_mgr.createFileID(
                *fileEntry, SourceLocation(), SrcMgr::C_User));
            created_main_file = true;
          }
        }
      }
    }
  }

  if (!created_main_file) {
    std::unique_ptr<MemoryBuffer> memory_buffer =
        MemoryBuffer::getMemBufferCopy(expr_text, m_filename);
    source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer)));
  }

  adapter->BeginSourceFile(m_compiler->getLangOpts(),
                           &m_compiler->getPreprocessor());

  ClangExpressionHelper *type_system_helper =
      dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());

  // If we want to parse for code completion, we need to attach our code
  // completion consumer to the Sema and specify a completion position.
  // While parsing the Sema will call this consumer with the provided
  // completion suggestions.
  if (completion_consumer) {
    auto main_file =
        source_mgr.getFileEntryRefForID(source_mgr.getMainFileID());
    auto &PP = m_compiler->getPreprocessor();
    // Lines and columns start at 1 in Clang, but code completion positions are
    // indexed from 0, so we need to add 1 to the line and column here.
    ++completion_line;
    ++completion_column;
    PP.SetCodeCompletionPoint(*main_file, completion_line, completion_column);
  }

  ASTConsumer *ast_transformer =
      type_system_helper->ASTTransformer(m_code_generator.get());

  std::unique_ptr<clang::ASTConsumer> Consumer;
  if (ast_transformer) {
    Consumer = std::make_unique<ASTConsumerForwarder>(ast_transformer);
  } else if (m_code_generator) {
    Consumer = std::make_unique<ASTConsumerForwarder>(m_code_generator.get());
  } else {
    Consumer = std::make_unique<ASTConsumer>();
  }

  clang::ASTContext &ast_context = m_compiler->getASTContext();

  m_compiler->setSema(new Sema(m_compiler->getPreprocessor(), ast_context,
                               *Consumer, TU_Complete, completion_consumer));
  m_compiler->setASTConsumer(std::move(Consumer));

  if (ast_context.getLangOpts().Modules) {
    m_compiler->createASTReader();
    m_ast_context->setSema(&m_compiler->getSema());
  }

  ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap();
  if (decl_map) {
    decl_map->InstallCodeGenerator(&m_compiler->getASTConsumer());
    decl_map->InstallDiagnosticManager(diagnostic_manager);

    llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source =
        decl_map->CreateProxy();

    auto ast_source_wrapper =
        llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(ast_source);

    if (ast_context.getExternalSource()) {
      auto module_wrapper = llvm::makeIntrusiveRefCnt<ExternalASTSourceWrapper>(
          ast_context.getExternalSourcePtr());

      auto multiplexer = llvm::makeIntrusiveRefCnt<SemaSourceWithPriorities>(
          module_wrapper, ast_source_wrapper);

      ast_context.setExternalSource(multiplexer);
    } else {
      ast_context.setExternalSource(ast_source);
    }
    m_compiler->getSema().addExternalSource(ast_source_wrapper);
    decl_map->InstallASTContext(*m_ast_context);
  }

  // Check that the ASTReader is properly attached to ASTContext and Sema.
  if (ast_context.getLangOpts().Modules) {
    assert(m_compiler->getASTContext().getExternalSource() &&
           "ASTContext doesn't know about the ASTReader?");
    assert(m_compiler->getSema().getExternalSource() &&
           "Sema doesn't know about the ASTReader?");
  }

  {
    llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(
        &m_compiler->getSema());
    ParseAST(m_compiler->getSema(), false, false);
  }

  // Make sure we have no pointer to the Sema we are about to destroy.
  if (ast_context.getLangOpts().Modules)
    m_ast_context->setSema(nullptr);
  // Destroy the Sema. This is necessary because we want to emulate the
  // original behavior of ParseAST (which also destroys the Sema after parsing).
  m_compiler->setSema(nullptr);

  adapter->EndSourceFile();
  // Creating persistent variables can trigger diagnostic emission.
  // Make sure we reset the manager so we don't get asked to handle
  // diagnostics after we finished parsing.
  adapter->ResetManager();

  unsigned num_errors = adapter->getNumErrors();

  if (m_pp_callbacks && m_pp_callbacks->hasErrors()) {
    num_errors++;
    diagnostic_manager.PutString(lldb::eSeverityError,
                                 "while importing modules:");
    diagnostic_manager.AppendMessageToDiagnostic(
        m_pp_callbacks->getErrorString());
  }

  if (!num_errors) {
    type_system_helper->CommitPersistentDecls();
  }

  return num_errors;
}

/// Applies the given Fix-It hint to the given commit.
static void ApplyFixIt(const FixItHint &fixit, clang::edit::Commit &commit) {
  // This is cobbed from clang::Rewrite::FixItRewriter.
  if (fixit.CodeToInsert.empty()) {
    if (fixit.InsertFromRange.isValid()) {
      commit.insertFromRange(fixit.RemoveRange.getBegin(),
                             fixit.InsertFromRange, /*afterToken=*/false,
                             fixit.BeforePreviousInsertions);
      return;
    }
    commit.remove(fixit.RemoveRange);
    return;
  }
  if (fixit.RemoveRange.isTokenRange() ||
      fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) {
    commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
    return;
  }
  commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
                /*afterToken=*/false, fixit.BeforePreviousInsertions);
}

bool ClangExpressionParser::RewriteExpression(
    DiagnosticManager &diagnostic_manager) {
  clang::SourceManager &source_manager = m_compiler->getSourceManager();
  clang::edit::EditedSource editor(source_manager, m_compiler->getLangOpts(),
                                   nullptr);
  clang::edit::Commit commit(editor);
  clang::Rewriter rewriter(source_manager, m_compiler->getLangOpts());

  class RewritesReceiver : public edit::EditsReceiver {
    Rewriter &rewrite;

  public:
    RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) {}

    void insert(SourceLocation loc, StringRef text) override {
      rewrite.InsertText(loc, text);
    }
    void replace(CharSourceRange range, StringRef text) override {
      rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
    }
  };

  RewritesReceiver rewrites_receiver(rewriter);

  const DiagnosticList &diagnostics = diagnostic_manager.Diagnostics();
  size_t num_diags = diagnostics.size();
  if (num_diags == 0)
    return false;

  for (const auto &diag : diagnostic_manager.Diagnostics()) {
    const auto *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag.get());
    if (!diagnostic)
      continue;
    if (!diagnostic->HasFixIts())
      continue;
    for (const FixItHint &fixit : diagnostic->FixIts())
      ApplyFixIt(fixit, commit);
  }

  // FIXME - do we want to try to propagate specific errors here?
  if (!commit.isCommitable())
    return false;
  else if (!editor.commit(commit))
    return false;

  // Now play all the edits, and stash the result in the diagnostic manager.
  editor.applyRewrites(rewrites_receiver);
  RewriteBuffer &main_file_buffer =
      rewriter.getEditBuffer(source_manager.getMainFileID());

  std::string fixed_expression;
  llvm::raw_string_ostream out_stream(fixed_expression);

  main_file_buffer.write(out_stream);
  diagnostic_manager.SetFixedExpression(fixed_expression);

  return true;
}

static bool FindFunctionInModule(ConstString &mangled_name,
                                 llvm::Module *module, const char *orig_name) {
  for (const auto &func : module->getFunctionList()) {
    const StringRef &name = func.getName();
    if (name.contains(orig_name)) {
      mangled_name.SetString(name);
      return true;
    }
  }

  return false;
}

lldb_private::Status ClangExpressionParser::DoPrepareForExecution(
    lldb::addr_t &func_addr, lldb::addr_t &func_end,
    lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx,
    bool &can_interpret, ExecutionPolicy execution_policy) {
  func_addr = LLDB_INVALID_ADDRESS;
  func_end = LLDB_INVALID_ADDRESS;
  Log *log = GetLog(LLDBLog::Expressions);

  lldb_private::Status err;

  std::unique_ptr<llvm::Module> llvm_module_up(
      m_code_generator->ReleaseModule());

  if (!llvm_module_up) {
    err = Status::FromErrorString("IR doesn't contain a module");
    return err;
  }

  ConstString function_name;

  if (execution_policy != eExecutionPolicyTopLevel) {
    // Find the actual name of the function (it's often mangled somehow)

    if (!FindFunctionInModule(function_name, llvm_module_up.get(),
                              m_expr.FunctionName())) {
      err = Status::FromErrorStringWithFormat(
          "Couldn't find %s() in the module", m_expr.FunctionName());
      return err;
    } else {
      LLDB_LOG(log, "Found function {0} for {1}", function_name,
               m_expr.FunctionName());
    }
  }

  SymbolContext sc;

  if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP()) {
    sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything);
  } else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) {
    sc.target_sp = target_sp;
  }

  LLVMUserExpression::IRPasses custom_passes;
  {
    auto lang = m_expr.Language();
    LLDB_LOGF(log, "%s - Current expression language is %s\n", __FUNCTION__,
              lang.GetDescription().data());
    lldb::ProcessSP process_sp = exe_ctx.GetProcessSP();
    if (process_sp && lang) {
      auto runtime = process_sp->GetLanguageRuntime(lang.AsLanguageType());
      if (runtime)
        runtime->GetIRPasses(custom_passes);
    }
  }

  if (custom_passes.EarlyPasses) {
    LLDB_LOGF(log,
              "%s - Running Early IR Passes from LanguageRuntime on "
              "expression module '%s'",
              __FUNCTION__, m_expr.FunctionName());

    custom_passes.EarlyPasses->run(*llvm_module_up);
  }

  execution_unit_sp = std::make_shared<IRExecutionUnit>(
      m_llvm_context, // handed off here
      llvm_module_up, // handed off here
      function_name, exe_ctx.GetTargetSP(), sc,
      m_compiler->getTargetOpts().Features);

  if (auto *options = m_expr.GetOptions())
    execution_unit_sp->AppendPreferredSymbolContexts(
        options->GetPreferredSymbolContexts());

  ClangExpressionHelper *type_system_helper =
      dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
  ClangExpressionDeclMap *decl_map =
      type_system_helper->DeclMap(); // result can be NULL

  if (decl_map) {
    StreamString error_stream;
    IRForTarget ir_for_target(
        decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp,
        error_stream, execution_policy, function_name.AsCString(nullptr));

    if (!ir_for_target.runOnModule(*execution_unit_sp->GetModule())) {
      err = Status(error_stream.GetString().str());
      return err;
    }

    Process *process = exe_ctx.GetProcessPtr();

    if (execution_policy != eExecutionPolicyAlways &&
        execution_policy != eExecutionPolicyTopLevel) {
      lldb_private::Status interpret_error;

      bool interpret_function_calls =
          !process ? false : process->CanInterpretFunctionCalls();
      can_interpret = IRInterpreter::CanInterpret(
          *execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(),
          interpret_error, interpret_function_calls);

      if (!can_interpret && execution_policy == eExecutionPolicyNever) {
        err = Status::FromErrorStringWithFormat(
            "Can't evaluate the expression without a running target due to: %s",
            interpret_error.AsCString());
        return err;
      }
    }

    if (!process && execution_policy == eExecutionPolicyAlways) {
      err = Status::FromErrorString(
          "Expression needed to run in the target, but the "
          "target can't be run");
      return err;
    }

    if (!process && execution_policy == eExecutionPolicyTopLevel) {
      err = Status::FromErrorString(
          "Top-level code needs to be inserted into a runnable "
          "target, but the target can't be run");
      return err;
    }

    if (execution_policy == eExecutionPolicyAlways ||
        (execution_policy != eExecutionPolicyTopLevel && !can_interpret)) {
      if (m_expr.NeedsValidation() && process) {
        if (!process->GetDynamicCheckers()) {
          ClangDynamicCheckerFunctions *dynamic_checkers =
              new ClangDynamicCheckerFunctions();

          DiagnosticManager install_diags;
          if (Error Err = dynamic_checkers->Install(install_diags, exe_ctx))
            return Status::FromError(install_diags.GetAsError(
                lldb::eExpressionSetupError, "couldn't install checkers:"));

          process->SetDynamicCheckers(dynamic_checkers);

          LLDB_LOGF(log, "== [ClangExpressionParser::PrepareForExecution] "
                         "Finished installing dynamic checkers ==");
        }

        if (auto *checker_funcs = llvm::dyn_cast<ClangDynamicCheckerFunctions>(
                process->GetDynamicCheckers())) {
          IRDynamicChecks ir_dynamic_checks(*checker_funcs,
                                            function_name.AsCString(nullptr));

          llvm::Module *module = execution_unit_sp->GetModule();
          if (!module || !ir_dynamic_checks.runOnModule(*module)) {
            err = Status::FromErrorString(
                "Couldn't add dynamic checks to the expression");
            return err;
          }

          if (custom_passes.LatePasses) {
            LLDB_LOGF(log,
                      "%s - Running Late IR Passes from LanguageRuntime on "
                      "expression module '%s'",
                      __FUNCTION__, m_expr.FunctionName());

            custom_passes.LatePasses->run(*module);
          }
        }
      }
    }

    if (execution_policy == eExecutionPolicyAlways ||
        execution_policy == eExecutionPolicyTopLevel || !can_interpret) {
      execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
    }
  } else {
    execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
  }

  return err;
}
