[Lldb-commits] [lldb] [lldb-dap] Allow evaluate requests without a frame context (PR #179667)

Ebuka Ezike via lldb-commits lldb-commits at lists.llvm.org
Wed Feb 4 06:57:52 PST 2026


================
@@ -23,24 +24,69 @@ using namespace lldb_dap::protocol;
 
 namespace lldb_dap {
 
+static bool RunExpressionAsLLDBCommand(DAP &dap, lldb::SBFrame &frame,
+                                       std::string &expression,
+                                       EvaluateContext context) {
+  if (context != eEvaluateContextRepl && context != eEvaluateContextUnknown)
+    return false;
+
+  // Since we don't know this context do not try to repeat the last command;
+  if (context == eEvaluateContextUnknown && expression.empty())
+    return false;
+
+  const bool repeat_last_command =
+      expression.empty() && dap.last_valid_variable_expression.empty();
+  if (repeat_last_command)
+    return true;
+
+  const ReplMode repl_mode = dap.DetectReplMode(frame, expression, false);
+  return repl_mode == ReplMode::Command;
+}
+
+static lldb::SBValue EvaluateVariableExpression(lldb::SBTarget &target,
+                                                lldb::SBFrame &frame,
+                                                llvm::StringRef expression,
+                                                bool run_as_expression) {
+  const char *expression_cstr = expression.data();
+
+  lldb::SBValue value;
+  if (frame) {
+    // Check if it is a variable or an expression path for a variable. i.e.
+    // 'foo->bar' finds the 'bar' variable. It is more reliable than the
+    // expression parser in many cases and it is faster.
+    value = frame.GetValueForVariablePath(expression_cstr,
+                                          lldb::eDynamicDontRunTarget);
+    if (value || !run_as_expression)
+      return value;
+
+    return frame.EvaluateExpression(expression_cstr);
+  }
+
+  if (run_as_expression)
+    value = target.EvaluateExpression(expression_cstr);
+
+  return value;
+}
+
 /// Evaluates the given expression in the context of a stack frame.
 ///
 /// The expression has access to any variables and arguments that are in scope.
 Expected<EvaluateResponseBody>
 EvaluateRequestHandler::Run(const EvaluateArguments &arguments) const {
+  const lldb::StateType process_state = dap.target.GetProcess().GetState();
+  if (!lldb::SBDebugger::StateIsStoppedState(process_state))
+    return llvm::make_error<NotStoppedError>();
----------------
da-viper wrote:

> To be honest, I expect that VS Code or other clients always send correct context, so we might omit checks that context is unknown

The context is optional. The client may omit the context entirely (currently the case in clion DAP) or the protocol adds a new context in the future. see https://microsoft.github.io/debug-adapter-protocol//specification.html#Requests_Evaluate

https://github.com/llvm/llvm-project/pull/179667


More information about the lldb-commits mailing list