[Lldb-commits] [lldb] [LLDB] Add DIL code for handling plain variable names. (PR #120971)

via lldb-commits lldb-commits at lists.llvm.org
Mon Dec 23 07:01:45 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: None (cmtice)

<details>
<summary>Changes</summary>

Add the Data Inspection Language (DIL) implementation pieces for handling plain local and global variable names.

See https://discourse.llvm.org/t/rfc-data-inspection-language/69893 for information about DIL.

This change includes the basic AST, Lexer, Parser and Evaluator pieces, as well as some tests.

---

Patch is 63.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/120971.diff


20 Files Affected:

- (added) lldb/docs/dil-expr-lang.ebnf (+40) 
- (added) lldb/include/lldb/ValueObject/DILAST.h (+161) 
- (added) lldb/include/lldb/ValueObject/DILEval.h (+62) 
- (added) lldb/include/lldb/ValueObject/DILLexer.h (+166) 
- (added) lldb/include/lldb/ValueObject/DILParser.h (+105) 
- (modified) lldb/source/Target/StackFrame.cpp (+45-7) 
- (modified) lldb/source/ValueObject/CMakeLists.txt (+4) 
- (added) lldb/source/ValueObject/DILAST.cpp (+228) 
- (added) lldb/source/ValueObject/DILEval.cpp (+117) 
- (added) lldb/source/ValueObject/DILLexer.cpp (+191) 
- (added) lldb/source/ValueObject/DILParser.cpp (+356) 
- (added) lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/Makefile (+3) 
- (added) lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/TestFrameVarDILGlobalVariableLookup.py (+82) 
- (added) lldb/test/API/commands/frame/var-dil/basics/GlobalVariableLookup/main.cpp (+18) 
- (added) lldb/test/API/commands/frame/var-dil/basics/InstanceVariables/Makefile (+3) 
- (added) lldb/test/API/commands/frame/var-dil/basics/InstanceVariables/TestFrameVarDILInstanceVariables.py (+62) 
- (added) lldb/test/API/commands/frame/var-dil/basics/InstanceVariables/main.cpp (+25) 
- (added) lldb/test/API/commands/frame/var-dil/basics/LocalVars/Makefile (+3) 
- (added) lldb/test/API/commands/frame/var-dil/basics/LocalVars/TestFrameVarDILLocalVars.py (+65) 
- (added) lldb/test/API/commands/frame/var-dil/basics/LocalVars/main.cpp (+26) 


``````````diff
diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf
new file mode 100644
index 00000000000000..64b3e7758229c2
--- /dev/null
+++ b/lldb/docs/dil-expr-lang.ebnf
@@ -0,0 +1,40 @@
+(* Data Inspection Language (DIL) definition - LLDB Debug Expressions *)
+
+(* This is currently a subset of the final DIL Language, matching the current
+   DIL implementation. *)
+
+expression = primary_expression ;
+
+primary_expression = id_expression
+                   | "this"
+                   | "(" expression ")";
+
+id_expression = unqualified_id
+              | qualified_id ;
+
+unqualified_id = identifier ;
+
+qualified_id = ["::"] [nested_name_specifier] unqualified_id
+             | ["::"] identifier ;
+
+identifier = ? dil::TokenKind::identifier ? ;
+
+nested_name_specifier = type_name "::"
+                      | namespace_name '::'
+                      | nested_name_specifier identifier "::" ;
+
+type_name = class_name
+          | enum_name
+          | typedef_name;
+
+class_name = identifier ;
+
+enum_name = identifier ;
+
+typedef_name = identifier ;
+
+namespace_name = identifier ;
+
+
+
+
diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h
new file mode 100644
index 00000000000000..9f0a1a2221e388
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -0,0 +1,161 @@
+//===-- DILAST.h ------------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_VALUEOBJECT_DILAST_H
+#define LLDB_VALUEOBJECT_DILAST_H
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "lldb/ValueObject/ValueObject.h"
+
+namespace lldb_private {
+
+namespace dil {
+
+/// The various types DIL AST nodes (used by the DIL parser).
+enum class NodeKind {
+  eErrorNode,
+  eIdentifierNode,
+};
+
+/// Class used to store & manipulate information about identifiers.
+class IdentifierInfo {
+public:
+  enum class Kind {
+    eValue,
+    eContextArg,
+  };
+
+  static std::unique_ptr<IdentifierInfo> FromValue(ValueObject &valobj) {
+    CompilerType type;
+    type = valobj.GetCompilerType();
+    return std::unique_ptr<IdentifierInfo>(
+        new IdentifierInfo(Kind::eValue, type, valobj.GetSP(), {}));
+  }
+
+  static std::unique_ptr<IdentifierInfo> FromContextArg(CompilerType type) {
+    lldb::ValueObjectSP empty_value;
+    return std::unique_ptr<IdentifierInfo>(
+        new IdentifierInfo(Kind::eContextArg, type, empty_value, {}));
+  }
+
+  Kind GetKind() const { return m_kind; }
+  lldb::ValueObjectSP GetValue() const { return m_value; }
+
+  CompilerType GetType() { return m_type; }
+  bool IsValid() const { return m_type.IsValid(); }
+
+  IdentifierInfo(Kind kind, CompilerType type, lldb::ValueObjectSP value,
+                 std::vector<uint32_t> path)
+      : m_kind(kind), m_type(type), m_value(std::move(value)) {}
+
+private:
+  Kind m_kind;
+  CompilerType m_type;
+  lldb::ValueObjectSP m_value;
+};
+
+/// Given the name of an identifier (variable name, member name, type name,
+/// etc.), find the ValueObject for that name (if it exists) and create and
+/// return an IdentifierInfo object containing all the relevant information
+/// about that object (for DIL parsing and evaluating).
+std::unique_ptr<IdentifierInfo> LookupIdentifier(
+    const std::string &name, std::shared_ptr<ExecutionContextScope> ctx_scope,
+    lldb::DynamicValueType use_dynamic, CompilerType *scope_ptr = nullptr);
+
+/// Forward declaration, for use in DIL AST nodes. Definition is at the very
+/// end of this file.
+class Visitor;
+
+/// The rest of the classes in this file, except for the Visitor class at the
+/// very end, define all the types of AST nodes used by the DIL parser and
+/// expression evaluator. The DIL parser parses the input string and creates
+/// the AST parse tree from the AST nodes. The resulting AST node tree gets
+/// passed to the DIL expression evaluator, which evaluates the DIL AST nodes
+/// and creates/returns a ValueObjectSP containing the result.
+
+/// Base class for AST nodes used by the Data Inspection Language (DIL) parser.
+/// All of the specialized types of AST nodes inherit from this (virtual) base
+/// class.
+class DILASTNode {
+public:
+  DILASTNode(uint32_t location, NodeKind kind)
+      : m_location(location), m_kind(kind) {}
+  virtual ~DILASTNode() = default;
+
+  virtual void Accept(Visitor *v) const = 0;
+
+  uint32_t GetLocation() const { return m_location; }
+  NodeKind GetKind() const { return m_kind; }
+
+private:
+  uint32_t m_location;
+  const NodeKind m_kind;
+};
+
+using DILASTNodeUP = std::unique_ptr<DILASTNode>;
+
+class ErrorNode : public DILASTNode {
+public:
+  ErrorNode(CompilerType empty_type)
+      : DILASTNode(0, NodeKind::eErrorNode), m_empty_type(empty_type) {}
+  void Accept(Visitor *v) const override;
+
+  static bool classof(const DILASTNode *node) {
+    return node->GetKind() == NodeKind::eErrorNode;
+  }
+
+private:
+  CompilerType m_empty_type;
+};
+
+class IdentifierNode : public DILASTNode {
+public:
+  IdentifierNode(uint32_t location, std::string name,
+                 lldb::DynamicValueType use_dynamic,
+                 std::shared_ptr<ExecutionContextScope> exe_ctx_scope)
+      : DILASTNode(location, NodeKind::eIdentifierNode),
+        m_name(std::move(name)), m_use_dynamic(use_dynamic),
+        m_ctx_scope(exe_ctx_scope) {}
+
+  void Accept(Visitor *v) const override;
+
+  lldb::DynamicValueType use_dynamic() const { return m_use_dynamic; }
+  std::string name() const { return m_name; }
+  std::shared_ptr<ExecutionContextScope> get_exe_context() const {
+    return m_ctx_scope;
+  }
+
+  static bool classof(const DILASTNode *node) {
+    return node->GetKind() == NodeKind::eIdentifierNode;
+  }
+
+private:
+  std::string m_name;
+  lldb::DynamicValueType m_use_dynamic;
+  std::shared_ptr<ExecutionContextScope> m_ctx_scope;
+};
+
+/// This class contains one Visit method for each specialized type of
+/// DIL AST node. The Visit methods are used to dispatch a DIL AST node to
+/// the correct function in the DIL expression evaluator for evaluating that
+/// type of AST node.
+class Visitor {
+public:
+  virtual ~Visitor() = default;
+  virtual void Visit(const ErrorNode *node) = 0;
+  virtual void Visit(const IdentifierNode *node) = 0;
+};
+
+} // namespace dil
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_DILAST_H
diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
new file mode 100644
index 00000000000000..4006bb10630f24
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -0,0 +1,62 @@
+//===-- DILEval.h -----------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_VALUEOBJECT_DILEVAL_H_
+#define LLDB_VALUEOBJECT_DILEVAL_H_
+
+#include <memory>
+#include <vector>
+
+#include "lldb/ValueObject/DILAST.h"
+#include "lldb/ValueObject/DILParser.h"
+
+namespace lldb_private {
+
+namespace dil {
+
+class DILInterpreter : Visitor {
+public:
+  DILInterpreter(lldb::TargetSP target, std::shared_ptr<std::string> sm);
+  DILInterpreter(lldb::TargetSP target, std::shared_ptr<std::string> sm,
+                 lldb::ValueObjectSP scope);
+  DILInterpreter(lldb::TargetSP target, std::shared_ptr<std::string> sm,
+                 lldb::DynamicValueType use_dynamic);
+
+  lldb::ValueObjectSP DILEval(const DILASTNode *tree, lldb::TargetSP target_sp,
+                              Status &error);
+
+private:
+  lldb::ValueObjectSP DILEvalNode(const DILASTNode *node);
+
+  bool Success() { return m_error.Success(); }
+
+  void SetError(ErrorCode error_code, std::string error, uint32_t loc);
+
+  void Visit(const ErrorNode *node) override;
+  void Visit(const IdentifierNode *node) override;
+
+private:
+  // Used by the interpreter to create objects, perform casts, etc.
+  lldb::TargetSP m_target;
+
+  std::shared_ptr<std::string> m_sm;
+
+  lldb::ValueObjectSP m_result;
+
+  lldb::ValueObjectSP m_scope;
+
+  lldb::DynamicValueType m_default_dynamic;
+
+  Status m_error;
+};
+
+} // namespace dil
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_DILEVAL_H_
diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
new file mode 100644
index 00000000000000..c794fb2bfc0ed3
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -0,0 +1,166 @@
+//===-- DILLexer.h ----------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_VALUEOBJECT_DILLEXER_H_
+#define LLDB_VALUEOBJECT_DILLEXER_H_
+
+#include <limits.h>
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "llvm/ADT/StringRef.h"
+
+namespace lldb_private {
+
+namespace dil {
+
+enum class TokenKind {
+  coloncolon,
+  eof,
+  identifier,
+  invalid,
+  kw_namespace,
+  kw_this,
+  l_paren,
+  none,
+  r_paren,
+  unknown,
+};
+
+/// Class defining the tokens generated by the DIL lexer and used by the
+/// DIL parser.
+class DILToken {
+public:
+  DILToken(dil::TokenKind kind, std::string spelling, uint32_t start,
+           uint32_t len)
+      : m_kind(kind), m_spelling(spelling), m_start_pos(start), m_length(len) {}
+
+  DILToken()
+      : m_kind(dil::TokenKind::none), m_spelling(""), m_start_pos(0),
+        m_length(0) {}
+
+  void setKind(dil::TokenKind kind) { m_kind = kind; }
+  dil::TokenKind getKind() const { return m_kind; }
+
+  std::string getSpelling() const { return m_spelling; }
+
+  uint32_t getLength() const { return m_length; }
+
+  bool is(dil::TokenKind kind) const { return m_kind == kind; }
+
+  bool isNot(dil::TokenKind kind) const { return m_kind != kind; }
+
+  bool isOneOf(dil::TokenKind kind1, dil::TokenKind kind2) const {
+    return is(kind1) || is(kind2);
+  }
+
+  template <typename... Ts> bool isOneOf(dil::TokenKind kind, Ts... Ks) const {
+    return is(kind) || isOneOf(Ks...);
+  }
+
+  uint32_t getLocation() const { return m_start_pos; }
+
+  void setValues(dil::TokenKind kind, std::string spelling, uint32_t start,
+                 uint32_t len) {
+    m_kind = kind;
+    m_spelling = spelling;
+    m_start_pos = start;
+    m_length = len;
+  }
+
+  static const std::string getTokenName(dil::TokenKind kind);
+
+private:
+  dil::TokenKind m_kind;
+  std::string m_spelling;
+  uint32_t m_start_pos; // within entire expression string
+  uint32_t m_length;
+};
+
+/// Class for doing the simple lexing required by DIL.
+class DILLexer {
+public:
+  DILLexer(std::shared_ptr<std::string> dil_sm) : m_expr(*dil_sm) {
+    m_cur_pos = m_expr.begin();
+    // Use UINT_MAX to indicate invalid/uninitialized value.
+    m_tokens_idx = UINT_MAX;
+  }
+
+  bool Lex(DILToken &result, bool look_ahead = false);
+
+  bool Is_Word(std::string::iterator start, uint32_t &length);
+
+  uint32_t GetLocation() { return m_cur_pos - m_expr.begin(); }
+
+  /// Update 'result' with the other paremeter values, create a
+  /// duplicate token, and push the duplicate token onto the vector of
+  /// lexed tokens.
+  void UpdateLexedTokens(DILToken &result, dil::TokenKind tok_kind,
+                         std::string tok_str, uint32_t tok_pos,
+                         uint32_t tok_len);
+
+  /// Return the lexed token N+1 positions ahead of the 'current' token
+  /// being handled by the DIL parser.
+  const DILToken &LookAhead(uint32_t N);
+
+  const DILToken &AcceptLookAhead(uint32_t N);
+
+  /// Return the index for the 'current' token being handled by the DIL parser.
+  uint32_t GetCurrentTokenIdx() { return m_tokens_idx; }
+
+  /// Return the current token to be handled by the DIL parser.
+  DILToken &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; }
+
+  /// Update the index for the 'current' token, to point to the next lexed
+  /// token.
+  bool IncrementTokenIdx() {
+    if (m_tokens_idx >= m_lexed_tokens.size() - 1)
+      return false;
+
+    m_tokens_idx++;
+    return true;
+  }
+
+  /// Set the index for the 'current' token (to be handled by the parser)
+  /// to a particular position. Used for either committing 'look ahead' parsing
+  /// or rolling back tentative parsing.
+  bool ResetTokenIdx(uint32_t new_value) {
+    if (new_value > m_lexed_tokens.size() - 1)
+      return false;
+
+    m_tokens_idx = new_value;
+    return true;
+  }
+
+private:
+  // The input string we are lexing & parsing.
+  std::string m_expr;
+
+  // The current position of the lexer within m_expr (the character position,
+  // within the string, of the next item to be lexed).
+  std::string::iterator m_cur_pos;
+
+  // Holds all of the tokens lexed so far.
+  std::vector<DILToken> m_lexed_tokens;
+
+  // Index into m_lexed_tokens; indicates which token the DIL parser is
+  // currently trying to parse/handle.
+  uint32_t m_tokens_idx;
+
+  // "invalid" token; to be returned by lexer when 'look ahead' fails.
+  DILToken m_invalid_token;
+};
+
+} // namespace dil
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_DILLEXER_H_
diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h
new file mode 100644
index 00000000000000..b718903b7bea49
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/DILParser.h
@@ -0,0 +1,105 @@
+//===-- DILParser.h ---------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_VALUEOBJECT_DILPARSER_H_
+#define LLDB_VALUEOBJECT_DILPARSER_H_
+
+#include <memory>
+#include <optional>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/ValueObject/DILAST.h"
+#include "lldb/ValueObject/DILLexer.h"
+
+namespace lldb_private {
+
+namespace dil {
+
+enum class ErrorCode : unsigned char {
+  kOk = 0,
+  kInvalidExpressionSyntax,
+  kUndeclaredIdentifier,
+  kUnknown,
+};
+
+std::string FormatDiagnostics(std::shared_ptr<std::string> input_expr,
+                              const std::string &message, uint32_t loc);
+
+/// Pure recursive descent parser for C++ like expressions.
+/// EBNF grammar for the parser is described in lldb/docs/dil-expr-lang.ebnf
+class DILParser {
+public:
+  explicit DILParser(std::shared_ptr<std::string> dil_input_expr,
+                     std::shared_ptr<ExecutionContextScope> exe_ctx_scope,
+                     lldb::DynamicValueType use_dynamic, bool use_synthetic,
+                     bool fragile_ivar, bool check_ptr_vs_member);
+
+  DILASTNodeUP Run(Status &error);
+
+  ~DILParser() { m_ctx_scope.reset(); }
+
+  bool UseSynthetic() { return m_use_synthetic; }
+
+  lldb::DynamicValueType UseDynamic() { return m_use_dynamic; }
+
+  using PtrOperator = std::tuple<dil::TokenKind, uint32_t>;
+
+private:
+  DILASTNodeUP ParseExpression();
+  DILASTNodeUP ParsePrimaryExpression();
+
+  std::string ParseNestedNameSpecifier();
+
+  std::string ParseIdExpression();
+  std::string ParseUnqualifiedId();
+
+  void ConsumeToken();
+
+  void BailOut(ErrorCode error_code, const std::string &error, uint32_t loc);
+
+  void BailOut(Status error);
+
+  void Expect(dil::TokenKind kind);
+
+  std::string TokenDescription(const DILToken &token);
+
+  template <typename... Ts> void ExpectOneOf(dil::TokenKind k, Ts... ks);
+
+  void TentativeParsingRollback(uint32_t saved_idx) {
+    m_error.Clear();
+    m_dil_lexer.ResetTokenIdx(saved_idx);
+    m_dil_token = m_dil_lexer.GetCurrentToken();
+  }
+
+  // Parser doesn't own the evaluation context. The produced AST may depend on
+  // it (for example, for source locations), so it's expected that expression
+  // context will outlive the parser.
+  std::shared_ptr<ExecutionContextScope> m_ctx_scope;
+
+  std::shared_ptr<std::string> m_input_expr;
+  // The token lexer is stopped at (aka "current token").
+  DILToken m_dil_token;
+  // Holds an error if it occures during parsing.
+  Status m_error;
+
+  lldb::DynamicValueType m_use_dynamic;
+  bool m_use_synthetic;
+  bool m_fragile_ivar;
+  bool m_check_ptr_vs_member;
+  DILLexer m_dil_lexer;
+}; // class DILParser
+
+} // namespace dil
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_DILPARSER_H_
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index 2633c976c13bf4..28450b1d1c1c1e 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -31,6 +31,8 @@
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
 #include "lldb/Utility/RegisterValue.h"
+#include "lldb/ValueObject/DILEval.h"
+#include "lldb/ValueObject/DILParser.h"
 #include "lldb/ValueObject/ValueObjectConstResult.h"
 #include "lldb/ValueObject/ValueObjectMemory.h"
 #include "lldb/ValueObject/ValueObjectVariable.h"
@@ -511,22 +513,58 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
     VariableSP &var_sp, Status &error) {
   ExecutionContext exe_ctx;
   CalculateExecutionContext(exe_ctx);
+
   bool use_DIL = exe_ctx.GetTargetRef().GetUseDIL(&exe_ctx);
+
   if (use_DIL)
     return DILGetValueForVariableExpressionPath(var_expr, use_dynamic, options,
                                                 var_sp, error);
-
-  return LegacyGetValueForVariableExpressionPath(var_expr, use_dynamic, options,
-                                                 var_sp, error);
+  else
+    return LegacyGetValueForVariableExpressionPath(var_expr, use_dynamic,
+                                                   options, var_sp, error);
 }
 
 ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath(
     llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
     uint32_t options, lldb::VariableSP &var_sp, Status &error) {
-  // This is a place-holder for the calls into the DIL parser and
-  // evaluator.  For now, just call the "real" frame variable implementation.
-  return LegacyGetValueForVariableExpressionPath(var_expr, use_dynamic, options,
-                                                 var_sp, error);
+  ValueObjectSP ret_val;
+  std::shared_ptr<std::string> source =
+      std::make_shared<std::string>(var_expr.data());
+
+  const bool check_ptr_vs_member =
+      (options & eExpressionPathOptionCheckPtrVsMember) != 0;
+  const bool no_fragile_ivar =
+      (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
+  const bool no_synth_child =
+      (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
+
+  // Parse the expression.
+  Status parse_error, eval_error;
+  dil::DILParser parser(source, shared_from_this(), use_dynamic,
+                        !no_synth_child, !no_fragile_ivar, check_ptr_vs_member);
+  dil::DILASTNodeUP tree = parser.Run(parse_error);
+  if (parse_error.Fail()) {
+    error = std::move(parse_error);
+    return ValueObjectSP();
+  }
+
+  // Evaluate the parsed expression.
+  lldb::TargetSP target = this->CalculateTarget();
+  dil::DILInterpreter interpreter(target, source, use_dynamic);
+
+  ret_val = interpreter.DILEval(tree.get(), target, eval_error);
+  if (eval_error.Fail()) {
+    error = std::move(eval_error);
+    return ValueObjectSP();
+  }
+
+  if (ret_val) {
+    var_sp = ret_val->GetVariable();
+    if (!var_sp && ret_val->GetParent()) {
+      var_sp = ret_val->GetParent()->GetVariable();
+    }
+  }
+  return ret_val;
 }
 
 ValueObjectSP StackFrame::LegacyGetValueForVariableExpressionPath(
diff --git a/lldb/source/ValueObject/CMakeLists.txt b/lldb/source/...
[truncated]

``````````

</details>


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


More information about the lldb-commits mailing list