//===-- ClangExpressionDeclMap.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 "ClangExpressionDeclMap.h"

#include "ClangASTSource.h"
#include "ClangExpressionUtil.h"
#include "ClangExpressionVariable.h"
#include "ClangModulesDeclVendor.h"
#include "ClangPersistentVariables.h"
#include "ClangUtil.h"

#include "NameSearchContext.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"
#include "lldb/ValueObject/ValueObjectVariable.h"
#include "lldb/lldb-private-types.h"
#include "lldb/lldb-private.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTImporter.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/RecursiveASTVisitor.h"

#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"

using namespace lldb;
using namespace lldb_private;
using namespace clang;

static const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars";

namespace {
/// A lambda is represented by Clang as an artifical class whose
/// members are the lambda captures. If we capture a 'this' pointer,
/// the artifical class will contain a member variable named 'this'.
/// The function returns a ValueObject for the captured 'this' if such
/// member exists. If no 'this' was captured, return a nullptr.
lldb::ValueObjectSP GetCapturedThisValueObject(StackFrame *frame) {
  assert(frame);

  if (auto thisValSP = frame->FindVariable(ConstString("this"))) {
    if (auto thisThisValSP = thisValSP->GetChildMemberWithName("this"))
      return thisThisValSP;
    // With CodeView/PDB, the member is named "__this".
    if (auto codeview_this_sp = thisValSP->GetChildMemberWithName("__this"))
      return codeview_this_sp;
  }

  return nullptr;
}
} // namespace

ClangExpressionDeclMap::ClangExpressionDeclMap(
    bool keep_result_in_memory,
    Materializer::PersistentVariableDelegate *result_delegate,
    const lldb::TargetSP &target,
    const std::shared_ptr<ClangASTImporter> &importer, ValueObject *ctx_obj,
    bool ignore_context_qualifiers)
    : ClangASTSource(target, importer), m_found_entities(), m_struct_members(),
      m_keep_result_in_memory(keep_result_in_memory),
      m_result_delegate(result_delegate), m_ctx_obj(ctx_obj),
      m_ignore_context_qualifiers(ignore_context_qualifiers), m_parser_vars(),
      m_struct_vars() {
  EnableStructVars();
}

ClangExpressionDeclMap::~ClangExpressionDeclMap() {
  // Note: The model is now that the parser's AST context and all associated
  //   data does not vanish until the expression has been executed.  This means
  //   that valuable lookup data (like namespaces) doesn't vanish, but

  DidParse();
  DisableStructVars();
}

bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
                                       Materializer *materializer) {
  EnableParserVars();
  m_parser_vars->m_exe_ctx = exe_ctx;

  Target *target = exe_ctx.GetTargetPtr();
  if (exe_ctx.GetFramePtr())
    m_parser_vars->m_sym_ctx =
        exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything);
  else if (exe_ctx.GetThreadPtr() &&
           exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0))
    m_parser_vars->m_sym_ctx =
        exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext(
            lldb::eSymbolContextEverything);
  else if (exe_ctx.GetProcessPtr()) {
    m_parser_vars->m_sym_ctx.Clear(true);
    m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP();
  } else if (target) {
    m_parser_vars->m_sym_ctx.Clear(true);
    m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP();
  }

  if (target) {
    m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>(
        target->GetPersistentExpressionStateForLanguage(eLanguageTypeC));

    if (!ScratchTypeSystemClang::GetForTarget(*target))
      return false;
  }

  m_parser_vars->m_target_info = GetTargetInfo();
  m_parser_vars->m_materializer = materializer;

  return true;
}

void ClangExpressionDeclMap::InstallCodeGenerator(
    clang::ASTConsumer *code_gen) {
  assert(m_parser_vars);
  m_parser_vars->m_code_gen = code_gen;
}

void ClangExpressionDeclMap::InstallDiagnosticManager(
    DiagnosticManager &diag_manager) {
  assert(m_parser_vars);
  m_parser_vars->m_diagnostics = &diag_manager;
}

void ClangExpressionDeclMap::DidParse() {
  if (m_parser_vars && m_parser_vars->m_persistent_vars) {
    for (size_t entity_index = 0, num_entities = m_found_entities.GetSize();
         entity_index < num_entities; ++entity_index) {
      ExpressionVariableSP var_sp(
          m_found_entities.GetVariableAtIndex(entity_index));
      if (var_sp)
        llvm::cast<ClangExpressionVariable>(var_sp.get())
            ->DisableParserVars(GetParserID());
    }

    for (size_t pvar_index = 0,
                num_pvars = m_parser_vars->m_persistent_vars->GetSize();
         pvar_index < num_pvars; ++pvar_index) {
      ExpressionVariableSP pvar_sp(
          m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index));
      if (ClangExpressionVariable *clang_var =
              llvm::dyn_cast<ClangExpressionVariable>(pvar_sp.get()))
        clang_var->DisableParserVars(GetParserID());
    }

    DisableParserVars();
  }
}

// Interface for IRForTarget

ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() {
  assert(m_parser_vars.get());

  TargetInfo ret;

  ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;

  Process *process = exe_ctx.GetProcessPtr();
  if (process) {
    ret.byte_order = process->GetByteOrder();
    ret.address_byte_size = process->GetAddressByteSize();
  } else {
    Target *target = exe_ctx.GetTargetPtr();
    if (target) {
      ret.byte_order = target->GetArchitecture().GetByteOrder();
      ret.address_byte_size = target->GetArchitecture().GetAddressByteSize();
    }
  }

  return ret;
}

TypeFromUser ClangExpressionDeclMap::DeportType(TypeSystemClang &target,
                                                TypeSystemClang &source,
                                                TypeFromParser parser_type) {
  assert(&target == GetScratchContext(*m_target).get());
  assert((TypeSystem *)&source ==
         parser_type.GetTypeSystem().GetSharedPointer().get());
  assert(&source.getASTContext() == m_ast_context);

  return TypeFromUser(m_ast_importer_sp->DeportType(target, parser_type));
}

bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
                                                   ConstString name,
                                                   TypeFromParser parser_type,
                                                   bool is_result,
                                                   bool is_lvalue) {
  assert(m_parser_vars.get());
  auto ast = parser_type.GetTypeSystem<TypeSystemClang>();
  if (ast == nullptr)
    return false;

  // Check if we already declared a persistent variable with the same name.
  if (lldb::ExpressionVariableSP conflicting_var =
          m_parser_vars->m_persistent_vars->GetVariable(name)) {
    std::string msg = llvm::formatv("redefinition of persistent variable '{0}'",
                                    name).str();
    m_parser_vars->m_diagnostics->AddDiagnostic(
        msg, lldb::eSeverityError, DiagnosticOrigin::eDiagnosticOriginLLDB);
    return false;
  }

  if (m_parser_vars->m_materializer && is_result) {
    Status err;

    ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
    Target *target = exe_ctx.GetTargetPtr();
    if (target == nullptr)
      return false;

    auto clang_ast_context = GetScratchContext(*target);
    if (!clang_ast_context)
      return false;

    TypeFromUser user_type = DeportType(*clang_ast_context, *ast, parser_type);

    uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(
        user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err);

    ClangExpressionVariable *var = new ClangExpressionVariable(
        exe_ctx.GetBestExecutionContextScope(), name, user_type,
        m_parser_vars->m_target_info.byte_order,
        m_parser_vars->m_target_info.address_byte_size);

    m_found_entities.AddNewlyConstructedVariable(var);

    var->EnableParserVars(GetParserID());

    ClangExpressionVariable::ParserVars *parser_vars =
        var->GetParserVars(GetParserID());

    parser_vars->m_named_decl = decl;

    var->EnableJITVars(GetParserID());

    ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(GetParserID());

    jit_vars->m_offset = offset;

    return true;
  }

  Log *log = GetLog(LLDBLog::Expressions);
  ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
  Target *target = exe_ctx.GetTargetPtr();
  if (target == nullptr)
    return false;

  auto context = GetScratchContext(*target);
  if (!context)
    return false;

  TypeFromUser user_type = DeportType(*context, *ast, parser_type);

  if (!user_type.GetOpaqueQualType()) {
    LLDB_LOG(log, "Persistent variable's type wasn't copied successfully");
    return false;
  }

  if (!m_parser_vars->m_target_info.IsValid())
    return false;

  if (!m_parser_vars->m_persistent_vars)
    return false;

  ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>(
      m_parser_vars->m_persistent_vars
          ->CreatePersistentVariable(
              exe_ctx.GetBestExecutionContextScope(), name, user_type,
              m_parser_vars->m_target_info.byte_order,
              m_parser_vars->m_target_info.address_byte_size)
          .get());

  if (!var)
    return false;

  var->m_frozen_sp->SetHasCompleteType();

  if (is_result)
    var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
  else
    var->m_flags |=
        ClangExpressionVariable::EVKeepInTarget; // explicitly-declared
                                                 // persistent variables should
                                                 // persist

  if (is_lvalue) {
    var->m_flags |= ClangExpressionVariable::EVIsProgramReference;
  } else {
    var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
    var->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
  }

  if (m_keep_result_in_memory) {
    var->m_flags |= ClangExpressionVariable::EVKeepInTarget;
  }

  LLDB_LOG(log, "Created persistent variable with flags {0:x}", var->m_flags);

  var->EnableParserVars(GetParserID());

  ClangExpressionVariable::ParserVars *parser_vars =
      var->GetParserVars(GetParserID());

  parser_vars->m_named_decl = decl;

  return true;
}

bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl,
                                              ConstString name,
                                              llvm::Value *value, size_t size,
                                              lldb::offset_t alignment) {
  assert(m_struct_vars.get());
  assert(m_parser_vars.get());

  bool is_persistent_variable = false;

  Log *log = GetLog(LLDBLog::Expressions);

  m_struct_vars->m_struct_laid_out = false;

  if (ClangExpressionVariable::FindVariableInList(m_struct_members, decl,
                                                  GetParserID()))
    return true;

  ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(
      m_found_entities, decl, GetParserID()));

  if (!var && m_parser_vars->m_persistent_vars) {
    var = ClangExpressionVariable::FindVariableInList(
        *m_parser_vars->m_persistent_vars, decl, GetParserID());
    is_persistent_variable = true;
  }

  if (!var)
    return false;

  LLDB_LOG(log, "Adding value for (NamedDecl*){0} [{1} - {2}] to the structure",
           decl, name, var->GetName());

  // We know entity->m_parser_vars is valid because we used a parser variable
  // to find it

  ClangExpressionVariable::ParserVars *parser_vars =
      llvm::cast<ClangExpressionVariable>(var)->GetParserVars(GetParserID());

  parser_vars->m_llvm_value = value;

  if (ClangExpressionVariable::JITVars *jit_vars =
          llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID())) {
    // We already laid this out; do not touch

    LLDB_LOG(log, "Already placed at {0:x}", jit_vars->m_offset);
  }

  llvm::cast<ClangExpressionVariable>(var)->EnableJITVars(GetParserID());

  ClangExpressionVariable::JITVars *jit_vars =
      llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID());

  jit_vars->m_alignment = alignment;
  jit_vars->m_size = size;

  m_struct_members.AddVariable(var->shared_from_this());

  if (m_parser_vars->m_materializer) {
    uint32_t offset = 0;

    Status err;

    if (is_persistent_variable) {
      ExpressionVariableSP var_sp(var->shared_from_this());
      offset = m_parser_vars->m_materializer->AddPersistentVariable(
          var_sp, nullptr, err);
    } else {
      if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym)
        offset = m_parser_vars->m_materializer->AddSymbol(*sym, err);
      else if (const RegisterInfo *reg_info = var->GetRegisterInfo())
        offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err);
      else if (parser_vars->m_lldb_var)
        offset = m_parser_vars->m_materializer->AddVariable(
            parser_vars->m_lldb_var, err);
      else if (parser_vars->m_lldb_valobj_provider) {
        offset = m_parser_vars->m_materializer->AddValueObject(
            name, parser_vars->m_lldb_valobj_provider, err);
      }
    }

    if (!err.Success())
      return false;

    LLDB_LOG(log, "Placed at {0:x}", offset);

    jit_vars->m_offset =
        offset; // TODO DoStructLayout() should not change this.
  }

  return true;
}

bool ClangExpressionDeclMap::DoStructLayout() {
  assert(m_struct_vars.get());

  if (m_struct_vars->m_struct_laid_out)
    return true;

  if (!m_parser_vars->m_materializer)
    return false;

  m_struct_vars->m_struct_alignment =
      m_parser_vars->m_materializer->GetStructAlignment();
  m_struct_vars->m_struct_size =
      m_parser_vars->m_materializer->GetStructByteSize();
  m_struct_vars->m_struct_laid_out = true;
  return true;
}

bool ClangExpressionDeclMap::GetStructInfo(uint32_t &num_elements, size_t &size,
                                           lldb::offset_t &alignment) {
  assert(m_struct_vars.get());

  if (!m_struct_vars->m_struct_laid_out)
    return false;

  num_elements = m_struct_members.GetSize();
  size = m_struct_vars->m_struct_size;
  alignment = m_struct_vars->m_struct_alignment;

  return true;
}

bool ClangExpressionDeclMap::GetStructElement(const NamedDecl *&decl,
                                              llvm::Value *&value,
                                              lldb::offset_t &offset,
                                              ConstString &name,
                                              uint32_t index) {
  assert(m_struct_vars.get());

  if (!m_struct_vars->m_struct_laid_out)
    return false;

  if (index >= m_struct_members.GetSize())
    return false;

  ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index));

  if (!member_sp)
    return false;

  ClangExpressionVariable::ParserVars *parser_vars =
      llvm::cast<ClangExpressionVariable>(member_sp.get())
          ->GetParserVars(GetParserID());
  ClangExpressionVariable::JITVars *jit_vars =
      llvm::cast<ClangExpressionVariable>(member_sp.get())
          ->GetJITVars(GetParserID());

  if (!parser_vars || !jit_vars || !member_sp->GetValueObject())
    return false;

  decl = parser_vars->m_named_decl;
  value = parser_vars->m_llvm_value;
  offset = jit_vars->m_offset;
  name = member_sp->GetName();

  return true;
}

bool ClangExpressionDeclMap::GetFunctionInfo(const NamedDecl *decl,
                                             uint64_t &ptr) {
  ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList(
      m_found_entities, decl, GetParserID()));

  if (!entity)
    return false;

  // We know m_parser_vars is valid since we searched for the variable by its
  // NamedDecl

  ClangExpressionVariable::ParserVars *parser_vars =
      entity->GetParserVars(GetParserID());

  ptr = parser_vars->m_lldb_value.GetScalar().ULongLong();

  return true;
}

addr_t ClangExpressionDeclMap::GetSymbolAddress(Target &target,
                                                Process *process,
                                                ConstString name,
                                                lldb::SymbolType symbol_type,
                                                lldb_private::Module *module) {
  SymbolContextList sc_list;

  if (module)
    module->FindSymbolsWithNameAndType(name, symbol_type, sc_list);
  else
    target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list);

  addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;

  for (const SymbolContext &sym_ctx : sc_list) {
    if (symbol_load_addr != 0 && symbol_load_addr != LLDB_INVALID_ADDRESS)
      break;

    const Address sym_address = sym_ctx.symbol->GetAddress();

    if (!sym_address.IsValid())
      continue;

    switch (sym_ctx.symbol->GetType()) {
    case eSymbolTypeCode:
    case eSymbolTypeTrampoline:
      symbol_load_addr = sym_address.GetCallableLoadAddress(&target);
      break;

    case eSymbolTypeResolver:
      symbol_load_addr = sym_address.GetCallableLoadAddress(&target, true);
      break;

    case eSymbolTypeReExported: {
      ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName();
      if (reexport_name) {
        ModuleSP reexport_module_sp;
        ModuleSpec reexport_module_spec;
        reexport_module_spec.GetPlatformFileSpec() =
            sym_ctx.symbol->GetReExportedSymbolSharedLibrary();
        if (reexport_module_spec.GetPlatformFileSpec()) {
          reexport_module_sp =
              target.GetImages().FindFirstModule(reexport_module_spec);
          if (!reexport_module_sp) {
            reexport_module_spec.GetPlatformFileSpec().ClearDirectory();
            reexport_module_sp =
                target.GetImages().FindFirstModule(reexport_module_spec);
          }
        }
        symbol_load_addr = GetSymbolAddress(
            target, process, sym_ctx.symbol->GetReExportedSymbolName(),
            symbol_type, reexport_module_sp.get());
      }
    } break;

    case eSymbolTypeData:
    case eSymbolTypeRuntime:
    case eSymbolTypeVariable:
    case eSymbolTypeLocal:
    case eSymbolTypeParam:
    case eSymbolTypeInvalid:
    case eSymbolTypeAbsolute:
    case eSymbolTypeException:
    case eSymbolTypeSourceFile:
    case eSymbolTypeHeaderFile:
    case eSymbolTypeObjectFile:
    case eSymbolTypeCommonBlock:
    case eSymbolTypeBlock:
    case eSymbolTypeVariableType:
    case eSymbolTypeLineEntry:
    case eSymbolTypeLineHeader:
    case eSymbolTypeScopeBegin:
    case eSymbolTypeScopeEnd:
    case eSymbolTypeAdditional:
    case eSymbolTypeCompiler:
    case eSymbolTypeInstrumentation:
    case eSymbolTypeUndefined:
    case eSymbolTypeObjCClass:
    case eSymbolTypeObjCMetaClass:
    case eSymbolTypeObjCIVar:
      symbol_load_addr = sym_address.GetLoadAddress(&target);
      break;
    }
  }

  if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) {
    ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process);

    if (runtime) {
      symbol_load_addr = runtime->LookupRuntimeSymbol(name);
    }
  }

  return symbol_load_addr;
}

addr_t ClangExpressionDeclMap::GetSymbolAddress(ConstString name,
                                                lldb::SymbolType symbol_type) {
  assert(m_parser_vars.get());

  if (!m_parser_vars->m_exe_ctx.GetTargetPtr())
    return LLDB_INVALID_ADDRESS;

  return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(),
                          m_parser_vars->m_exe_ctx.GetProcessPtr(), name,
                          symbol_type);
}

lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
    Target &target, ModuleSP &module, ConstString name,
    const CompilerDeclContext &namespace_decl) {
  VariableList vars;

  if (module && namespace_decl)
    module->FindGlobalVariables(name, namespace_decl, -1, vars);
  else
    target.GetImages().FindGlobalVariables(name, -1, vars);

  if (vars.GetSize() == 0)
    return VariableSP();
  return vars.GetVariableAtIndex(0);
}

TypeSystemClang *ClangExpressionDeclMap::GetTypeSystemClang() {
  StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
  if (frame == nullptr)
    return nullptr;

  SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
                                                  lldb::eSymbolContextBlock);
  if (sym_ctx.block == nullptr)
    return nullptr;

  CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext();
  if (!frame_decl_context)
    return nullptr;

  return llvm::dyn_cast_or_null<TypeSystemClang>(
      frame_decl_context.GetTypeSystem());
}

// Interface for ClangASTSource

void ClangExpressionDeclMap::FindExternalVisibleDecls(
    NameSearchContext &context) {
  assert(m_ast_context);

  const auto name = context.m_decl_name.getAsString();

  Log *log = GetLog(LLDBLog::Expressions);

  if (log) {
    if (!context.m_decl_context)
      LLDB_LOG(log,
               "ClangExpressionDeclMap::FindExternalVisibleDecls for "
               "'{0}' in a NULL DeclContext",
               name);
    else if (const NamedDecl *context_named_decl =
                 dyn_cast<NamedDecl>(context.m_decl_context))
      LLDB_LOG(log,
               "ClangExpressionDeclMap::FindExternalVisibleDecls for "
               "'{0}' in '{1}'",
               name, context_named_decl->getNameAsString());
    else
      LLDB_LOG(log,
               "ClangExpressionDeclMap::FindExternalVisibleDecls for "
               "'{0}' in a '{1}'",
               name, context.m_decl_context->getDeclKindName());
  }

  if (const NamespaceDecl *namespace_context =
          dyn_cast<NamespaceDecl>(context.m_decl_context)) {
    if (namespace_context->getName() == g_lldb_local_vars_namespace_cstr) {
      CompilerDeclContext compiler_decl_ctx =
          m_clang_ast_context->CreateDeclContext(
              const_cast<clang::DeclContext *>(context.m_decl_context));
      FindExternalVisibleDecls(context, lldb::ModuleSP(), compiler_decl_ctx);
      return;
    }

    ClangASTImporter::NamespaceMapSP namespace_map =
        m_ast_importer_sp->GetNamespaceMap(namespace_context);

    if (!namespace_map)
      return;

    LLDB_LOG_VERBOSE(
        log, "  CEDM::FEVD Inspecting (NamespaceMap*){0:x} ({1} entries)",
        namespace_map.get(), namespace_map->size());

    for (ClangASTImporter::NamespaceMapItem &n : *namespace_map) {
      LLDB_LOG(log, "  CEDM::FEVD Searching namespace {0} in module {1}",
               n.second.GetName(), n.first->GetFileSpec().GetFilename());

      FindExternalVisibleDecls(context, n.first, n.second);
    }
  } else if (isa<TranslationUnitDecl>(context.m_decl_context)) {
    CompilerDeclContext namespace_decl;

    LLDB_LOG(log, "  CEDM::FEVD Searching the root namespace");

    FindExternalVisibleDecls(context, lldb::ModuleSP(), namespace_decl);
  }

  ClangASTSource::FindExternalVisibleDecls(context);
}

void ClangExpressionDeclMap::MaybeRegisterFunctionBody(
    FunctionDecl *copied_function_decl) {
  if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) {
    clang::DeclGroupRef decl_group_ref(copied_function_decl);
    m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref);
  }
}

clang::NamedDecl *ClangExpressionDeclMap::GetPersistentDecl(ConstString name) {
  if (!m_parser_vars)
    return nullptr;
  Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
  if (!target)
    return nullptr;

  ScratchTypeSystemClang::GetForTarget(*target);

  if (!m_parser_vars->m_persistent_vars)
    return nullptr;
  return m_parser_vars->m_persistent_vars->GetPersistentDecl(name);
}

void ClangExpressionDeclMap::SearchPersistenDecls(NameSearchContext &context,
                                                  const ConstString name) {
  Log *log = GetLog(LLDBLog::Expressions);

  NamedDecl *persistent_decl = GetPersistentDecl(name);

  if (!persistent_decl)
    return;

  Decl *parser_persistent_decl = CopyDecl(persistent_decl);

  if (!parser_persistent_decl)
    return;

  NamedDecl *parser_named_decl = dyn_cast<NamedDecl>(parser_persistent_decl);

  if (!parser_named_decl)
    return;

  if (clang::FunctionDecl *parser_function_decl =
          llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) {
    MaybeRegisterFunctionBody(parser_function_decl);
  }

  LLDB_LOG(log, "  CEDM::FEVD Found persistent decl {0}", name);

  context.AddNamedDecl(parser_named_decl);
}

void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context) {
  Log *log = GetLog(LLDBLog::Expressions);

  StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
  SymbolContext sym_ctx;
  if (frame != nullptr)
    sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
                                      lldb::eSymbolContextBlock);

  // FIXME: Currently m_ctx_obj is only used through
  // SBValue::EvaluateExpression. Can we instead *always* use m_ctx_obj
  // regardless of which EvaluateExpression path we go through? Then we wouldn't
  // need two separate code-paths here.
  if (m_ctx_obj) {
    Status status;
    lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
    if (!ctx_obj_ptr || status.Fail())
      return;

    AddContextClassType(context, TypeFromUser(m_ctx_obj->GetCompilerType()));
    return;
  }

  // Clang is looking for the type of "this"

  if (frame == nullptr)
    return;

  // Find the block that defines the function represented by "sym_ctx"
  Block *function_block = sym_ctx.GetFunctionBlock();

  if (!function_block)
    return;

  CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();

  if (!function_decl_ctx)
    return;

  clang::CXXMethodDecl *method_decl =
      TypeSystemClang::DeclContextGetAsCXXMethodDecl(function_decl_ctx);

  if (method_decl) {
    if (auto capturedThis = GetCapturedThisValueObject(frame)) {
      // We're inside a lambda and we captured a 'this'.
      // Import the outer class's AST instead of the
      // (unnamed) lambda structure AST so unqualified
      // member lookups are understood by the Clang parser.
      //
      // If we're in a lambda which didn't capture 'this',
      // $__lldb_class will correspond to the lambda closure
      // AST and references to captures will resolve like
      // regular member varaiable accesses do.
      TypeFromUser pointee_type =
          capturedThis->GetCompilerType().GetPointeeType();

      LLDB_LOG(log,
               "  CEDM::FEVD Adding captured type ({0} for"
               " $__lldb_class: {1}",
               capturedThis->GetTypeName(), capturedThis->GetName());

      AddContextClassType(context, pointee_type);
      return;
    }

    clang::CXXRecordDecl *class_decl = method_decl->getParent();

    QualType class_qual_type = m_ast_context->getCanonicalTagType(class_decl);

    // The synthesized __lldb_expr will adopt the qualifiers from this class
    // type. Make sure we use the qualifiers of the method that we're currently
    // stopped in.
    class_qual_type.addFastQualifiers(
        method_decl->getMethodQualifiers().getFastQualifiers());

    TypeFromUser class_user_type(
        class_qual_type.getAsOpaquePtr(),
        function_decl_ctx.GetTypeSystem()->weak_from_this());

    LLDB_LOG(log, "  CEDM::FEVD Adding type for $__lldb_class: {0}",
             class_qual_type.getAsString());

    AddContextClassType(context, class_user_type);
    return;
  }

  // FIXME: this code is supposed to handl cases where a function decl
  // was not attached to a class scope but its DIE had a `DW_AT_object_pointer`
  // (and thus has a local `this` variable). This isn't a tested flow and
  // even -flimit-debug-info doesn't seem to generate DWARF like that, so
  // we should get rid of this code-path. An alternative fix if we ever
  // encounter such DWARF is for the TypeSystem to attach the function
  // to some valid class context (we can derive the type of the context
  // through the `this` pointer anyway.
  //
  // The actual reason we can't remove this code is that LLDB currently
  // creates decls for function templates by attaching them to the TU instead
  // of a class context. So we can actually have template methods scoped
  // outside of a class. Once we fix that, we can remove this code-path.
  // Additionally, we exclude synthetic variables from here. Clang-based
  // languages are unlikely candidates for synthetic variables anyway, and
  // especially in this case, we're looking for something specific to C++.
  VariableList *vars = frame->GetVariableList(
      /*get_file_globals=*/false, /*include_synthetic_vars=*/false, nullptr);

  lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));

  if (this_var && this_var->IsInScope(frame) &&
      this_var->LocationIsValidForFrame(frame)) {
    Type *this_type = this_var->GetType();

    if (!this_type)
      return;

    TypeFromUser pointee_type =
        this_type->GetForwardCompilerType().GetPointeeType();

    LLDB_LOG(log, "  FEVD Adding type for $__lldb_class: {0}",
             ClangUtil::GetQualType(pointee_type).getAsString());

    AddContextClassType(context, pointee_type);
  }
}

void ClangExpressionDeclMap::LookUpLldbObjCClass(NameSearchContext &context) {
  Log *log = GetLog(LLDBLog::Expressions);

  StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();

  if (m_ctx_obj) {
    Status status;
    lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
    if (!ctx_obj_ptr || status.Fail())
      return;

    AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()));
    return;
  }

  // Clang is looking for the type of "*self"

  if (!frame)
    return;

  SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
                                                  lldb::eSymbolContextBlock);

  // Find the block that defines the function represented by "sym_ctx"
  Block *function_block = sym_ctx.GetFunctionBlock();

  if (!function_block)
    return;

  CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();

  if (!function_decl_ctx)
    return;

  clang::ObjCMethodDecl *method_decl =
      TypeSystemClang::DeclContextGetAsObjCMethodDecl(function_decl_ctx);

  if (method_decl) {
    ObjCInterfaceDecl *self_interface = method_decl->getClassInterface();

    if (!self_interface)
      return;

    const clang::Type *interface_type = self_interface->getTypeForDecl();

    if (!interface_type)
      return; // This is unlikely, but we have seen crashes where this
              // occurred

    TypeFromUser class_user_type(
        QualType(interface_type, 0).getAsOpaquePtr(),
        function_decl_ctx.GetTypeSystem()->weak_from_this());

    LLDB_LOG(log, "  FEVD Adding type for $__lldb_objc_class: {0}",
             ClangUtil::ToString(interface_type));

    AddOneType(context, class_user_type);
    return;
  }
  // This branch will get hit if we are executing code in the context of
  // a function that claims to have an object pointer (through
  // DW_AT_object_pointer?) but is not formally a method of the class.
  // In that case, just look up the "self" variable in the current scope
  // and use its type.

  // We exclude synthetic variables from here. Like above, it's highly unlikely
  // we care about synthetic variables here, and indeed this code is looking for
  // an obj-C specific construct.
  VariableList *vars = frame->GetVariableList(
      /*get_file_globals=*/false, /*include_synthetic_vars=*/false, nullptr);

  lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));

  if (!self_var)
    return;
  if (!self_var->IsInScope(frame))
    return;
  if (!self_var->LocationIsValidForFrame(frame))
    return;

  Type *self_type = self_var->GetType();

  if (!self_type)
    return;

  CompilerType self_clang_type = self_type->GetFullCompilerType();

  if (TypeSystemClang::IsObjCClassType(self_clang_type)) {
    return;
  }
  if (!TypeSystemClang::IsObjCObjectPointerType(self_clang_type))
    return;
  self_clang_type = self_clang_type.GetPointeeType();

  if (!self_clang_type)
    return;

  LLDB_LOG(log, "  FEVD Adding type for $__lldb_objc_class: {0}",
           ClangUtil::ToString(self_type->GetFullCompilerType()));

  TypeFromUser class_user_type(self_clang_type);

  AddOneType(context, class_user_type);
}

void ClangExpressionDeclMap::LookupLocalVarNamespace(
    SymbolContext &sym_ctx, NameSearchContext &name_context) {
  if (sym_ctx.block == nullptr)
    return;

  CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext();
  if (!frame_decl_context)
    return;

  TypeSystemClang *frame_ast = llvm::dyn_cast_or_null<TypeSystemClang>(
      frame_decl_context.GetTypeSystem());
  if (!frame_ast)
    return;

  clang::NamespaceDecl *namespace_decl =
      m_clang_ast_context->GetUniqueNamespaceDeclaration(
          g_lldb_local_vars_namespace_cstr, nullptr, OptionalClangModuleID());
  if (!namespace_decl)
    return;

  name_context.AddNamedDecl(namespace_decl);
  clang::DeclContext *ctxt = clang::Decl::castToDeclContext(namespace_decl);
  ctxt->setHasExternalVisibleStorage(true);
  name_context.m_found_local_vars_nsp = true;
}

void ClangExpressionDeclMap::LookupInModulesDeclVendor(
    NameSearchContext &context, ConstString name) {
  Log *log = GetLog(LLDBLog::Expressions);

  if (!m_target)
    return;

  std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
      GetClangModulesDeclVendor();
  if (!modules_decl_vendor)
    return;

  bool append = false;
  uint32_t max_matches = 1;
  std::vector<CompilerDecl> decls;

  if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls))
    return;

  assert(!decls.empty() && "FindDecls returned true but no decls?");
  auto *const decl_from_modules =
      llvm::cast<NamedDecl>(ClangUtil::GetDecl(decls[0]));

  LLDB_LOG(log,
           "  CAS::FEVD Matching decl found for "
           "\"{0}\" in the modules",
           name);

  clang::Decl *copied_decl = CopyDecl(decl_from_modules);
  if (!copied_decl) {
    LLDB_LOG(log, "  CAS::FEVD - Couldn't export a "
                  "declaration from the modules");
    return;
  }

  if (auto copied_function = dyn_cast<clang::FunctionDecl>(copied_decl)) {
    MaybeRegisterFunctionBody(copied_function);

    context.AddNamedDecl(copied_function);
  } else if (auto copied_var = dyn_cast<clang::VarDecl>(copied_decl)) {
    context.AddNamedDecl(copied_var);
    context.m_found_variable = true;
  }
}

bool ClangExpressionDeclMap::LookupLocalVariable(
    NameSearchContext &context, ConstString name, SymbolContext &sym_ctx,
    const CompilerDeclContext &namespace_decl) {
  if (sym_ctx.block == nullptr)
    return false;

  CompilerDeclContext decl_context = sym_ctx.block->GetDeclContext();
  if (!decl_context)
    return false;

  // Make sure that the variables are parsed so that we have the
  // declarations.
  StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
  VariableListSP vars = frame->GetInScopeVariableList(true);
  for (size_t i = 0; i < vars->GetSize(); i++)
    vars->GetVariableAtIndex(i)->GetDecl();

  // Search for declarations matching the name. Do not include imported
  // decls in the search if we are looking for decls in the artificial
  // namespace $__lldb_local_vars.
  std::vector<CompilerDecl> found_decls =
      decl_context.FindDeclByName(name, namespace_decl.IsValid());

  VariableSP var;
  bool variable_found = false;
  for (CompilerDecl decl : found_decls) {
    for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) {
      VariableSP candidate_var = vars->GetVariableAtIndex(vi);
      if (candidate_var->GetDecl() == decl) {
        var = candidate_var;
        break;
      }
    }

    if (var && !variable_found) {
      variable_found = true;
      ValueObjectSP valobj = ValueObjectVariable::Create(frame, var);
      AddOneVariable(context, var, valobj);
      context.m_found_variable = true;
    }
  }

  // We're in a local_var_lookup but haven't found any local variables
  // so far. When performing a variable lookup from within the context of
  // a lambda, we count the lambda captures as local variables. Thus,
  // see if we captured any variables with the requested 'name'.
  if (!variable_found) {
    auto find_capture = [](ConstString varname,
                           StackFrame *frame) -> ValueObjectSP {
      if (auto lambda = ClangExpressionUtil::GetLambdaValueObject(frame)) {
        if (auto capture = lambda->GetChildMemberWithName(varname)) {
          return capture;
        }
      }

      return nullptr;
    };

    if (auto capture = find_capture(name, frame)) {
      variable_found = true;
      context.m_found_variable = true;
      AddOneVariable(context, std::move(capture), std::move(find_capture));
    }
  }

  return variable_found;
}

/// Structure to hold the info needed when comparing function
/// declarations.
namespace {
struct FuncDeclInfo {
  ConstString m_name;
  CompilerType m_copied_type;
  uint32_t m_decl_lvl;
  SymbolContext m_sym_ctx;
};
} // namespace

SymbolContextList ClangExpressionDeclMap::SearchFunctionsInSymbolContexts(
    const SymbolContextList &sc_list,
    const CompilerDeclContext &frame_decl_context) {
  // First, symplify things by looping through the symbol contexts to
  // remove unwanted functions and separate out the functions we want to
  // compare and prune into a separate list. Cache the info needed about
  // the function declarations in a vector for efficiency.
  SymbolContextList sc_sym_list;
  std::vector<FuncDeclInfo> decl_infos;
  decl_infos.reserve(sc_list.GetSize());
  clang::DeclContext *frame_decl_ctx =
      (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext();
  TypeSystemClang *ast = llvm::dyn_cast_or_null<TypeSystemClang>(
      frame_decl_context.GetTypeSystem());

  for (const SymbolContext &sym_ctx : sc_list) {
    FuncDeclInfo fdi;

    // We don't know enough about symbols to compare them, but we should
    // keep them in the list.
    Function *function = sym_ctx.function;
    if (!function) {
      sc_sym_list.Append(sym_ctx);
      continue;
    }
    // Filter out functions without declaration contexts, as well as
    // class/instance methods, since they'll be skipped in the code that
    // follows anyway.
    CompilerDeclContext func_decl_context = function->GetDeclContext();
    if (!func_decl_context || func_decl_context.IsClassMethod())
      continue;
    // We can only prune functions for which we can copy the type.
    CompilerType func_clang_type = function->GetType()->GetFullCompilerType();
    CompilerType copied_func_type = GuardedCopyType(func_clang_type);
    if (!copied_func_type) {
      sc_sym_list.Append(sym_ctx);
      continue;
    }

    fdi.m_sym_ctx = sym_ctx;
    fdi.m_name = function->GetName();
    fdi.m_copied_type = copied_func_type;
    fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
    if (fdi.m_copied_type && func_decl_context) {
      // Call CountDeclLevels to get the number of parent scopes we have
      // to look through before we find the function declaration. When
      // comparing functions of the same type, the one with a lower count
      // will be closer to us in the lookup scope and shadows the other.
      clang::DeclContext *func_decl_ctx =
          (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext();
      fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, func_decl_ctx,
                                            &fdi.m_name, &fdi.m_copied_type);
    }
    decl_infos.emplace_back(fdi);
  }

  // Loop through the functions in our cache looking for matching types,
  // then compare their scope levels to see which is closer.
  std::multimap<CompilerType, const FuncDeclInfo *> matches;
  for (const FuncDeclInfo &fdi : decl_infos) {
    const CompilerType t = fdi.m_copied_type;
    auto q = matches.find(t);
    if (q != matches.end()) {
      if (q->second->m_decl_lvl > fdi.m_decl_lvl)
        // This function is closer; remove the old set.
        matches.erase(t);
      else if (q->second->m_decl_lvl < fdi.m_decl_lvl)
        // The functions in our set are closer - skip this one.
        continue;
    }
    matches.insert(std::make_pair(t, &fdi));
  }

  // Loop through our matches and add their symbol contexts to our list.
  SymbolContextList sc_func_list;
  for (const auto &q : matches)
    sc_func_list.Append(q.second->m_sym_ctx);

  // Rejoin the lists with the functions in front.
  sc_func_list.Append(sc_sym_list);
  return sc_func_list;
}

bool ClangExpressionDeclMap::LookupFunction(
    NameSearchContext &context, lldb::ModuleSP module_sp, ConstString name,
    const CompilerDeclContext &namespace_decl) {
  if (!m_parser_vars)
    return false;

  Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();

  std::vector<CompilerDecl> decls_from_modules;

  if (target) {
    if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
            GetClangModulesDeclVendor()) {
      decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
    }
  }

  SymbolContextList sc_list;
  if (namespace_decl && module_sp) {
    ModuleFunctionSearchOptions function_options;
    function_options.include_inlines = false;
    function_options.include_symbols = false;

    module_sp->FindFunctions(name, namespace_decl, eFunctionNameTypeBase,
                             function_options, sc_list);
  } else if (target && !namespace_decl) {
    ModuleFunctionSearchOptions function_options;
    function_options.include_inlines = false;
    function_options.include_symbols = true;

    // TODO Fix FindFunctions so that it doesn't return
    //   instance methods for eFunctionNameTypeBase.

    target->GetImages().FindFunctions(
        name, eFunctionNameTypeFull | eFunctionNameTypeBase, function_options,
        sc_list);
  }

  // If we found more than one function, see if we can use the frame's decl
  // context to remove functions that are shadowed by other functions which
  // match in type but are nearer in scope.
  //
  // AddOneFunction will not add a function whose type has already been
  // added, so if there's another function in the list with a matching type,
  // check to see if their decl context is a parent of the current frame's or
  // was imported via a and using statement, and pick the best match
  // according to lookup rules.
  if (sc_list.GetSize() > 1) {
    // Collect some info about our frame's context.
    StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
    SymbolContext frame_sym_ctx;
    if (frame != nullptr)
      frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
                                              lldb::eSymbolContextBlock);
    CompilerDeclContext frame_decl_context =
        frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext()
                                       : CompilerDeclContext();

    // We can't do this without a compiler decl context for our frame.
    if (frame_decl_context) {
      sc_list = SearchFunctionsInSymbolContexts(sc_list, frame_decl_context);
    }
  }

  bool found_function_with_type_info = false;

  if (sc_list.GetSize()) {
    const Symbol *extern_symbol = nullptr;
    const Symbol *non_extern_symbol = nullptr;

    for (const SymbolContext &sym_ctx : sc_list) {
      if (sym_ctx.function) {
        CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();

        if (!decl_ctx)
          continue;

        // Filter out class/instance methods.
        if (decl_ctx.IsClassMethod())
          continue;

        AddOneFunction(context, sym_ctx.function, nullptr);
        found_function_with_type_info = true;
      } else if (sym_ctx.symbol) {
        const Symbol *symbol = sym_ctx.symbol;
        if (target && symbol->GetType() == eSymbolTypeReExported) {
          symbol = symbol->ResolveReExportedSymbol(*target);
          if (symbol == nullptr)
            continue;
        }

        if (symbol->IsExternal())
          extern_symbol = symbol;
        else
          non_extern_symbol = symbol;
      }
    }

    if (!found_function_with_type_info) {
      for (const CompilerDecl &compiler_decl : decls_from_modules) {
        clang::Decl *decl = ClangUtil::GetDecl(compiler_decl);
        if (llvm::isa<clang::FunctionDecl>(decl)) {
          clang::NamedDecl *copied_decl =
              llvm::cast_or_null<FunctionDecl>(CopyDecl(decl));
          if (copied_decl) {
            context.AddNamedDecl(copied_decl);
            found_function_with_type_info = true;
          }
        }
      }
    }

    if (!found_function_with_type_info) {
      if (extern_symbol) {
        AddOneFunction(context, nullptr, extern_symbol);
      } else if (non_extern_symbol) {
        AddOneFunction(context, nullptr, non_extern_symbol);
      }
    }
  }

  return found_function_with_type_info;
}

void ClangExpressionDeclMap::FindExternalVisibleDecls(
    NameSearchContext &context, lldb::ModuleSP module_sp,
    const CompilerDeclContext &namespace_decl) {
  assert(m_ast_context);

  Log *log = GetLog(LLDBLog::Expressions);

  const ConstString name(context.m_decl_name.getAsString());
  if (IgnoreName(name, false))
    return;

  // Only look for functions by name out in our symbols if the function doesn't
  // start with our phony prefix of '$'

  Target *target = nullptr;
  StackFrame *frame = nullptr;
  SymbolContext sym_ctx;
  if (m_parser_vars) {
    target = m_parser_vars->m_exe_ctx.GetTargetPtr();
    frame = m_parser_vars->m_exe_ctx.GetFramePtr();
  }
  if (frame != nullptr)
    sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
                                      lldb::eSymbolContextBlock);

  // Try the persistent decls, which take precedence over all else.
  if (!namespace_decl)
    SearchPersistenDecls(context, name);

  if (name.GetStringRef().starts_with("$") && !namespace_decl) {
    if (name == "$__lldb_class") {
      LookUpLldbClass(context);
      return;
    }

    if (name == "$__lldb_objc_class") {
      LookUpLldbObjCClass(context);
      return;
    }
    if (name == g_lldb_local_vars_namespace_cstr) {
      LookupLocalVarNamespace(sym_ctx, context);
      return;
    }

    // any other $__lldb names should be weeded out now
    if (name.GetStringRef().starts_with("$__lldb"))
      return;

    // No ParserVars means we can't do register or variable lookup.
    if (!m_parser_vars || !m_parser_vars->m_persistent_vars)
      return;

    ExpressionVariableSP pvar_sp(
        m_parser_vars->m_persistent_vars->GetVariable(name));

    if (pvar_sp) {
      AddOneVariable(context, pvar_sp);
      return;
    }

    assert(name.GetStringRef().starts_with("$"));
    llvm::StringRef reg_name = name.GetStringRef().substr(1);

    if (m_parser_vars->m_exe_ctx.GetRegisterContext()) {
      const RegisterInfo *reg_info(
          m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(
              reg_name));

      if (reg_info) {
        LLDB_LOG(log, "  CEDM::FEVD Found register {0}", reg_info->name);

        AddOneRegister(context, reg_info);
      }
    }
    return;
  }

  bool local_var_lookup = !namespace_decl || (namespace_decl.GetName() ==
                                              g_lldb_local_vars_namespace_cstr);
  if (frame && local_var_lookup)
    if (LookupLocalVariable(context, name, sym_ctx, namespace_decl))
      return;

  if (target) {
    ValueObjectSP valobj;
    VariableSP var;
    var = FindGlobalVariable(*target, module_sp, name, namespace_decl);

    if (var) {
      valobj = ValueObjectVariable::Create(target, var);
      AddOneVariable(context, var, valobj);
      context.m_found_variable = true;
      return;
    }
  }

  if (!LookupFunction(context, module_sp, name, namespace_decl))
    LookupInModulesDeclVendor(context, name);

  if (target && !context.m_found_variable && !namespace_decl) {
    // We couldn't find a non-symbol variable for this.  Now we'll hunt for a
    // generic data symbol, and -- if it is found -- treat it as a variable.
    Status error;

    const Symbol *data_symbol =
        m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error);

    if (!error.Success()) {
      const unsigned diag_id =
          m_ast_context->getDiagnostics().getCustomDiagID(
              clang::DiagnosticsEngine::Level::Error, "%0");
      m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString();
    }

    if (data_symbol) {
      std::string warning("got name from symbols: ");
      warning.append(name.GetStringRef());
      const unsigned diag_id =
          m_ast_context->getDiagnostics().getCustomDiagID(
              clang::DiagnosticsEngine::Level::Warning, "%0");
      m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str();
      AddOneGenericVariable(context, *data_symbol);
      context.m_found_variable = true;
    }
  }
}

bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
                                              lldb_private::Value &var_location,
                                              TypeFromUser *user_type,
                                              TypeFromParser *parser_type) {
  Log *log = GetLog(LLDBLog::Expressions);

  Type *var_type = var->GetType();

  if (!var_type) {
    LLDB_LOG(log, "Skipped a definition because it has no type");
    return false;
  }

  CompilerType var_clang_type = var_type->GetFullCompilerType();

  if (!var_clang_type) {
    LLDB_LOG(log, "Skipped a definition because it has no Clang type");
    return false;
  }

  auto clang_ast =
      var_type->GetForwardCompilerType().GetTypeSystem<TypeSystemClang>();

  if (!clang_ast) {
    LLDB_LOG(log, "Skipped a definition because it has no Clang AST");
    return false;
  }

  DWARFExpressionList &var_location_list = var->LocationExpressionList();

  Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
  Status err;

  if (var->GetLocationIsConstantValueData()) {
    DataExtractor const_value_extractor;
    if (var_location_list.GetExpressionData(const_value_extractor)) {
      var_location = Value(const_value_extractor.GetDataStart(),
                           const_value_extractor.GetByteSize());
      var_location.SetValueType(Value::ValueType::HostAddress);
    } else {
      LLDB_LOG(log, "Error evaluating constant variable: {0}", err.AsCString());
      return false;
    }
  }

  CompilerType type_to_use = GuardedCopyType(var_clang_type);

  if (!type_to_use) {
    LLDB_LOG(log,
             "Couldn't copy a variable's type into the parser's AST context");

    return false;
  }

  if (parser_type)
    *parser_type = TypeFromParser(type_to_use);

  if (var_location.GetContextType() == Value::ContextType::Invalid)
    var_location.SetCompilerType(type_to_use);

  if (var_location.GetValueType() == Value::ValueType::FileAddress) {
    SymbolContext var_sc;
    var->CalculateSymbolContext(&var_sc);

    if (!var_sc.module_sp)
      return false;

    Address so_addr(var_location.GetScalar().ULongLong(),
                    var_sc.module_sp->GetSectionList());

    lldb::addr_t load_addr = so_addr.GetLoadAddress(target);

    if (load_addr != LLDB_INVALID_ADDRESS) {
      var_location.GetScalar() = load_addr;
      var_location.SetValueType(Value::ValueType::LoadAddress);
    }
  }

  if (user_type)
    *user_type = TypeFromUser(var_clang_type);

  return true;
}

ClangExpressionVariable::ParserVars *
ClangExpressionDeclMap::AddExpressionVariable(NameSearchContext &context,
                                              TypeFromParser const &pt,
                                              ValueObjectSP valobj) {
  clang::QualType parser_opaque_type =
      QualType::getFromOpaquePtr(pt.GetOpaqueQualType());

  if (parser_opaque_type.isNull())
    return nullptr;

  if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) {
    if (const TagType *tag_type = dyn_cast<TagType>(parser_type))
      CompleteType(tag_type->getDecl()->getDefinitionOrSelf());
    if (const ObjCObjectPointerType *objc_object_ptr_type =
            dyn_cast<ObjCObjectPointerType>(parser_type))
      CompleteType(objc_object_ptr_type->getInterfaceDecl());
  }

  bool is_reference = pt.IsReferenceType();

  NamedDecl *var_decl = nullptr;
  if (is_reference)
    var_decl = context.AddVarDecl(pt);
  else
    var_decl = context.AddVarDecl(pt.GetLValueReferenceType());

  std::string decl_name(context.m_decl_name.getAsString());
  ConstString entity_name(decl_name);
  ClangExpressionVariable *entity(new ClangExpressionVariable(valobj));
  m_found_entities.AddNewlyConstructedVariable(entity);

  assert(entity);
  entity->EnableParserVars(GetParserID());
  ClangExpressionVariable::ParserVars *parser_vars =
      entity->GetParserVars(GetParserID());

  parser_vars->m_named_decl = var_decl;

  if (is_reference)
    entity->m_flags |= ClangExpressionVariable::EVTypeIsReference;

  return parser_vars;
}

void ClangExpressionDeclMap::AddOneVariable(
    NameSearchContext &context, ValueObjectSP valobj,
    ValueObjectProviderTy valobj_provider) {
  assert(m_parser_vars.get());
  assert(valobj);

  Log *log = GetLog(LLDBLog::Expressions);

  Value var_location = valobj->GetValue();

  TypeFromUser user_type = valobj->GetCompilerType();

  auto clang_ast = user_type.GetTypeSystem<TypeSystemClang>();

  if (!clang_ast) {
    LLDB_LOG(log, "Skipped a definition because it has no Clang AST");
    return;
  }

  TypeFromParser parser_type = GuardedCopyType(user_type);

  if (!parser_type) {
    LLDB_LOG(log,
             "Couldn't copy a variable's type into the parser's AST context");

    return;
  }

  if (var_location.GetContextType() == Value::ContextType::Invalid)
    var_location.SetCompilerType(parser_type);

  ClangExpressionVariable::ParserVars *parser_vars =
      AddExpressionVariable(context, parser_type, valobj);

  if (!parser_vars)
    return;

  LLDB_LOG(log, "  CEDM::FEVD Found variable {0}, returned\n{1} (original {2})",
           context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl),
           ClangUtil::ToString(user_type));

  parser_vars->m_llvm_value = nullptr;
  parser_vars->m_lldb_value = std::move(var_location);
  parser_vars->m_lldb_valobj_provider = std::move(valobj_provider);
}

void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
                                            VariableSP var,
                                            ValueObjectSP valobj) {
  assert(m_parser_vars.get());

  Log *log = GetLog(LLDBLog::Expressions);

  TypeFromUser ut;
  TypeFromParser pt;
  Value var_location;

  if (!GetVariableValue(var, var_location, &ut, &pt))
    return;

  ClangExpressionVariable::ParserVars *parser_vars =
      AddExpressionVariable(context, pt, std::move(valobj));

  if (!parser_vars)
    return;

  LLDB_LOG(log, "  CEDM::FEVD Found variable {0}, returned\n{1} (original {2})",
           context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl),
           ClangUtil::ToString(ut));

  parser_vars->m_llvm_value = nullptr;
  parser_vars->m_lldb_value = var_location;
  parser_vars->m_lldb_var = var;
}

void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
                                            ExpressionVariableSP &pvar_sp) {
  Log *log = GetLog(LLDBLog::Expressions);

  TypeFromUser user_type(
      llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetTypeFromUser());

  TypeFromParser parser_type(GuardedCopyType(user_type));

  if (!parser_type.GetOpaqueQualType()) {
    LLDB_LOG(log, "  CEDM::FEVD Couldn't import type for pvar {0}",
             pvar_sp->GetName());
    return;
  }

  NamedDecl *var_decl =
      context.AddVarDecl(parser_type.GetLValueReferenceType());

  llvm::cast<ClangExpressionVariable>(pvar_sp.get())
      ->EnableParserVars(GetParserID());
  ClangExpressionVariable::ParserVars *parser_vars =
      llvm::cast<ClangExpressionVariable>(pvar_sp.get())
          ->GetParserVars(GetParserID());
  parser_vars->m_named_decl = var_decl;
  parser_vars->m_llvm_value = nullptr;
  parser_vars->m_lldb_value.Clear();

  LLDB_LOG(log, "  CEDM::FEVD Added pvar {0}, returned\n{1}",
           pvar_sp->GetName(), ClangUtil::DumpDecl(var_decl));
}

void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
                                                   const Symbol &symbol) {
  assert(m_parser_vars.get());

  Log *log = GetLog(LLDBLog::Expressions);

  Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();

  if (target == nullptr)
    return;

  auto scratch_ast_context = GetScratchContext(*target);
  if (!scratch_ast_context)
    return;

  TypeFromUser user_type(scratch_ast_context->GetBasicType(eBasicTypeVoid)
                             .GetPointerType()
                             .GetLValueReferenceType());
  TypeFromParser parser_type(m_clang_ast_context->GetBasicType(eBasicTypeVoid)
                                 .GetPointerType()
                                 .GetLValueReferenceType());
  NamedDecl *var_decl = context.AddVarDecl(parser_type);

  std::string decl_name(context.m_decl_name.getAsString());
  ConstString entity_name(decl_name);
  ClangExpressionVariable *entity(new ClangExpressionVariable(
      m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), entity_name,
      user_type, m_parser_vars->m_target_info.byte_order,
      m_parser_vars->m_target_info.address_byte_size));
  m_found_entities.AddNewlyConstructedVariable(entity);

  entity->EnableParserVars(GetParserID());
  ClangExpressionVariable::ParserVars *parser_vars =
      entity->GetParserVars(GetParserID());

  const Address symbol_address = symbol.GetAddress();
  lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target);

  // parser_vars->m_lldb_value.SetContext(Value::ContextType::ClangType,
  // user_type.GetOpaqueQualType());
  parser_vars->m_lldb_value.SetCompilerType(user_type);
  parser_vars->m_lldb_value.GetScalar() = symbol_load_addr;
  parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress);

  parser_vars->m_named_decl = var_decl;
  parser_vars->m_llvm_value = nullptr;
  parser_vars->m_lldb_sym = &symbol;

  LLDB_LOG(log, "  CEDM::FEVD Found variable {0}, returned\n{1}", decl_name,
           ClangUtil::DumpDecl(var_decl));
}

void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context,
                                            const RegisterInfo *reg_info) {
  Log *log = GetLog(LLDBLog::Expressions);

  CompilerType clang_type =
      m_clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
          reg_info->encoding, reg_info->byte_size * 8);

  if (!clang_type) {
    LLDB_LOG(log, "  Tried to add a type for {0}, but couldn't get one",
             context.m_decl_name.getAsString());
    return;
  }

  TypeFromParser parser_clang_type(clang_type);

  NamedDecl *var_decl = context.AddVarDecl(parser_clang_type);

  ClangExpressionVariable *entity(new ClangExpressionVariable(
      m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
      m_parser_vars->m_target_info.byte_order,
      m_parser_vars->m_target_info.address_byte_size));
  m_found_entities.AddNewlyConstructedVariable(entity);

  std::string decl_name(context.m_decl_name.getAsString());
  entity->SetName(decl_name);
  entity->SetRegisterInfo(reg_info);
  entity->EnableParserVars(GetParserID());
  ClangExpressionVariable::ParserVars *parser_vars =
      entity->GetParserVars(GetParserID());
  parser_vars->m_named_decl = var_decl;
  parser_vars->m_llvm_value = nullptr;
  parser_vars->m_lldb_value.Clear();
  entity->m_flags |= ClangExpressionVariable::EVBareRegister;

  LLDB_LOG(log, "  CEDM::FEVD Added register {0}, returned\n{1}",
           context.m_decl_name.getAsString(), ClangUtil::DumpDecl(var_decl));
}

void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
                                            Function *function,
                                            const Symbol *symbol) {
  assert(m_parser_vars.get());

  Log *log = GetLog(LLDBLog::Expressions);

  NamedDecl *function_decl = nullptr;
  Address fun_address;
  CompilerType function_clang_type;

  bool is_indirect_function = false;

  if (function) {
    Type *function_type = function->GetType();

    const auto lang = function->GetCompileUnit()->GetLanguage();
    const llvm::StringRef name =
        function->GetMangled().GetMangledName().GetStringRef();
    const bool extern_c =
        (Language::LanguageIsC(lang) && !Mangled::IsMangledName(name)) ||
        (Language::LanguageIsObjC(lang) &&
         !Language::LanguageIsCPlusPlus(lang));

    if (!extern_c) {
      TypeSystem *type_system = function->GetDeclContext().GetTypeSystem();
      if (llvm::isa<TypeSystemClang>(type_system)) {
        clang::DeclContext *src_decl_context =
            (clang::DeclContext *)function->GetDeclContext()
                .GetOpaqueDeclContext();
        clang::FunctionDecl *src_function_decl =
            llvm::dyn_cast_or_null<clang::FunctionDecl>(src_decl_context);
        if (src_function_decl &&
            src_function_decl->getTemplateSpecializationInfo()) {
          clang::FunctionTemplateDecl *function_template =
              src_function_decl->getTemplateSpecializationInfo()->getTemplate();
          clang::FunctionTemplateDecl *copied_function_template =
              llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>(
                  CopyDecl(function_template));
          if (copied_function_template) {
            if (log) {
              StreamString ss;

              function->DumpSymbolContext(&ss);

              LLDB_LOG(log,
                       "  CEDM::FEVD Imported decl for function template"
                       " {0} (description {1}), returned\n{2}",
                       copied_function_template->getNameAsString(),
                       ss.GetData(),
                       ClangUtil::DumpDecl(copied_function_template));
            }

            context.AddNamedDecl(copied_function_template);
          }
        } else if (src_function_decl) {
          if (clang::FunctionDecl *copied_function_decl =
                  llvm::dyn_cast_or_null<clang::FunctionDecl>(
                      CopyDecl(src_function_decl))) {
            if (log) {
              StreamString ss;

              function->DumpSymbolContext(&ss);

              LLDB_LOG(log,
                       "  CEDM::FEVD Imported decl for function {0} "
                       "(description {1}), returned\n{2}",
                       copied_function_decl->getNameAsString(), ss.GetData(),
                       ClangUtil::DumpDecl(copied_function_decl));
            }

            context.AddNamedDecl(copied_function_decl);
            return;
          } else {
            LLDB_LOG(log, "  Failed to import the function decl for '{0}'",
                     src_function_decl->getName());
          }
        }
      }
    }

    if (!function_type) {
      LLDB_LOG(log, "  Skipped a function because it has no type");
      return;
    }

    function_clang_type = function_type->GetFullCompilerType();

    if (!function_clang_type) {
      LLDB_LOG(log, "  Skipped a function because it has no Clang type");
      return;
    }

    fun_address = function->GetAddress();

    CompilerType copied_function_type = GuardedCopyType(function_clang_type);
    if (copied_function_type) {
      function_decl = context.AddFunDecl(copied_function_type, extern_c);

      if (!function_decl) {
        LLDB_LOG(log, "  Failed to create a function decl for '{0}' ({1:x})",
                 function_type->GetName(), function_type->GetID());

        return;
      }
    } else {
      // We failed to copy the type we found
      LLDB_LOG(log,
               "  Failed to import the function type '{0}' ({1:x})"
               " into the expression parser AST context",
               function_type->GetName(), function_type->GetID());

      return;
    }
  } else if (symbol) {
    fun_address = symbol->GetAddress();
    function_decl = context.AddGenericFunDecl();
    is_indirect_function = symbol->IsIndirect();
  } else {
    LLDB_LOG(log, "  AddOneFunction called with no function and no symbol");
    return;
  }

  Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();

  lldb::addr_t load_addr =
      fun_address.GetCallableLoadAddress(target, is_indirect_function);

  ClangExpressionVariable *entity(new ClangExpressionVariable(
      m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
      m_parser_vars->m_target_info.byte_order,
      m_parser_vars->m_target_info.address_byte_size));
  m_found_entities.AddNewlyConstructedVariable(entity);

  std::string decl_name(context.m_decl_name.getAsString());
  entity->SetName(decl_name);
  entity->SetCompilerType(function_clang_type);
  entity->EnableParserVars(GetParserID());

  ClangExpressionVariable::ParserVars *parser_vars =
      entity->GetParserVars(GetParserID());

  if (load_addr != LLDB_INVALID_ADDRESS) {
    parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress);
    parser_vars->m_lldb_value.GetScalar() = load_addr;
  } else {
    // We have to try finding a file address.

    lldb::addr_t file_addr = fun_address.GetFileAddress();

    parser_vars->m_lldb_value.SetValueType(Value::ValueType::FileAddress);
    parser_vars->m_lldb_value.GetScalar() = file_addr;
  }

  parser_vars->m_named_decl = function_decl;
  parser_vars->m_llvm_value = nullptr;

  if (log) {
    StreamString ss;

    fun_address.Dump(&ss,
                     m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
                     Address::DumpStyleResolvedDescription);

    LLDB_LOG(log,
             "  CEDM::FEVD Found {0} function {1} (description {2}), "
             "returned\n{3}",
             (function ? "specific" : "generic"), decl_name, ss.GetData(),
             ClangUtil::DumpDecl(function_decl));
  }
}

void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context,
                                                 const TypeFromUser &ut) {
  CompilerType copied_clang_type = GuardedCopyType(ut);

  Log *log = GetLog(LLDBLog::Expressions);

  if (!copied_clang_type) {
    LLDB_LOG(log,
             "ClangExpressionDeclMap::AddThisType - Couldn't import the type");

    return;
  }

  if (copied_clang_type.IsAggregateType() &&
      copied_clang_type.GetCompleteType()) {
    CompilerType void_clang_type =
        m_clang_ast_context->GetBasicType(eBasicTypeVoid);
    std::array<CompilerType, 1> args{void_clang_type.GetPointerType()};

    CompilerType method_type = m_clang_ast_context->CreateFunctionType(
        void_clang_type, args, false,
        m_ignore_context_qualifiers ? 0 : ut.GetTypeQualifiers());

    const bool is_virtual = false;
    const bool is_static = false;
    const bool is_inline = false;
    const bool is_explicit = false;
    const bool is_attr_used = true;
    const bool is_artificial = false;

    CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType(
        copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", /*asm_label=*/{},
        method_type, is_virtual, is_static, is_inline, is_explicit,
        is_attr_used, is_artificial);

    LLDB_LOG(log,
             "  CEDM::AddThisType Added function $__lldb_expr "
             "(description {0}) for this type\n{1}",
             ClangUtil::ToString(copied_clang_type),
             ClangUtil::DumpDecl(method_decl));
  }

  if (!copied_clang_type.IsValid())
    return;

  TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(
      QualType::getFromOpaquePtr(copied_clang_type.GetOpaqueQualType()));

  if (!type_source_info)
    return;

  // Construct a typedef type because if "*this" is a templated type we can't
  // just return ClassTemplateSpecializationDecls in response to name queries.
  // Using a typedef makes this much more robust.

  TypedefDecl *typedef_decl = TypedefDecl::Create(
      *m_ast_context, m_ast_context->getTranslationUnitDecl(), SourceLocation(),
      SourceLocation(), context.m_decl_name.getAsIdentifierInfo(),
      type_source_info);

  if (!typedef_decl)
    return;

  context.AddNamedDecl(typedef_decl);
}

void ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
                                        const TypeFromUser &ut) {
  CompilerType copied_clang_type = GuardedCopyType(ut);

  if (!copied_clang_type) {
    Log *log = GetLog(LLDBLog::Expressions);

    LLDB_LOG(log,
             "ClangExpressionDeclMap::AddOneType - Couldn't import the type");

    return;
  }

  context.AddTypeDecl(copied_clang_type);
}
