//===-- 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/DiagnosticIDs.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/FrontendDiagnostic.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 "ClangDiagnostic.h"
#include "ClangExpressionDeclMap.h"
#include "ClangExpressionHelper.h"
#include "ClangExpressionParser.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/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 <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;
  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 std::pair<IdentifierInfo *, SourceLocation> &component : path)
      module.path.push_back(ConstString(component.first->getName()));

    StreamString error_stream;

    ClangModulesDeclVendor::ModuleVector exported_modules;
    if (!m_decl_vendor.AddModule(module, &exported_modules, m_error_stream))
      m_has_errors = true;

    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_filename(filename) {
    DiagnosticOptions *options = new DiagnosticOptions(opts);
    options->ShowPresumedLoc = true;
    options->ShowLevel = false;
    m_os = std::make_shared<llvm::raw_string_ostream>(m_output);
    m_passthrough =
        std::make_shared<clang::TextDiagnosticPrinter>(*m_os, 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;
  std::shared_ptr<clang::TextDiagnosticPrinter> m_passthrough;
  /// Output stream of m_passthrough.
  std::shared_ptr<llvm::raw_string_ostream> m_os;
  /// Output string filled by m_os.
  std::string m_output;
  StringRef m_filename;
};

/// Returns true if the SDK for the specified triple supports
/// builtin modules in system headers. This is used to decide
/// whether to pass -fbuiltin-headers-in-system-modules to
/// the compiler instance when compiling the `std` module.
static llvm::Expected<bool>
sdkSupportsBuiltinModules(lldb_private::Target &target) {
  auto arch_spec = target.GetArchitecture();
  auto const &triple = arch_spec.GetTriple();
  auto module_sp = target.GetExecutableModule();
  if (!module_sp)
    return llvm::createStringError("Executable module not found.");

  // Get SDK path that the target was compiled against.
  auto platform_sp = target.GetPlatform();
  if (!platform_sp)
    return llvm::createStringError("No Platform plugin found on target.");

  auto sdk_or_err = platform_sp->GetSDKPathFromDebugInfo(*module_sp);
  if (!sdk_or_err)
    return sdk_or_err.takeError();

  // Use the SDK path from debug-info to find a local matching SDK directory.
  auto sdk_path_or_err =
      HostInfo::GetSDKRoot(HostInfo::SDKOptions{std::move(sdk_or_err->first)});
  if (!sdk_path_or_err)
    return sdk_path_or_err.takeError();

  auto VFS = FileSystem::Instance().GetVirtualFileSystem();
  if (!VFS)
    return llvm::createStringError("No virtual filesystem available.");

  // Extract SDK version from the /path/to/some.sdk/SDKSettings.json
  auto parsed_or_err = clang::parseDarwinSDKInfo(*VFS, *sdk_path_or_err);
  if (!parsed_or_err)
    return parsed_or_err.takeError();

  auto maybe_sdk = *parsed_or_err;
  if (!maybe_sdk)
    return llvm::createStringError("Couldn't find Darwin SDK info.");

  return XcodeSDK::SDKSupportsBuiltinModules(triple, maybe_sdk->getVersion());
}

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 {};
    }
  }

  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");
}

static void SetupLangOpts(CompilerInstance &compiler,
                          ExecutionContextScope &exe_scope,
                          const Expression &expr) {
  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();

  // Defaults to lldb::eLanguageTypeUnknown.
  lldb::LanguageType frame_lang = expr.Language().AsLanguageType();

  // Make sure the user hasn't provided a preferred execution language with
  // `expression --language X -- ...`
  if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown)
    frame_lang = frame_sp->GetLanguage().AsLanguageType();

  if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) {
    LLDB_LOGF(log, "Frame has language of type %s",
              lldb_private::Language::GetNameForLanguageType(frame_lang));
  }

  lldb::LanguageType language = expr.Language().AsLanguageType();
  LangOptions &lang_opts = compiler.getLangOpts();

  // FIXME: should this switch on frame_lang?
  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;
    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;

    // 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;
    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;
    break;
  }

  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) {
  Log *log = GetLog(LLDBLog::Expressions);
  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;

  if (auto supported_or_err = sdkSupportsBuiltinModules(target))
    lang_opts.BuiltinHeadersInSystemModules = !*supported_or_err;
  else
    LLDB_LOG_ERROR(log, supported_or_err.takeError(),
                   "Failed to determine BuiltinHeadersInSystemModules when "
                   "setting up import-std-module: {0}");

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

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

ClangExpressionParser::ClangExpressionParser(
    ExecutionContextScope *exe_scope, Expression &expr,
    bool generate_debug_info, std::vector<std::string> include_directories,
    std::string filename)
    : 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->createFileManager(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().TargetOpts)) {
    if (log) {
      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 {
    if (log)
      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);
  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);

  // 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());

  // 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->getFileManager());
  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.reset(CreateLLVMCodeGen(
      m_compiler->getDiagnostics(), module_name,
      &m_compiler->getVirtualFileSystem(), m_compiler->getHeaderSearchOpts(),
      m_compiler->getPreprocessorOpts(), m_compiler->getCodeGenOpts(),
      *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);

    clang::ExternalASTSource *ast_source = decl_map->CreateProxy();

    auto *ast_source_wrapper = new ExternalASTSourceWrapper(ast_source);

    if (ast_context.getExternalSource()) {
      auto *module_wrapper =
          new ExternalASTSourceWrapper(ast_context.getExternalSource());

      auto *multiplexer =
          new 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();

  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();
  }

  adapter->ResetManager();

  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_LOGF(log, "Found function %s for %s", function_name.AsCString(),
                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 != lldb::eLanguageTypeUnknown) {
      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);

  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,
                              function_name.AsCString());

    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());

          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;
}
