brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.0 KiB · d1feda1 Raw
999 lines · cpp
1//===-- ClangUserExpression.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <cstdio>10#include <sys/types.h>11 12#include <cstdlib>13#include <map>14#include <string>15 16#include "ClangUserExpression.h"17 18#include "ASTResultSynthesizer.h"19#include "ClangASTMetadata.h"20#include "ClangDiagnostic.h"21#include "ClangExpressionDeclMap.h"22#include "ClangExpressionParser.h"23#include "ClangModulesDeclVendor.h"24#include "ClangPersistentVariables.h"25#include "CppModuleConfiguration.h"26 27#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"28#include "lldb/Core/Debugger.h"29#include "lldb/Core/Module.h"30#include "lldb/Expression/ExpressionSourceCode.h"31#include "lldb/Expression/IRExecutionUnit.h"32#include "lldb/Expression/IRInterpreter.h"33#include "lldb/Expression/Materializer.h"34#include "lldb/Host/HostInfo.h"35#include "lldb/Symbol/Block.h"36#include "lldb/Symbol/CompileUnit.h"37#include "lldb/Symbol/Function.h"38#include "lldb/Symbol/ObjectFile.h"39#include "lldb/Symbol/SymbolFile.h"40#include "lldb/Symbol/SymbolVendor.h"41#include "lldb/Symbol/Type.h"42#include "lldb/Symbol/VariableList.h"43#include "lldb/Target/ExecutionContext.h"44#include "lldb/Target/Process.h"45#include "lldb/Target/StackFrame.h"46#include "lldb/Target/Target.h"47#include "lldb/Target/ThreadPlan.h"48#include "lldb/Target/ThreadPlanCallUserExpression.h"49#include "lldb/Utility/ConstString.h"50#include "lldb/Utility/LLDBLog.h"51#include "lldb/Utility/Log.h"52#include "lldb/Utility/StreamString.h"53#include "lldb/ValueObject/ValueObjectConstResult.h"54 55#include "clang/AST/DeclCXX.h"56#include "clang/AST/DeclObjC.h"57 58#include "llvm/ADT/ScopeExit.h"59#include "llvm/BinaryFormat/Dwarf.h"60 61using namespace lldb_private;62 63char ClangUserExpression::ID;64 65ClangUserExpression::ClangUserExpression(66    ExecutionContextScope &exe_scope, llvm::StringRef expr,67    llvm::StringRef prefix, SourceLanguage language, ResultType desired_type,68    const EvaluateExpressionOptions &options, ValueObject *ctx_obj)69    : LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,70                         options),71      m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==72                                                    eExecutionPolicyTopLevel),73      m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {74  switch (m_language.name) {75  case llvm::dwarf::DW_LNAME_C_plus_plus:76    m_allow_cxx = true;77    break;78  case llvm::dwarf::DW_LNAME_ObjC:79    m_allow_objc = true;80    break;81  case llvm::dwarf::DW_LNAME_ObjC_plus_plus:82  default:83    m_allow_cxx = true;84    m_allow_objc = true;85    break;86  }87}88 89ClangUserExpression::~ClangUserExpression() = default;90 91void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {92  Log *log = GetLog(LLDBLog::Expressions);93 94  LLDB_LOGF(log, "ClangUserExpression::ScanContext()");95 96  m_target = exe_ctx.GetTargetPtr();97 98  if (!(m_allow_cxx || m_allow_objc)) {99    LLDB_LOGF(log, "  [CUE::SC] Settings inhibit C++ and Objective-C");100    return;101  }102 103  StackFrame *frame = exe_ctx.GetFramePtr();104  if (frame == nullptr) {105    LLDB_LOGF(log, "  [CUE::SC] Null stack frame");106    return;107  }108 109  SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |110                                                  lldb::eSymbolContextBlock);111 112  if (!sym_ctx.function) {113    LLDB_LOGF(log, "  [CUE::SC] Null function");114    return;115  }116 117  // Find the block that defines the function represented by "sym_ctx"118  Block *function_block = sym_ctx.GetFunctionBlock();119 120  if (!function_block) {121    LLDB_LOGF(log, "  [CUE::SC] Null function block");122    return;123  }124 125  CompilerDeclContext decl_context = function_block->GetDeclContext();126 127  if (!decl_context) {128    LLDB_LOGF(log, "  [CUE::SC] Null decl context");129    return;130  }131 132  if (m_ctx_obj) {133    switch (m_ctx_obj->GetObjectRuntimeLanguage()) {134    case lldb::eLanguageTypeC:135    case lldb::eLanguageTypeC89:136    case lldb::eLanguageTypeC99:137    case lldb::eLanguageTypeC11:138    case lldb::eLanguageTypeC_plus_plus:139    case lldb::eLanguageTypeC_plus_plus_03:140    case lldb::eLanguageTypeC_plus_plus_11:141    case lldb::eLanguageTypeC_plus_plus_14:142      m_in_cplusplus_method = true;143      break;144    case lldb::eLanguageTypeObjC:145    case lldb::eLanguageTypeObjC_plus_plus:146      m_in_objectivec_method = true;147      break;148    default:149      break;150    }151    m_needs_object_ptr = true;152  } else if (clang::CXXMethodDecl *method_decl =153          TypeSystemClang::DeclContextGetAsCXXMethodDecl(decl_context)) {154    if (m_allow_cxx && method_decl->isInstance()) {155      if (m_enforce_valid_object) {156        lldb::VariableListSP variable_list_sp(157            function_block->GetBlockVariableList(true));158 159        const char *thisErrorString = "Stopped in a C++ method, but 'this' "160                                      "isn't available; pretending we are in a "161                                      "generic context";162 163        if (!variable_list_sp) {164          err = Status::FromErrorString(thisErrorString);165          return;166        }167 168        lldb::VariableSP this_var_sp(169            variable_list_sp->FindVariable(ConstString("this")));170 171        if (!this_var_sp || !this_var_sp->IsInScope(frame) ||172            !this_var_sp->LocationIsValidForFrame(frame)) {173          err = Status::FromErrorString(thisErrorString);174          return;175        }176      }177 178      m_in_cplusplus_method = true;179      m_needs_object_ptr = true;180    }181  } else if (clang::ObjCMethodDecl *method_decl =182                 TypeSystemClang::DeclContextGetAsObjCMethodDecl(183                     decl_context)) {184    if (m_allow_objc) {185      if (m_enforce_valid_object) {186        lldb::VariableListSP variable_list_sp(187            function_block->GetBlockVariableList(true));188 189        const char *selfErrorString = "Stopped in an Objective-C method, but "190                                      "'self' isn't available; pretending we "191                                      "are in a generic context";192 193        if (!variable_list_sp) {194          err = Status::FromErrorString(selfErrorString);195          return;196        }197 198        lldb::VariableSP self_variable_sp =199            variable_list_sp->FindVariable(ConstString("self"));200 201        if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||202            !self_variable_sp->LocationIsValidForFrame(frame)) {203          err = Status::FromErrorString(selfErrorString);204          return;205        }206      }207 208      m_in_objectivec_method = true;209      m_needs_object_ptr = true;210 211      if (!method_decl->isInstanceMethod())212        m_in_static_method = true;213    }214  } else if (clang::FunctionDecl *function_decl =215                 TypeSystemClang::DeclContextGetAsFunctionDecl(decl_context)) {216    // We might also have a function that said in the debug information that it217    // captured an object pointer.  The best way to deal with getting to the218    // ivars at present is by pretending that this is a method of a class in219    // whatever runtime the debug info says the object pointer belongs to.  Do220    // that here.221 222    if (std::optional<ClangASTMetadata> metadata =223            TypeSystemClang::DeclContextGetMetaData(decl_context,224                                                    function_decl);225        metadata && metadata->HasObjectPtr()) {226      lldb::LanguageType language = metadata->GetObjectPtrLanguage();227      if (language == lldb::eLanguageTypeC_plus_plus) {228        if (m_enforce_valid_object) {229          lldb::VariableListSP variable_list_sp(230              function_block->GetBlockVariableList(true));231 232          const char *thisErrorString = "Stopped in a context claiming to "233                                        "capture a C++ object pointer, but "234                                        "'this' isn't available; pretending we "235                                        "are in a generic context";236 237          if (!variable_list_sp) {238            err = Status::FromErrorString(thisErrorString);239            return;240          }241 242          lldb::VariableSP this_var_sp(243              variable_list_sp->FindVariable(ConstString("this")));244 245          if (!this_var_sp || !this_var_sp->IsInScope(frame) ||246              !this_var_sp->LocationIsValidForFrame(frame)) {247            err = Status::FromErrorString(thisErrorString);248            return;249          }250        }251 252        m_in_cplusplus_method = true;253        m_needs_object_ptr = true;254      } else if (language == lldb::eLanguageTypeObjC) {255        if (m_enforce_valid_object) {256          lldb::VariableListSP variable_list_sp(257              function_block->GetBlockVariableList(true));258 259          const char *selfErrorString =260              "Stopped in a context claiming to capture an Objective-C object "261              "pointer, but 'self' isn't available; pretending we are in a "262              "generic context";263 264          if (!variable_list_sp) {265            err = Status::FromErrorString(selfErrorString);266            return;267          }268 269          lldb::VariableSP self_variable_sp =270              variable_list_sp->FindVariable(ConstString("self"));271 272          if (!self_variable_sp || !self_variable_sp->IsInScope(frame) ||273              !self_variable_sp->LocationIsValidForFrame(frame)) {274            err = Status::FromErrorString(selfErrorString);275            return;276          }277 278          Type *self_type = self_variable_sp->GetType();279 280          if (!self_type) {281            err = Status::FromErrorString(selfErrorString);282            return;283          }284 285          CompilerType self_clang_type = self_type->GetForwardCompilerType();286 287          if (!self_clang_type) {288            err = Status::FromErrorString(selfErrorString);289            return;290          }291 292          if (TypeSystemClang::IsObjCClassType(self_clang_type)) {293            return;294          } else if (TypeSystemClang::IsObjCObjectPointerType(295                         self_clang_type)) {296            m_in_objectivec_method = true;297            m_needs_object_ptr = true;298          } else {299            err = Status::FromErrorString(selfErrorString);300            return;301          }302        } else {303          m_in_objectivec_method = true;304          m_needs_object_ptr = true;305        }306      }307    }308  }309}310 311// This is a really nasty hack, meant to fix Objective-C expressions of the312// form (int)[myArray count].  Right now, because the type information for313// count is not available, [myArray count] returns id, which can't be directly314// cast to int without causing a clang error.315static void ApplyObjcCastHack(std::string &expr) {316  const std::string from = "(int)[";317  const std::string to = "(int)(long long)[";318 319  size_t offset;320 321  while ((offset = expr.find(from)) != expr.npos)322    expr.replace(offset, from.size(), to);323}324 325bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,326                                 ExecutionContext &exe_ctx) {327  if (Target *target = exe_ctx.GetTargetPtr()) {328    if (PersistentExpressionState *persistent_state =329            target->GetPersistentExpressionStateForLanguage(330                lldb::eLanguageTypeC)) {331      m_clang_state = llvm::cast<ClangPersistentVariables>(persistent_state);332      m_result_delegate.RegisterPersistentState(persistent_state);333    } else {334      diagnostic_manager.PutString(335          lldb::eSeverityError, "couldn't start parsing (no persistent data)");336      return false;337    }338  } else {339    diagnostic_manager.PutString(lldb::eSeverityError,340                                 "error: couldn't start parsing (no target)");341    return false;342  }343  return true;344}345 346static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,347                            DiagnosticManager &diagnostic_manager) {348  if (!target->GetEnableAutoImportClangModules())349    return;350 351  auto *persistent_state = llvm::cast<ClangPersistentVariables>(352      target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));353  if (!persistent_state)354    return;355 356  std::shared_ptr<ClangModulesDeclVendor> decl_vendor =357      persistent_state->GetClangModulesDeclVendor();358  if (!decl_vendor)359    return;360 361  StackFrame *frame = exe_ctx.GetFramePtr();362  if (!frame)363    return;364 365  Block *block = frame->GetFrameBlock();366  if (!block)367    return;368  SymbolContext sc;369 370  block->CalculateSymbolContext(&sc);371 372  if (!sc.comp_unit)373    return;374  ClangModulesDeclVendor::ModuleVector modules_for_macros =375      persistent_state->GetHandLoadedClangModules();376 377  auto err =378      decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros);379  if (!err)380    return;381 382  // Module load errors aren't fatal to the expression evaluator. Printing383  // them as diagnostics to the console would be too noisy and misleading384  // Hence just print them to the expression log.385  llvm::handleAllErrors(std::move(err), [](const llvm::StringError &e) {386    LLDB_LOG(GetLog(LLDBLog::Expressions), "{0}", e.getMessage());387  });388}389 390ClangExpressionSourceCode::WrapKind ClangUserExpression::GetWrapKind() const {391  assert(m_options.GetExecutionPolicy() != eExecutionPolicyTopLevel &&392         "Top level expressions aren't wrapped.");393  using Kind = ClangExpressionSourceCode::WrapKind;394  if (m_in_cplusplus_method)395    return Kind::CppMemberFunction;396  else if (m_in_objectivec_method) {397    if (m_in_static_method)398      return Kind::ObjCStaticMethod;399    return Kind::ObjCInstanceMethod;400  }401  // Not in any kind of 'special' function, so just wrap it in a normal C402  // function.403  return Kind::Function;404}405 406void ClangUserExpression::CreateSourceCode(407    DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,408    std::vector<std::string> modules_to_import, bool for_completion) {409 410  std::string prefix = m_expr_prefix;411 412  if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {413    m_transformed_text = m_expr_text;414  } else {415    m_source_code.reset(ClangExpressionSourceCode::CreateWrapped(416        m_filename, prefix, m_expr_text, GetWrapKind()));417 418    if (!m_source_code->GetText(m_transformed_text, exe_ctx, !m_ctx_obj,419                                for_completion, modules_to_import)) {420      diagnostic_manager.PutString(lldb::eSeverityError,421                                   "couldn't construct expression body");422      return;423    }424 425    // Find and store the start position of the original code inside the426    // transformed code. We need this later for the code completion.427    std::size_t original_start;428    std::size_t original_end;429    bool found_bounds = m_source_code->GetOriginalBodyBounds(430        m_transformed_text, original_start, original_end);431    if (found_bounds)432      m_user_expression_start_pos = original_start;433  }434}435 436static bool SupportsCxxModuleImport(lldb::LanguageType language) {437  switch (language) {438  case lldb::eLanguageTypeC_plus_plus:439  case lldb::eLanguageTypeC_plus_plus_03:440  case lldb::eLanguageTypeC_plus_plus_11:441  case lldb::eLanguageTypeC_plus_plus_14:442  case lldb::eLanguageTypeObjC_plus_plus:443    return true;444  default:445    return false;446  }447}448 449/// Utility method that puts a message into the expression log and450/// returns an invalid module configuration.451static CppModuleConfiguration LogConfigError(const std::string &msg) {452  Log *log = GetLog(LLDBLog::Expressions);453  LLDB_LOG(log, "[C++ module config] {0}", msg);454  return CppModuleConfiguration();455}456 457CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,458                                       ExecutionContext &exe_ctx) {459  Log *log = GetLog(LLDBLog::Expressions);460 461  // Don't do anything if this is not a C++ module configuration.462  if (!SupportsCxxModuleImport(language))463    return LogConfigError("Language doesn't support C++ modules");464 465  Target *target = exe_ctx.GetTargetPtr();466  if (!target)467    return LogConfigError("No target");468 469  StackFrame *frame = exe_ctx.GetFramePtr();470  if (!frame)471    return LogConfigError("No frame");472 473  Block *block = frame->GetFrameBlock();474  if (!block)475    return LogConfigError("No block");476 477  SymbolContext sc;478  block->CalculateSymbolContext(&sc);479  if (!sc.comp_unit)480    return LogConfigError("Couldn't calculate symbol context");481 482  // Build a list of files we need to analyze to build the configuration.483  FileSpecList files;484  for (auto &f : sc.comp_unit->GetSupportFiles())485    files.AppendIfUnique(f->Materialize());486  // We also need to look at external modules in the case of -gmodules as they487  // contain the support files for libc++ and the C library.488  llvm::DenseSet<SymbolFile *> visited_symbol_files;489  sc.comp_unit->ForEachExternalModule(490      visited_symbol_files, [&files](Module &module) {491        for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {492          const SupportFileList &support_files =493              module.GetCompileUnitAtIndex(i)->GetSupportFiles();494          for (auto &f : support_files) {495            files.AppendIfUnique(f->Materialize());496          }497        }498        return false;499      });500 501  LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",502           files.GetSize());503  if (log && log->GetVerbose()) {504    for (auto &f : files)505      LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}",506                f.GetPath());507  }508 509  // Try to create a configuration from the files. If there is no valid510  // configuration possible with the files, this just returns an invalid511  // configuration.512  return CppModuleConfiguration(files, target->GetArchitecture().GetTriple());513}514 515bool ClangUserExpression::PrepareForParsing(516    DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,517    bool for_completion) {518  InstallContext(exe_ctx);519 520  if (!SetupPersistentState(diagnostic_manager, exe_ctx))521    return false;522 523  Status err;524  ScanContext(exe_ctx, err);525 526  if (!err.Success()) {527    diagnostic_manager.PutString(lldb::eSeverityWarning, err.AsCString());528  }529 530  ////////////////////////////////////531  // Generate the expression532  //533 534  ApplyObjcCastHack(m_expr_text);535 536  SetupDeclVendor(exe_ctx, m_target, diagnostic_manager);537 538  m_filename = m_clang_state->GetNextExprFileName();539 540  if (m_target->GetImportStdModule() == eImportStdModuleTrue)541    SetupCppModuleImports(exe_ctx);542 543  CreateSourceCode(diagnostic_manager, exe_ctx, m_imported_cpp_modules,544                   for_completion);545  return true;546}547 548bool ClangUserExpression::TryParse(549    DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,550    lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory,551    bool generate_debug_info) {552  m_materializer_up = std::make_unique<Materializer>();553 554  ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);555 556  auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });557 558  if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {559    diagnostic_manager.PutString(560        lldb::eSeverityError,561        "current process state is unsuitable for expression parsing");562    return false;563  }564 565  if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {566    DeclMap()->SetLookupsEnabled(true);567  }568 569  m_parser = std::make_unique<ClangExpressionParser>(570      exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info,571      diagnostic_manager, m_include_directories, m_filename);572 573  unsigned num_errors = m_parser->Parse(diagnostic_manager);574 575  // Check here for FixItHints.  If there are any try to apply the fixits and576  // set the fixed text in m_fixed_text before returning an error.577  if (num_errors) {578    if (diagnostic_manager.HasFixIts()) {579      if (m_parser->RewriteExpression(diagnostic_manager)) {580        size_t fixed_start;581        size_t fixed_end;582        m_fixed_text = diagnostic_manager.GetFixedExpression();583        // Retrieve the original expression in case we don't have a top level584        // expression (which has no surrounding source code).585        if (m_source_code && m_source_code->GetOriginalBodyBounds(586                                 m_fixed_text, fixed_start, fixed_end))587          m_fixed_text =588              m_fixed_text.substr(fixed_start, fixed_end - fixed_start);589      }590    }591    return false;592  }593 594  //////////////////////////////////////////////////////////////////////////////595  // Prepare the output of the parser for execution, evaluating it statically596  // if possible597  //598 599  {600    Status jit_error = m_parser->PrepareForExecution(601        m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,602        m_can_interpret, execution_policy);603 604    if (!jit_error.Success()) {605      const char *error_cstr = jit_error.AsCString();606      if (error_cstr && error_cstr[0])607        diagnostic_manager.PutString(lldb::eSeverityError, error_cstr);608      else609        diagnostic_manager.PutString(lldb::eSeverityError,610                                     "expression can't be interpreted or run");611      return false;612    }613  }614  return true;615}616 617void ClangUserExpression::SetupCppModuleImports(ExecutionContext &exe_ctx) {618  Log *log = GetLog(LLDBLog::Expressions);619 620  CppModuleConfiguration module_config =621      GetModuleConfig(m_language.AsLanguageType(), exe_ctx);622  m_imported_cpp_modules = module_config.GetImportedModules();623  m_include_directories = module_config.GetIncludeDirs();624 625  LLDB_LOG(log, "List of imported modules in expression: {0}",626           llvm::make_range(m_imported_cpp_modules.begin(),627                            m_imported_cpp_modules.end()));628  LLDB_LOG(log, "List of include directories gathered for modules: {0}",629           llvm::make_range(m_include_directories.begin(),630                            m_include_directories.end()));631}632 633static bool shouldRetryWithCppModule(Target &target, ExecutionPolicy exe_policy) {634  // Top-level expression don't yet support importing C++ modules.635  if (exe_policy == ExecutionPolicy::eExecutionPolicyTopLevel)636    return false;637  return target.GetImportStdModule() == eImportStdModuleFallback;638}639 640bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,641                                ExecutionContext &exe_ctx,642                                lldb_private::ExecutionPolicy execution_policy,643                                bool keep_result_in_memory,644                                bool generate_debug_info) {645  Log *log = GetLog(LLDBLog::Expressions);646 647  if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ false))648    return false;649 650  LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());651 652  ////////////////////////////////////653  // Set up the target and compiler654  //655 656  Target *target = exe_ctx.GetTargetPtr();657 658  if (!target) {659    diagnostic_manager.PutString(lldb::eSeverityError, "invalid target");660    return false;661  }662 663  //////////////////////////664  // Parse the expression665  //666 667  bool parse_success = TryParse(diagnostic_manager, exe_ctx, execution_policy,668                                keep_result_in_memory, generate_debug_info);669  // If the expression failed to parse, check if retrying parsing with a loaded670  // C++ module is possible.671  if (!parse_success && shouldRetryWithCppModule(*target, execution_policy)) {672    // Load the loaded C++ modules.673    SetupCppModuleImports(exe_ctx);674    // If we did load any modules, then retry parsing.675    if (!m_imported_cpp_modules.empty()) {676      // Create a dedicated diagnostic manager for the second parse attempt.677      // These diagnostics are only returned to the caller if using the fallback678      // actually succeeded in getting the expression to parse. This prevents679      // that module-specific issues regress diagnostic quality with the680      // fallback mode.681      DiagnosticManager retry_manager;682      // The module imports are injected into the source code wrapper,683      // so recreate those.684      CreateSourceCode(retry_manager, exe_ctx, m_imported_cpp_modules,685                       /*for_completion*/ false);686      parse_success = TryParse(retry_manager, exe_ctx, execution_policy,687                               keep_result_in_memory, generate_debug_info);688      // Return the parse diagnostics if we were successful.689      if (parse_success)690        diagnostic_manager = std::move(retry_manager);691    }692  }693  if (!parse_success)694    return false;695 696  if (m_execution_unit_sp) {697    bool register_execution_unit = false;698 699    if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {700      register_execution_unit = true;701    }702 703    // If there is more than one external function in the execution unit, it704    // needs to keep living even if it's not top level, because the result705    // could refer to that function.706 707    if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {708      register_execution_unit = true;709    }710 711    if (register_execution_unit) {712      if (auto *persistent_state =713              exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(714                  m_language.AsLanguageType()))715        persistent_state->RegisterExecutionUnit(m_execution_unit_sp);716    }717  }718 719  if (generate_debug_info) {720    lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());721 722    if (jit_module_sp) {723      ConstString const_func_name(FunctionName());724      FileSpec jit_file;725      jit_file.SetFilename(const_func_name);726      jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());727      m_jit_module_wp = jit_module_sp;728      target->GetImages().Append(jit_module_sp);729    }730  }731 732  Process *process = exe_ctx.GetProcessPtr();733  if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)734    m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());735  return true;736}737 738/// Converts an absolute position inside a given code string into739/// a column/line pair.740///741/// \param[in] abs_pos742///     A absolute position in the code string that we want to convert743///     to a column/line pair.744///745/// \param[in] code746///     A multi-line string usually representing source code.747///748/// \param[out] line749///     The line in the code that contains the given absolute position.750///     The first line in the string is indexed as 1.751///752/// \param[out] column753///     The column in the line that contains the absolute position.754///     The first character in a line is indexed as 0.755static void AbsPosToLineColumnPos(size_t abs_pos, llvm::StringRef code,756                                  unsigned &line, unsigned &column) {757  // Reset to code position to beginning of the file.758  line = 0;759  column = 0;760 761  assert(abs_pos <= code.size() && "Absolute position outside code string?");762 763  // We have to walk up to the position and count lines/columns.764  for (std::size_t i = 0; i < abs_pos; ++i) {765    // If we hit a line break, we go back to column 0 and enter a new line.766    // We only handle \n because that's what we internally use to make new767    // lines for our temporary code strings.768    if (code[i] == '\n') {769      ++line;770      column = 0;771      continue;772    }773    ++column;774  }775}776 777bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,778                                   CompletionRequest &request,779                                   unsigned complete_pos) {780  Log *log = GetLog(LLDBLog::Expressions);781 782  // We don't want any visible feedback when completing an expression. Mostly783  // because the results we get from an incomplete invocation are probably not784  // correct.785  DiagnosticManager diagnostic_manager;786 787  if (!PrepareForParsing(diagnostic_manager, exe_ctx, /*for_completion*/ true))788    return false;789 790  LLDB_LOGF(log, "Parsing the following code:\n%s", m_transformed_text.c_str());791 792  //////////////////////////793  // Parse the expression794  //795 796  m_materializer_up = std::make_unique<Materializer>();797 798  ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);799 800  auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });801 802  if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {803    diagnostic_manager.PutString(804        lldb::eSeverityError,805        "current process state is unsuitable for expression parsing");806 807    return false;808  }809 810  if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {811    DeclMap()->SetLookupsEnabled(true);812  }813 814  ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this,815                               false, diagnostic_manager);816 817  // We have to find the source code location where the user text is inside818  // the transformed expression code. When creating the transformed text, we819  // already stored the absolute position in the m_transformed_text string. The820  // only thing left to do is to transform it into the line:column format that821  // Clang expects.822 823  // The line and column of the user expression inside the transformed source824  // code.825  unsigned user_expr_line, user_expr_column;826  if (m_user_expression_start_pos)827    AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text,828                          user_expr_line, user_expr_column);829  else830    return false;831 832  // The actual column where we have to complete is the start column of the833  // user expression + the offset inside the user code that we were given.834  const unsigned completion_column = user_expr_column + complete_pos;835  parser.Complete(request, user_expr_line, completion_column, complete_pos);836 837  return true;838}839 840lldb::addr_t ClangUserExpression::GetCppObjectPointer(841    lldb::StackFrameSP frame_sp, llvm::StringRef object_name, Status &err) {842  auto valobj_sp =843      GetObjectPointerValueObject(std::move(frame_sp), object_name, err);844 845  // We're inside a C++ class method. This could potentially be an unnamed846  // lambda structure. If the lambda captured a "this", that should be847  // the object pointer.848  if (auto thisChildSP = valobj_sp->GetChildMemberWithName("this")) {849    valobj_sp = thisChildSP;850  }851 852  if (!err.Success() || !valobj_sp.get())853    return LLDB_INVALID_ADDRESS;854 855  lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);856 857  if (ret == LLDB_INVALID_ADDRESS) {858    err = Status::FromErrorStringWithFormatv(859        "Couldn't load '{0}' because its value couldn't be evaluated",860        object_name);861    return LLDB_INVALID_ADDRESS;862  }863 864  return ret;865}866 867bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,868                                       std::vector<lldb::addr_t> &args,869                                       lldb::addr_t struct_address,870                                       DiagnosticManager &diagnostic_manager) {871  lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;872  lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;873 874  if (m_needs_object_ptr) {875    lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();876    if (!frame_sp)877      return true;878 879    if (!m_in_cplusplus_method && !m_in_objectivec_method) {880      diagnostic_manager.PutString(881          lldb::eSeverityError,882          "need object pointer but don't know the language");883      return false;884    }885 886    static constexpr llvm::StringLiteral g_cplusplus_object_name("this");887    static constexpr llvm::StringLiteral g_objc_object_name("self");888    llvm::StringRef object_name =889        m_in_cplusplus_method ? g_cplusplus_object_name : g_objc_object_name;890 891    Status object_ptr_error;892 893    if (m_ctx_obj) {894      ValueObject::AddrAndType address = m_ctx_obj->GetAddressOf(false);895      if (address.address == LLDB_INVALID_ADDRESS ||896          address.type != eAddressTypeLoad)897        object_ptr_error = Status::FromErrorString("Can't get context object's "898                                                   "debuggee address");899      else900        object_ptr = address.address;901    } else {902      if (m_in_cplusplus_method) {903        object_ptr =904            GetCppObjectPointer(frame_sp, object_name, object_ptr_error);905      } else {906        object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);907      }908    }909 910    if (!object_ptr_error.Success()) {911      exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Format(912          "warning: `{0}' is not accessible (substituting 0). {1}\n",913          object_name, object_ptr_error.AsCString());914      object_ptr = 0;915    }916 917    if (m_in_objectivec_method) {918      static constexpr llvm::StringLiteral cmd_name("_cmd");919 920      cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);921 922      if (!object_ptr_error.Success()) {923        diagnostic_manager.Printf(924            lldb::eSeverityWarning,925            "couldn't get cmd pointer (substituting NULL): %s",926            object_ptr_error.AsCString());927        cmd_ptr = 0;928      }929    }930 931    args.push_back(object_ptr);932 933    if (m_in_objectivec_method)934      args.push_back(cmd_ptr);935 936    args.push_back(struct_address);937  } else {938    args.push_back(struct_address);939  }940  return true;941}942 943lldb::ExpressionVariableSP ClangUserExpression::GetResultAfterDematerialization(944    ExecutionContextScope *exe_scope) {945  return m_result_delegate.GetVariable();946}947 948char ClangUserExpression::ClangUserExpressionHelper::ID;949 950void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(951    ExecutionContext &exe_ctx,952    Materializer::PersistentVariableDelegate &delegate,953    bool keep_result_in_memory,954    ValueObject *ctx_obj) {955  std::shared_ptr<ClangASTImporter> ast_importer;956  auto *state = exe_ctx.GetTargetSP()->GetPersistentExpressionStateForLanguage(957      lldb::eLanguageTypeC);958  if (state) {959    auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);960    ast_importer = persistent_vars->GetClangASTImporter();961  }962  m_expr_decl_map_up = std::make_unique<ClangExpressionDeclMap>(963      keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(), ast_importer,964      ctx_obj);965}966 967clang::ASTConsumer *968ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(969    clang::ASTConsumer *passthrough) {970  m_result_synthesizer_up = std::make_unique<ASTResultSynthesizer>(971      passthrough, m_top_level, m_target);972 973  return m_result_synthesizer_up.get();974}975 976void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {977  if (m_result_synthesizer_up) {978    m_result_synthesizer_up->CommitPersistentDecls();979  }980}981 982ConstString ClangUserExpression::ResultDelegate::GetName() {983  return m_persistent_state->GetNextPersistentVariableName(false);984}985 986void ClangUserExpression::ResultDelegate::DidDematerialize(987    lldb::ExpressionVariableSP &variable) {988  m_variable = variable;989}990 991void ClangUserExpression::ResultDelegate::RegisterPersistentState(992    PersistentExpressionState *persistent_state) {993  m_persistent_state = persistent_state;994}995 996lldb::ExpressionVariableSP &ClangUserExpression::ResultDelegate::GetVariable() {997  return m_variable;998}999