[Lldb-commits] [lldb] [LLDB] Add Lexer (with tests) for DIL (Data Inspection Language). (PR #123521)

via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 4 11:36:38 PST 2025


https://github.com/cmtice updated https://github.com/llvm/llvm-project/pull/123521

>From 468f73f8539dcb8addf8ed9618d9eb797dabbb01 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 19 Jan 2025 09:15:34 -0800
Subject: [PATCH 01/10] [LLDB] Add Lexer (with tests) for DIL (Data Inspection
 Language).

This adds the basic lexer, with unittests, for the Data Inspection
Language (DIL) -- see
https://discourse.llvm.org/t/rfc-data-inspection-language/69893

This version of the lexer only handles local variables and namespaces,
and is designed to work  with
https://github.com/llvm/llvm-project/pull/120971.
---
 lldb/include/lldb/ValueObject/DILLexer.h     | 156 ++++++++++++++
 lldb/source/ValueObject/DILLexer.cpp         | 205 +++++++++++++++++++
 lldb/unittests/ValueObject/CMakeLists.txt    |   1 +
 lldb/unittests/ValueObject/DILLexerTests.cpp | 193 +++++++++++++++++
 4 files changed, 555 insertions(+)
 create mode 100644 lldb/include/lldb/ValueObject/DILLexer.h
 create mode 100644 lldb/source/ValueObject/DILLexer.cpp
 create mode 100644 lldb/unittests/ValueObject/DILLexerTests.cpp

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
new file mode 100644
index 00000000000000..45c506b2f4106d
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -0,0 +1,156 @@
+//===-- 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 "llvm/ADT/StringRef.h"
+#include <cstdint>
+#include <limits.h>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace lldb_private {
+
+namespace dil {
+
+enum class TokenKind {
+  coloncolon,
+  eof,
+  identifier,
+  invalid,
+  kw_namespace,
+  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)
+      : m_kind(kind), m_spelling(spelling), m_start_pos(start) {}
+
+  DILToken() : m_kind(dil::TokenKind::none), m_spelling(""), m_start_pos(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_spelling.size(); }
+
+  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) {
+    m_kind = kind;
+    m_spelling = spelling;
+    m_start_pos = start;
+  }
+
+  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
+};
+
+/// Class for doing the simple lexing required by DIL.
+class DILLexer {
+public:
+  DILLexer(llvm::StringRef dil_expr) : m_expr(dil_expr.str()) {
+    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);
+
+  /// 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/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp
new file mode 100644
index 00000000000000..4c2b0b1813bb96
--- /dev/null
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -0,0 +1,205 @@
+//===-- DILLexer.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
+//
+// This implements the recursive descent parser for the Data Inspection
+// Language (DIL), and its helper functions, which will eventually underlie the
+// 'frame variable' command. The language that this parser recognizes is
+// described in lldb/docs/dil-expr-lang.ebnf
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/ValueObject/DILLexer.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace lldb_private {
+
+namespace dil {
+
+// For fast keyword lookup. More keywords will be added later.
+const llvm::StringMap<dil::TokenKind> Keywords = {
+    {"namespace", dil::TokenKind::kw_namespace},
+};
+
+const std::string DILToken::getTokenName(dil::TokenKind kind) {
+  switch (kind) {
+  case dil::TokenKind::coloncolon:
+    return "coloncolon";
+  case dil::TokenKind::eof:
+    return "eof";
+  case dil::TokenKind::identifier:
+    return "identifier";
+  case dil::TokenKind::kw_namespace:
+    return "namespace";
+  case dil::TokenKind::l_paren:
+    return "l_paren";
+  case dil::TokenKind::r_paren:
+    return "r_paren";
+  case dil::TokenKind::unknown:
+    return "unknown";
+  default:
+    return "token_name";
+  }
+}
+
+static bool Is_Letter(char c) {
+  if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
+    return true;
+  return false;
+}
+
+static bool Is_Digit(char c) { return ('0' <= c && c <= '9'); }
+
+// A word starts with a letter, underscore, or dollar sign, followed by
+// letters ('a'..'z','A'..'Z'), digits ('0'..'9'), and/or  underscores.
+bool DILLexer::Is_Word(std::string::iterator start, uint32_t &length) {
+  bool done = false;
+  bool dollar_start = false;
+
+  // Must not start with a digit.
+  if (m_cur_pos == m_expr.end() || Is_Digit(*m_cur_pos))
+    return false;
+
+  // First character *may* be a '$', for a register name or convenience
+  // variable.
+  if (*m_cur_pos == '$') {
+    dollar_start = true;
+    ++m_cur_pos;
+    length++;
+  }
+
+  // Contains only letters, digits or underscores
+  for (; m_cur_pos != m_expr.end() && !done; ++m_cur_pos) {
+    char c = *m_cur_pos;
+    if (!Is_Letter(c) && !Is_Digit(c) && c != '_') {
+      done = true;
+      break;
+    } else
+      length++;
+  }
+
+  if (dollar_start && length > 1) // Must have something besides just '$'
+    return true;
+
+  if (!dollar_start && length > 0)
+    return true;
+
+  // Not a valid word, so re-set the lexing position.
+  m_cur_pos = start;
+  return false;
+}
+
+void DILLexer::UpdateLexedTokens(DILToken &result, dil::TokenKind tok_kind,
+                                 std::string tok_str, uint32_t tok_pos) {
+  DILToken new_token;
+  result.setValues(tok_kind, tok_str, tok_pos);
+  new_token = result;
+  m_lexed_tokens.push_back(std::move(new_token));
+}
+
+bool DILLexer::Lex(DILToken &result, bool look_ahead) {
+  bool retval = true;
+
+  if (!look_ahead) {
+    // We're being asked for the 'next' token, and not a part of a LookAhead.
+    // Check to see if we've already lexed it and pushed it onto our tokens
+    // vector; if so, return the next token from the vector, rather than doing
+    // more lexing.
+    if ((m_tokens_idx != UINT_MAX) &&
+        (m_tokens_idx < m_lexed_tokens.size() - 1)) {
+      result = m_lexed_tokens[m_tokens_idx + 1];
+      return retval;
+    }
+  }
+
+  // Skip over whitespace (spaces).
+  while (m_cur_pos != m_expr.end() && *m_cur_pos == ' ')
+    m_cur_pos++;
+
+  // Check to see if we've reached the end of our input string.
+  if (m_cur_pos == m_expr.end()) {
+    UpdateLexedTokens(result, dil::TokenKind::eof, "", m_expr.length());
+    return retval;
+  }
+
+  uint32_t position = m_cur_pos - m_expr.begin();
+  ;
+  std::string::iterator start = m_cur_pos;
+  uint32_t length = 0;
+  if (Is_Word(start, length)) {
+    dil::TokenKind kind;
+    std::string word = m_expr.substr(position, length);
+    auto iter = Keywords.find(word);
+    if (iter != Keywords.end())
+      kind = iter->second;
+    else
+      kind = dil::TokenKind::identifier;
+
+    UpdateLexedTokens(result, kind, word, position);
+    return true;
+  }
+
+  switch (*m_cur_pos) {
+  case '(':
+    m_cur_pos++;
+    UpdateLexedTokens(result, dil::TokenKind::l_paren, "(", position);
+    return true;
+  case ')':
+    m_cur_pos++;
+    UpdateLexedTokens(result, dil::TokenKind::r_paren, ")", position);
+    return true;
+  case ':':
+    if (position + 1 < m_expr.size() && m_expr[position + 1] == ':') {
+      m_cur_pos += 2;
+      UpdateLexedTokens(result, dil::TokenKind::coloncolon, "::", position);
+      return true;
+    }
+    break;
+  default:
+    break;
+  }
+  // Empty Token
+  result.setValues(dil::TokenKind::none, "", m_expr.length());
+  return false;
+}
+
+const DILToken &DILLexer::LookAhead(uint32_t N) {
+  uint32_t extra_lexed_tokens = m_lexed_tokens.size() - m_tokens_idx - 1;
+
+  if (N + 1 < extra_lexed_tokens)
+    return m_lexed_tokens[m_tokens_idx + N + 1];
+
+  uint32_t remaining_tokens =
+      (m_tokens_idx + N + 1) - m_lexed_tokens.size() + 1;
+
+  bool done = false;
+  bool look_ahead = true;
+  while (!done && remaining_tokens > 0) {
+    DILToken tok;
+    Lex(tok, look_ahead);
+    if (tok.getKind() == dil::TokenKind::eof)
+      done = true;
+    remaining_tokens--;
+  };
+
+  if (remaining_tokens > 0) {
+    m_invalid_token.setValues(dil::TokenKind::invalid, "", 0);
+    return m_invalid_token;
+  }
+
+  return m_lexed_tokens[m_tokens_idx + N + 1];
+}
+
+const DILToken &DILLexer::AcceptLookAhead(uint32_t N) {
+  if (m_tokens_idx + N + 1 > m_lexed_tokens.size())
+    return m_invalid_token;
+
+  m_tokens_idx += N + 1;
+  return m_lexed_tokens[m_tokens_idx];
+}
+
+} // namespace dil
+
+} // namespace lldb_private
diff --git a/lldb/unittests/ValueObject/CMakeLists.txt b/lldb/unittests/ValueObject/CMakeLists.txt
index 8fcc8d62a79979..952f5411a98057 100644
--- a/lldb/unittests/ValueObject/CMakeLists.txt
+++ b/lldb/unittests/ValueObject/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_lldb_unittest(LLDBValueObjectTests
   DumpValueObjectOptionsTests.cpp
+  DILLexerTests.cpp
 
   LINK_LIBS
     lldbValueObject
diff --git a/lldb/unittests/ValueObject/DILLexerTests.cpp b/lldb/unittests/ValueObject/DILLexerTests.cpp
new file mode 100644
index 00000000000000..ec6ff86b64d36b
--- /dev/null
+++ b/lldb/unittests/ValueObject/DILLexerTests.cpp
@@ -0,0 +1,193 @@
+//===-- DILLexerTests.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 "lldb/ValueObject/DILLexer.h"
+#include "llvm/ADT/StringRef.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using llvm::StringRef;
+
+TEST(DILLexerTests, SimpleTest) {
+  StringRef dil_input_expr("simple_var");
+  uint32_t tok_len = 10;
+  lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
+  lldb_private::dil::DILToken dil_token;
+  dil_token.setKind(lldb_private::dil::TokenKind::unknown);
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::unknown);
+  dil_lexer.Lex(dil_token);
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  EXPECT_EQ(dil_token.getSpelling(), "simple_var");
+  EXPECT_EQ(dil_token.getLength(), tok_len);
+  dil_lexer.Lex(dil_token);
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::eof);
+}
+
+TEST(DILLexerTests, TokenKindTest) {
+  StringRef dil_input_expr("namespace");
+  lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
+  lldb_private::dil::DILToken dil_token;
+  dil_token.setKind(lldb_private::dil::TokenKind::unknown);
+
+  dil_lexer.Lex(dil_token);
+  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), UINT_MAX);
+  dil_lexer.ResetTokenIdx(0);
+
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::kw_namespace);
+  EXPECT_TRUE(dil_token.isNot(lldb_private::dil::TokenKind::identifier));
+  EXPECT_FALSE(dil_token.is(lldb_private::dil::TokenKind::l_paren));
+  EXPECT_TRUE(dil_token.isOneOf(lldb_private::dil::TokenKind::eof,
+                                lldb_private::dil::TokenKind::kw_namespace));
+  EXPECT_FALSE(dil_token.isOneOf(lldb_private::dil::TokenKind::l_paren,
+                                 lldb_private::dil::TokenKind::r_paren,
+                                 lldb_private::dil::TokenKind::coloncolon,
+                                 lldb_private::dil::TokenKind::eof));
+
+  dil_token.setKind(lldb_private::dil::TokenKind::identifier);
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+}
+
+TEST(DILLexerTests, LookAheadTest) {
+  StringRef dil_input_expr("(anonymous namespace)::some_var");
+  lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
+  lldb_private::dil::DILToken dil_token;
+  dil_token.setKind(lldb_private::dil::TokenKind::unknown);
+  uint32_t expect_loc = 23;
+
+  dil_lexer.Lex(dil_token);
+  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), UINT_MAX);
+  dil_lexer.ResetTokenIdx(0);
+
+  // Current token is '('; check the next 4 tokens, to make
+  // sure they are the identifier 'anonymous', the namespace keyword,
+  // ')' and '::', in that order.
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::l_paren);
+  EXPECT_EQ(dil_lexer.LookAhead(0).getKind(),
+            lldb_private::dil::TokenKind::identifier);
+  EXPECT_EQ(dil_lexer.LookAhead(0).getSpelling(), "anonymous");
+  EXPECT_EQ(dil_lexer.LookAhead(1).getKind(),
+            lldb_private::dil::TokenKind::kw_namespace);
+  EXPECT_EQ(dil_lexer.LookAhead(2).getKind(),
+            lldb_private::dil::TokenKind::r_paren);
+  EXPECT_EQ(dil_lexer.LookAhead(3).getKind(),
+            lldb_private::dil::TokenKind::coloncolon);
+  // Verify we've advanced our position counter (lexing location) in the
+  // input 23 characters (the length of '(anonymous namespace)::'.
+  EXPECT_EQ(dil_lexer.GetLocation(), expect_loc);
+
+  // Our current index should still be 0, as we only looked ahead; we are still
+  // officially on the '('.
+  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), 0);
+
+  // Accept the 'lookahead', so our current token is '::', which has the index
+  // 4 in our vector of tokens (which starts at zero).
+  dil_token = dil_lexer.AcceptLookAhead(3);
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::coloncolon);
+  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), 4);
+
+  // Lex the final variable name in the input string
+  dil_lexer.Lex(dil_token);
+  dil_lexer.IncrementTokenIdx();
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  EXPECT_EQ(dil_token.getSpelling(), "some_var");
+  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), 5);
+
+  dil_lexer.Lex(dil_token);
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::eof);
+}
+
+TEST(DILLexerTests, MultiTokenLexTest) {
+  StringRef dil_input_expr("This string has several identifiers");
+  lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
+  lldb_private::dil::DILToken dil_token;
+  dil_token.setKind(lldb_private::dil::TokenKind::unknown);
+
+  dil_lexer.Lex(dil_token);
+  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), UINT_MAX);
+  dil_lexer.ResetTokenIdx(0);
+
+  EXPECT_EQ(dil_token.getSpelling(), "This");
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  dil_lexer.Lex(dil_token);
+  dil_lexer.IncrementTokenIdx();
+
+  EXPECT_EQ(dil_token.getSpelling(), "string");
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  dil_lexer.Lex(dil_token);
+  dil_lexer.IncrementTokenIdx();
+
+  EXPECT_EQ(dil_token.getSpelling(), "has");
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  dil_lexer.Lex(dil_token);
+  dil_lexer.IncrementTokenIdx();
+
+  EXPECT_EQ(dil_token.getSpelling(), "several");
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  dil_lexer.Lex(dil_token);
+  dil_lexer.IncrementTokenIdx();
+
+  EXPECT_EQ(dil_token.getSpelling(), "identifiers");
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  dil_lexer.Lex(dil_token);
+  dil_lexer.IncrementTokenIdx();
+
+  EXPECT_EQ(dil_token.getSpelling(), "");
+  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::eof);
+}
+
+TEST(DILLexerTests, IdentifiersTest) {
+  std::vector<std::string> valid_identifiers = {
+    "$My_name1",
+    "$pc",
+    "abcd",
+    "ab cd",
+    "_",
+    "_a",
+    "_a_",
+    "a_b",
+    "this",
+    "self",
+    "a",
+    "MyName"
+  };
+  std::vector<std::string> invalid_identifiers = {
+    "234",
+    "2a",
+    "2",
+    "$",
+    "1MyName",
+    "",
+    "namespace"
+  };
+
+  // Verify that all of the valid identifiers come out as identifier tokens.
+  for (auto str : valid_identifiers) {
+    StringRef dil_input_expr(str);
+    lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
+    lldb_private::dil::DILToken dil_token;
+    dil_token.setKind(lldb_private::dil::TokenKind::unknown);
+
+    dil_lexer.Lex(dil_token);
+    EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  }
+
+  // Verify that none of the invalid identifiers come out as identifier tokens.
+  for (auto str : invalid_identifiers) {
+    StringRef dil_input_expr(str);
+    lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
+    lldb_private::dil::DILToken dil_token;
+    dil_token.setKind(lldb_private::dil::TokenKind::unknown);
+
+    dil_lexer.Lex(dil_token);
+    EXPECT_TRUE(dil_token.isNot(lldb_private::dil::TokenKind::identifier));
+    EXPECT_TRUE(dil_token.isOneOf(lldb_private::dil::TokenKind::unknown,
+                                  lldb_private::dil::TokenKind::none,
+                                  lldb_private::dil::TokenKind::eof,
+                                  lldb_private::dil::TokenKind::kw_namespace));
+  }
+}

>From 61a2607a70d90688d395321e846a3be58ccbebcb Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 19 Jan 2025 09:22:51 -0800
Subject: [PATCH 02/10] [LLDB] Add Lexer (with tests) for DIL (Data Inspection
 Language)

Update CMakeLists.txt to build DILLexer.cpp.
---
 lldb/source/ValueObject/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lldb/source/ValueObject/CMakeLists.txt b/lldb/source/ValueObject/CMakeLists.txt
index 70cb3d6d53f071..30c34472289e7b 100644
--- a/lldb/source/ValueObject/CMakeLists.txt
+++ b/lldb/source/ValueObject/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_lldb_library(lldbValueObject
+  DILLexer.cpp
   ValueObject.cpp
   ValueObjectCast.cpp
   ValueObjectChild.cpp

>From 5e2ee55f800726910ad6e56a192554375f61bfb8 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sat, 25 Jan 2025 16:56:30 -0800
Subject: [PATCH 03/10] Many changes, to address all the review	comments:

- Remove "DIL" prefix from DILTokenKind	and DILToken.
- Change the token kind	from an	enum class to an enum inside the Token
  class.
- Use CamelCase	for all	the method names.
- Replace Token::SetValues method with assignments.
- Use a	StringRef, not std::string,  to hold the input string in the lexer.
- Update the lexer to lex all the tokens at one	time. Added two	new methods
  for this: LexAll and GetNextToken.
- Made some of the Lexer methods private.
- Replaces StringMap with StringSwitch for fast keyword lookups.
- Updated GetTokenName to directly return StringRefs; removed default case from
  switch statement.
- Cleaned up code format in IsLetter	& IsDigit.
- Updated IsWord too return an iterator	range containing the word (if any).
- Updated Lex function (now called by LexAll) to return	an llvm::Expected
  token; removed look_ahead checks; changed the	operator lexing	to use
  a vector of operators	(as suggested).
- Cleaned up LookAhead method, now that	we know	all tokens have	already	been
  lexed.
- Added	helper function	to unittests, to help check a sequence of tokens.
- Generally cleaned up the tests to deal with all the code changes.
---
 lldb/include/lldb/ValueObject/DILLexer.h     | 110 ++++----
 lldb/source/ValueObject/DILLexer.cpp         | 214 +++++++--------
 lldb/unittests/ValueObject/DILLexerTests.cpp | 269 ++++++++++---------
 3 files changed, 302 insertions(+), 291 deletions(-)

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index 45c506b2f4106d..61e5fe622e51e6 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -10,6 +10,8 @@
 #define LLDB_VALUEOBJECT_DILLEXER_H_
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Error.h"
 #include <cstdint>
 #include <limits.h>
 #include <memory>
@@ -20,58 +22,51 @@ namespace lldb_private {
 
 namespace dil {
 
-enum class TokenKind {
-  coloncolon,
-  eof,
-  identifier,
-  invalid,
-  kw_namespace,
-  l_paren,
-  none,
-  r_paren,
-  unknown,
-};
-
 /// Class defining the tokens generated by the DIL lexer and used by the
 /// DIL parser.
-class DILToken {
+class Token {
 public:
-  DILToken(dil::TokenKind kind, std::string spelling, uint32_t start)
+  enum Kind {
+    coloncolon,
+    eof,
+    identifier,
+    invalid,
+    kw_namespace,
+    l_paren,
+    none,
+    r_paren,
+    unknown,
+  };
+
+  Token(Kind kind, std::string spelling, uint32_t start)
       : m_kind(kind), m_spelling(spelling), m_start_pos(start) {}
 
-  DILToken() : m_kind(dil::TokenKind::none), m_spelling(""), m_start_pos(0) {}
+  Token() : m_kind(Kind::none), m_spelling(""), m_start_pos(0) {}
 
-  void setKind(dil::TokenKind kind) { m_kind = kind; }
-  dil::TokenKind getKind() const { return m_kind; }
+  void SetKind(Kind kind) { m_kind = kind; }
 
-  std::string getSpelling() const { return m_spelling; }
+  Kind GetKind() const { return m_kind; }
 
-  uint32_t getLength() const { return m_spelling.size(); }
+  std::string GetSpelling() const { return m_spelling; }
 
-  bool is(dil::TokenKind kind) const { return m_kind == kind; }
+  uint32_t GetLength() const { return m_spelling.size(); }
 
-  bool isNot(dil::TokenKind kind) const { return m_kind != kind; }
+  bool Is(Kind kind) const { return m_kind == kind; }
 
-  bool isOneOf(dil::TokenKind kind1, dil::TokenKind kind2) const {
-    return is(kind1) || is(kind2);
-  }
+  bool IsNot(Kind kind) const { return m_kind != kind; }
 
-  template <typename... Ts> bool isOneOf(dil::TokenKind kind, Ts... Ks) const {
-    return is(kind) || isOneOf(Ks...);
-  }
+  bool IsOneOf(Kind kind1, Kind kind2) const { return Is(kind1) || Is(kind2); }
 
-  uint32_t getLocation() const { return m_start_pos; }
-
-  void setValues(dil::TokenKind kind, std::string spelling, uint32_t start) {
-    m_kind = kind;
-    m_spelling = spelling;
-    m_start_pos = start;
+  template <typename... Ts> bool IsOneOf(Kind kind, Ts... Ks) const {
+    return Is(kind) || IsOneOf(Ks...);
   }
 
-  static const std::string getTokenName(dil::TokenKind kind);
+  uint32_t GetLocation() const { return m_start_pos; }
+
+  static llvm::StringRef GetTokenName(Kind kind);
 
 private:
-  dil::TokenKind m_kind;
+  Kind m_kind;
   std::string m_spelling;
   uint32_t m_start_pos; // within entire expression string
 };
@@ -79,35 +74,30 @@ class DILToken {
 /// Class for doing the simple lexing required by DIL.
 class DILLexer {
 public:
-  DILLexer(llvm::StringRef dil_expr) : m_expr(dil_expr.str()) {
+  DILLexer(llvm::StringRef dil_expr) : m_expr(dil_expr) {
     m_cur_pos = m_expr.begin();
     // Use UINT_MAX to indicate invalid/uninitialized value.
     m_tokens_idx = UINT_MAX;
+    m_invalid_token = Token(Token::invalid, "", 0);
   }
 
-  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);
+  llvm::Expected<bool> LexAll();
 
   /// 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 Token &LookAhead(uint32_t N);
+
+  const Token &AcceptLookAhead(uint32_t N);
 
-  const DILToken &AcceptLookAhead(uint32_t N);
+  const Token &GetNextToken();
 
   /// 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]; }
+  const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; }
+
+  uint32_t NumLexedTokens() { return m_lexed_tokens.size(); }
 
   /// Update the index for the 'current' token, to point to the next lexed
   /// token.
@@ -130,23 +120,35 @@ class DILLexer {
     return true;
   }
 
+  uint32_t GetLocation() { return m_cur_pos - m_expr.begin(); }
+
 private:
+  llvm::Expected<Token> Lex();
+
+  llvm::iterator_range<llvm::StringRef::iterator> IsWord();
+
+  /// Update 'result' with the other paremeter values, create a
+  /// duplicate token, and push the duplicate token onto the vector of
+  /// lexed tokens.
+  void UpdateLexedTokens(Token &result, Token::Kind tok_kind,
+                         std::string tok_str, uint32_t tok_pos);
+
   // The input string we are lexing & parsing.
-  std::string m_expr;
+  llvm::StringRef 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;
+  llvm::StringRef::iterator m_cur_pos;
 
   // Holds all of the tokens lexed so far.
-  std::vector<DILToken> m_lexed_tokens;
+  std::vector<Token> 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;
+  Token m_invalid_token;
 };
 
 } // namespace dil
diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp
index 4c2b0b1813bb96..30e4bcb04e6505 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -12,107 +12,99 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/ValueObject/DILLexer.h"
-#include "llvm/ADT/StringMap.h"
+#include "lldb/Utility/Status.h"
+#include "llvm/ADT/StringSwitch.h"
 
 namespace lldb_private {
 
 namespace dil {
 
-// For fast keyword lookup. More keywords will be added later.
-const llvm::StringMap<dil::TokenKind> Keywords = {
-    {"namespace", dil::TokenKind::kw_namespace},
-};
-
-const std::string DILToken::getTokenName(dil::TokenKind kind) {
+llvm::StringRef Token::GetTokenName(Kind kind) {
   switch (kind) {
-  case dil::TokenKind::coloncolon:
+  case Kind::coloncolon:
     return "coloncolon";
-  case dil::TokenKind::eof:
+  case Kind::eof:
     return "eof";
-  case dil::TokenKind::identifier:
+  case Kind::identifier:
     return "identifier";
-  case dil::TokenKind::kw_namespace:
+  case Kind::invalid:
+    return "invalid";
+  case Kind::kw_namespace:
     return "namespace";
-  case dil::TokenKind::l_paren:
+  case Kind::l_paren:
     return "l_paren";
-  case dil::TokenKind::r_paren:
+  case Kind::none:
+    return "none";
+  case Kind::r_paren:
     return "r_paren";
-  case dil::TokenKind::unknown:
+  case Kind::unknown:
     return "unknown";
-  default:
-    return "token_name";
   }
 }
 
-static bool Is_Letter(char c) {
-  if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
-    return true;
-  return false;
+static bool IsLetter(char c) {
+  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
 }
 
-static bool Is_Digit(char c) { return ('0' <= c && c <= '9'); }
+static bool IsDigit(char c) { return '0' <= c && c <= '9'; }
 
 // A word starts with a letter, underscore, or dollar sign, followed by
 // letters ('a'..'z','A'..'Z'), digits ('0'..'9'), and/or  underscores.
-bool DILLexer::Is_Word(std::string::iterator start, uint32_t &length) {
-  bool done = false;
+llvm::iterator_range<llvm::StringRef::iterator> DILLexer::IsWord() {
+  llvm::StringRef::iterator start = m_cur_pos;
   bool dollar_start = false;
 
   // Must not start with a digit.
-  if (m_cur_pos == m_expr.end() || Is_Digit(*m_cur_pos))
-    return false;
+  if (m_cur_pos == m_expr.end() || IsDigit(*m_cur_pos))
+    return llvm::make_range(m_cur_pos, m_cur_pos);
 
   // First character *may* be a '$', for a register name or convenience
   // variable.
   if (*m_cur_pos == '$') {
     dollar_start = true;
     ++m_cur_pos;
-    length++;
   }
 
   // Contains only letters, digits or underscores
-  for (; m_cur_pos != m_expr.end() && !done; ++m_cur_pos) {
+  for (; m_cur_pos != m_expr.end(); ++m_cur_pos) {
     char c = *m_cur_pos;
-    if (!Is_Letter(c) && !Is_Digit(c) && c != '_') {
-      done = true;
+    if (!IsLetter(c) && !IsDigit(c) && c != '_')
       break;
-    } else
-      length++;
   }
 
-  if (dollar_start && length > 1) // Must have something besides just '$'
-    return true;
-
-  if (!dollar_start && length > 0)
-    return true;
+  // If first char is '$', make sure there's at least one mare char, or it's
+  // invalid.
+  if (dollar_start && (m_cur_pos - start <= 1)) {
+    m_cur_pos = start;
+    return llvm::make_range(start, start); // Empty range
+  }
 
-  // Not a valid word, so re-set the lexing position.
-  m_cur_pos = start;
-  return false;
+  return llvm::make_range(start, m_cur_pos);
 }
 
-void DILLexer::UpdateLexedTokens(DILToken &result, dil::TokenKind tok_kind,
+void DILLexer::UpdateLexedTokens(Token &result, Token::Kind tok_kind,
                                  std::string tok_str, uint32_t tok_pos) {
-  DILToken new_token;
-  result.setValues(tok_kind, tok_str, tok_pos);
-  new_token = result;
+  Token new_token(tok_kind, tok_str, tok_pos);
+  result = new_token;
   m_lexed_tokens.push_back(std::move(new_token));
 }
 
-bool DILLexer::Lex(DILToken &result, bool look_ahead) {
-  bool retval = true;
-
-  if (!look_ahead) {
-    // We're being asked for the 'next' token, and not a part of a LookAhead.
-    // Check to see if we've already lexed it and pushed it onto our tokens
-    // vector; if so, return the next token from the vector, rather than doing
-    // more lexing.
-    if ((m_tokens_idx != UINT_MAX) &&
-        (m_tokens_idx < m_lexed_tokens.size() - 1)) {
-      result = m_lexed_tokens[m_tokens_idx + 1];
-      return retval;
+llvm::Expected<bool> DILLexer::LexAll() {
+  bool done = false;
+  while (!done) {
+    auto tok_or_err = Lex();
+    if (!tok_or_err)
+      return tok_or_err.takeError();
+    Token token = *tok_or_err;
+    if (token.GetKind() == Token::eof) {
+      done = true;
     }
   }
+  return true;
+}
+
+llvm::Expected<Token> DILLexer::Lex() {
+  Token result;
 
   // Skip over whitespace (spaces).
   while (m_cur_pos != m_expr.end() && *m_cur_pos == ' ')
@@ -120,79 +112,52 @@ bool DILLexer::Lex(DILToken &result, bool look_ahead) {
 
   // Check to see if we've reached the end of our input string.
   if (m_cur_pos == m_expr.end()) {
-    UpdateLexedTokens(result, dil::TokenKind::eof, "", m_expr.length());
-    return retval;
+    UpdateLexedTokens(result, Token::eof, "", (uint32_t)m_expr.size());
+    return result;
   }
 
   uint32_t position = m_cur_pos - m_expr.begin();
-  ;
-  std::string::iterator start = m_cur_pos;
-  uint32_t length = 0;
-  if (Is_Word(start, length)) {
-    dil::TokenKind kind;
-    std::string word = m_expr.substr(position, length);
-    auto iter = Keywords.find(word);
-    if (iter != Keywords.end())
-      kind = iter->second;
-    else
-      kind = dil::TokenKind::identifier;
-
-    UpdateLexedTokens(result, kind, word, position);
-    return true;
+  llvm::StringRef::iterator start = m_cur_pos;
+  llvm::iterator_range<llvm::StringRef::iterator> word_range = IsWord();
+  if (!word_range.empty()) {
+    uint32_t length = word_range.end() - word_range.begin();
+    llvm::StringRef word(m_expr.substr(position, length));
+    // We will be adding more keywords here in the future...
+    Token::Kind kind = llvm::StringSwitch<Token::Kind>(word)
+                           .Case("namespace", Token::kw_namespace)
+                           .Default(Token::identifier);
+    UpdateLexedTokens(result, kind, word.str(), position);
+    return result;
   }
 
-  switch (*m_cur_pos) {
-  case '(':
-    m_cur_pos++;
-    UpdateLexedTokens(result, dil::TokenKind::l_paren, "(", position);
-    return true;
-  case ')':
-    m_cur_pos++;
-    UpdateLexedTokens(result, dil::TokenKind::r_paren, ")", position);
-    return true;
-  case ':':
-    if (position + 1 < m_expr.size() && m_expr[position + 1] == ':') {
-      m_cur_pos += 2;
-      UpdateLexedTokens(result, dil::TokenKind::coloncolon, "::", position);
-      return true;
+  m_cur_pos = start;
+  llvm::StringRef remainder(m_expr.substr(position, m_expr.end() - m_cur_pos));
+  std::vector<std::pair<Token::Kind, const char *>> operators = {
+      {Token::l_paren, "("},
+      {Token::r_paren, ")"},
+      {Token::coloncolon, "::"},
+  };
+  for (auto [kind, str] : operators) {
+    if (remainder.consume_front(str)) {
+      m_cur_pos += strlen(str);
+      UpdateLexedTokens(result, kind, str, position);
+      return result;
     }
-    break;
-  default:
-    break;
   }
-  // Empty Token
-  result.setValues(dil::TokenKind::none, "", m_expr.length());
-  return false;
-}
 
-const DILToken &DILLexer::LookAhead(uint32_t N) {
-  uint32_t extra_lexed_tokens = m_lexed_tokens.size() - m_tokens_idx - 1;
+  // Unrecognized character(s) in string; unable to lex it.
+  Status error("Unable to lex input string");
+  return error.ToError();
+}
 
-  if (N + 1 < extra_lexed_tokens)
+const Token &DILLexer::LookAhead(uint32_t N) {
+  if (m_tokens_idx + N + 1 < m_lexed_tokens.size())
     return m_lexed_tokens[m_tokens_idx + N + 1];
 
-  uint32_t remaining_tokens =
-      (m_tokens_idx + N + 1) - m_lexed_tokens.size() + 1;
-
-  bool done = false;
-  bool look_ahead = true;
-  while (!done && remaining_tokens > 0) {
-    DILToken tok;
-    Lex(tok, look_ahead);
-    if (tok.getKind() == dil::TokenKind::eof)
-      done = true;
-    remaining_tokens--;
-  };
-
-  if (remaining_tokens > 0) {
-    m_invalid_token.setValues(dil::TokenKind::invalid, "", 0);
-    return m_invalid_token;
-  }
-
-  return m_lexed_tokens[m_tokens_idx + N + 1];
+  return m_invalid_token;
 }
 
-const DILToken &DILLexer::AcceptLookAhead(uint32_t N) {
+const Token &DILLexer::AcceptLookAhead(uint32_t N) {
   if (m_tokens_idx + N + 1 > m_lexed_tokens.size())
     return m_invalid_token;
 
@@ -200,6 +165,25 @@ const DILToken &DILLexer::AcceptLookAhead(uint32_t N) {
   return m_lexed_tokens[m_tokens_idx];
 }
 
+const Token &DILLexer::GetNextToken() {
+  if (m_tokens_idx == UINT_MAX)
+    m_tokens_idx = 0;
+  else
+    m_tokens_idx++;
+
+  // Return the next token in the vector of lexed tokens.
+  if (m_tokens_idx < m_lexed_tokens.size())
+    return m_lexed_tokens[m_tokens_idx];
+
+  // We're already at/beyond the end of our lexed tokens. If the last token
+  // is an eof token, return it.
+  if (m_lexed_tokens[m_lexed_tokens.size() - 1].GetKind() == Token::eof)
+    return m_lexed_tokens[m_lexed_tokens.size() - 1];
+
+  // Return the invalid token.
+  return m_invalid_token;
+}
+
 } // namespace dil
 
 } // namespace lldb_private
diff --git a/lldb/unittests/ValueObject/DILLexerTests.cpp b/lldb/unittests/ValueObject/DILLexerTests.cpp
index ec6ff86b64d36b..137013e40d6adf 100644
--- a/lldb/unittests/ValueObject/DILLexerTests.cpp
+++ b/lldb/unittests/ValueObject/DILLexerTests.cpp
@@ -13,131 +13,145 @@
 
 using llvm::StringRef;
 
+bool VerifyExpectedTokens(
+    lldb_private::dil::DILLexer &lexer,
+    std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>>
+        exp_tokens,
+    uint32_t start_pos) {
+  if (lexer.NumLexedTokens() - start_pos < exp_tokens.size())
+    return false;
+
+  if (start_pos > 0)
+    lexer.ResetTokenIdx(start_pos -
+                        1); // GetNextToken increments the idx first.
+  for (const auto &pair : exp_tokens) {
+    lldb_private::dil::Token token = lexer.GetNextToken();
+    if (token.GetKind() != pair.first || token.GetSpelling() != pair.second)
+      return false;
+  }
+
+  return true;
+}
+
 TEST(DILLexerTests, SimpleTest) {
-  StringRef dil_input_expr("simple_var");
+  StringRef input_expr("simple_var");
   uint32_t tok_len = 10;
-  lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
-  lldb_private::dil::DILToken dil_token;
-  dil_token.setKind(lldb_private::dil::TokenKind::unknown);
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::unknown);
-  dil_lexer.Lex(dil_token);
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
-  EXPECT_EQ(dil_token.getSpelling(), "simple_var");
-  EXPECT_EQ(dil_token.getLength(), tok_len);
-  dil_lexer.Lex(dil_token);
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::eof);
+  lldb_private::dil::DILLexer lexer(input_expr);
+  lldb_private::dil::Token token;
+  token.SetKind(lldb_private::dil::Token::unknown);
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::unknown);
+  auto success = lexer.LexAll();
+
+  if (!success) {
+    EXPECT_TRUE(false);
+  }
+  token = lexer.GetNextToken();
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(token.GetSpelling(), "simple_var");
+  EXPECT_EQ(token.GetLength(), tok_len);
+  token = lexer.GetNextToken();
+  ;
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
 }
 
 TEST(DILLexerTests, TokenKindTest) {
-  StringRef dil_input_expr("namespace");
-  lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
-  lldb_private::dil::DILToken dil_token;
-  dil_token.setKind(lldb_private::dil::TokenKind::unknown);
-
-  dil_lexer.Lex(dil_token);
-  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), UINT_MAX);
-  dil_lexer.ResetTokenIdx(0);
-
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::kw_namespace);
-  EXPECT_TRUE(dil_token.isNot(lldb_private::dil::TokenKind::identifier));
-  EXPECT_FALSE(dil_token.is(lldb_private::dil::TokenKind::l_paren));
-  EXPECT_TRUE(dil_token.isOneOf(lldb_private::dil::TokenKind::eof,
-                                lldb_private::dil::TokenKind::kw_namespace));
-  EXPECT_FALSE(dil_token.isOneOf(lldb_private::dil::TokenKind::l_paren,
-                                 lldb_private::dil::TokenKind::r_paren,
-                                 lldb_private::dil::TokenKind::coloncolon,
-                                 lldb_private::dil::TokenKind::eof));
-
-  dil_token.setKind(lldb_private::dil::TokenKind::identifier);
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  StringRef input_expr("namespace");
+  lldb_private::dil::DILLexer lexer(input_expr);
+  lldb_private::dil::Token token;
+  token.SetKind(lldb_private::dil::Token::unknown);
+
+  auto success = lexer.LexAll();
+  if (!success) {
+    EXPECT_TRUE(false);
+  }
+  token = lexer.GetNextToken();
+
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::kw_namespace);
+  EXPECT_TRUE(token.IsNot(lldb_private::dil::Token::identifier));
+  EXPECT_FALSE(token.Is(lldb_private::dil::Token::l_paren));
+  EXPECT_TRUE(token.IsOneOf(lldb_private::dil::Token::eof,
+                            lldb_private::dil::Token::kw_namespace));
+  EXPECT_FALSE(token.IsOneOf(
+      lldb_private::dil::Token::l_paren, lldb_private::dil::Token::r_paren,
+      lldb_private::dil::Token::coloncolon, lldb_private::dil::Token::eof));
+
+  token.SetKind(lldb_private::dil::Token::identifier);
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
 }
 
 TEST(DILLexerTests, LookAheadTest) {
-  StringRef dil_input_expr("(anonymous namespace)::some_var");
-  lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
-  lldb_private::dil::DILToken dil_token;
-  dil_token.setKind(lldb_private::dil::TokenKind::unknown);
+  StringRef input_expr("(anonymous namespace)::some_var");
+  lldb_private::dil::DILLexer lexer(input_expr);
+  lldb_private::dil::Token token;
+  token.SetKind(lldb_private::dil::Token::unknown);
   uint32_t expect_loc = 23;
 
-  dil_lexer.Lex(dil_token);
-  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), UINT_MAX);
-  dil_lexer.ResetTokenIdx(0);
+  auto success = lexer.LexAll();
+  if (!success) {
+    EXPECT_TRUE(false);
+  }
+  token = lexer.GetNextToken();
 
   // Current token is '('; check the next 4 tokens, to make
   // sure they are the identifier 'anonymous', the namespace keyword,
   // ')' and '::', in that order.
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::l_paren);
-  EXPECT_EQ(dil_lexer.LookAhead(0).getKind(),
-            lldb_private::dil::TokenKind::identifier);
-  EXPECT_EQ(dil_lexer.LookAhead(0).getSpelling(), "anonymous");
-  EXPECT_EQ(dil_lexer.LookAhead(1).getKind(),
-            lldb_private::dil::TokenKind::kw_namespace);
-  EXPECT_EQ(dil_lexer.LookAhead(2).getKind(),
-            lldb_private::dil::TokenKind::r_paren);
-  EXPECT_EQ(dil_lexer.LookAhead(3).getKind(),
-            lldb_private::dil::TokenKind::coloncolon);
-  // Verify we've advanced our position counter (lexing location) in the
-  // input 23 characters (the length of '(anonymous namespace)::'.
-  EXPECT_EQ(dil_lexer.GetLocation(), expect_loc);
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::l_paren);
+  EXPECT_EQ(lexer.LookAhead(0).GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(lexer.LookAhead(0).GetSpelling(), "anonymous");
+  EXPECT_EQ(lexer.LookAhead(1).GetKind(),
+            lldb_private::dil::Token::kw_namespace);
+  EXPECT_EQ(lexer.LookAhead(2).GetKind(), lldb_private::dil::Token::r_paren);
+  EXPECT_EQ(lexer.LookAhead(3).GetKind(), lldb_private::dil::Token::coloncolon);
 
   // Our current index should still be 0, as we only looked ahead; we are still
   // officially on the '('.
-  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), 0);
+  EXPECT_EQ(lexer.GetCurrentTokenIdx(), (uint32_t)0);
 
   // Accept the 'lookahead', so our current token is '::', which has the index
   // 4 in our vector of tokens (which starts at zero).
-  dil_token = dil_lexer.AcceptLookAhead(3);
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::coloncolon);
-  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), 4);
-
-  // Lex the final variable name in the input string
-  dil_lexer.Lex(dil_token);
-  dil_lexer.IncrementTokenIdx();
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
-  EXPECT_EQ(dil_token.getSpelling(), "some_var");
-  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), 5);
-
-  dil_lexer.Lex(dil_token);
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::eof);
+  token = lexer.AcceptLookAhead(3);
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::coloncolon);
+  EXPECT_EQ(lexer.GetCurrentTokenIdx(), (uint32_t)4);
+
+  token = lexer.GetNextToken();
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(token.GetSpelling(), "some_var");
+  EXPECT_EQ(lexer.GetCurrentTokenIdx(), (uint32_t)5);
+  // Verify we've advanced our position counter (lexing location) in the
+  // input 23 characters (the length of '(anonymous namespace)::'.
+  EXPECT_EQ(token.GetLocation(), expect_loc);
+  token = lexer.GetNextToken();
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
 }
 
 TEST(DILLexerTests, MultiTokenLexTest) {
-  StringRef dil_input_expr("This string has several identifiers");
-  lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
-  lldb_private::dil::DILToken dil_token;
-  dil_token.setKind(lldb_private::dil::TokenKind::unknown);
-
-  dil_lexer.Lex(dil_token);
-  EXPECT_EQ(dil_lexer.GetCurrentTokenIdx(), UINT_MAX);
-  dil_lexer.ResetTokenIdx(0);
-
-  EXPECT_EQ(dil_token.getSpelling(), "This");
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
-  dil_lexer.Lex(dil_token);
-  dil_lexer.IncrementTokenIdx();
-
-  EXPECT_EQ(dil_token.getSpelling(), "string");
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
-  dil_lexer.Lex(dil_token);
-  dil_lexer.IncrementTokenIdx();
-
-  EXPECT_EQ(dil_token.getSpelling(), "has");
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
-  dil_lexer.Lex(dil_token);
-  dil_lexer.IncrementTokenIdx();
-
-  EXPECT_EQ(dil_token.getSpelling(), "several");
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
-  dil_lexer.Lex(dil_token);
-  dil_lexer.IncrementTokenIdx();
-
-  EXPECT_EQ(dil_token.getSpelling(), "identifiers");
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
-  dil_lexer.Lex(dil_token);
-  dil_lexer.IncrementTokenIdx();
-
-  EXPECT_EQ(dil_token.getSpelling(), "");
-  EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::eof);
+  StringRef input_expr("This string has (several ) ::identifiers");
+  lldb_private::dil::DILLexer lexer(input_expr);
+  lldb_private::dil::Token token;
+  token.SetKind(lldb_private::dil::Token::unknown);
+
+  auto success = lexer.LexAll();
+  if (!success) {
+    EXPECT_TRUE(false);
+  }
+
+  std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>>
+      expected_tokens = {
+          {lldb_private::dil::Token::identifier, "This"},
+          {lldb_private::dil::Token::identifier, "string"},
+          {lldb_private::dil::Token::identifier, "has"},
+          {lldb_private::dil::Token::l_paren, "("},
+          {lldb_private::dil::Token::identifier, "several"},
+          {lldb_private::dil::Token::r_paren, ")"},
+          {lldb_private::dil::Token::coloncolon, "::"},
+          {lldb_private::dil::Token::identifier, "identifiers"},
+      };
+
+  EXPECT_TRUE(VerifyExpectedTokens(lexer, expected_tokens, 0));
+
+  token = lexer.GetNextToken();
+  EXPECT_EQ(token.GetSpelling(), "");
+  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
 }
 
 TEST(DILLexerTests, IdentifiersTest) {
@@ -166,28 +180,39 @@ TEST(DILLexerTests, IdentifiersTest) {
   };
 
   // Verify that all of the valid identifiers come out as identifier tokens.
-  for (auto str : valid_identifiers) {
-    StringRef dil_input_expr(str);
-    lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
-    lldb_private::dil::DILToken dil_token;
-    dil_token.setKind(lldb_private::dil::TokenKind::unknown);
-
-    dil_lexer.Lex(dil_token);
-    EXPECT_EQ(dil_token.getKind(), lldb_private::dil::TokenKind::identifier);
+  for (auto &str : valid_identifiers) {
+    SCOPED_TRACE(str);
+    lldb_private::dil::DILLexer lexer(str);
+    lldb_private::dil::Token token;
+    token.SetKind(lldb_private::dil::Token::unknown);
+
+    auto success = lexer.LexAll();
+    if (!success) {
+      EXPECT_TRUE(false);
+    }
+    token = lexer.GetNextToken();
+    EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
   }
 
   // Verify that none of the invalid identifiers come out as identifier tokens.
-  for (auto str : invalid_identifiers) {
-    StringRef dil_input_expr(str);
-    lldb_private::dil::DILLexer dil_lexer(dil_input_expr);
-    lldb_private::dil::DILToken dil_token;
-    dil_token.setKind(lldb_private::dil::TokenKind::unknown);
-
-    dil_lexer.Lex(dil_token);
-    EXPECT_TRUE(dil_token.isNot(lldb_private::dil::TokenKind::identifier));
-    EXPECT_TRUE(dil_token.isOneOf(lldb_private::dil::TokenKind::unknown,
-                                  lldb_private::dil::TokenKind::none,
-                                  lldb_private::dil::TokenKind::eof,
-                                  lldb_private::dil::TokenKind::kw_namespace));
+  for (auto &str : invalid_identifiers) {
+    SCOPED_TRACE(str);
+    lldb_private::dil::DILLexer lexer(str);
+    lldb_private::dil::Token token;
+    token.SetKind(lldb_private::dil::Token::unknown);
+
+    auto success = lexer.LexAll();
+    // In this case, it's ok for Lex() to return an error.
+    if (!success) {
+      llvm::consumeError(success.takeError());
+    } else {
+      // We didn't get an error; make sure we did not get an identifier token.
+      token = lexer.GetNextToken();
+      EXPECT_TRUE(token.IsNot(lldb_private::dil::Token::identifier));
+      EXPECT_TRUE(token.IsOneOf(lldb_private::dil::Token::unknown,
+                                lldb_private::dil::Token::none,
+                                lldb_private::dil::Token::eof,
+                                lldb_private::dil::Token::kw_namespace));
+    }
   }
 }

>From ccf5203595ec22d2e58d774ecbe58cdccfc2f106 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Thu, 30 Jan 2025 15:07:33 -0800
Subject: [PATCH 04/10] Address	latest review comments:

- Remove 'namespace' as	a keyword (make it a normal identifier)
- Remove 'invalid' and 'none' token types.
- Remove unnecessary SetKind and GetLength methods from	Tokens.
- Re-arrange Lexer:
  - Give it a static Create method, which pre-lexes all	the tokens
  - Make Lex method static
  - Pull IsWord	method out of Lexer class
  - Make the Lexer constructor private.
- Remove LexAll, GetLocation, UpdateLexedTokens, AcceptLookAhead, GetNextToken,
  and IncrementTokenIdx methods from Lexer class.
- Add new 'Advance' method (to help replace some of the removed methods).
- Update indexing in LookAhead (LookAead(0) now means the 'current' token).
- Remove m_cur_pos data	member from Lexer class.
- Replace m_invalid_token with m_eof_token.
- Use 'remainder' StringRef to help with lexing.
- Update the unit tests	to handle all the code changes in the Lexer.
- Update the unit tests	to use ASSERT_THAT_EXPECTED to check llvm::Expected
  return values.
- Update the unit tests	to use "testing::ElementsAre(testing::Pair ..."	to
  verify all the lexed tokens; also added helper function ExtractTokenData, and
  deleted function VerifyExpectedTokens.
---
 lldb/include/lldb/ValueObject/DILLexer.h     |  97 +++-----
 lldb/source/ValueObject/DILLexer.cpp         | 153 ++++--------
 lldb/unittests/ValueObject/CMakeLists.txt    |   1 +
 lldb/unittests/ValueObject/DILLexerTests.cpp | 232 ++++++++-----------
 4 files changed, 187 insertions(+), 296 deletions(-)

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index 61e5fe622e51e6..9e6cec18a68672 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -18,9 +18,7 @@
 #include <string>
 #include <vector>
 
-namespace lldb_private {
-
-namespace dil {
+namespace lldb_private::dil {
 
 /// Class defining the tokens generated by the DIL lexer and used by the
 /// DIL parser.
@@ -30,10 +28,7 @@ class Token {
     coloncolon,
     eof,
     identifier,
-    invalid,
-    kw_namespace,
     l_paren,
-    none,
     r_paren,
     unknown,
   };
@@ -41,16 +36,10 @@ class Token {
   Token(Kind kind, std::string spelling, uint32_t start)
       : m_kind(kind), m_spelling(spelling), m_start_pos(start) {}
 
-  Token() : m_kind(Kind::none), m_spelling(""), m_start_pos(0) {}
-
-  void SetKind(Kind kind) { m_kind = kind; }
-
   Kind GetKind() const { return m_kind; }
 
   std::string GetSpelling() const { return m_spelling; }
 
-  uint32_t GetLength() const { return m_spelling.size(); }
-
   bool Is(Kind kind) const { return m_kind == kind; }
 
   bool IsNot(Kind kind) const { return m_kind != kind; }
@@ -74,72 +63,58 @@ class Token {
 /// Class for doing the simple lexing required by DIL.
 class DILLexer {
 public:
-  DILLexer(llvm::StringRef dil_expr) : m_expr(dil_expr) {
-    m_cur_pos = m_expr.begin();
-    // Use UINT_MAX to indicate invalid/uninitialized value.
-    m_tokens_idx = UINT_MAX;
-    m_invalid_token = Token(Token::invalid, "", 0);
-  }
-
-  llvm::Expected<bool> LexAll();
-
-  /// Return the lexed token N+1 positions ahead of the 'current' token
-  /// being handled by the DIL parser.
-  const Token &LookAhead(uint32_t N);
-
-  const Token &AcceptLookAhead(uint32_t N);
-
-  const Token &GetNextToken();
-
-  /// Return the index for the 'current' token being handled by the DIL parser.
-  uint32_t GetCurrentTokenIdx() { return m_tokens_idx; }
+  /// Lexes all the tokens in expr and calls the private constructor
+  /// with the lexed tokens.
+  static llvm::Expected<DILLexer> Create(llvm::StringRef expr);
 
   /// Return the current token to be handled by the DIL parser.
   const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; }
 
-  uint32_t NumLexedTokens() { return m_lexed_tokens.size(); }
+  /// Advance the current token position by N.
+  void Advance(uint32_t N = 1) {
+    // UINT_MAX means uninitialized, no "current" position, so move to start.
+    if (m_tokens_idx == UINT_MAX)
+      m_tokens_idx = 0;
+    else if (m_tokens_idx + N >= m_lexed_tokens.size())
+      // N is too large; advance to the end of the lexed tokens.
+      m_tokens_idx = m_lexed_tokens.size() - 1;
+    else
+      m_tokens_idx += N;
+  }
 
-  /// 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;
+  /// Return the lexed token N positions ahead of the 'current' token
+  /// being handled by the DIL parser.
+  const Token &LookAhead(uint32_t N) {
+    if (m_tokens_idx + N < m_lexed_tokens.size())
+      return m_lexed_tokens[m_tokens_idx + N];
 
-    m_tokens_idx++;
-    return true;
+    return m_eof_token;
   }
 
+  /// Return the index for the 'current' token being handled by the DIL parser.
+  uint32_t GetCurrentTokenIdx() { return m_tokens_idx; }
+
   /// 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;
-
+  void ResetTokenIdx(uint32_t new_value) {
+    assert(new_value == UINT_MAX || new_value < m_lexed_tokens.size());
     m_tokens_idx = new_value;
-    return true;
   }
 
-  uint32_t GetLocation() { return m_cur_pos - m_expr.begin(); }
+  uint32_t NumLexedTokens() { return m_lexed_tokens.size(); }
 
 private:
-  llvm::Expected<Token> Lex();
+  DILLexer(llvm::StringRef dil_expr, std::vector<Token> lexed_tokens)
+      : m_expr(dil_expr), m_lexed_tokens(lexed_tokens), m_tokens_idx(UINT_MAX),
+        m_eof_token(Token(Token::eof, "", 0)) {}
 
-  llvm::iterator_range<llvm::StringRef::iterator> IsWord();
-
-  /// Update 'result' with the other paremeter values, create a
-  /// duplicate token, and push the duplicate token onto the vector of
-  /// lexed tokens.
-  void UpdateLexedTokens(Token &result, Token::Kind tok_kind,
-                         std::string tok_str, uint32_t tok_pos);
+  static llvm::Expected<Token> Lex(llvm::StringRef expr,
+                                   llvm::StringRef &remainder);
 
   // The input string we are lexing & parsing.
   llvm::StringRef m_expr;
 
-  // The current position of the lexer within m_expr (the character position,
-  // within the string, of the next item to be lexed).
-  llvm::StringRef::iterator m_cur_pos;
-
   // Holds all of the tokens lexed so far.
   std::vector<Token> m_lexed_tokens;
 
@@ -147,12 +122,10 @@ class DILLexer {
   // currently trying to parse/handle.
   uint32_t m_tokens_idx;
 
-  // "invalid" token; to be returned by lexer when 'look ahead' fails.
-  Token m_invalid_token;
+  // "eof" token; to be returned by lexer when 'look ahead' fails.
+  Token m_eof_token;
 };
 
-} // namespace dil
-
-} // namespace lldb_private
+} // namespace lldb_private::dil
 
 #endif // LLDB_VALUEOBJECT_DILLEXER_H_
diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp
index 30e4bcb04e6505..b92bb86c8219c6 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -15,9 +15,7 @@
 #include "lldb/Utility/Status.h"
 #include "llvm/ADT/StringSwitch.h"
 
-namespace lldb_private {
-
-namespace dil {
+namespace lldb_private::dil {
 
 llvm::StringRef Token::GetTokenName(Kind kind) {
   switch (kind) {
@@ -27,14 +25,8 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
     return "eof";
   case Kind::identifier:
     return "identifier";
-  case Kind::invalid:
-    return "invalid";
-  case Kind::kw_namespace:
-    return "namespace";
   case Kind::l_paren:
     return "l_paren";
-  case Kind::none:
-    return "none";
   case Kind::r_paren:
     return "r_paren";
   case Kind::unknown:
@@ -50,140 +42,91 @@ static bool IsDigit(char c) { return '0' <= c && c <= '9'; }
 
 // A word starts with a letter, underscore, or dollar sign, followed by
 // letters ('a'..'z','A'..'Z'), digits ('0'..'9'), and/or  underscores.
-llvm::iterator_range<llvm::StringRef::iterator> DILLexer::IsWord() {
-  llvm::StringRef::iterator start = m_cur_pos;
+static std::optional<llvm::StringRef> IsWord(llvm::StringRef expr,
+                                             llvm::StringRef &remainder) {
+  llvm::StringRef::iterator cur_pos = expr.end() - remainder.size();
+  llvm::StringRef::iterator start = cur_pos;
   bool dollar_start = false;
 
   // Must not start with a digit.
-  if (m_cur_pos == m_expr.end() || IsDigit(*m_cur_pos))
-    return llvm::make_range(m_cur_pos, m_cur_pos);
+  if (cur_pos == expr.end() || IsDigit(*cur_pos))
+    return std::nullopt;
 
   // First character *may* be a '$', for a register name or convenience
   // variable.
-  if (*m_cur_pos == '$') {
+  if (*cur_pos == '$') {
     dollar_start = true;
-    ++m_cur_pos;
+    ++cur_pos;
   }
 
   // Contains only letters, digits or underscores
-  for (; m_cur_pos != m_expr.end(); ++m_cur_pos) {
-    char c = *m_cur_pos;
+  for (; cur_pos != expr.end(); ++cur_pos) {
+    char c = *cur_pos;
     if (!IsLetter(c) && !IsDigit(c) && c != '_')
       break;
   }
 
   // If first char is '$', make sure there's at least one mare char, or it's
   // invalid.
-  if (dollar_start && (m_cur_pos - start <= 1)) {
-    m_cur_pos = start;
-    return llvm::make_range(start, start); // Empty range
+  if (dollar_start && (cur_pos - start <= 1)) {
+    cur_pos = start;
+    return std::nullopt;
   }
 
-  return llvm::make_range(start, m_cur_pos);
-}
+  if (cur_pos == start)
+    return std::nullopt;
+
+  llvm::StringRef word = expr.substr(start - expr.begin(), cur_pos - start);
+  if (remainder.consume_front(word))
+    return word;
 
-void DILLexer::UpdateLexedTokens(Token &result, Token::Kind tok_kind,
-                                 std::string tok_str, uint32_t tok_pos) {
-  Token new_token(tok_kind, tok_str, tok_pos);
-  result = new_token;
-  m_lexed_tokens.push_back(std::move(new_token));
+  return std::nullopt;
 }
 
-llvm::Expected<bool> DILLexer::LexAll() {
-  bool done = false;
-  while (!done) {
-    auto tok_or_err = Lex();
-    if (!tok_or_err)
-      return tok_or_err.takeError();
-    Token token = *tok_or_err;
-    if (token.GetKind() == Token::eof) {
-      done = true;
+llvm::Expected<DILLexer> DILLexer::Create(llvm::StringRef expr) {
+  std::vector<Token> tokens;
+  llvm::StringRef remainder = expr;
+  do {
+    if (llvm::Expected<Token> t = Lex(expr, remainder)) {
+      tokens.push_back(std::move(*t));
+    } else {
+      return t.takeError();
     }
-  }
-  return true;
+  } while (tokens.back().GetKind() != Token::eof);
+  return DILLexer(expr, std::move(tokens));
 }
 
-llvm::Expected<Token> DILLexer::Lex() {
-  Token result;
-
+llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
+                                    llvm::StringRef &remainder) {
   // Skip over whitespace (spaces).
-  while (m_cur_pos != m_expr.end() && *m_cur_pos == ' ')
-    m_cur_pos++;
+  remainder = remainder.ltrim();
+  llvm::StringRef::iterator cur_pos = expr.end() - remainder.size();
 
   // Check to see if we've reached the end of our input string.
-  if (m_cur_pos == m_expr.end()) {
-    UpdateLexedTokens(result, Token::eof, "", (uint32_t)m_expr.size());
-    return result;
+  if (remainder.empty() || cur_pos == expr.end())
+    return Token(Token::eof, "", (uint32_t)expr.size());
+
+  uint32_t position = cur_pos - expr.begin();
+  std::optional<llvm::StringRef> maybe_word = IsWord(expr, remainder);
+  if (maybe_word) {
+    llvm::StringRef word = *maybe_word;
+    return Token(Token::identifier, word.str(), position);
   }
 
-  uint32_t position = m_cur_pos - m_expr.begin();
-  llvm::StringRef::iterator start = m_cur_pos;
-  llvm::iterator_range<llvm::StringRef::iterator> word_range = IsWord();
-  if (!word_range.empty()) {
-    uint32_t length = word_range.end() - word_range.begin();
-    llvm::StringRef word(m_expr.substr(position, length));
-    // We will be adding more keywords here in the future...
-    Token::Kind kind = llvm::StringSwitch<Token::Kind>(word)
-                           .Case("namespace", Token::kw_namespace)
-                           .Default(Token::identifier);
-    UpdateLexedTokens(result, kind, word.str(), position);
-    return result;
-  }
-
-  m_cur_pos = start;
-  llvm::StringRef remainder(m_expr.substr(position, m_expr.end() - m_cur_pos));
-  std::vector<std::pair<Token::Kind, const char *>> operators = {
+  constexpr std::pair<Token::Kind, const char *> operators[] = {
       {Token::l_paren, "("},
       {Token::r_paren, ")"},
       {Token::coloncolon, "::"},
   };
   for (auto [kind, str] : operators) {
     if (remainder.consume_front(str)) {
-      m_cur_pos += strlen(str);
-      UpdateLexedTokens(result, kind, str, position);
-      return result;
+      cur_pos += strlen(str);
+      return Token(kind, str, position);
     }
   }
 
   // Unrecognized character(s) in string; unable to lex it.
-  Status error("Unable to lex input string");
-  return error.ToError();
-}
-
-const Token &DILLexer::LookAhead(uint32_t N) {
-  if (m_tokens_idx + N + 1 < m_lexed_tokens.size())
-    return m_lexed_tokens[m_tokens_idx + N + 1];
-
-  return m_invalid_token;
+  return llvm::createStringError("Unable to lex input string");
 }
 
-const Token &DILLexer::AcceptLookAhead(uint32_t N) {
-  if (m_tokens_idx + N + 1 > m_lexed_tokens.size())
-    return m_invalid_token;
-
-  m_tokens_idx += N + 1;
-  return m_lexed_tokens[m_tokens_idx];
-}
-
-const Token &DILLexer::GetNextToken() {
-  if (m_tokens_idx == UINT_MAX)
-    m_tokens_idx = 0;
-  else
-    m_tokens_idx++;
-
-  // Return the next token in the vector of lexed tokens.
-  if (m_tokens_idx < m_lexed_tokens.size())
-    return m_lexed_tokens[m_tokens_idx];
-
-  // We're already at/beyond the end of our lexed tokens. If the last token
-  // is an eof token, return it.
-  if (m_lexed_tokens[m_lexed_tokens.size() - 1].GetKind() == Token::eof)
-    return m_lexed_tokens[m_lexed_tokens.size() - 1];
-
-  // Return the invalid token.
-  return m_invalid_token;
-}
-
-} // namespace dil
-
-} // namespace lldb_private
+} // namespace lldb_private::dil
diff --git a/lldb/unittests/ValueObject/CMakeLists.txt b/lldb/unittests/ValueObject/CMakeLists.txt
index 952f5411a98057..14808aa2f213a5 100644
--- a/lldb/unittests/ValueObject/CMakeLists.txt
+++ b/lldb/unittests/ValueObject/CMakeLists.txt
@@ -6,6 +6,7 @@ add_lldb_unittest(LLDBValueObjectTests
     lldbValueObject
     lldbPluginPlatformLinux
     lldbPluginScriptInterpreterNone
+    LLVMTestingSupport
 
   LINK_COMPONENTS
     Support
diff --git a/lldb/unittests/ValueObject/DILLexerTests.cpp b/lldb/unittests/ValueObject/DILLexerTests.cpp
index 137013e40d6adf..f5523d3c5c4068 100644
--- a/lldb/unittests/ValueObject/DILLexerTests.cpp
+++ b/lldb/unittests/ValueObject/DILLexerTests.cpp
@@ -8,100 +8,90 @@
 
 #include "lldb/ValueObject/DILLexer.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Testing/Support/Error.h"
 #include "gtest/gtest.h"
 #include <string>
 
 using llvm::StringRef;
 
-bool VerifyExpectedTokens(
-    lldb_private::dil::DILLexer &lexer,
-    std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>>
-        exp_tokens,
-    uint32_t start_pos) {
-  if (lexer.NumLexedTokens() - start_pos < exp_tokens.size())
-    return false;
-
-  if (start_pos > 0)
-    lexer.ResetTokenIdx(start_pos -
-                        1); // GetNextToken increments the idx first.
-  for (const auto &pair : exp_tokens) {
-    lldb_private::dil::Token token = lexer.GetNextToken();
-    if (token.GetKind() != pair.first || token.GetSpelling() != pair.second)
-      return false;
-  }
-
-  return true;
+std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>>
+ExtractTokenData(lldb_private::dil::DILLexer &lexer) {
+  std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>> data;
+  if (lexer.NumLexedTokens() == 0)
+    return data;
+
+  lexer.ResetTokenIdx(UINT_MAX);
+  do {
+    lexer.Advance();
+    lldb_private::dil::Token tok = lexer.GetCurrentToken();
+    data.push_back(std::make_pair(tok.GetKind(), tok.GetSpelling()));
+  } while (data.back().first != lldb_private::dil::Token::eof);
+  return data;
 }
 
 TEST(DILLexerTests, SimpleTest) {
   StringRef input_expr("simple_var");
   uint32_t tok_len = 10;
-  lldb_private::dil::DILLexer lexer(input_expr);
-  lldb_private::dil::Token token;
-  token.SetKind(lldb_private::dil::Token::unknown);
+  llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
+      lldb_private::dil::DILLexer::Create(input_expr);
+  ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
+  lldb_private::dil::DILLexer lexer(*maybe_lexer);
+  lldb_private::dil::Token token =
+      lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
   EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::unknown);
-  auto success = lexer.LexAll();
 
-  if (!success) {
-    EXPECT_TRUE(false);
-  }
-  token = lexer.GetNextToken();
+  lexer.Advance();
+  token = lexer.GetCurrentToken();
   EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
   EXPECT_EQ(token.GetSpelling(), "simple_var");
-  EXPECT_EQ(token.GetLength(), tok_len);
-  token = lexer.GetNextToken();
-  ;
+  EXPECT_EQ(token.GetSpelling().size(), tok_len);
+  lexer.Advance();
+  token = lexer.GetCurrentToken();
   EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
 }
 
 TEST(DILLexerTests, TokenKindTest) {
   StringRef input_expr("namespace");
-  lldb_private::dil::DILLexer lexer(input_expr);
-  lldb_private::dil::Token token;
-  token.SetKind(lldb_private::dil::Token::unknown);
-
-  auto success = lexer.LexAll();
-  if (!success) {
-    EXPECT_TRUE(false);
-  }
-  token = lexer.GetNextToken();
-
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::kw_namespace);
-  EXPECT_TRUE(token.IsNot(lldb_private::dil::Token::identifier));
+  llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
+      lldb_private::dil::DILLexer::Create(input_expr);
+  ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
+  lldb_private::dil::DILLexer lexer(*maybe_lexer);
+  lldb_private::dil::Token token =
+      lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
+  lexer.Advance();
+  token = lexer.GetCurrentToken();
+
+  EXPECT_TRUE(token.Is(lldb_private::dil::Token::identifier));
   EXPECT_FALSE(token.Is(lldb_private::dil::Token::l_paren));
   EXPECT_TRUE(token.IsOneOf(lldb_private::dil::Token::eof,
-                            lldb_private::dil::Token::kw_namespace));
+                            lldb_private::dil::Token::identifier));
   EXPECT_FALSE(token.IsOneOf(
       lldb_private::dil::Token::l_paren, lldb_private::dil::Token::r_paren,
       lldb_private::dil::Token::coloncolon, lldb_private::dil::Token::eof));
-
-  token.SetKind(lldb_private::dil::Token::identifier);
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
 }
 
 TEST(DILLexerTests, LookAheadTest) {
   StringRef input_expr("(anonymous namespace)::some_var");
-  lldb_private::dil::DILLexer lexer(input_expr);
-  lldb_private::dil::Token token;
-  token.SetKind(lldb_private::dil::Token::unknown);
+  llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
+      lldb_private::dil::DILLexer::Create(input_expr);
+  ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
+  lldb_private::dil::DILLexer lexer(*maybe_lexer);
+  lldb_private::dil::Token token =
+      lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
   uint32_t expect_loc = 23;
-
-  auto success = lexer.LexAll();
-  if (!success) {
-    EXPECT_TRUE(false);
-  }
-  token = lexer.GetNextToken();
+  lexer.Advance();
+  token = lexer.GetCurrentToken();
 
   // Current token is '('; check the next 4 tokens, to make
-  // sure they are the identifier 'anonymous', the namespace keyword,
+  // sure they are the identifier 'anonymous', the identifier 'namespace'
   // ')' and '::', in that order.
   EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::l_paren);
-  EXPECT_EQ(lexer.LookAhead(0).GetKind(), lldb_private::dil::Token::identifier);
-  EXPECT_EQ(lexer.LookAhead(0).GetSpelling(), "anonymous");
-  EXPECT_EQ(lexer.LookAhead(1).GetKind(),
-            lldb_private::dil::Token::kw_namespace);
-  EXPECT_EQ(lexer.LookAhead(2).GetKind(), lldb_private::dil::Token::r_paren);
-  EXPECT_EQ(lexer.LookAhead(3).GetKind(), lldb_private::dil::Token::coloncolon);
+  EXPECT_EQ(lexer.LookAhead(1).GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(lexer.LookAhead(1).GetSpelling(), "anonymous");
+  EXPECT_EQ(lexer.LookAhead(2).GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(lexer.LookAhead(2).GetSpelling(), "namespace");
+  EXPECT_EQ(lexer.LookAhead(3).GetKind(), lldb_private::dil::Token::r_paren);
+  EXPECT_EQ(lexer.LookAhead(4).GetKind(), lldb_private::dil::Token::coloncolon);
 
   // Our current index should still be 0, as we only looked ahead; we are still
   // officially on the '('.
@@ -109,110 +99,94 @@ TEST(DILLexerTests, LookAheadTest) {
 
   // Accept the 'lookahead', so our current token is '::', which has the index
   // 4 in our vector of tokens (which starts at zero).
-  token = lexer.AcceptLookAhead(3);
+  lexer.Advance(4);
+  token = lexer.GetCurrentToken();
   EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::coloncolon);
   EXPECT_EQ(lexer.GetCurrentTokenIdx(), (uint32_t)4);
 
-  token = lexer.GetNextToken();
+  lexer.Advance();
+  token = lexer.GetCurrentToken();
   EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
   EXPECT_EQ(token.GetSpelling(), "some_var");
   EXPECT_EQ(lexer.GetCurrentTokenIdx(), (uint32_t)5);
   // Verify we've advanced our position counter (lexing location) in the
   // input 23 characters (the length of '(anonymous namespace)::'.
   EXPECT_EQ(token.GetLocation(), expect_loc);
-  token = lexer.GetNextToken();
+
+  lexer.Advance();
+  token = lexer.GetCurrentToken();
   EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
 }
 
 TEST(DILLexerTests, MultiTokenLexTest) {
   StringRef input_expr("This string has (several ) ::identifiers");
-  lldb_private::dil::DILLexer lexer(input_expr);
-  lldb_private::dil::Token token;
-  token.SetKind(lldb_private::dil::Token::unknown);
-
-  auto success = lexer.LexAll();
-  if (!success) {
-    EXPECT_TRUE(false);
-  }
+  llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
+      lldb_private::dil::DILLexer::Create(input_expr);
+  ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
+  lldb_private::dil::DILLexer lexer(*maybe_lexer);
+  lldb_private::dil::Token token =
+      lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
 
   std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>>
-      expected_tokens = {
-          {lldb_private::dil::Token::identifier, "This"},
-          {lldb_private::dil::Token::identifier, "string"},
-          {lldb_private::dil::Token::identifier, "has"},
-          {lldb_private::dil::Token::l_paren, "("},
-          {lldb_private::dil::Token::identifier, "several"},
-          {lldb_private::dil::Token::r_paren, ")"},
-          {lldb_private::dil::Token::coloncolon, "::"},
-          {lldb_private::dil::Token::identifier, "identifiers"},
-      };
-
-  EXPECT_TRUE(VerifyExpectedTokens(lexer, expected_tokens, 0));
-
-  token = lexer.GetNextToken();
+      lexer_tokens_data = ExtractTokenData(lexer);
+
+  EXPECT_THAT(
+      lexer_tokens_data,
+      testing::ElementsAre(
+          testing::Pair(lldb_private::dil::Token::identifier, "This"),
+          testing::Pair(lldb_private::dil::Token::identifier, "string"),
+          testing::Pair(lldb_private::dil::Token::identifier, "has"),
+          testing::Pair(lldb_private::dil::Token::l_paren, "("),
+          testing::Pair(lldb_private::dil::Token::identifier, "several"),
+          testing::Pair(lldb_private::dil::Token::r_paren, ")"),
+          testing::Pair(lldb_private::dil::Token::coloncolon, "::"),
+          testing::Pair(lldb_private::dil::Token::identifier, "identifiers"),
+          testing::Pair(lldb_private::dil::Token::eof, "")));
+  lexer.Advance();
+  token = lexer.GetCurrentToken();
   EXPECT_EQ(token.GetSpelling(), "");
   EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
 }
 
 TEST(DILLexerTests, IdentifiersTest) {
   std::vector<std::string> valid_identifiers = {
-    "$My_name1",
-    "$pc",
-    "abcd",
-    "ab cd",
-    "_",
-    "_a",
-    "_a_",
-    "a_b",
-    "this",
-    "self",
-    "a",
-    "MyName"
-  };
-  std::vector<std::string> invalid_identifiers = {
-    "234",
-    "2a",
-    "2",
-    "$",
-    "1MyName",
-    "",
-    "namespace"
-  };
+      "$My_name1", "$pc",  "abcd", "ab cd", "_",      "_a",       "_a_",
+      "a_b",       "this", "self", "a",     "MyName", "namespace"};
+  std::vector<std::string> invalid_identifiers = {"234", "2a",      "2",
+                                                  "$",   "1MyName", ""};
 
   // Verify that all of the valid identifiers come out as identifier tokens.
   for (auto &str : valid_identifiers) {
     SCOPED_TRACE(str);
-    lldb_private::dil::DILLexer lexer(str);
-    lldb_private::dil::Token token;
-    token.SetKind(lldb_private::dil::Token::unknown);
-
-    auto success = lexer.LexAll();
-    if (!success) {
-      EXPECT_TRUE(false);
-    }
-    token = lexer.GetNextToken();
+    llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
+        lldb_private::dil::DILLexer::Create(str);
+    ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
+    lldb_private::dil::DILLexer lexer(*maybe_lexer);
+    lldb_private::dil::Token token =
+        lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
+    lexer.Advance();
+    token = lexer.GetCurrentToken();
     EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
   }
 
   // Verify that none of the invalid identifiers come out as identifier tokens.
   for (auto &str : invalid_identifiers) {
     SCOPED_TRACE(str);
-    lldb_private::dil::DILLexer lexer(str);
-    lldb_private::dil::Token token;
-    token.SetKind(lldb_private::dil::Token::unknown);
-
-    auto success = lexer.LexAll();
-    // In this case, it's ok for Lex() to return an error.
-    if (!success) {
-      llvm::consumeError(success.takeError());
+    llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
+        lldb_private::dil::DILLexer::Create(str);
+    if (!maybe_lexer) {
+      llvm::consumeError(maybe_lexer.takeError());
+      // In this case, it's ok for lexing to return an error.
     } else {
+      lldb_private::dil::DILLexer lexer(*maybe_lexer);
+      lldb_private::dil::Token token =
+          lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
       // We didn't get an error; make sure we did not get an identifier token.
-      token = lexer.GetNextToken();
+      lexer.Advance();
+      token = lexer.GetCurrentToken();
       EXPECT_TRUE(token.IsNot(lldb_private::dil::Token::identifier));
       EXPECT_TRUE(token.IsOneOf(lldb_private::dil::Token::unknown,
-                                lldb_private::dil::Token::none,
-                                lldb_private::dil::Token::eof,
-                                lldb_private::dil::Token::kw_namespace));
+                                lldb_private::dil::Token::eof));
     }
   }
 }

>From 29e9f265ea342e84372c63adbfdac0882d2fd434 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 2 Feb 2025 22:06:04 -0800
Subject: [PATCH 05/10] Address	more review comments:

- Use std::move	on std::string & std::vector in	constructor initializers.
- Remove some unnecessary code.
- Update ExtractTokenData (helper function in unit tests) to set up the	lexer
  and to the lexing inside the function; return	an llvm::Expected value.
- Add 'using namespace lldb_private::dil;' to unit tests; clean	up tests
  accordingly.
- Minor	code cleanups in the unit tests.
---
 lldb/include/lldb/ValueObject/DILLexer.h     |   9 +-
 lldb/source/ValueObject/DILLexer.cpp         |  10 +-
 lldb/unittests/ValueObject/DILLexerTests.cpp | 162 ++++++++-----------
 3 files changed, 72 insertions(+), 109 deletions(-)

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index 9e6cec18a68672..3935bf7e8e5c5e 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -34,7 +34,7 @@ class Token {
   };
 
   Token(Kind kind, std::string spelling, uint32_t start)
-      : m_kind(kind), m_spelling(spelling), m_start_pos(start) {}
+      : m_kind(kind), m_spelling(std::move(spelling)), m_start_pos(start) {}
 
   Kind GetKind() const { return m_kind; }
 
@@ -88,7 +88,8 @@ class DILLexer {
     if (m_tokens_idx + N < m_lexed_tokens.size())
       return m_lexed_tokens[m_tokens_idx + N];
 
-    return m_eof_token;
+    // Last token should be an 'eof' token.
+    return m_lexed_tokens.back();
   }
 
   /// Return the index for the 'current' token being handled by the DIL parser.
@@ -106,8 +107,8 @@ class DILLexer {
 
 private:
   DILLexer(llvm::StringRef dil_expr, std::vector<Token> lexed_tokens)
-      : m_expr(dil_expr), m_lexed_tokens(lexed_tokens), m_tokens_idx(UINT_MAX),
-        m_eof_token(Token(Token::eof, "", 0)) {}
+      : m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)),
+        m_tokens_idx(UINT_MAX), m_eof_token(Token(Token::eof, "", 0)) {}
 
   static llvm::Expected<Token> Lex(llvm::StringRef expr,
                                    llvm::StringRef &remainder);
diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp
index b92bb86c8219c6..46ecea9b585f56 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -108,10 +108,8 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
 
   uint32_t position = cur_pos - expr.begin();
   std::optional<llvm::StringRef> maybe_word = IsWord(expr, remainder);
-  if (maybe_word) {
-    llvm::StringRef word = *maybe_word;
-    return Token(Token::identifier, word.str(), position);
-  }
+  if (maybe_word)
+    return Token(Token::identifier, maybe_word->str(), position);
 
   constexpr std::pair<Token::Kind, const char *> operators[] = {
       {Token::l_paren, "("},
@@ -119,10 +117,8 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
       {Token::coloncolon, "::"},
   };
   for (auto [kind, str] : operators) {
-    if (remainder.consume_front(str)) {
-      cur_pos += strlen(str);
+    if (remainder.consume_front(str))
       return Token(kind, str, position);
-    }
   }
 
   // Unrecognized character(s) in string; unable to lex it.
diff --git a/lldb/unittests/ValueObject/DILLexerTests.cpp b/lldb/unittests/ValueObject/DILLexerTests.cpp
index f5523d3c5c4068..b6858246b8850c 100644
--- a/lldb/unittests/ValueObject/DILLexerTests.cpp
+++ b/lldb/unittests/ValueObject/DILLexerTests.cpp
@@ -14,179 +14,145 @@
 
 using llvm::StringRef;
 
-std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>>
-ExtractTokenData(lldb_private::dil::DILLexer &lexer) {
-  std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>> data;
+using namespace lldb_private::dil;
+
+llvm::Expected<std::vector<std::pair<Token::Kind, std::string>>>
+ExtractTokenData(llvm::StringRef input_expr) {
+
+  llvm::Expected<DILLexer> maybe_lexer = DILLexer::Create(input_expr);
+  if (!maybe_lexer)
+    return maybe_lexer.takeError();
+  DILLexer lexer(*maybe_lexer);
+
   if (lexer.NumLexedTokens() == 0)
-    return data;
+    return llvm::createStringError("No lexed tokens");
 
   lexer.ResetTokenIdx(UINT_MAX);
+  std::vector<std::pair<Token::Kind, std::string>> data;
   do {
     lexer.Advance();
-    lldb_private::dil::Token tok = lexer.GetCurrentToken();
+    Token tok = lexer.GetCurrentToken();
     data.push_back(std::make_pair(tok.GetKind(), tok.GetSpelling()));
-  } while (data.back().first != lldb_private::dil::Token::eof);
+  } while (data.back().first != Token::eof);
   return data;
 }
 
 TEST(DILLexerTests, SimpleTest) {
   StringRef input_expr("simple_var");
-  uint32_t tok_len = 10;
-  llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
-      lldb_private::dil::DILLexer::Create(input_expr);
+  llvm::Expected<DILLexer> maybe_lexer = DILLexer::Create(input_expr);
   ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
-  lldb_private::dil::DILLexer lexer(*maybe_lexer);
-  lldb_private::dil::Token token =
-      lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::unknown);
+  DILLexer lexer(*maybe_lexer);
+  Token token = Token(Token::unknown, "", 0);
+  EXPECT_EQ(token.GetKind(), Token::unknown);
 
   lexer.Advance();
   token = lexer.GetCurrentToken();
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(token.GetKind(), Token::identifier);
   EXPECT_EQ(token.GetSpelling(), "simple_var");
-  EXPECT_EQ(token.GetSpelling().size(), tok_len);
   lexer.Advance();
   token = lexer.GetCurrentToken();
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
+  EXPECT_EQ(token.GetKind(), Token::eof);
 }
 
 TEST(DILLexerTests, TokenKindTest) {
-  StringRef input_expr("namespace");
-  llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
-      lldb_private::dil::DILLexer::Create(input_expr);
-  ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
-  lldb_private::dil::DILLexer lexer(*maybe_lexer);
-  lldb_private::dil::Token token =
-      lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
-  lexer.Advance();
-  token = lexer.GetCurrentToken();
+  Token token = Token(Token::identifier, "ident", 0);
 
-  EXPECT_TRUE(token.Is(lldb_private::dil::Token::identifier));
-  EXPECT_FALSE(token.Is(lldb_private::dil::Token::l_paren));
-  EXPECT_TRUE(token.IsOneOf(lldb_private::dil::Token::eof,
-                            lldb_private::dil::Token::identifier));
-  EXPECT_FALSE(token.IsOneOf(
-      lldb_private::dil::Token::l_paren, lldb_private::dil::Token::r_paren,
-      lldb_private::dil::Token::coloncolon, lldb_private::dil::Token::eof));
+  EXPECT_TRUE(token.Is(Token::identifier));
+  EXPECT_FALSE(token.Is(Token::l_paren));
+  EXPECT_TRUE(token.IsOneOf(Token::eof, Token::identifier));
+  EXPECT_FALSE(token.IsOneOf(Token::l_paren, Token::r_paren, Token::coloncolon,
+                             Token::eof));
 }
 
 TEST(DILLexerTests, LookAheadTest) {
   StringRef input_expr("(anonymous namespace)::some_var");
-  llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
-      lldb_private::dil::DILLexer::Create(input_expr);
+  llvm::Expected<DILLexer> maybe_lexer = DILLexer::Create(input_expr);
   ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
-  lldb_private::dil::DILLexer lexer(*maybe_lexer);
-  lldb_private::dil::Token token =
-      lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
-  uint32_t expect_loc = 23;
+  DILLexer lexer(*maybe_lexer);
+  Token token = Token(Token::unknown, "", 0);
   lexer.Advance();
   token = lexer.GetCurrentToken();
 
   // Current token is '('; check the next 4 tokens, to make
   // sure they are the identifier 'anonymous', the identifier 'namespace'
   // ')' and '::', in that order.
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::l_paren);
-  EXPECT_EQ(lexer.LookAhead(1).GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(token.GetKind(), Token::l_paren);
+  EXPECT_EQ(lexer.LookAhead(1).GetKind(), Token::identifier);
   EXPECT_EQ(lexer.LookAhead(1).GetSpelling(), "anonymous");
-  EXPECT_EQ(lexer.LookAhead(2).GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(lexer.LookAhead(2).GetKind(), Token::identifier);
   EXPECT_EQ(lexer.LookAhead(2).GetSpelling(), "namespace");
-  EXPECT_EQ(lexer.LookAhead(3).GetKind(), lldb_private::dil::Token::r_paren);
-  EXPECT_EQ(lexer.LookAhead(4).GetKind(), lldb_private::dil::Token::coloncolon);
+  EXPECT_EQ(lexer.LookAhead(3).GetKind(), Token::r_paren);
+  EXPECT_EQ(lexer.LookAhead(4).GetKind(), Token::coloncolon);
 
   // Our current index should still be 0, as we only looked ahead; we are still
   // officially on the '('.
-  EXPECT_EQ(lexer.GetCurrentTokenIdx(), (uint32_t)0);
+  EXPECT_EQ(lexer.GetCurrentTokenIdx(), 0u);
 
   // Accept the 'lookahead', so our current token is '::', which has the index
   // 4 in our vector of tokens (which starts at zero).
   lexer.Advance(4);
   token = lexer.GetCurrentToken();
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::coloncolon);
-  EXPECT_EQ(lexer.GetCurrentTokenIdx(), (uint32_t)4);
+  EXPECT_EQ(token.GetKind(), Token::coloncolon);
+  EXPECT_EQ(lexer.GetCurrentTokenIdx(), 4u);
 
   lexer.Advance();
   token = lexer.GetCurrentToken();
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
+  EXPECT_EQ(token.GetKind(), Token::identifier);
   EXPECT_EQ(token.GetSpelling(), "some_var");
-  EXPECT_EQ(lexer.GetCurrentTokenIdx(), (uint32_t)5);
-  // Verify we've advanced our position counter (lexing location) in the
-  // input 23 characters (the length of '(anonymous namespace)::'.
-  EXPECT_EQ(token.GetLocation(), expect_loc);
+  EXPECT_EQ(lexer.GetCurrentTokenIdx(), 5u);
+  EXPECT_EQ(token.GetLocation(), strlen("(anonymous namespace)::"));
 
   lexer.Advance();
   token = lexer.GetCurrentToken();
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
+  EXPECT_EQ(token.GetKind(), Token::eof);
 }
 
 TEST(DILLexerTests, MultiTokenLexTest) {
-  StringRef input_expr("This string has (several ) ::identifiers");
-  llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
-      lldb_private::dil::DILLexer::Create(input_expr);
-  ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
-  lldb_private::dil::DILLexer lexer(*maybe_lexer);
-  lldb_private::dil::Token token =
-      lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
-
-  std::vector<std::pair<lldb_private::dil::Token::Kind, std::string>>
-      lexer_tokens_data = ExtractTokenData(lexer);
-
-  EXPECT_THAT(
-      lexer_tokens_data,
-      testing::ElementsAre(
-          testing::Pair(lldb_private::dil::Token::identifier, "This"),
-          testing::Pair(lldb_private::dil::Token::identifier, "string"),
-          testing::Pair(lldb_private::dil::Token::identifier, "has"),
-          testing::Pair(lldb_private::dil::Token::l_paren, "("),
-          testing::Pair(lldb_private::dil::Token::identifier, "several"),
-          testing::Pair(lldb_private::dil::Token::r_paren, ")"),
-          testing::Pair(lldb_private::dil::Token::coloncolon, "::"),
-          testing::Pair(lldb_private::dil::Token::identifier, "identifiers"),
-          testing::Pair(lldb_private::dil::Token::eof, "")));
-  lexer.Advance();
-  token = lexer.GetCurrentToken();
-  EXPECT_EQ(token.GetSpelling(), "");
-  EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::eof);
+  EXPECT_THAT_EXPECTED(
+      ExtractTokenData("This string has (several ) ::identifiers"),
+      llvm::HasValue(
+          testing::ElementsAre(testing::Pair(Token::identifier, "This"),
+                               testing::Pair(Token::identifier, "string"),
+                               testing::Pair(Token::identifier, "has"),
+                               testing::Pair(Token::l_paren, "("),
+                               testing::Pair(Token::identifier, "several"),
+                               testing::Pair(Token::r_paren, ")"),
+                               testing::Pair(Token::coloncolon, "::"),
+                               testing::Pair(Token::identifier, "identifiers"),
+                               testing::Pair(Token::eof, ""))));
 }
 
 TEST(DILLexerTests, IdentifiersTest) {
   std::vector<std::string> valid_identifiers = {
-      "$My_name1", "$pc",  "abcd", "ab cd", "_",      "_a",       "_a_",
-      "a_b",       "this", "self", "a",     "MyName", "namespace"};
+      "$My_name1", "$pc",  "abcd", "_", "_a",     "_a_",
+      "a_b",       "this", "self", "a", "MyName", "namespace"};
   std::vector<std::string> invalid_identifiers = {"234", "2a",      "2",
                                                   "$",   "1MyName", ""};
 
   // Verify that all of the valid identifiers come out as identifier tokens.
   for (auto &str : valid_identifiers) {
     SCOPED_TRACE(str);
-    llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
-        lldb_private::dil::DILLexer::Create(str);
-    ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
-    lldb_private::dil::DILLexer lexer(*maybe_lexer);
-    lldb_private::dil::Token token =
-        lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
-    lexer.Advance();
-    token = lexer.GetCurrentToken();
-    EXPECT_EQ(token.GetKind(), lldb_private::dil::Token::identifier);
+    EXPECT_THAT_EXPECTED(ExtractTokenData(str),
+                         llvm::HasValue(testing::ElementsAre(
+                             testing::Pair(Token::identifier, str),
+                             testing::Pair(Token::eof, ""))));
   }
 
   // Verify that none of the invalid identifiers come out as identifier tokens.
   for (auto &str : invalid_identifiers) {
     SCOPED_TRACE(str);
-    llvm::Expected<lldb_private::dil::DILLexer> maybe_lexer =
-        lldb_private::dil::DILLexer::Create(str);
+    llvm::Expected<DILLexer> maybe_lexer = DILLexer::Create(str);
     if (!maybe_lexer) {
       llvm::consumeError(maybe_lexer.takeError());
       // In this case, it's ok for lexing to return an error.
     } else {
-      lldb_private::dil::DILLexer lexer(*maybe_lexer);
-      lldb_private::dil::Token token =
-          lldb_private::dil::Token(lldb_private::dil::Token::unknown, "", 0);
+      DILLexer lexer(*maybe_lexer);
+      Token token = Token(Token::unknown, "", 0);
       // We didn't get an error; make sure we did not get an identifier token.
       lexer.Advance();
       token = lexer.GetCurrentToken();
-      EXPECT_TRUE(token.IsNot(lldb_private::dil::Token::identifier));
-      EXPECT_TRUE(token.IsOneOf(lldb_private::dil::Token::unknown,
-                                lldb_private::dil::Token::eof));
+      EXPECT_TRUE(token.IsNot(Token::identifier));
+      EXPECT_TRUE(token.IsOneOf(Token::unknown, Token::eof));
     }
   }
 }

>From 0b33ab7ea76ef707b26e4359f9fc1336dd703ab0 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Mon, 3 Feb 2025 12:36:26 -0800
Subject: [PATCH 06/10] Address	remaining review comments:

- Remove 'unknown' token type.
- Remove UINT_MAX as a valid token index; always start at 0.
- Update IsWord	to use Pavel's more efficient StringRef	implementation.
- Allow '$' anywhere in an identifer string.
- Adjust unit tests to handle changes mentioned above.
- Clean	up test	of invalid identifiers (remove if-then-else; split invalid
  identifiers from unrecognized	strings).
---
 lldb/include/lldb/ValueObject/DILLexer.h     | 10 +--
 lldb/source/ValueObject/DILLexer.cpp         | 49 +++----------
 lldb/unittests/ValueObject/DILLexerTests.cpp | 74 ++++++++++----------
 3 files changed, 50 insertions(+), 83 deletions(-)

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index 3935bf7e8e5c5e..3be2533f886a90 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -30,7 +30,6 @@ class Token {
     identifier,
     l_paren,
     r_paren,
-    unknown,
   };
 
   Token(Kind kind, std::string spelling, uint32_t start)
@@ -72,10 +71,7 @@ class DILLexer {
 
   /// Advance the current token position by N.
   void Advance(uint32_t N = 1) {
-    // UINT_MAX means uninitialized, no "current" position, so move to start.
-    if (m_tokens_idx == UINT_MAX)
-      m_tokens_idx = 0;
-    else if (m_tokens_idx + N >= m_lexed_tokens.size())
+    if (m_tokens_idx + N >= m_lexed_tokens.size())
       // N is too large; advance to the end of the lexed tokens.
       m_tokens_idx = m_lexed_tokens.size() - 1;
     else
@@ -99,7 +95,7 @@ class DILLexer {
   /// to a particular position. Used for either committing 'look ahead' parsing
   /// or rolling back tentative parsing.
   void ResetTokenIdx(uint32_t new_value) {
-    assert(new_value == UINT_MAX || new_value < m_lexed_tokens.size());
+    assert(new_value < m_lexed_tokens.size());
     m_tokens_idx = new_value;
   }
 
@@ -108,7 +104,7 @@ class DILLexer {
 private:
   DILLexer(llvm::StringRef dil_expr, std::vector<Token> lexed_tokens)
       : m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)),
-        m_tokens_idx(UINT_MAX), m_eof_token(Token(Token::eof, "", 0)) {}
+        m_tokens_idx(0), m_eof_token(Token(Token::eof, "", 0)) {}
 
   static llvm::Expected<Token> Lex(llvm::StringRef expr,
                                    llvm::StringRef &remainder);
diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp
index 46ecea9b585f56..c7acfec347af48 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -29,8 +29,6 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
     return "l_paren";
   case Kind::r_paren:
     return "r_paren";
-  case Kind::unknown:
-    return "unknown";
   }
 }
 
@@ -44,43 +42,14 @@ static bool IsDigit(char c) { return '0' <= c && c <= '9'; }
 // letters ('a'..'z','A'..'Z'), digits ('0'..'9'), and/or  underscores.
 static std::optional<llvm::StringRef> IsWord(llvm::StringRef expr,
                                              llvm::StringRef &remainder) {
-  llvm::StringRef::iterator cur_pos = expr.end() - remainder.size();
-  llvm::StringRef::iterator start = cur_pos;
-  bool dollar_start = false;
-
-  // Must not start with a digit.
-  if (cur_pos == expr.end() || IsDigit(*cur_pos))
-    return std::nullopt;
-
-  // First character *may* be a '$', for a register name or convenience
-  // variable.
-  if (*cur_pos == '$') {
-    dollar_start = true;
-    ++cur_pos;
-  }
-
-  // Contains only letters, digits or underscores
-  for (; cur_pos != expr.end(); ++cur_pos) {
-    char c = *cur_pos;
-    if (!IsLetter(c) && !IsDigit(c) && c != '_')
-      break;
-  }
-
-  // If first char is '$', make sure there's at least one mare char, or it's
-  // invalid.
-  if (dollar_start && (cur_pos - start <= 1)) {
-    cur_pos = start;
-    return std::nullopt;
-  }
-
-  if (cur_pos == start)
+  // Find the longest prefix consisting of letters, digits, underscors and
+  // '$'. If it doesn't start with a digit, then it's a word.
+  llvm::StringRef candidate = remainder.take_while(
+      [](char c) { return IsDigit(c) || IsLetter(c) || c == '_' || c == '$'; });
+  if (candidate.empty() || IsDigit(candidate[0]))
     return std::nullopt;
-
-  llvm::StringRef word = expr.substr(start - expr.begin(), cur_pos - start);
-  if (remainder.consume_front(word))
-    return word;
-
-  return std::nullopt;
+  remainder = remainder.drop_front(candidate.size());
+  return candidate;
 }
 
 llvm::Expected<DILLexer> DILLexer::Create(llvm::StringRef expr) {
@@ -100,10 +69,10 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
                                     llvm::StringRef &remainder) {
   // Skip over whitespace (spaces).
   remainder = remainder.ltrim();
-  llvm::StringRef::iterator cur_pos = expr.end() - remainder.size();
+  llvm::StringRef::iterator cur_pos = remainder.begin();
 
   // Check to see if we've reached the end of our input string.
-  if (remainder.empty() || cur_pos == expr.end())
+  if (remainder.empty())
     return Token(Token::eof, "", (uint32_t)expr.size());
 
   uint32_t position = cur_pos - expr.begin();
diff --git a/lldb/unittests/ValueObject/DILLexerTests.cpp b/lldb/unittests/ValueObject/DILLexerTests.cpp
index b6858246b8850c..e96e82e53d415e 100644
--- a/lldb/unittests/ValueObject/DILLexerTests.cpp
+++ b/lldb/unittests/ValueObject/DILLexerTests.cpp
@@ -27,13 +27,15 @@ ExtractTokenData(llvm::StringRef input_expr) {
   if (lexer.NumLexedTokens() == 0)
     return llvm::createStringError("No lexed tokens");
 
-  lexer.ResetTokenIdx(UINT_MAX);
+  lexer.ResetTokenIdx(0);
   std::vector<std::pair<Token::Kind, std::string>> data;
   do {
-    lexer.Advance();
     Token tok = lexer.GetCurrentToken();
     data.push_back(std::make_pair(tok.GetKind(), tok.GetSpelling()));
+    lexer.Advance();
   } while (data.back().first != Token::eof);
+  // Don't return the eof token.
+  data.pop_back();
   return data;
 }
 
@@ -42,11 +44,8 @@ TEST(DILLexerTests, SimpleTest) {
   llvm::Expected<DILLexer> maybe_lexer = DILLexer::Create(input_expr);
   ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
   DILLexer lexer(*maybe_lexer);
-  Token token = Token(Token::unknown, "", 0);
-  EXPECT_EQ(token.GetKind(), Token::unknown);
+  Token token = lexer.GetCurrentToken();
 
-  lexer.Advance();
-  token = lexer.GetCurrentToken();
   EXPECT_EQ(token.GetKind(), Token::identifier);
   EXPECT_EQ(token.GetSpelling(), "simple_var");
   lexer.Advance();
@@ -69,9 +68,7 @@ TEST(DILLexerTests, LookAheadTest) {
   llvm::Expected<DILLexer> maybe_lexer = DILLexer::Create(input_expr);
   ASSERT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
   DILLexer lexer(*maybe_lexer);
-  Token token = Token(Token::unknown, "", 0);
-  lexer.Advance();
-  token = lexer.GetCurrentToken();
+  Token token = lexer.GetCurrentToken();
 
   // Current token is '('; check the next 4 tokens, to make
   // sure they are the identifier 'anonymous', the identifier 'namespace'
@@ -110,49 +107,54 @@ TEST(DILLexerTests, LookAheadTest) {
 TEST(DILLexerTests, MultiTokenLexTest) {
   EXPECT_THAT_EXPECTED(
       ExtractTokenData("This string has (several ) ::identifiers"),
-      llvm::HasValue(
-          testing::ElementsAre(testing::Pair(Token::identifier, "This"),
-                               testing::Pair(Token::identifier, "string"),
-                               testing::Pair(Token::identifier, "has"),
-                               testing::Pair(Token::l_paren, "("),
-                               testing::Pair(Token::identifier, "several"),
-                               testing::Pair(Token::r_paren, ")"),
-                               testing::Pair(Token::coloncolon, "::"),
-                               testing::Pair(Token::identifier, "identifiers"),
-                               testing::Pair(Token::eof, ""))));
+      llvm::HasValue(testing::ElementsAre(
+          testing::Pair(Token::identifier, "This"),
+          testing::Pair(Token::identifier, "string"),
+          testing::Pair(Token::identifier, "has"),
+          testing::Pair(Token::l_paren, "("),
+          testing::Pair(Token::identifier, "several"),
+          testing::Pair(Token::r_paren, ")"),
+          testing::Pair(Token::coloncolon, "::"),
+          testing::Pair(Token::identifier, "identifiers"))));
 }
 
 TEST(DILLexerTests, IdentifiersTest) {
+  // These strings should lex into identifier tokens.
   std::vector<std::string> valid_identifiers = {
-      "$My_name1", "$pc",  "abcd", "_", "_a",     "_a_",
+      "$My_name1", "$pc",  "abcd", "_", "_a",     "_a_",      "$",
       "a_b",       "this", "self", "a", "MyName", "namespace"};
-  std::vector<std::string> invalid_identifiers = {"234", "2a",      "2",
-                                                  "$",   "1MyName", ""};
+
+  // The lexer can lex these strings, but they should not be identifiers.
+  std::vector<std::string> invalid_identifiers = {"", "::", "(", ")"};
+
+  // The lexer is expected to fail attempting to lex these strings (it cannot
+  // create valid tokens out of them).
+  std::vector<std::string> invalid_tok_strings = {"234", "2a", "2", "1MyName"};
 
   // Verify that all of the valid identifiers come out as identifier tokens.
   for (auto &str : valid_identifiers) {
     SCOPED_TRACE(str);
     EXPECT_THAT_EXPECTED(ExtractTokenData(str),
                          llvm::HasValue(testing::ElementsAre(
-                             testing::Pair(Token::identifier, str),
-                             testing::Pair(Token::eof, ""))));
+                             testing::Pair(Token::identifier, str))));
+  }
+
+  // Verify that the lexer fails on invalid token strings.
+  for (auto &str : invalid_tok_strings) {
+    SCOPED_TRACE(str);
+    auto maybe_lexer = DILLexer::Create(str);
+    EXPECT_THAT_EXPECTED(maybe_lexer, llvm::Failed());
   }
 
   // Verify that none of the invalid identifiers come out as identifier tokens.
   for (auto &str : invalid_identifiers) {
     SCOPED_TRACE(str);
     llvm::Expected<DILLexer> maybe_lexer = DILLexer::Create(str);
-    if (!maybe_lexer) {
-      llvm::consumeError(maybe_lexer.takeError());
-      // In this case, it's ok for lexing to return an error.
-    } else {
-      DILLexer lexer(*maybe_lexer);
-      Token token = Token(Token::unknown, "", 0);
-      // We didn't get an error; make sure we did not get an identifier token.
-      lexer.Advance();
-      token = lexer.GetCurrentToken();
-      EXPECT_TRUE(token.IsNot(Token::identifier));
-      EXPECT_TRUE(token.IsOneOf(Token::unknown, Token::eof));
-    }
+    EXPECT_THAT_EXPECTED(maybe_lexer, llvm::Succeeded());
+    DILLexer lexer(*maybe_lexer);
+    Token token = lexer.GetCurrentToken();
+    EXPECT_TRUE(token.IsNot(Token::identifier));
+    EXPECT_TRUE(token.IsOneOf(Token::eof, Token::coloncolon, Token::l_paren,
+                              Token::r_paren));
   }
 }

>From 4103144dcbdb3c1cff9dca5806c855aa093250e1 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Tue, 4 Feb 2025 08:50:07 -0800
Subject: [PATCH 07/10] Remove trailing '_' from LLDB_VALUEOBJECT_DILLEXER_H

---
 lldb/include/lldb/ValueObject/DILLexer.h | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index 3be2533f886a90..fa0b5338834d78 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -6,11 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_VALUEOBJECT_DILLEXER_H_
-#define LLDB_VALUEOBJECT_DILLEXER_H_
+#ifndef LLDB_VALUEOBJECT_DILLEXER_H
+#define LLDB_VALUEOBJECT_DILLEXER_H
 
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/Error.h"
 #include <cstdint>
 #include <limits.h>
@@ -125,4 +124,4 @@ class DILLexer {
 
 } // namespace lldb_private::dil
 
-#endif // LLDB_VALUEOBJECT_DILLEXER_H_
+#endif // LLDB_VALUEOBJECT_DILLEXER_H

>From 29ad86c7f6ffc48f9574813cbc413e33862b9bfa Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Tue, 4 Feb 2025 09:52:34 -0800
Subject: [PATCH 08/10] Clearing the git cache.

---
 lldb/include/lldb/ValueObject/DILLexer.h      |  127 --
 lldb/include/lldb/ValueObject/ValueObject.h   | 1103 -----------------
 .../lldb/ValueObject/ValueObjectCast.h        |   66 -
 .../lldb/ValueObject/ValueObjectChild.h       |   91 --
 .../lldb/ValueObject/ValueObjectConstResult.h |  166 ---
 .../ValueObject/ValueObjectConstResultCast.h  |   75 --
 .../ValueObject/ValueObjectConstResultChild.h |   81 --
 .../ValueObject/ValueObjectConstResultImpl.h  |   80 --
 .../ValueObject/ValueObjectDynamicValue.h     |  129 --
 .../lldb/ValueObject/ValueObjectList.h        |   63 -
 .../lldb/ValueObject/ValueObjectMemory.h      |   82 --
 .../lldb/ValueObject/ValueObjectRegister.h    |  143 ---
 .../ValueObject/ValueObjectSyntheticFilter.h  |  179 ---
 .../lldb/ValueObject/ValueObjectUpdater.h     |   43 -
 .../lldb/ValueObject/ValueObjectVTable.h      |  107 --
 .../lldb/ValueObject/ValueObjectVariable.h    |   93 --
 16 files changed, 2628 deletions(-)
 delete mode 100644 lldb/include/lldb/ValueObject/DILLexer.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObject.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectCast.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectChild.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectConstResult.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectConstResultCast.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectDynamicValue.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectList.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectMemory.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectRegister.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectSyntheticFilter.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectUpdater.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectVTable.h
 delete mode 100644 lldb/include/lldb/ValueObject/ValueObjectVariable.h

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
deleted file mode 100644
index fa0b5338834d78..00000000000000
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ /dev/null
@@ -1,127 +0,0 @@
-//===-- 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 "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
-#include <cstdint>
-#include <limits.h>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace lldb_private::dil {
-
-/// Class defining the tokens generated by the DIL lexer and used by the
-/// DIL parser.
-class Token {
-public:
-  enum Kind {
-    coloncolon,
-    eof,
-    identifier,
-    l_paren,
-    r_paren,
-  };
-
-  Token(Kind kind, std::string spelling, uint32_t start)
-      : m_kind(kind), m_spelling(std::move(spelling)), m_start_pos(start) {}
-
-  Kind GetKind() const { return m_kind; }
-
-  std::string GetSpelling() const { return m_spelling; }
-
-  bool Is(Kind kind) const { return m_kind == kind; }
-
-  bool IsNot(Kind kind) const { return m_kind != kind; }
-
-  bool IsOneOf(Kind kind1, Kind kind2) const { return Is(kind1) || Is(kind2); }
-
-  template <typename... Ts> bool IsOneOf(Kind kind, Ts... Ks) const {
-    return Is(kind) || IsOneOf(Ks...);
-  }
-
-  uint32_t GetLocation() const { return m_start_pos; }
-
-  static llvm::StringRef GetTokenName(Kind kind);
-
-private:
-  Kind m_kind;
-  std::string m_spelling;
-  uint32_t m_start_pos; // within entire expression string
-};
-
-/// Class for doing the simple lexing required by DIL.
-class DILLexer {
-public:
-  /// Lexes all the tokens in expr and calls the private constructor
-  /// with the lexed tokens.
-  static llvm::Expected<DILLexer> Create(llvm::StringRef expr);
-
-  /// Return the current token to be handled by the DIL parser.
-  const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; }
-
-  /// Advance the current token position by N.
-  void Advance(uint32_t N = 1) {
-    if (m_tokens_idx + N >= m_lexed_tokens.size())
-      // N is too large; advance to the end of the lexed tokens.
-      m_tokens_idx = m_lexed_tokens.size() - 1;
-    else
-      m_tokens_idx += N;
-  }
-
-  /// Return the lexed token N positions ahead of the 'current' token
-  /// being handled by the DIL parser.
-  const Token &LookAhead(uint32_t N) {
-    if (m_tokens_idx + N < m_lexed_tokens.size())
-      return m_lexed_tokens[m_tokens_idx + N];
-
-    // Last token should be an 'eof' token.
-    return m_lexed_tokens.back();
-  }
-
-  /// Return the index for the 'current' token being handled by the DIL parser.
-  uint32_t GetCurrentTokenIdx() { return m_tokens_idx; }
-
-  /// 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.
-  void ResetTokenIdx(uint32_t new_value) {
-    assert(new_value < m_lexed_tokens.size());
-    m_tokens_idx = new_value;
-  }
-
-  uint32_t NumLexedTokens() { return m_lexed_tokens.size(); }
-
-private:
-  DILLexer(llvm::StringRef dil_expr, std::vector<Token> lexed_tokens)
-      : m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)),
-        m_tokens_idx(0), m_eof_token(Token(Token::eof, "", 0)) {}
-
-  static llvm::Expected<Token> Lex(llvm::StringRef expr,
-                                   llvm::StringRef &remainder);
-
-  // The input string we are lexing & parsing.
-  llvm::StringRef m_expr;
-
-  // Holds all of the tokens lexed so far.
-  std::vector<Token> 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;
-
-  // "eof" token; to be returned by lexer when 'look ahead' fails.
-  Token m_eof_token;
-};
-
-} // namespace lldb_private::dil
-
-#endif // LLDB_VALUEOBJECT_DILLEXER_H
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h b/lldb/include/lldb/ValueObject/ValueObject.h
deleted file mode 100644
index 4f77384bb8f136..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObject.h
+++ /dev/null
@@ -1,1103 +0,0 @@
-//===-- ValueObject.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_VALUEOBJECT_H
-#define LLDB_VALUEOBJECT_VALUEOBJECT_H
-
-#include "lldb/Core/Value.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/DataExtractor.h"
-#include "lldb/Utility/SharedCluster.h"
-#include "lldb/Utility/Status.h"
-#include "lldb/Utility/UserID.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private-enumerations.h"
-#include "lldb/lldb-types.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-
-#include <functional>
-#include <initializer_list>
-#include <map>
-#include <mutex>
-#include <optional>
-#include <string>
-#include <utility>
-
-#include <cstddef>
-#include <cstdint>
-
-namespace lldb_private {
-class Declaration;
-class DumpValueObjectOptions;
-class EvaluateExpressionOptions;
-class ExecutionContextScope;
-class Log;
-class Scalar;
-class Stream;
-class SymbolContextScope;
-class TypeFormatImpl;
-class TypeSummaryImpl;
-class TypeSummaryOptions;
-
-/// ValueObject:
-///
-/// This abstract class provides an interface to a particular value, be it a
-/// register, a local or global variable,
-/// that is evaluated in some particular scope.  The ValueObject also has the
-/// capability of being the "child" of
-/// some other variable object, and in turn of having children.
-/// If a ValueObject is a root variable object - having no parent - then it must
-/// be constructed with respect to some
-/// particular ExecutionContextScope.  If it is a child, it inherits the
-/// ExecutionContextScope from its parent.
-/// The ValueObject will update itself if necessary before fetching its value,
-/// summary, object description, etc.
-/// But it will always update itself in the ExecutionContextScope with which it
-/// was originally created.
-
-/// A brief note on life cycle management for ValueObjects.  This is a little
-/// tricky because a ValueObject can contain
-/// various other ValueObjects - the Dynamic Value, its children, the
-/// dereference value, etc.  Any one of these can be
-/// handed out as a shared pointer, but for that contained value object to be
-/// valid, the root object and potentially other
-/// of the value objects need to stay around.
-/// We solve this problem by handing out shared pointers to the Value Object and
-/// any of its dependents using a shared
-/// ClusterManager.  This treats each shared pointer handed out for the entire
-/// cluster as a reference to the whole
-/// cluster.  The whole cluster will stay around until the last reference is
-/// released.
-///
-/// The ValueObject mostly handle this automatically, if a value object is made
-/// with a Parent ValueObject, then it adds
-/// itself to the ClusterManager of the parent.
-
-/// It does mean that external to the ValueObjects we should only ever make
-/// available ValueObjectSP's, never ValueObjects
-/// or pointers to them.  So all the "Root level" ValueObject derived
-/// constructors should be private, and
-/// should implement a Create function that new's up object and returns a Shared
-/// Pointer that it gets from the GetSP() method.
-///
-/// However, if you are making an derived ValueObject that will be contained in
-/// a parent value object, you should just
-/// hold onto a pointer to it internally, and by virtue of passing the parent
-/// ValueObject into its constructor, it will
-/// be added to the ClusterManager for the parent.  Then if you ever hand out a
-/// Shared Pointer to the contained ValueObject,
-/// just do so by calling GetSP() on the contained object.
-
-class ValueObject {
-public:
-  enum GetExpressionPathFormat {
-    eGetExpressionPathFormatDereferencePointers = 1,
-    eGetExpressionPathFormatHonorPointers
-  };
-
-  enum ValueObjectRepresentationStyle {
-    eValueObjectRepresentationStyleValue = 1,
-    eValueObjectRepresentationStyleSummary,
-    eValueObjectRepresentationStyleLanguageSpecific,
-    eValueObjectRepresentationStyleLocation,
-    eValueObjectRepresentationStyleChildrenCount,
-    eValueObjectRepresentationStyleType,
-    eValueObjectRepresentationStyleName,
-    eValueObjectRepresentationStyleExpressionPath
-  };
-
-  enum ExpressionPathScanEndReason {
-    /// Out of data to parse.
-    eExpressionPathScanEndReasonEndOfString = 1,
-    /// Child element not found.
-    eExpressionPathScanEndReasonNoSuchChild,
-    /// (Synthetic) child  element not found.
-    eExpressionPathScanEndReasonNoSuchSyntheticChild,
-    /// [] only allowed for arrays.
-    eExpressionPathScanEndReasonEmptyRangeNotAllowed,
-    /// . used when -> should be used.
-    eExpressionPathScanEndReasonDotInsteadOfArrow,
-    /// -> used when . should be used.
-    eExpressionPathScanEndReasonArrowInsteadOfDot,
-    /// ObjC ivar expansion not allowed.
-    eExpressionPathScanEndReasonFragileIVarNotAllowed,
-    /// [] not allowed by options.
-    eExpressionPathScanEndReasonRangeOperatorNotAllowed,
-    /// [] not valid on objects  other than scalars, pointers or arrays.
-    eExpressionPathScanEndReasonRangeOperatorInvalid,
-    /// [] is good for arrays,  but I cannot parse it.
-    eExpressionPathScanEndReasonArrayRangeOperatorMet,
-    /// [] is good for bitfields, but I cannot parse after it.
-    eExpressionPathScanEndReasonBitfieldRangeOperatorMet,
-    /// Something is malformed in he expression.
-    eExpressionPathScanEndReasonUnexpectedSymbol,
-    /// Impossible to apply &  operator.
-    eExpressionPathScanEndReasonTakingAddressFailed,
-    /// Impossible to apply *  operator.
-    eExpressionPathScanEndReasonDereferencingFailed,
-    /// [] was expanded into a  VOList.
-    eExpressionPathScanEndReasonRangeOperatorExpanded,
-    /// getting the synthetic children failed.
-    eExpressionPathScanEndReasonSyntheticValueMissing,
-    eExpressionPathScanEndReasonUnknown = 0xFFFF
-  };
-
-  enum ExpressionPathEndResultType {
-    /// Anything but...
-    eExpressionPathEndResultTypePlain = 1,
-    /// A bitfield.
-    eExpressionPathEndResultTypeBitfield,
-    /// A range [low-high].
-    eExpressionPathEndResultTypeBoundedRange,
-    /// A range [].
-    eExpressionPathEndResultTypeUnboundedRange,
-    /// Several items in a VOList.
-    eExpressionPathEndResultTypeValueObjectList,
-    eExpressionPathEndResultTypeInvalid = 0xFFFF
-  };
-
-  enum ExpressionPathAftermath {
-    /// Just return it.
-    eExpressionPathAftermathNothing = 1,
-    /// Dereference the target.
-    eExpressionPathAftermathDereference,
-    /// Take target's address.
-    eExpressionPathAftermathTakeAddress
-  };
-
-  enum ClearUserVisibleDataItems {
-    eClearUserVisibleDataItemsNothing = 1u << 0,
-    eClearUserVisibleDataItemsValue = 1u << 1,
-    eClearUserVisibleDataItemsSummary = 1u << 2,
-    eClearUserVisibleDataItemsLocation = 1u << 3,
-    eClearUserVisibleDataItemsDescription = 1u << 4,
-    eClearUserVisibleDataItemsSyntheticChildren = 1u << 5,
-    eClearUserVisibleDataItemsAllStrings =
-        eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary |
-        eClearUserVisibleDataItemsLocation |
-        eClearUserVisibleDataItemsDescription,
-    eClearUserVisibleDataItemsAll = 0xFFFF
-  };
-
-  struct GetValueForExpressionPathOptions {
-    enum class SyntheticChildrenTraversal {
-      None,
-      ToSynthetic,
-      FromSynthetic,
-      Both
-    };
-
-    bool m_check_dot_vs_arrow_syntax;
-    bool m_no_fragile_ivar;
-    bool m_allow_bitfields_syntax;
-    SyntheticChildrenTraversal m_synthetic_children_traversal;
-
-    GetValueForExpressionPathOptions(
-        bool dot = false, bool no_ivar = false, bool bitfield = true,
-        SyntheticChildrenTraversal synth_traverse =
-            SyntheticChildrenTraversal::ToSynthetic)
-        : m_check_dot_vs_arrow_syntax(dot), m_no_fragile_ivar(no_ivar),
-          m_allow_bitfields_syntax(bitfield),
-          m_synthetic_children_traversal(synth_traverse) {}
-
-    GetValueForExpressionPathOptions &DoCheckDotVsArrowSyntax() {
-      m_check_dot_vs_arrow_syntax = true;
-      return *this;
-    }
-
-    GetValueForExpressionPathOptions &DontCheckDotVsArrowSyntax() {
-      m_check_dot_vs_arrow_syntax = false;
-      return *this;
-    }
-
-    GetValueForExpressionPathOptions &DoAllowFragileIVar() {
-      m_no_fragile_ivar = false;
-      return *this;
-    }
-
-    GetValueForExpressionPathOptions &DontAllowFragileIVar() {
-      m_no_fragile_ivar = true;
-      return *this;
-    }
-
-    GetValueForExpressionPathOptions &DoAllowBitfieldSyntax() {
-      m_allow_bitfields_syntax = true;
-      return *this;
-    }
-
-    GetValueForExpressionPathOptions &DontAllowBitfieldSyntax() {
-      m_allow_bitfields_syntax = false;
-      return *this;
-    }
-
-    GetValueForExpressionPathOptions &
-    SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse) {
-      m_synthetic_children_traversal = traverse;
-      return *this;
-    }
-
-    static const GetValueForExpressionPathOptions DefaultOptions() {
-      static GetValueForExpressionPathOptions g_default_options;
-
-      return g_default_options;
-    }
-  };
-
-  class EvaluationPoint {
-  public:
-    EvaluationPoint();
-
-    EvaluationPoint(ExecutionContextScope *exe_scope,
-                    bool use_selected = false);
-
-    EvaluationPoint(const EvaluationPoint &rhs);
-
-    ~EvaluationPoint();
-
-    const ExecutionContextRef &GetExecutionContextRef() const {
-      return m_exe_ctx_ref;
-    }
-
-    void SetIsConstant() {
-      SetUpdated();
-      m_mod_id.SetInvalid();
-    }
-
-    bool IsConstant() const { return !m_mod_id.IsValid(); }
-
-    ProcessModID GetModID() const { return m_mod_id; }
-
-    void SetUpdateID(ProcessModID new_id) { m_mod_id = new_id; }
-
-    void SetNeedsUpdate() { m_needs_update = true; }
-
-    void SetUpdated();
-
-    bool NeedsUpdating(bool accept_invalid_exe_ctx) {
-      SyncWithProcessState(accept_invalid_exe_ctx);
-      return m_needs_update;
-    }
-
-    bool IsValid() {
-      const bool accept_invalid_exe_ctx = false;
-      if (!m_mod_id.IsValid())
-        return false;
-      else if (SyncWithProcessState(accept_invalid_exe_ctx)) {
-        if (!m_mod_id.IsValid())
-          return false;
-      }
-      return true;
-    }
-
-    void SetInvalid() {
-      // Use the stop id to mark us as invalid, leave the thread id and the
-      // stack id around for logging and history purposes.
-      m_mod_id.SetInvalid();
-
-      // Can't update an invalid state.
-      m_needs_update = false;
-    }
-
-  private:
-    bool SyncWithProcessState(bool accept_invalid_exe_ctx);
-
-    ProcessModID m_mod_id; // This is the stop id when this ValueObject was last
-                           // evaluated.
-    ExecutionContextRef m_exe_ctx_ref;
-    bool m_needs_update = true;
-  };
-
-  virtual ~ValueObject();
-
-  const EvaluationPoint &GetUpdatePoint() const { return m_update_point; }
-
-  EvaluationPoint &GetUpdatePoint() { return m_update_point; }
-
-  const ExecutionContextRef &GetExecutionContextRef() const {
-    return m_update_point.GetExecutionContextRef();
-  }
-
-  lldb::TargetSP GetTargetSP() const {
-    return m_update_point.GetExecutionContextRef().GetTargetSP();
-  }
-
-  lldb::ProcessSP GetProcessSP() const {
-    return m_update_point.GetExecutionContextRef().GetProcessSP();
-  }
-
-  lldb::ThreadSP GetThreadSP() const {
-    return m_update_point.GetExecutionContextRef().GetThreadSP();
-  }
-
-  lldb::StackFrameSP GetFrameSP() const {
-    return m_update_point.GetExecutionContextRef().GetFrameSP();
-  }
-
-  void SetNeedsUpdate();
-
-  CompilerType GetCompilerType() { return MaybeCalculateCompleteType(); }
-
-  // this vends a TypeImpl that is useful at the SB API layer
-  virtual TypeImpl GetTypeImpl() { return TypeImpl(GetCompilerType()); }
-
-  virtual bool CanProvideValue();
-
-  // Subclasses must implement the functions below.
-  virtual std::optional<uint64_t> GetByteSize() = 0;
-
-  virtual lldb::ValueType GetValueType() const = 0;
-
-  // Subclasses can implement the functions below.
-  virtual ConstString GetTypeName() { return GetCompilerType().GetTypeName(); }
-
-  virtual ConstString GetDisplayTypeName() { return GetTypeName(); }
-
-  virtual ConstString GetQualifiedTypeName() {
-    return GetCompilerType().GetTypeName();
-  }
-
-  lldb::LanguageType GetObjectRuntimeLanguage() {
-    return GetCompilerType().GetMinimumLanguage();
-  }
-
-  uint32_t
-  GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr) {
-    return GetCompilerType().GetTypeInfo(pointee_or_element_compiler_type);
-  }
-
-  bool IsPointerType() { return GetCompilerType().IsPointerType(); }
-
-  bool IsArrayType() { return GetCompilerType().IsArrayType(); }
-
-  bool IsScalarType() { return GetCompilerType().IsScalarType(); }
-
-  bool IsPointerOrReferenceType() {
-    return GetCompilerType().IsPointerOrReferenceType();
-  }
-
-  bool IsPossibleDynamicType();
-
-  bool IsNilReference();
-
-  bool IsUninitializedReference();
-
-  virtual bool IsBaseClass() { return false; }
-
-  bool IsBaseClass(uint32_t &depth);
-
-  virtual bool IsDereferenceOfParent() { return false; }
-
-  bool IsIntegerType(bool &is_signed) {
-    return GetCompilerType().IsIntegerType(is_signed);
-  }
-
-  virtual void GetExpressionPath(
-      Stream &s,
-      GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers);
-
-  lldb::ValueObjectSP GetValueForExpressionPath(
-      llvm::StringRef expression,
-      ExpressionPathScanEndReason *reason_to_stop = nullptr,
-      ExpressionPathEndResultType *final_value_type = nullptr,
-      const GetValueForExpressionPathOptions &options =
-          GetValueForExpressionPathOptions::DefaultOptions(),
-      ExpressionPathAftermath *final_task_on_target = nullptr);
-
-  virtual bool IsInScope() { return true; }
-
-  virtual lldb::offset_t GetByteOffset() { return 0; }
-
-  virtual uint32_t GetBitfieldBitSize() { return 0; }
-
-  virtual uint32_t GetBitfieldBitOffset() { return 0; }
-
-  bool IsBitfield() {
-    return (GetBitfieldBitSize() != 0) || (GetBitfieldBitOffset() != 0);
-  }
-
-  virtual const char *GetValueAsCString();
-
-  virtual bool GetValueAsCString(const lldb_private::TypeFormatImpl &format,
-                                 std::string &destination);
-
-  bool GetValueAsCString(lldb::Format format, std::string &destination);
-
-  virtual uint64_t GetValueAsUnsigned(uint64_t fail_value,
-                                      bool *success = nullptr);
-
-  virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = nullptr);
-
-  /// If the current ValueObject is of an appropriate type, convert the
-  /// value to an APSInt and return that. Otherwise return an error.
-  llvm::Expected<llvm::APSInt> GetValueAsAPSInt();
-
-  /// If the current ValueObject is of an appropriate type, convert the
-  /// value to an APFloat and return that. Otherwise return an error.
-  llvm::Expected<llvm::APFloat> GetValueAsAPFloat();
-
-  /// If the current ValueObject is of an appropriate type, convert the
-  /// value to a boolean and return that. Otherwise return an error.
-  llvm::Expected<bool> GetValueAsBool();
-
-  /// Update an existing integer ValueObject with a new integer value. This
-  /// is only intended to be used with 'temporary' ValueObjects, i.e. ones that
-  /// are not associated with program variables. It does not update program
-  /// memory, registers, stack, etc.
-  void SetValueFromInteger(const llvm::APInt &value, Status &error);
-
-  /// Update an existing integer ValueObject with an integer value created
-  /// frome 'new_val_sp'.  This is only intended to be used with 'temporary'
-  /// ValueObjects, i.e. ones that are not associated with program variables.
-  /// It does not update program  memory, registers, stack, etc.
-  void SetValueFromInteger(lldb::ValueObjectSP new_val_sp, Status &error);
-
-  virtual bool SetValueFromCString(const char *value_str, Status &error);
-
-  /// Return the module associated with this value object in case the value is
-  /// from an executable file and might have its data in sections of the file.
-  /// This can be used for variables.
-  virtual lldb::ModuleSP GetModule();
-
-  ValueObject *GetRoot();
-
-  /// Given a ValueObject, loop over itself and its parent, and its parent's
-  /// parent, .. until either the given callback returns false, or you end up at
-  /// a null pointer
-  ValueObject *FollowParentChain(std::function<bool(ValueObject *)>);
-
-  virtual bool GetDeclaration(Declaration &decl);
-
-  // The functions below should NOT be modified by subclasses
-  const Status &GetError();
-
-  ConstString GetName() const { return m_name; }
-
-  /// Returns a unique id for this ValueObject.
-  lldb::user_id_t GetID() const { return m_id.GetID(); }
-
-  virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx,
-                                              bool can_create = true);
-
-  // The method always creates missing children in the path, if necessary.
-  lldb::ValueObjectSP GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names);
-
-  virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
-                                                     bool can_create = true);
-
-  virtual size_t GetIndexOfChildWithName(llvm::StringRef name);
-
-  llvm::Expected<uint32_t> GetNumChildren(uint32_t max = UINT32_MAX);
-  /// Like \c GetNumChildren but returns 0 on error.  You probably
-  /// shouldn't be using this function. It exists primarily to ease the
-  /// transition to more pervasive error handling while not all APIs
-  /// have been updated.
-  uint32_t GetNumChildrenIgnoringErrors(uint32_t max = UINT32_MAX);
-  bool HasChildren() { return GetNumChildrenIgnoringErrors() > 0; }
-
-  const Value &GetValue() const { return m_value; }
-
-  Value &GetValue() { return m_value; }
-
-  virtual bool ResolveValue(Scalar &scalar);
-
-  // return 'false' whenever you set the error, otherwise callers may assume
-  // true means everything is OK - this will break breakpoint conditions among
-  // potentially a few others
-  virtual bool IsLogicalTrue(Status &error);
-
-  virtual const char *GetLocationAsCString() {
-    return GetLocationAsCStringImpl(m_value, m_data);
-  }
-
-  const char *
-  GetSummaryAsCString(lldb::LanguageType lang = lldb::eLanguageTypeUnknown);
-
-  bool
-  GetSummaryAsCString(TypeSummaryImpl *summary_ptr, std::string &destination,
-                      lldb::LanguageType lang = lldb::eLanguageTypeUnknown);
-
-  bool GetSummaryAsCString(std::string &destination,
-                           const TypeSummaryOptions &options);
-
-  bool GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
-                           std::string &destination,
-                           const TypeSummaryOptions &options);
-
-  llvm::Expected<std::string> GetObjectDescription();
-
-  bool HasSpecialPrintableRepresentation(
-      ValueObjectRepresentationStyle val_obj_display,
-      lldb::Format custom_format);
-
-  enum class PrintableRepresentationSpecialCases : bool {
-    eDisable = false,
-    eAllow = true
-  };
-
-  bool
-  DumpPrintableRepresentation(Stream &s,
-                              ValueObjectRepresentationStyle val_obj_display =
-                                  eValueObjectRepresentationStyleSummary,
-                              lldb::Format custom_format = lldb::eFormatInvalid,
-                              PrintableRepresentationSpecialCases special =
-                                  PrintableRepresentationSpecialCases::eAllow,
-                              bool do_dump_error = true);
-  bool GetValueIsValid() const { return m_flags.m_value_is_valid; }
-
-  // If you call this on a newly created ValueObject, it will always return
-  // false.
-  bool GetValueDidChange() { return m_flags.m_value_did_change; }
-
-  bool UpdateValueIfNeeded(bool update_format = true);
-
-  bool UpdateFormatsIfNeeded();
-
-  lldb::ValueObjectSP GetSP() { return m_manager->GetSharedPointer(this); }
-
-  /// Change the name of the current ValueObject. Should *not* be used from a
-  /// synthetic child provider as it would change the name of the non synthetic
-  /// child as well.
-  void SetName(ConstString name) { m_name = name; }
-
-  virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
-                                    AddressType *address_type = nullptr);
-
-  lldb::addr_t GetPointerValue(AddressType *address_type = nullptr);
-
-  lldb::ValueObjectSP GetSyntheticChild(ConstString key) const;
-
-  lldb::ValueObjectSP GetSyntheticArrayMember(size_t index, bool can_create);
-
-  lldb::ValueObjectSP GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
-                                                bool can_create);
-
-  lldb::ValueObjectSP GetSyntheticExpressionPathChild(const char *expression,
-                                                      bool can_create);
-
-  virtual lldb::ValueObjectSP
-  GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type,
-                            bool can_create,
-                            ConstString name_const_str = ConstString());
-
-  virtual lldb::ValueObjectSP
-  GetSyntheticBase(uint32_t offset, const CompilerType &type, bool can_create,
-                   ConstString name_const_str = ConstString());
-
-  virtual lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType);
-
-  lldb::DynamicValueType GetDynamicValueType();
-
-  virtual lldb::ValueObjectSP GetStaticValue() { return GetSP(); }
-
-  virtual lldb::ValueObjectSP GetNonSyntheticValue() { return GetSP(); }
-
-  lldb::ValueObjectSP GetSyntheticValue();
-
-  virtual bool HasSyntheticValue();
-
-  virtual bool IsSynthetic() { return false; }
-
-  lldb::ValueObjectSP
-  GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue,
-                                        bool synthValue);
-
-  virtual lldb::ValueObjectSP CreateConstantValue(ConstString name);
-
-  virtual lldb::ValueObjectSP Dereference(Status &error);
-
-  /// Creates a copy of the ValueObject with a new name and setting the current
-  /// ValueObject as its parent. It should be used when we want to change the
-  /// name of a ValueObject without modifying the actual ValueObject itself
-  /// (e.g. sythetic child provider).
-  virtual lldb::ValueObjectSP Clone(ConstString new_name);
-
-  virtual lldb::ValueObjectSP AddressOf(Status &error);
-
-  virtual lldb::addr_t GetLiveAddress() { return LLDB_INVALID_ADDRESS; }
-
-  virtual void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
-                              AddressType address_type = eAddressTypeLoad) {}
-
-  lldb::ValueObjectSP Cast(const CompilerType &compiler_type);
-
-  virtual lldb::ValueObjectSP DoCast(const CompilerType &compiler_type);
-
-  virtual lldb::ValueObjectSP CastPointerType(const char *name,
-                                              CompilerType &ast_type);
-
-  virtual lldb::ValueObjectSP CastPointerType(const char *name,
-                                              lldb::TypeSP &type_sp);
-
-  /// Return the target load address associated with this value object.
-  lldb::addr_t GetLoadAddress();
-
-  /// Take a ValueObject whose type is an inherited class, and cast it to
-  /// 'type', which should be one of its base classes. 'base_type_indices'
-  /// contains the indices of direct base classes on the path from the
-  /// ValueObject's current type to 'type'
-  llvm::Expected<lldb::ValueObjectSP>
-  CastDerivedToBaseType(CompilerType type,
-                        const llvm::ArrayRef<uint32_t> &base_type_indices);
-
-  /// Take a ValueObject whose type is a base class, and cast it to 'type',
-  /// which should be one of its derived classes. 'base_type_indices'
-  /// contains the indices of direct base classes on the path from the
-  /// ValueObject's current type to 'type'
-  llvm::Expected<lldb::ValueObjectSP> CastBaseToDerivedType(CompilerType type,
-                                                            uint64_t offset);
-
-  // Take a ValueObject that contains a scalar, enum or pointer type, and
-  // cast it to a "basic" type (integer, float or boolean).
-  lldb::ValueObjectSP CastToBasicType(CompilerType type);
-
-  // Take a ValueObject that contain an integer, float or enum, and cast it
-  // to an enum.
-  lldb::ValueObjectSP CastToEnumType(CompilerType type);
-
-  /// If this object represents a C++ class with a vtable, return an object
-  /// that represents the virtual function table. If the object isn't a class
-  /// with a vtable, return a valid ValueObject with the error set correctly.
-  lldb::ValueObjectSP GetVTable();
-  // The backing bits of this value object were updated, clear any descriptive
-  // string, so we know we have to refetch them.
-  void ValueUpdated() {
-    ClearUserVisibleData(eClearUserVisibleDataItemsValue |
-                         eClearUserVisibleDataItemsSummary |
-                         eClearUserVisibleDataItemsDescription);
-  }
-
-  virtual bool IsDynamic() { return false; }
-
-  virtual bool DoesProvideSyntheticValue() { return false; }
-
-  virtual bool IsSyntheticChildrenGenerated() {
-    return m_flags.m_is_synthetic_children_generated;
-  }
-
-  virtual void SetSyntheticChildrenGenerated(bool b) {
-    m_flags.m_is_synthetic_children_generated = b;
-  }
-
-  virtual SymbolContextScope *GetSymbolContextScope();
-
-  llvm::Error Dump(Stream &s);
-
-  llvm::Error Dump(Stream &s, const DumpValueObjectOptions &options);
-
-  static lldb::ValueObjectSP
-  CreateValueObjectFromExpression(llvm::StringRef name,
-                                  llvm::StringRef expression,
-                                  const ExecutionContext &exe_ctx);
-
-  static lldb::ValueObjectSP
-  CreateValueObjectFromExpression(llvm::StringRef name,
-                                  llvm::StringRef expression,
-                                  const ExecutionContext &exe_ctx,
-                                  const EvaluateExpressionOptions &options);
-
-  /// Given an address either create a value object containing the value at
-  /// that address, or create a value object containing the address itself
-  /// (pointer value), depending on whether the parameter 'do_deref' is true or
-  /// false.
-  static lldb::ValueObjectSP
-  CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
-                               const ExecutionContext &exe_ctx,
-                               CompilerType type, bool do_deref = true);
-
-  static lldb::ValueObjectSP
-  CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data,
-                            const ExecutionContext &exe_ctx, CompilerType type);
-
-  /// Create a value object containing the given APInt value.
-  static lldb::ValueObjectSP CreateValueObjectFromAPInt(lldb::TargetSP target,
-                                                        const llvm::APInt &v,
-                                                        CompilerType type,
-                                                        llvm::StringRef name);
-
-  /// Create a value object containing the given APFloat value.
-  static lldb::ValueObjectSP
-  CreateValueObjectFromAPFloat(lldb::TargetSP target, const llvm::APFloat &v,
-                               CompilerType type, llvm::StringRef name);
-
-  /// Create a value object containing the given boolean value.
-  static lldb::ValueObjectSP CreateValueObjectFromBool(lldb::TargetSP target,
-                                                       bool value,
-                                                       llvm::StringRef name);
-
-  /// Create a nullptr value object with the specified type (must be a
-  /// nullptr type).
-  static lldb::ValueObjectSP CreateValueObjectFromNullptr(lldb::TargetSP target,
-                                                          CompilerType type,
-                                                          llvm::StringRef name);
-
-  lldb::ValueObjectSP Persist();
-
-  /// Returns true if this is a char* or a char[] if it is a char* and
-  /// check_pointer is true, it also checks that the pointer is valid.
-  bool IsCStringContainer(bool check_pointer = false);
-
-  std::pair<size_t, bool>
-  ReadPointedString(lldb::WritableDataBufferSP &buffer_sp, Status &error,
-                    bool honor_array);
-
-  virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
-                                uint32_t item_count = 1);
-
-  virtual uint64_t GetData(DataExtractor &data, Status &error);
-
-  virtual bool SetData(DataExtractor &data, Status &error);
-
-  virtual bool GetIsConstant() const { return m_update_point.IsConstant(); }
-
-  bool NeedsUpdating() {
-    const bool accept_invalid_exe_ctx =
-        (CanUpdateWithInvalidExecutionContext() == eLazyBoolYes);
-    return m_update_point.NeedsUpdating(accept_invalid_exe_ctx);
-  }
-
-  void SetIsConstant() { m_update_point.SetIsConstant(); }
-
-  lldb::Format GetFormat() const;
-
-  virtual void SetFormat(lldb::Format format) {
-    if (format != m_format)
-      ClearUserVisibleData(eClearUserVisibleDataItemsValue);
-    m_format = format;
-  }
-
-  virtual lldb::LanguageType GetPreferredDisplayLanguage();
-
-  void SetPreferredDisplayLanguage(lldb::LanguageType lt) {
-    m_preferred_display_language = lt;
-  }
-
-  lldb::TypeSummaryImplSP GetSummaryFormat() {
-    UpdateFormatsIfNeeded();
-    return m_type_summary_sp;
-  }
-
-  void SetSummaryFormat(lldb::TypeSummaryImplSP format) {
-    m_type_summary_sp = std::move(format);
-    ClearUserVisibleData(eClearUserVisibleDataItemsSummary);
-  }
-
-  void SetDerefValobj(ValueObject *deref) { m_deref_valobj = deref; }
-
-  ValueObject *GetDerefValobj() { return m_deref_valobj; }
-
-  void SetValueFormat(lldb::TypeFormatImplSP format) {
-    m_type_format_sp = std::move(format);
-    ClearUserVisibleData(eClearUserVisibleDataItemsValue);
-  }
-
-  lldb::TypeFormatImplSP GetValueFormat() {
-    UpdateFormatsIfNeeded();
-    return m_type_format_sp;
-  }
-
-  void SetSyntheticChildren(const lldb::SyntheticChildrenSP &synth_sp) {
-    if (synth_sp.get() == m_synthetic_children_sp.get())
-      return;
-    ClearUserVisibleData(eClearUserVisibleDataItemsSyntheticChildren);
-    m_synthetic_children_sp = synth_sp;
-  }
-
-  lldb::SyntheticChildrenSP GetSyntheticChildren() {
-    UpdateFormatsIfNeeded();
-    return m_synthetic_children_sp;
-  }
-
-  // Use GetParent for display purposes, but if you want to tell the parent to
-  // update itself then use m_parent.  The ValueObjectDynamicValue's parent is
-  // not the correct parent for displaying, they are really siblings, so for
-  // display it needs to route through to its grandparent.
-  virtual ValueObject *GetParent() { return m_parent; }
-
-  virtual const ValueObject *GetParent() const { return m_parent; }
-
-  ValueObject *GetNonBaseClassParent();
-
-  void SetAddressTypeOfChildren(AddressType at) {
-    m_address_type_of_ptr_or_ref_children = at;
-  }
-
-  AddressType GetAddressTypeOfChildren();
-
-  void SetHasCompleteType() {
-    m_flags.m_did_calculate_complete_objc_class_type = true;
-  }
-
-  /// Find out if a ValueObject might have children.
-  ///
-  /// This call is much more efficient than CalculateNumChildren() as
-  /// it doesn't need to complete the underlying type. This is designed
-  /// to be used in a UI environment in order to detect if the
-  /// disclosure triangle should be displayed or not.
-  ///
-  /// This function returns true for class, union, structure,
-  /// pointers, references, arrays and more. Again, it does so without
-  /// doing any expensive type completion.
-  ///
-  /// \return
-  ///     Returns \b true if the ValueObject might have children, or \b
-  ///     false otherwise.
-  virtual bool MightHaveChildren();
-
-  virtual lldb::VariableSP GetVariable() { return nullptr; }
-
-  virtual bool IsRuntimeSupportValue();
-
-  virtual uint64_t GetLanguageFlags() { return m_language_flags; }
-
-  virtual void SetLanguageFlags(uint64_t flags) { m_language_flags = flags; }
-
-protected:
-  typedef ClusterManager<ValueObject> ValueObjectManager;
-
-  class ChildrenManager {
-  public:
-    ChildrenManager() = default;
-
-    bool HasChildAtIndex(size_t idx) {
-      std::lock_guard<std::recursive_mutex> guard(m_mutex);
-      return (m_children.find(idx) != m_children.end());
-    }
-
-    ValueObject *GetChildAtIndex(uint32_t idx) {
-      std::lock_guard<std::recursive_mutex> guard(m_mutex);
-      const auto iter = m_children.find(idx);
-      return ((iter == m_children.end()) ? nullptr : iter->second);
-    }
-
-    void SetChildAtIndex(size_t idx, ValueObject *valobj) {
-      // we do not need to be mutex-protected to make a pair
-      ChildrenPair pair(idx, valobj);
-      std::lock_guard<std::recursive_mutex> guard(m_mutex);
-      m_children.insert(pair);
-    }
-
-    void SetChildrenCount(size_t count) { Clear(count); }
-
-    size_t GetChildrenCount() { return m_children_count; }
-
-    void Clear(size_t new_count = 0) {
-      std::lock_guard<std::recursive_mutex> guard(m_mutex);
-      m_children_count = new_count;
-      m_children.clear();
-    }
-
-  private:
-    typedef std::map<size_t, ValueObject *> ChildrenMap;
-    typedef ChildrenMap::iterator ChildrenIterator;
-    typedef ChildrenMap::value_type ChildrenPair;
-    std::recursive_mutex m_mutex;
-    ChildrenMap m_children;
-    size_t m_children_count = 0;
-  };
-
-  // Classes that inherit from ValueObject can see and modify these
-
-  /// The parent value object, or nullptr if this has no parent.
-  ValueObject *m_parent = nullptr;
-  /// The root of the hierarchy for this ValueObject (or nullptr if never
-  /// calculated).
-  ValueObject *m_root = nullptr;
-  /// Stores both the stop id and the full context at which this value was last
-  /// updated.  When we are asked to update the value object, we check whether
-  /// the context & stop id are the same before updating.
-  EvaluationPoint m_update_point;
-  /// The name of this object.
-  ConstString m_name;
-  /// A data extractor that can be used to extract the value.
-  DataExtractor m_data;
-  Value m_value;
-  /// An error object that can describe any errors that occur when updating
-  /// values.
-  Status m_error;
-  /// Cached value string that will get cleared if/when the value is updated.
-  std::string m_value_str;
-  /// Cached old value string from the last time the value was gotten
-  std::string m_old_value_str;
-  /// Cached location string that will get cleared if/when the value is updated.
-  std::string m_location_str;
-  /// Cached summary string that will get cleared if/when the value is updated.
-  std::string m_summary_str;
-  /// Cached result of the "object printer". This differs from the summary
-  /// in that the summary is consed up by us, the object_desc_string is builtin.
-  std::string m_object_desc_str;
-  /// If the type of the value object should be overridden, the type to impose.
-  CompilerType m_override_type;
-
-  /// This object is managed by the root object (any ValueObject that gets
-  /// created without a parent.) The manager gets passed through all the
-  /// generations of dependent objects, and will keep the whole cluster of
-  /// objects alive as long as a shared pointer to any of them has been handed
-  /// out. Shared pointers to value objects must always be made with the GetSP
-  /// method.
-  ValueObjectManager *m_manager = nullptr;
-
-  ChildrenManager m_children;
-  std::map<ConstString, ValueObject *> m_synthetic_children;
-
-  ValueObject *m_dynamic_value = nullptr;
-  ValueObject *m_synthetic_value = nullptr;
-  ValueObject *m_deref_valobj = nullptr;
-
-  /// We have to hold onto a shared  pointer to this one because it is created
-  /// as an independent ValueObjectConstResult, which isn't managed by us.
-  lldb::ValueObjectSP m_addr_of_valobj_sp;
-
-  lldb::Format m_format = lldb::eFormatDefault;
-  lldb::Format m_last_format = lldb::eFormatDefault;
-  uint32_t m_last_format_mgr_revision = 0;
-  lldb::TypeSummaryImplSP m_type_summary_sp;
-  lldb::TypeFormatImplSP m_type_format_sp;
-  lldb::SyntheticChildrenSP m_synthetic_children_sp;
-  ProcessModID m_user_id_of_forced_summary;
-  AddressType m_address_type_of_ptr_or_ref_children = eAddressTypeInvalid;
-
-  llvm::SmallVector<uint8_t, 16> m_value_checksum;
-
-  lldb::LanguageType m_preferred_display_language = lldb::eLanguageTypeUnknown;
-
-  uint64_t m_language_flags = 0;
-
-  /// Unique identifier for every value object.
-  UserID m_id;
-
-  // Utility class for initializing all bitfields in ValueObject's constructors.
-  // FIXME: This could be done via default initializers once we have C++20.
-  struct Bitflags {
-    bool m_value_is_valid : 1, m_value_did_change : 1,
-        m_children_count_valid : 1, m_old_value_valid : 1,
-        m_is_deref_of_parent : 1, m_is_array_item_for_pointer : 1,
-        m_is_bitfield_for_scalar : 1, m_is_child_at_offset : 1,
-        m_is_getting_summary : 1, m_did_calculate_complete_objc_class_type : 1,
-        m_is_synthetic_children_generated : 1;
-    Bitflags() {
-      m_value_is_valid = false;
-      m_value_did_change = false;
-      m_children_count_valid = false;
-      m_old_value_valid = false;
-      m_is_deref_of_parent = false;
-      m_is_array_item_for_pointer = false;
-      m_is_bitfield_for_scalar = false;
-      m_is_child_at_offset = false;
-      m_is_getting_summary = false;
-      m_did_calculate_complete_objc_class_type = false;
-      m_is_synthetic_children_generated = false;
-    }
-  } m_flags;
-
-  friend class ValueObjectChild;
-  friend class ExpressionVariable; // For SetName
-  friend class Target;             // For SetName
-  friend class ValueObjectConstResultImpl;
-  friend class ValueObjectSynthetic; // For ClearUserVisibleData
-
-  /// Use this constructor to create a "root variable object".  The ValueObject
-  /// will be locked to this context through-out its lifespan.
-  ValueObject(ExecutionContextScope *exe_scope, ValueObjectManager &manager,
-              AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad);
-
-  /// Use this constructor to create a ValueObject owned by another ValueObject.
-  /// It will inherit the ExecutionContext of its parent.
-  ValueObject(ValueObject &parent);
-
-  ValueObjectManager *GetManager() { return m_manager; }
-
-  virtual bool UpdateValue() = 0;
-
-  virtual LazyBool CanUpdateWithInvalidExecutionContext() {
-    return eLazyBoolCalculate;
-  }
-
-  virtual void CalculateDynamicValue(lldb::DynamicValueType use_dynamic);
-
-  virtual lldb::DynamicValueType GetDynamicValueTypeImpl() {
-    return lldb::eNoDynamicValues;
-  }
-
-  virtual bool HasDynamicValueTypeInfo() { return false; }
-
-  virtual void CalculateSyntheticValue();
-
-  /// Should only be called by ValueObject::GetChildAtIndex().
-  ///
-  /// \return A ValueObject managed by this ValueObject's manager.
-  virtual ValueObject *CreateChildAtIndex(size_t idx);
-
-  /// Should only be called by ValueObject::GetSyntheticArrayMember().
-  ///
-  /// \return A ValueObject managed by this ValueObject's manager.
-  virtual ValueObject *CreateSyntheticArrayMember(size_t idx);
-
-  /// Should only be called by ValueObject::GetNumChildren().
-  virtual llvm::Expected<uint32_t>
-  CalculateNumChildren(uint32_t max = UINT32_MAX) = 0;
-
-  void SetNumChildren(uint32_t num_children);
-
-  void SetValueDidChange(bool value_changed) {
-    m_flags.m_value_did_change = value_changed;
-  }
-
-  void SetValueIsValid(bool valid) { m_flags.m_value_is_valid = valid; }
-
-  void ClearUserVisibleData(
-      uint32_t items = ValueObject::eClearUserVisibleDataItemsAllStrings);
-
-  void AddSyntheticChild(ConstString key, ValueObject *valobj);
-
-  DataExtractor &GetDataExtractor();
-
-  void ClearDynamicTypeInformation();
-
-  // Subclasses must implement the functions below.
-
-  virtual CompilerType GetCompilerTypeImpl() = 0;
-
-  const char *GetLocationAsCStringImpl(const Value &value,
-                                       const DataExtractor &data);
-
-  bool IsChecksumEmpty() { return m_value_checksum.empty(); }
-
-  void SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType);
-
-protected:
-  virtual void DoUpdateChildrenAddressType(ValueObject &valobj) {};
-
-private:
-  virtual CompilerType MaybeCalculateCompleteType();
-  void UpdateChildrenAddressType() {
-    GetRoot()->DoUpdateChildrenAddressType(*this);
-  }
-
-  lldb::ValueObjectSP GetValueForExpressionPath_Impl(
-      llvm::StringRef expression_cstr,
-      ExpressionPathScanEndReason *reason_to_stop,
-      ExpressionPathEndResultType *final_value_type,
-      const GetValueForExpressionPathOptions &options,
-      ExpressionPathAftermath *final_task_on_target);
-
-  ValueObject(const ValueObject &) = delete;
-  const ValueObject &operator=(const ValueObject &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECT_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectCast.h b/lldb/include/lldb/ValueObject/ValueObjectCast.h
deleted file mode 100644
index 9d174ae5ca609d..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectCast.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//===-- ValueObjectCast.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_VALUEOBJECTCAST_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTCAST_H
-
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/ValueObject/ValueObject.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-
-namespace lldb_private {
-class ConstString;
-
-/// A ValueObject that represents a given value represented as a different type.
-class ValueObjectCast : public ValueObject {
-public:
-  ~ValueObjectCast() override;
-
-  static lldb::ValueObjectSP Create(ValueObject &parent, ConstString name,
-                                    const CompilerType &cast_type);
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  lldb::ValueType GetValueType() const override;
-
-  bool IsInScope() override;
-
-  ValueObject *GetParent() override {
-    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
-  }
-
-  const ValueObject *GetParent() const override {
-    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
-  }
-
-protected:
-  ValueObjectCast(ValueObject &parent, ConstString name,
-                  const CompilerType &cast_type);
-
-  bool UpdateValue() override;
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  CompilerType m_cast_type;
-
-private:
-  ValueObjectCast(const ValueObjectCast &) = delete;
-  const ValueObjectCast &operator=(const ValueObjectCast &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTCAST_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectChild.h b/lldb/include/lldb/ValueObject/ValueObjectChild.h
deleted file mode 100644
index e8c974a3a10a76..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectChild.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//===-- ValueObjectChild.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_VALUEOBJECTCHILD_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTCHILD_H
-
-#include "lldb/ValueObject/ValueObject.h"
-
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-private-enumerations.h"
-#include "lldb/lldb-types.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-
-namespace lldb_private {
-
-/// A child of another ValueObject.
-class ValueObjectChild : public ValueObject {
-public:
-  ~ValueObjectChild() override;
-
-  std::optional<uint64_t> GetByteSize() override { return m_byte_size; }
-
-  lldb::offset_t GetByteOffset() override { return m_byte_offset; }
-
-  uint32_t GetBitfieldBitSize() override { return m_bitfield_bit_size; }
-
-  uint32_t GetBitfieldBitOffset() override { return m_bitfield_bit_offset; }
-
-  lldb::ValueType GetValueType() const override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  ConstString GetTypeName() override;
-
-  ConstString GetQualifiedTypeName() override;
-
-  ConstString GetDisplayTypeName() override;
-
-  bool IsInScope() override;
-
-  bool IsBaseClass() override { return m_is_base_class; }
-
-  bool IsDereferenceOfParent() override { return m_is_deref_of_parent; }
-
-protected:
-  bool UpdateValue() override;
-
-  LazyBool CanUpdateWithInvalidExecutionContext() override;
-
-  CompilerType GetCompilerTypeImpl() override { return m_compiler_type; }
-
-  CompilerType m_compiler_type;
-  ConstString m_type_name;
-  uint64_t m_byte_size;
-  int32_t m_byte_offset;
-  uint8_t m_bitfield_bit_size;
-  uint8_t m_bitfield_bit_offset;
-  bool m_is_base_class;
-  bool m_is_deref_of_parent;
-  std::optional<LazyBool> m_can_update_with_invalid_exe_ctx;
-
-  friend class ValueObject;
-  friend class ValueObjectConstResult;
-  friend class ValueObjectConstResultImpl;
-  friend class ValueObjectVTable;
-
-  ValueObjectChild(ValueObject &parent, const CompilerType &compiler_type,
-                   ConstString name, uint64_t byte_size, int32_t byte_offset,
-                   uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
-                   bool is_base_class, bool is_deref_of_parent,
-                   AddressType child_ptr_or_ref_addr_type,
-                   uint64_t language_flags);
-
-  ValueObjectChild(const ValueObjectChild &) = delete;
-  const ValueObjectChild &operator=(const ValueObjectChild &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTCHILD_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResult.h b/lldb/include/lldb/ValueObject/ValueObjectConstResult.h
deleted file mode 100644
index e4ed1f399bf6bd..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectConstResult.h
+++ /dev/null
@@ -1,166 +0,0 @@
-//===-- ValueObjectConstResult.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_VALUEOBJECTCONSTRESULT_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULT_H
-
-#include "lldb/Core/Value.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/Status.h"
-#include "lldb/ValueObject/ValueObject.h"
-#include "lldb/ValueObject/ValueObjectConstResultImpl.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private-enumerations.h"
-#include "lldb/lldb-types.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-
-namespace lldb_private {
-class DataExtractor;
-class ExecutionContextScope;
-class Module;
-
-/// A frozen ValueObject copied into host memory.
-class ValueObjectConstResult : public ValueObject {
-public:
-  ~ValueObjectConstResult() override;
-
-  static lldb::ValueObjectSP
-  Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order,
-         uint32_t addr_byte_size, lldb::addr_t address = LLDB_INVALID_ADDRESS);
-
-  static lldb::ValueObjectSP
-  Create(ExecutionContextScope *exe_scope, const CompilerType &compiler_type,
-         ConstString name, const DataExtractor &data,
-         lldb::addr_t address = LLDB_INVALID_ADDRESS);
-
-  static lldb::ValueObjectSP
-  Create(ExecutionContextScope *exe_scope, const CompilerType &compiler_type,
-         ConstString name, const lldb::DataBufferSP &result_data_sp,
-         lldb::ByteOrder byte_order, uint32_t addr_size,
-         lldb::addr_t address = LLDB_INVALID_ADDRESS);
-
-  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    const CompilerType &compiler_type,
-                                    ConstString name, lldb::addr_t address,
-                                    AddressType address_type,
-                                    uint32_t addr_byte_size);
-
-  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    Value &value, ConstString name,
-                                    Module *module = nullptr);
-
-  // When an expression fails to evaluate, we return an error
-  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    Status &&error);
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  lldb::ValueType GetValueType() const override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  ConstString GetTypeName() override;
-
-  ConstString GetDisplayTypeName() override;
-
-  bool IsInScope() override;
-
-  void SetByteSize(size_t size);
-
-  lldb::ValueObjectSP Dereference(Status &error) override;
-
-  lldb::ValueObjectSP GetSyntheticChildAtOffset(
-      uint32_t offset, const CompilerType &type, bool can_create,
-      ConstString name_const_str = ConstString()) override;
-
-  lldb::ValueObjectSP AddressOf(Status &error) override;
-
-  lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
-                            AddressType *address_type = nullptr) override;
-
-  size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
-                        uint32_t item_count = 1) override;
-
-  lldb::addr_t GetLiveAddress() override { return m_impl.GetLiveAddress(); }
-
-  void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
-                      AddressType address_type = eAddressTypeLoad) override {
-    m_impl.SetLiveAddress(addr, address_type);
-  }
-
-  lldb::ValueObjectSP
-  GetDynamicValue(lldb::DynamicValueType valueType) override;
-
-  lldb::LanguageType GetPreferredDisplayLanguage() override;
-
-  lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
-
-protected:
-  bool UpdateValue() override;
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  ConstString m_type_name;
-  std::optional<uint64_t> m_byte_size;
-
-  ValueObjectConstResultImpl m_impl;
-
-private:
-  friend class ValueObjectConstResultImpl;
-
-  ValueObjectConstResult(ExecutionContextScope *exe_scope,
-                         ValueObjectManager &manager,
-                         lldb::ByteOrder byte_order, uint32_t addr_byte_size,
-                         lldb::addr_t address);
-
-  ValueObjectConstResult(ExecutionContextScope *exe_scope,
-                         ValueObjectManager &manager,
-                         const CompilerType &compiler_type, ConstString name,
-                         const DataExtractor &data, lldb::addr_t address);
-
-  ValueObjectConstResult(ExecutionContextScope *exe_scope,
-                         ValueObjectManager &manager,
-                         const CompilerType &compiler_type, ConstString name,
-                         const lldb::DataBufferSP &result_data_sp,
-                         lldb::ByteOrder byte_order, uint32_t addr_size,
-                         lldb::addr_t address);
-
-  ValueObjectConstResult(ExecutionContextScope *exe_scope,
-                         ValueObjectManager &manager,
-                         const CompilerType &compiler_type, ConstString name,
-                         lldb::addr_t address, AddressType address_type,
-                         uint32_t addr_byte_size);
-
-  ValueObjectConstResult(ExecutionContextScope *exe_scope,
-                         ValueObjectManager &manager, const Value &value,
-                         ConstString name, Module *module = nullptr);
-
-  ValueObjectConstResult(ExecutionContextScope *exe_scope,
-                         ValueObjectManager &manager, Status &&error);
-
-  ValueObject *CreateChildAtIndex(size_t idx) override {
-    return m_impl.CreateChildAtIndex(idx);
-  }
-  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
-    return m_impl.CreateSyntheticArrayMember(idx);
-  }
-
-  ValueObjectConstResult(const ValueObjectConstResult &) = delete;
-  const ValueObjectConstResult &
-  operator=(const ValueObjectConstResult &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULT_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultCast.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultCast.h
deleted file mode 100644
index e786467eae6e26..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectConstResultCast.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//===-- ValueObjectConstResultCast.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_VALUEOBJECTCONSTRESULTCAST_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTCAST_H
-
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/ValueObject/ValueObjectCast.h"
-#include "lldb/ValueObject/ValueObjectConstResultImpl.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-types.h"
-
-#include <cstddef>
-#include <cstdint>
-
-namespace lldb_private {
-class DataExtractor;
-class Status;
-class ValueObject;
-
-class ValueObjectConstResultCast : public ValueObjectCast {
-public:
-  ValueObjectConstResultCast(ValueObject &parent, ConstString name,
-                             const CompilerType &cast_type,
-                             lldb::addr_t live_address = LLDB_INVALID_ADDRESS);
-
-  ~ValueObjectConstResultCast() override;
-
-  lldb::ValueObjectSP Dereference(Status &error) override;
-
-  virtual CompilerType GetCompilerType() {
-    return ValueObjectCast::GetCompilerType();
-  }
-
-  lldb::ValueObjectSP GetSyntheticChildAtOffset(
-      uint32_t offset, const CompilerType &type, bool can_create,
-      ConstString name_const_str = ConstString()) override;
-
-  lldb::ValueObjectSP AddressOf(Status &error) override;
-
-  size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
-                        uint32_t item_count = 1) override;
-
-  lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
-
-protected:
-  ValueObjectConstResultImpl m_impl;
-
-private:
-  friend class ValueObject;
-  friend class ValueObjectConstResult;
-  friend class ValueObjectConstResultImpl;
-
-  ValueObject *CreateChildAtIndex(size_t idx) override {
-    return m_impl.CreateChildAtIndex(idx);
-  }
-  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
-    return m_impl.CreateSyntheticArrayMember(idx);
-  }
-
-  ValueObjectConstResultCast(const ValueObjectConstResultCast &) = delete;
-  const ValueObjectConstResultCast &
-  operator=(const ValueObjectConstResultCast &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTCAST_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
deleted file mode 100644
index ad97b885684ee5..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
+++ /dev/null
@@ -1,81 +0,0 @@
-//===-- ValueObjectConstResultChild.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_VALUEOBJECTCONSTRESULTCHILD_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTCHILD_H
-
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/ValueObject/ValueObjectChild.h"
-#include "lldb/ValueObject/ValueObjectConstResultImpl.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-types.h"
-
-#include <cstddef>
-#include <cstdint>
-
-namespace lldb_private {
-class DataExtractor;
-class Status;
-class ValueObject;
-
-// A child of a ValueObjectConstResult.
-class ValueObjectConstResultChild : public ValueObjectChild {
-public:
-  ValueObjectConstResultChild(
-      ValueObject &parent, const CompilerType &compiler_type, ConstString name,
-      uint32_t byte_size, int32_t byte_offset, uint32_t bitfield_bit_size,
-      uint32_t bitfield_bit_offset, bool is_base_class, bool is_deref_of_parent,
-      lldb::addr_t live_address, uint64_t language_flags);
-
-  ~ValueObjectConstResultChild() override;
-
-  lldb::ValueObjectSP Dereference(Status &error) override;
-
-  virtual CompilerType GetCompilerType() {
-    return ValueObjectChild::GetCompilerType();
-  }
-
-  lldb::ValueObjectSP GetSyntheticChildAtOffset(
-      uint32_t offset, const CompilerType &type, bool can_create,
-      ConstString name_const_str = ConstString()) override;
-
-  lldb::ValueObjectSP AddressOf(Status &error) override;
-
-  lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
-                            AddressType *address_type = nullptr) override;
-
-  size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
-                        uint32_t item_count = 1) override;
-
-  lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
-
-protected:
-  ValueObjectConstResultImpl m_impl;
-
-private:
-  friend class ValueObject;
-  friend class ValueObjectConstResult;
-  friend class ValueObjectConstResultImpl;
-
-  ValueObject *CreateChildAtIndex(size_t idx) override {
-    return m_impl.CreateChildAtIndex(idx);
-  }
-  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
-    return m_impl.CreateSyntheticArrayMember(idx);
-  }
-
-  ValueObjectConstResultChild(const ValueObjectConstResultChild &) = delete;
-  const ValueObjectConstResultChild &
-  operator=(const ValueObjectConstResultChild &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTCHILD_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
deleted file mode 100644
index dbd68160acb4dc..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//===-- ValueObjectConstResultImpl.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_VALUEOBJECTCONSTRESULTIMPL_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTIMPL_H
-
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private-enumerations.h"
-#include "lldb/lldb-types.h"
-
-#include <cstddef>
-#include <cstdint>
-namespace lldb_private {
-class CompilerType;
-class DataExtractor;
-class Status;
-class ValueObject;
-} // namespace lldb_private
-
-namespace lldb_private {
-
-/// A class wrapping common implementation details for operations in
-/// ValueObjectConstResult ( & Child ) that may need to jump from the host
-/// memory space into the target's memory space.
-class ValueObjectConstResultImpl {
-public:
-  ValueObjectConstResultImpl(ValueObject *valobj,
-                             lldb::addr_t live_address = LLDB_INVALID_ADDRESS);
-
-  virtual ~ValueObjectConstResultImpl() = default;
-
-  lldb::ValueObjectSP Dereference(Status &error);
-
-  ValueObject *CreateChildAtIndex(size_t idx);
-  ValueObject *CreateSyntheticArrayMember(size_t idx);
-
-  lldb::ValueObjectSP
-  GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type,
-                            bool can_create,
-                            ConstString name_const_str = ConstString());
-
-  lldb::ValueObjectSP AddressOf(Status &error);
-
-  lldb::addr_t GetLiveAddress() { return m_live_address; }
-
-  lldb::ValueObjectSP Cast(const CompilerType &compiler_type);
-
-  void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
-                      AddressType address_type = eAddressTypeLoad) {
-    m_live_address = addr;
-    m_live_address_type = address_type;
-  }
-
-  virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
-                                    AddressType *address_type = nullptr);
-
-  virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
-                                uint32_t item_count = 1);
-
-private:
-  ValueObject *m_impl_backend;
-  lldb::addr_t m_live_address;
-  AddressType m_live_address_type;
-  lldb::ValueObjectSP m_address_of_backend;
-
-  ValueObjectConstResultImpl(const ValueObjectConstResultImpl &) = delete;
-  const ValueObjectConstResultImpl &
-  operator=(const ValueObjectConstResultImpl &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTIMPL_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectDynamicValue.h b/lldb/include/lldb/ValueObject/ValueObjectDynamicValue.h
deleted file mode 100644
index 145a46e2955667..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectDynamicValue.h
+++ /dev/null
@@ -1,129 +0,0 @@
-//===-- ValueObjectDynamicValue.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_VALUEOBJECTDYNAMICVALUE_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTDYNAMICVALUE_H
-
-#include "lldb/Core/Address.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/ValueObject/ValueObject.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private-enumerations.h"
-
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-
-namespace lldb_private {
-class DataExtractor;
-class Declaration;
-class Status;
-
-/// A ValueObject that represents memory at a given address, viewed as some
-/// set lldb type.
-class ValueObjectDynamicValue : public ValueObject {
-public:
-  ~ValueObjectDynamicValue() override = default;
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  ConstString GetTypeName() override;
-
-  ConstString GetQualifiedTypeName() override;
-
-  ConstString GetDisplayTypeName() override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  lldb::ValueType GetValueType() const override;
-
-  bool IsInScope() override;
-
-  bool IsDynamic() override { return true; }
-
-  bool IsBaseClass() override {
-    if (m_parent)
-      return m_parent->IsBaseClass();
-    return false;
-  }
-
-  bool GetIsConstant() const override { return false; }
-
-  ValueObject *GetParent() override {
-    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
-  }
-
-  const ValueObject *GetParent() const override {
-    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
-  }
-
-  lldb::ValueObjectSP GetStaticValue() override { return m_parent->GetSP(); }
-
-  bool SetValueFromCString(const char *value_str, Status &error) override;
-
-  bool SetData(DataExtractor &data, Status &error) override;
-
-  TypeImpl GetTypeImpl() override;
-
-  lldb::VariableSP GetVariable() override {
-    return m_parent ? m_parent->GetVariable() : nullptr;
-  }
-
-  lldb::LanguageType GetPreferredDisplayLanguage() override;
-
-  void SetPreferredDisplayLanguage(lldb::LanguageType);
-
-  bool IsSyntheticChildrenGenerated() override;
-
-  void SetSyntheticChildrenGenerated(bool b) override;
-
-  bool GetDeclaration(Declaration &decl) override;
-
-  uint64_t GetLanguageFlags() override;
-
-  void SetLanguageFlags(uint64_t flags) override;
-
-protected:
-  bool UpdateValue() override;
-
-  LazyBool CanUpdateWithInvalidExecutionContext() override {
-    return eLazyBoolYes;
-  }
-
-  lldb::DynamicValueType GetDynamicValueTypeImpl() override {
-    return m_use_dynamic;
-  }
-
-  bool HasDynamicValueTypeInfo() override { return true; }
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  Address m_address; ///< The variable that this value object is based upon
-  TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name
-  lldb::DynamicValueType m_use_dynamic;
-  TypeImpl m_type_impl;
-
-private:
-  friend class ValueObject;
-  friend class ValueObjectConstResult;
-  ValueObjectDynamicValue(ValueObject &parent,
-                          lldb::DynamicValueType use_dynamic);
-
-  ValueObjectDynamicValue(const ValueObjectDynamicValue &) = delete;
-  const ValueObjectDynamicValue &
-  operator=(const ValueObjectDynamicValue &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTDYNAMICVALUE_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectList.h b/lldb/include/lldb/ValueObject/ValueObjectList.h
deleted file mode 100644
index 5d63c65a96e5f3..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectList.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===-- ValueObjectList.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_VALUEOBJECTLIST_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTLIST_H
-
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-types.h"
-
-#include <vector>
-
-#include <cstddef>
-
-namespace lldb_private {
-class ValueObject;
-
-/// A collection of ValueObject values that.
-class ValueObjectList {
-public:
-  const ValueObjectList &operator=(const ValueObjectList &rhs);
-
-  void Append(const lldb::ValueObjectSP &val_obj_sp);
-
-  void Append(const ValueObjectList &valobj_list);
-
-  lldb::ValueObjectSP FindValueObjectByPointer(ValueObject *valobj);
-
-  size_t GetSize() const;
-
-  void Resize(size_t size);
-
-  lldb::ValueObjectSP GetValueObjectAtIndex(size_t idx);
-
-  lldb::ValueObjectSP RemoveValueObjectAtIndex(size_t idx);
-
-  void SetValueObjectAtIndex(size_t idx, const lldb::ValueObjectSP &valobj_sp);
-
-  lldb::ValueObjectSP FindValueObjectByValueName(const char *name);
-
-  lldb::ValueObjectSP FindValueObjectByUID(lldb::user_id_t uid);
-
-  void Swap(ValueObjectList &value_object_list);
-
-  void Clear() { m_value_objects.clear(); }
-
-  const std::vector<lldb::ValueObjectSP> &GetObjects() const {
-    return m_value_objects;
-  }
-
-protected:
-  typedef std::vector<lldb::ValueObjectSP> collection;
-  // Classes that inherit from ValueObjectList can see and modify these
-  collection m_value_objects;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTLIST_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectMemory.h b/lldb/include/lldb/ValueObject/ValueObjectMemory.h
deleted file mode 100644
index cfc36d0d610dba..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectMemory.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- ValueObjectMemory.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_VALUEOBJECTMEMORY_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTMEMORY_H
-
-#include "lldb/Core/Address.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/ValueObject/ValueObject.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-#include "llvm/ADT/StringRef.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-
-namespace lldb_private {
-class ExecutionContextScope;
-
-/// A ValueObject that represents memory at a given address, viewed as some
-/// set lldb type.
-class ValueObjectMemory : public ValueObject {
-public:
-  ~ValueObjectMemory() override;
-
-  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    llvm::StringRef name,
-                                    const Address &address,
-                                    lldb::TypeSP &type_sp);
-
-  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    llvm::StringRef name,
-                                    const Address &address,
-                                    const CompilerType &ast_type);
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  ConstString GetTypeName() override;
-
-  ConstString GetDisplayTypeName() override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  lldb::ValueType GetValueType() const override;
-
-  bool IsInScope() override;
-
-  lldb::ModuleSP GetModule() override;
-
-protected:
-  bool UpdateValue() override;
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  Address m_address; ///< The variable that this value object is based upon
-  lldb::TypeSP m_type_sp;
-  CompilerType m_compiler_type;
-
-private:
-  ValueObjectMemory(ExecutionContextScope *exe_scope,
-                    ValueObjectManager &manager, llvm::StringRef name,
-                    const Address &address, lldb::TypeSP &type_sp);
-
-  ValueObjectMemory(ExecutionContextScope *exe_scope,
-                    ValueObjectManager &manager, llvm::StringRef name,
-                    const Address &address, const CompilerType &ast_type);
-  // For ValueObject only
-  ValueObjectMemory(const ValueObjectMemory &) = delete;
-  const ValueObjectMemory &operator=(const ValueObjectMemory &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTMEMORY_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectRegister.h b/lldb/include/lldb/ValueObject/ValueObjectRegister.h
deleted file mode 100644
index fafbfd0341115c..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectRegister.h
+++ /dev/null
@@ -1,143 +0,0 @@
-//===-- ValueObjectRegister.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_VALUEOBJECTREGISTER_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTREGISTER_H
-
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/RegisterValue.h"
-#include "lldb/ValueObject/ValueObject.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private-types.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-
-namespace lldb_private {
-class DataExtractor;
-class Status;
-class ExecutionContextScope;
-class Scalar;
-class Stream;
-
-class ValueObjectRegisterSet : public ValueObject {
-public:
-  ~ValueObjectRegisterSet() override;
-
-  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    lldb::RegisterContextSP &reg_ctx_sp,
-                                    uint32_t set_idx);
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  lldb::ValueType GetValueType() const override {
-    return lldb::eValueTypeRegisterSet;
-  }
-
-  ConstString GetTypeName() override;
-
-  ConstString GetQualifiedTypeName() override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
-                                             bool can_create = true) override;
-
-  size_t GetIndexOfChildWithName(llvm::StringRef name) override;
-
-protected:
-  bool UpdateValue() override;
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  lldb::RegisterContextSP m_reg_ctx_sp;
-  const RegisterSet *m_reg_set;
-  uint32_t m_reg_set_idx;
-
-private:
-  friend class ValueObjectRegisterContext;
-
-  ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
-                         ValueObjectManager &manager,
-                         lldb::RegisterContextSP &reg_ctx_sp, uint32_t set_idx);
-
-  ValueObject *CreateChildAtIndex(size_t idx) override;
-  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
-    return nullptr;
-  }
-
-  // For ValueObject only
-  ValueObjectRegisterSet(const ValueObjectRegisterSet &) = delete;
-  const ValueObjectRegisterSet &
-  operator=(const ValueObjectRegisterSet &) = delete;
-};
-
-class ValueObjectRegister : public ValueObject {
-public:
-  ~ValueObjectRegister() override;
-
-  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    lldb::RegisterContextSP &reg_ctx_sp,
-                                    const RegisterInfo *reg_info);
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  lldb::ValueType GetValueType() const override {
-    return lldb::eValueTypeRegister;
-  }
-
-  ConstString GetTypeName() override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  bool SetValueFromCString(const char *value_str, Status &error) override;
-
-  bool SetData(DataExtractor &data, Status &error) override;
-
-  bool ResolveValue(Scalar &scalar) override;
-
-  void
-  GetExpressionPath(Stream &s,
-                    GetExpressionPathFormat epformat =
-                        eGetExpressionPathFormatDereferencePointers) override;
-
-protected:
-  bool UpdateValue() override;
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  lldb::RegisterContextSP m_reg_ctx_sp;
-  RegisterInfo m_reg_info;
-  RegisterValue m_reg_value;
-  ConstString m_type_name;
-  CompilerType m_compiler_type;
-
-private:
-  void ConstructObject(const RegisterInfo *reg_info);
-
-  friend class ValueObjectRegisterSet;
-
-  ValueObjectRegister(ValueObject &parent, lldb::RegisterContextSP &reg_ctx_sp,
-                      const RegisterInfo *reg_info);
-  ValueObjectRegister(ExecutionContextScope *exe_scope,
-                      ValueObjectManager &manager,
-                      lldb::RegisterContextSP &reg_ctx_sp,
-                      const RegisterInfo *reg_info);
-
-  // For ValueObject only
-  ValueObjectRegister(const ValueObjectRegister &) = delete;
-  const ValueObjectRegister &operator=(const ValueObjectRegister &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTREGISTER_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectSyntheticFilter.h b/lldb/include/lldb/ValueObject/ValueObjectSyntheticFilter.h
deleted file mode 100644
index 2811658fd8f1f4..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectSyntheticFilter.h
+++ /dev/null
@@ -1,179 +0,0 @@
-//===-- ValueObjectSyntheticFilter.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_VALUEOBJECTSYNTHETICFILTER_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTSYNTHETICFILTER_H
-
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/ValueObject/ValueObject.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private-enumerations.h"
-
-#include <cstdint>
-#include <memory>
-#include <optional>
-
-#include <cstddef>
-
-namespace lldb_private {
-class Declaration;
-class Status;
-class SyntheticChildrenFrontEnd;
-
-/// A ValueObject that obtains its children from some source other than
-/// real information.
-/// This is currently used to implement Python-based children and filters but
-/// you can bind it to any source of synthetic information and have it behave
-/// accordingly.
-class ValueObjectSynthetic : public ValueObject {
-public:
-  ~ValueObjectSynthetic() override;
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  ConstString GetTypeName() override;
-
-  ConstString GetQualifiedTypeName() override;
-
-  ConstString GetDisplayTypeName() override;
-
-  bool MightHaveChildren() override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  lldb::ValueType GetValueType() const override;
-
-  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx,
-                                      bool can_create = true) override;
-
-  lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
-                                             bool can_create = true) override;
-
-  size_t GetIndexOfChildWithName(llvm::StringRef name) override;
-
-  lldb::ValueObjectSP
-  GetDynamicValue(lldb::DynamicValueType valueType) override;
-
-  bool IsInScope() override;
-
-  bool HasSyntheticValue() override { return false; }
-
-  bool IsSynthetic() override { return true; }
-
-  void CalculateSyntheticValue() override {}
-
-  bool IsDynamic() override {
-    return ((m_parent != nullptr) ? m_parent->IsDynamic() : false);
-  }
-
-  lldb::ValueObjectSP GetStaticValue() override {
-    return ((m_parent != nullptr) ? m_parent->GetStaticValue() : GetSP());
-  }
-
-  virtual lldb::DynamicValueType GetDynamicValueType() {
-    return ((m_parent != nullptr) ? m_parent->GetDynamicValueType()
-                                  : lldb::eNoDynamicValues);
-  }
-
-  lldb::VariableSP GetVariable() override {
-    return m_parent != nullptr ? m_parent->GetVariable() : nullptr;
-  }
-
-  ValueObject *GetParent() override {
-    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
-  }
-
-  const ValueObject *GetParent() const override {
-    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
-  }
-
-  lldb::ValueObjectSP GetNonSyntheticValue() override;
-
-  bool CanProvideValue() override;
-
-  bool DoesProvideSyntheticValue() override {
-    return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes);
-  }
-
-  bool GetIsConstant() const override { return false; }
-
-  bool SetValueFromCString(const char *value_str, Status &error) override;
-
-  void SetFormat(lldb::Format format) override;
-
-  lldb::LanguageType GetPreferredDisplayLanguage() override;
-
-  void SetPreferredDisplayLanguage(lldb::LanguageType);
-
-  bool IsSyntheticChildrenGenerated() override;
-
-  void SetSyntheticChildrenGenerated(bool b) override;
-
-  bool GetDeclaration(Declaration &decl) override;
-
-  uint64_t GetLanguageFlags() override;
-
-  void SetLanguageFlags(uint64_t flags) override;
-
-protected:
-  bool UpdateValue() override;
-
-  LazyBool CanUpdateWithInvalidExecutionContext() override {
-    return eLazyBoolYes;
-  }
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  virtual void CreateSynthFilter();
-
-  // we need to hold on to the SyntheticChildren because someone might delete
-  // the type binding while we are alive
-  lldb::SyntheticChildrenSP m_synth_sp;
-  std::unique_ptr<SyntheticChildrenFrontEnd> m_synth_filter_up;
-
-  typedef std::map<uint32_t, ValueObject *> ByIndexMap;
-  typedef std::map<const char *, uint32_t> NameToIndexMap;
-  typedef std::vector<lldb::ValueObjectSP> SyntheticChildrenCache;
-
-  typedef ByIndexMap::iterator ByIndexIterator;
-  typedef NameToIndexMap::iterator NameToIndexIterator;
-
-  std::mutex m_child_mutex;
-  /// Guarded by m_child_mutex;
-  ByIndexMap m_children_byindex;
-  /// Guarded by m_child_mutex;
-  NameToIndexMap m_name_toindex;
-  /// Guarded by m_child_mutex;
-  SyntheticChildrenCache m_synthetic_children_cache;
-
-  // FIXME: use the ValueObject's  ChildrenManager instead of a special purpose
-  // solution.
-  uint32_t m_synthetic_children_count;
-
-  ConstString m_parent_type_name;
-
-  LazyBool m_might_have_children;
-
-  LazyBool m_provides_value;
-
-private:
-  friend class ValueObject;
-  ValueObjectSynthetic(ValueObject &parent, lldb::SyntheticChildrenSP filter);
-
-  void CopyValueData(ValueObject *source);
-
-  ValueObjectSynthetic(const ValueObjectSynthetic &) = delete;
-  const ValueObjectSynthetic &operator=(const ValueObjectSynthetic &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTSYNTHETICFILTER_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectUpdater.h b/lldb/include/lldb/ValueObject/ValueObjectUpdater.h
deleted file mode 100644
index 3f1d887b47a7b6..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectUpdater.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===-- ValueObjectUpdater.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_VALUEOBJECTUPDATER_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTUPDATER_H
-
-#include "lldb/ValueObject/ValueObject.h"
-
-namespace lldb_private {
-
-/// A value object class that is seeded with the static variable value
-/// and it vends the user facing value object. If the type is dynamic it can
-/// vend the dynamic type. If this user type also has a synthetic type
-/// associated with it, it will vend the synthetic type. The class watches the
-/// process' stop ID and will update the user type when needed.
-class ValueObjectUpdater {
-  /// The root value object is the static typed variable object.
-  lldb::ValueObjectSP m_root_valobj_sp;
-  /// The user value object is the value object the user wants to see.
-  lldb::ValueObjectSP m_user_valobj_sp;
-  /// The stop ID that m_user_valobj_sp is valid for.
-  uint32_t m_stop_id = UINT32_MAX;
-
-public:
-  ValueObjectUpdater(lldb::ValueObjectSP in_valobj_sp);
-
-  /// Gets the correct value object from the root object for a given process
-  /// stop ID. If dynamic values are enabled, or if synthetic children are
-  /// enabled, the value object that the user wants to see might change while
-  /// debugging.
-  lldb::ValueObjectSP GetSP();
-
-  lldb::ProcessSP GetProcessSP() const;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTUPDATER_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectVTable.h b/lldb/include/lldb/ValueObject/ValueObjectVTable.h
deleted file mode 100644
index 9cf13be093a8db..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectVTable.h
+++ /dev/null
@@ -1,107 +0,0 @@
-//===-- ValueObjectVTable.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_VALUEOBJECTVTABLE_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTVTABLE_H
-
-#include "lldb/ValueObject/ValueObject.h"
-
-namespace lldb_private {
-
-/// A class that represents a virtual function table for a C++ class.
-///
-/// ValueObject::GetError() will be in the success state if this value
-/// represents a C++ class with a vtable, or an appropriate error describing
-/// that the object isn't a C++ class with a vtable or not a C++ class.
-///
-/// ValueObject::GetName() will be the demangled symbol name for the virtual
-/// function table like "vtable for <classname>".
-///
-/// ValueObject::GetValueAsCString() will be the address of the first vtable
-/// entry if the current ValueObject is a class with a vtable, or nothing the
-/// current ValueObject is not a C++ class or not a C++ class that has a
-/// vtable.
-///
-/// ValueObject::GetValueAtUnsigned(...) will return the address of the first
-/// vtable entry.
-///
-/// ValueObject::GetAddressOf() will return the address of the vtable pointer
-/// found in the parent ValueObject.
-///
-/// ValueObject::GetNumChildren() will return the number of virtual function
-/// pointers in the vtable, or zero on error.
-///
-/// ValueObject::GetChildAtIndex(...) will return each virtual function pointer
-/// as a ValueObject object.
-///
-/// The child ValueObjects will have the following values:
-///
-/// ValueObject::GetError() will indicate success if the vtable entry was
-/// successfully read from memory, or an error if not.
-///
-/// ValueObject::GetName() will be the vtable function index in the form "[%u]"
-/// where %u is the index.
-///
-/// ValueObject::GetValueAsCString() will be the virtual function pointer value
-///
-/// ValueObject::GetValueAtUnsigned(...) will return the virtual function
-/// pointer value.
-///
-/// ValueObject::GetAddressOf() will return the address of the virtual function
-/// pointer.
-///
-/// ValueObject::GetNumChildren() returns 0
-class ValueObjectVTable : public ValueObject {
-public:
-  ~ValueObjectVTable() override;
-
-  static lldb::ValueObjectSP Create(ValueObject &parent);
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  lldb::ValueType GetValueType() const override;
-
-  ConstString GetTypeName() override;
-
-  ConstString GetQualifiedTypeName() override;
-
-  ConstString GetDisplayTypeName() override;
-
-  bool IsInScope() override;
-
-protected:
-  bool UpdateValue() override;
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  /// The symbol for the C++ virtual function table.
-  const Symbol *m_vtable_symbol = nullptr;
-  /// Cache the number of vtable children when we update the value.
-  uint32_t m_num_vtable_entries = 0;
-  /// Cache the address size in bytes to avoid checking with the process to
-  /// many times.
-  uint32_t m_addr_size = 0;
-
-private:
-  ValueObjectVTable(ValueObject &parent);
-
-  ValueObject *CreateChildAtIndex(size_t idx) override;
-  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
-    return nullptr;
-  }
-
-  // For ValueObject only
-  ValueObjectVTable(const ValueObjectVTable &) = delete;
-  const ValueObjectVTable &operator=(const ValueObjectVTable &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTVTABLE_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectVariable.h b/lldb/include/lldb/ValueObject/ValueObjectVariable.h
deleted file mode 100644
index 9f66af808425ab..00000000000000
--- a/lldb/include/lldb/ValueObject/ValueObjectVariable.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//===-- ValueObjectVariable.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_VALUEOBJECTVARIABLE_H
-#define LLDB_VALUEOBJECT_VALUEOBJECTVARIABLE_H
-
-#include "lldb/ValueObject/ValueObject.h"
-
-#include "lldb/Core/Value.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-forward.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <optional>
-
-namespace lldb_private {
-class DataExtractor;
-class Declaration;
-class Status;
-class ExecutionContextScope;
-class SymbolContextScope;
-
-/// A ValueObject that contains a root variable that may or may not
-/// have children.
-class ValueObjectVariable : public ValueObject {
-public:
-  ~ValueObjectVariable() override;
-
-  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    const lldb::VariableSP &var_sp);
-
-  std::optional<uint64_t> GetByteSize() override;
-
-  ConstString GetTypeName() override;
-
-  ConstString GetQualifiedTypeName() override;
-
-  ConstString GetDisplayTypeName() override;
-
-  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
-
-  lldb::ValueType GetValueType() const override;
-
-  bool IsInScope() override;
-
-  lldb::ModuleSP GetModule() override;
-
-  SymbolContextScope *GetSymbolContextScope() override;
-
-  bool GetDeclaration(Declaration &decl) override;
-
-  const char *GetLocationAsCString() override;
-
-  bool SetValueFromCString(const char *value_str, Status &error) override;
-
-  bool SetData(DataExtractor &data, Status &error) override;
-
-  lldb::VariableSP GetVariable() override { return m_variable_sp; }
-
-protected:
-  bool UpdateValue() override;
-
-  void DoUpdateChildrenAddressType(ValueObject &valobj) override;
-
-  CompilerType GetCompilerTypeImpl() override;
-
-  /// The variable that this value object is based upon.
-  lldb::VariableSP m_variable_sp;
-  ///< The value that DWARFExpression resolves this variable to before we patch
-  ///< it up.
-  Value m_resolved_value;
-
-private:
-  ValueObjectVariable(ExecutionContextScope *exe_scope,
-                      ValueObjectManager &manager,
-                      const lldb::VariableSP &var_sp);
-  // For ValueObject only
-  ValueObjectVariable(const ValueObjectVariable &) = delete;
-  const ValueObjectVariable &operator=(const ValueObjectVariable &) = delete;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_VALUEOBJECT_VALUEOBJECTVARIABLE_H

>From 41416de0c61a313cccd89419d9efc24dc1fc80be Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Tue, 4 Feb 2025 09:56:16 -0800
Subject: [PATCH 09/10] Restore .h files after clearing the cache.

---
 lldb/include/lldb/ValueObject/DILLexer.h      |  127 ++
 lldb/include/lldb/ValueObject/ValueObject.h   | 1103 +++++++++++++++++
 .../lldb/ValueObject/ValueObjectCast.h        |   66 +
 .../lldb/ValueObject/ValueObjectChild.h       |   91 ++
 .../lldb/ValueObject/ValueObjectConstResult.h |  166 +++
 .../ValueObject/ValueObjectConstResultCast.h  |   75 ++
 .../ValueObject/ValueObjectConstResultChild.h |   81 ++
 .../ValueObject/ValueObjectConstResultImpl.h  |   80 ++
 .../ValueObject/ValueObjectDynamicValue.h     |  129 ++
 .../lldb/ValueObject/ValueObjectList.h        |   63 +
 .../lldb/ValueObject/ValueObjectMemory.h      |   82 ++
 .../lldb/ValueObject/ValueObjectRegister.h    |  143 +++
 .../ValueObject/ValueObjectSyntheticFilter.h  |  179 +++
 .../lldb/ValueObject/ValueObjectUpdater.h     |   43 +
 .../lldb/ValueObject/ValueObjectVTable.h      |  107 ++
 .../lldb/ValueObject/ValueObjectVariable.h    |   93 ++
 16 files changed, 2628 insertions(+)
 create mode 100644 lldb/include/lldb/ValueObject/DILLexer.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObject.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectCast.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectChild.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectConstResult.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectConstResultCast.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectDynamicValue.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectList.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectMemory.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectRegister.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectSyntheticFilter.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectUpdater.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectVTable.h
 create mode 100644 lldb/include/lldb/ValueObject/ValueObjectVariable.h

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
new file mode 100644
index 00000000000000..fa0b5338834d78
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -0,0 +1,127 @@
+//===-- 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 "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <limits.h>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace lldb_private::dil {
+
+/// Class defining the tokens generated by the DIL lexer and used by the
+/// DIL parser.
+class Token {
+public:
+  enum Kind {
+    coloncolon,
+    eof,
+    identifier,
+    l_paren,
+    r_paren,
+  };
+
+  Token(Kind kind, std::string spelling, uint32_t start)
+      : m_kind(kind), m_spelling(std::move(spelling)), m_start_pos(start) {}
+
+  Kind GetKind() const { return m_kind; }
+
+  std::string GetSpelling() const { return m_spelling; }
+
+  bool Is(Kind kind) const { return m_kind == kind; }
+
+  bool IsNot(Kind kind) const { return m_kind != kind; }
+
+  bool IsOneOf(Kind kind1, Kind kind2) const { return Is(kind1) || Is(kind2); }
+
+  template <typename... Ts> bool IsOneOf(Kind kind, Ts... Ks) const {
+    return Is(kind) || IsOneOf(Ks...);
+  }
+
+  uint32_t GetLocation() const { return m_start_pos; }
+
+  static llvm::StringRef GetTokenName(Kind kind);
+
+private:
+  Kind m_kind;
+  std::string m_spelling;
+  uint32_t m_start_pos; // within entire expression string
+};
+
+/// Class for doing the simple lexing required by DIL.
+class DILLexer {
+public:
+  /// Lexes all the tokens in expr and calls the private constructor
+  /// with the lexed tokens.
+  static llvm::Expected<DILLexer> Create(llvm::StringRef expr);
+
+  /// Return the current token to be handled by the DIL parser.
+  const Token &GetCurrentToken() { return m_lexed_tokens[m_tokens_idx]; }
+
+  /// Advance the current token position by N.
+  void Advance(uint32_t N = 1) {
+    if (m_tokens_idx + N >= m_lexed_tokens.size())
+      // N is too large; advance to the end of the lexed tokens.
+      m_tokens_idx = m_lexed_tokens.size() - 1;
+    else
+      m_tokens_idx += N;
+  }
+
+  /// Return the lexed token N positions ahead of the 'current' token
+  /// being handled by the DIL parser.
+  const Token &LookAhead(uint32_t N) {
+    if (m_tokens_idx + N < m_lexed_tokens.size())
+      return m_lexed_tokens[m_tokens_idx + N];
+
+    // Last token should be an 'eof' token.
+    return m_lexed_tokens.back();
+  }
+
+  /// Return the index for the 'current' token being handled by the DIL parser.
+  uint32_t GetCurrentTokenIdx() { return m_tokens_idx; }
+
+  /// 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.
+  void ResetTokenIdx(uint32_t new_value) {
+    assert(new_value < m_lexed_tokens.size());
+    m_tokens_idx = new_value;
+  }
+
+  uint32_t NumLexedTokens() { return m_lexed_tokens.size(); }
+
+private:
+  DILLexer(llvm::StringRef dil_expr, std::vector<Token> lexed_tokens)
+      : m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)),
+        m_tokens_idx(0), m_eof_token(Token(Token::eof, "", 0)) {}
+
+  static llvm::Expected<Token> Lex(llvm::StringRef expr,
+                                   llvm::StringRef &remainder);
+
+  // The input string we are lexing & parsing.
+  llvm::StringRef m_expr;
+
+  // Holds all of the tokens lexed so far.
+  std::vector<Token> 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;
+
+  // "eof" token; to be returned by lexer when 'look ahead' fails.
+  Token m_eof_token;
+};
+
+} // namespace lldb_private::dil
+
+#endif // LLDB_VALUEOBJECT_DILLEXER_H
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h b/lldb/include/lldb/ValueObject/ValueObject.h
new file mode 100644
index 00000000000000..4f77384bb8f136
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObject.h
@@ -0,0 +1,1103 @@
+//===-- ValueObject.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_VALUEOBJECT_H
+#define LLDB_VALUEOBJECT_VALUEOBJECT_H
+
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/SharedCluster.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/UserID.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <functional>
+#include <initializer_list>
+#include <map>
+#include <mutex>
+#include <optional>
+#include <string>
+#include <utility>
+
+#include <cstddef>
+#include <cstdint>
+
+namespace lldb_private {
+class Declaration;
+class DumpValueObjectOptions;
+class EvaluateExpressionOptions;
+class ExecutionContextScope;
+class Log;
+class Scalar;
+class Stream;
+class SymbolContextScope;
+class TypeFormatImpl;
+class TypeSummaryImpl;
+class TypeSummaryOptions;
+
+/// ValueObject:
+///
+/// This abstract class provides an interface to a particular value, be it a
+/// register, a local or global variable,
+/// that is evaluated in some particular scope.  The ValueObject also has the
+/// capability of being the "child" of
+/// some other variable object, and in turn of having children.
+/// If a ValueObject is a root variable object - having no parent - then it must
+/// be constructed with respect to some
+/// particular ExecutionContextScope.  If it is a child, it inherits the
+/// ExecutionContextScope from its parent.
+/// The ValueObject will update itself if necessary before fetching its value,
+/// summary, object description, etc.
+/// But it will always update itself in the ExecutionContextScope with which it
+/// was originally created.
+
+/// A brief note on life cycle management for ValueObjects.  This is a little
+/// tricky because a ValueObject can contain
+/// various other ValueObjects - the Dynamic Value, its children, the
+/// dereference value, etc.  Any one of these can be
+/// handed out as a shared pointer, but for that contained value object to be
+/// valid, the root object and potentially other
+/// of the value objects need to stay around.
+/// We solve this problem by handing out shared pointers to the Value Object and
+/// any of its dependents using a shared
+/// ClusterManager.  This treats each shared pointer handed out for the entire
+/// cluster as a reference to the whole
+/// cluster.  The whole cluster will stay around until the last reference is
+/// released.
+///
+/// The ValueObject mostly handle this automatically, if a value object is made
+/// with a Parent ValueObject, then it adds
+/// itself to the ClusterManager of the parent.
+
+/// It does mean that external to the ValueObjects we should only ever make
+/// available ValueObjectSP's, never ValueObjects
+/// or pointers to them.  So all the "Root level" ValueObject derived
+/// constructors should be private, and
+/// should implement a Create function that new's up object and returns a Shared
+/// Pointer that it gets from the GetSP() method.
+///
+/// However, if you are making an derived ValueObject that will be contained in
+/// a parent value object, you should just
+/// hold onto a pointer to it internally, and by virtue of passing the parent
+/// ValueObject into its constructor, it will
+/// be added to the ClusterManager for the parent.  Then if you ever hand out a
+/// Shared Pointer to the contained ValueObject,
+/// just do so by calling GetSP() on the contained object.
+
+class ValueObject {
+public:
+  enum GetExpressionPathFormat {
+    eGetExpressionPathFormatDereferencePointers = 1,
+    eGetExpressionPathFormatHonorPointers
+  };
+
+  enum ValueObjectRepresentationStyle {
+    eValueObjectRepresentationStyleValue = 1,
+    eValueObjectRepresentationStyleSummary,
+    eValueObjectRepresentationStyleLanguageSpecific,
+    eValueObjectRepresentationStyleLocation,
+    eValueObjectRepresentationStyleChildrenCount,
+    eValueObjectRepresentationStyleType,
+    eValueObjectRepresentationStyleName,
+    eValueObjectRepresentationStyleExpressionPath
+  };
+
+  enum ExpressionPathScanEndReason {
+    /// Out of data to parse.
+    eExpressionPathScanEndReasonEndOfString = 1,
+    /// Child element not found.
+    eExpressionPathScanEndReasonNoSuchChild,
+    /// (Synthetic) child  element not found.
+    eExpressionPathScanEndReasonNoSuchSyntheticChild,
+    /// [] only allowed for arrays.
+    eExpressionPathScanEndReasonEmptyRangeNotAllowed,
+    /// . used when -> should be used.
+    eExpressionPathScanEndReasonDotInsteadOfArrow,
+    /// -> used when . should be used.
+    eExpressionPathScanEndReasonArrowInsteadOfDot,
+    /// ObjC ivar expansion not allowed.
+    eExpressionPathScanEndReasonFragileIVarNotAllowed,
+    /// [] not allowed by options.
+    eExpressionPathScanEndReasonRangeOperatorNotAllowed,
+    /// [] not valid on objects  other than scalars, pointers or arrays.
+    eExpressionPathScanEndReasonRangeOperatorInvalid,
+    /// [] is good for arrays,  but I cannot parse it.
+    eExpressionPathScanEndReasonArrayRangeOperatorMet,
+    /// [] is good for bitfields, but I cannot parse after it.
+    eExpressionPathScanEndReasonBitfieldRangeOperatorMet,
+    /// Something is malformed in he expression.
+    eExpressionPathScanEndReasonUnexpectedSymbol,
+    /// Impossible to apply &  operator.
+    eExpressionPathScanEndReasonTakingAddressFailed,
+    /// Impossible to apply *  operator.
+    eExpressionPathScanEndReasonDereferencingFailed,
+    /// [] was expanded into a  VOList.
+    eExpressionPathScanEndReasonRangeOperatorExpanded,
+    /// getting the synthetic children failed.
+    eExpressionPathScanEndReasonSyntheticValueMissing,
+    eExpressionPathScanEndReasonUnknown = 0xFFFF
+  };
+
+  enum ExpressionPathEndResultType {
+    /// Anything but...
+    eExpressionPathEndResultTypePlain = 1,
+    /// A bitfield.
+    eExpressionPathEndResultTypeBitfield,
+    /// A range [low-high].
+    eExpressionPathEndResultTypeBoundedRange,
+    /// A range [].
+    eExpressionPathEndResultTypeUnboundedRange,
+    /// Several items in a VOList.
+    eExpressionPathEndResultTypeValueObjectList,
+    eExpressionPathEndResultTypeInvalid = 0xFFFF
+  };
+
+  enum ExpressionPathAftermath {
+    /// Just return it.
+    eExpressionPathAftermathNothing = 1,
+    /// Dereference the target.
+    eExpressionPathAftermathDereference,
+    /// Take target's address.
+    eExpressionPathAftermathTakeAddress
+  };
+
+  enum ClearUserVisibleDataItems {
+    eClearUserVisibleDataItemsNothing = 1u << 0,
+    eClearUserVisibleDataItemsValue = 1u << 1,
+    eClearUserVisibleDataItemsSummary = 1u << 2,
+    eClearUserVisibleDataItemsLocation = 1u << 3,
+    eClearUserVisibleDataItemsDescription = 1u << 4,
+    eClearUserVisibleDataItemsSyntheticChildren = 1u << 5,
+    eClearUserVisibleDataItemsAllStrings =
+        eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary |
+        eClearUserVisibleDataItemsLocation |
+        eClearUserVisibleDataItemsDescription,
+    eClearUserVisibleDataItemsAll = 0xFFFF
+  };
+
+  struct GetValueForExpressionPathOptions {
+    enum class SyntheticChildrenTraversal {
+      None,
+      ToSynthetic,
+      FromSynthetic,
+      Both
+    };
+
+    bool m_check_dot_vs_arrow_syntax;
+    bool m_no_fragile_ivar;
+    bool m_allow_bitfields_syntax;
+    SyntheticChildrenTraversal m_synthetic_children_traversal;
+
+    GetValueForExpressionPathOptions(
+        bool dot = false, bool no_ivar = false, bool bitfield = true,
+        SyntheticChildrenTraversal synth_traverse =
+            SyntheticChildrenTraversal::ToSynthetic)
+        : m_check_dot_vs_arrow_syntax(dot), m_no_fragile_ivar(no_ivar),
+          m_allow_bitfields_syntax(bitfield),
+          m_synthetic_children_traversal(synth_traverse) {}
+
+    GetValueForExpressionPathOptions &DoCheckDotVsArrowSyntax() {
+      m_check_dot_vs_arrow_syntax = true;
+      return *this;
+    }
+
+    GetValueForExpressionPathOptions &DontCheckDotVsArrowSyntax() {
+      m_check_dot_vs_arrow_syntax = false;
+      return *this;
+    }
+
+    GetValueForExpressionPathOptions &DoAllowFragileIVar() {
+      m_no_fragile_ivar = false;
+      return *this;
+    }
+
+    GetValueForExpressionPathOptions &DontAllowFragileIVar() {
+      m_no_fragile_ivar = true;
+      return *this;
+    }
+
+    GetValueForExpressionPathOptions &DoAllowBitfieldSyntax() {
+      m_allow_bitfields_syntax = true;
+      return *this;
+    }
+
+    GetValueForExpressionPathOptions &DontAllowBitfieldSyntax() {
+      m_allow_bitfields_syntax = false;
+      return *this;
+    }
+
+    GetValueForExpressionPathOptions &
+    SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse) {
+      m_synthetic_children_traversal = traverse;
+      return *this;
+    }
+
+    static const GetValueForExpressionPathOptions DefaultOptions() {
+      static GetValueForExpressionPathOptions g_default_options;
+
+      return g_default_options;
+    }
+  };
+
+  class EvaluationPoint {
+  public:
+    EvaluationPoint();
+
+    EvaluationPoint(ExecutionContextScope *exe_scope,
+                    bool use_selected = false);
+
+    EvaluationPoint(const EvaluationPoint &rhs);
+
+    ~EvaluationPoint();
+
+    const ExecutionContextRef &GetExecutionContextRef() const {
+      return m_exe_ctx_ref;
+    }
+
+    void SetIsConstant() {
+      SetUpdated();
+      m_mod_id.SetInvalid();
+    }
+
+    bool IsConstant() const { return !m_mod_id.IsValid(); }
+
+    ProcessModID GetModID() const { return m_mod_id; }
+
+    void SetUpdateID(ProcessModID new_id) { m_mod_id = new_id; }
+
+    void SetNeedsUpdate() { m_needs_update = true; }
+
+    void SetUpdated();
+
+    bool NeedsUpdating(bool accept_invalid_exe_ctx) {
+      SyncWithProcessState(accept_invalid_exe_ctx);
+      return m_needs_update;
+    }
+
+    bool IsValid() {
+      const bool accept_invalid_exe_ctx = false;
+      if (!m_mod_id.IsValid())
+        return false;
+      else if (SyncWithProcessState(accept_invalid_exe_ctx)) {
+        if (!m_mod_id.IsValid())
+          return false;
+      }
+      return true;
+    }
+
+    void SetInvalid() {
+      // Use the stop id to mark us as invalid, leave the thread id and the
+      // stack id around for logging and history purposes.
+      m_mod_id.SetInvalid();
+
+      // Can't update an invalid state.
+      m_needs_update = false;
+    }
+
+  private:
+    bool SyncWithProcessState(bool accept_invalid_exe_ctx);
+
+    ProcessModID m_mod_id; // This is the stop id when this ValueObject was last
+                           // evaluated.
+    ExecutionContextRef m_exe_ctx_ref;
+    bool m_needs_update = true;
+  };
+
+  virtual ~ValueObject();
+
+  const EvaluationPoint &GetUpdatePoint() const { return m_update_point; }
+
+  EvaluationPoint &GetUpdatePoint() { return m_update_point; }
+
+  const ExecutionContextRef &GetExecutionContextRef() const {
+    return m_update_point.GetExecutionContextRef();
+  }
+
+  lldb::TargetSP GetTargetSP() const {
+    return m_update_point.GetExecutionContextRef().GetTargetSP();
+  }
+
+  lldb::ProcessSP GetProcessSP() const {
+    return m_update_point.GetExecutionContextRef().GetProcessSP();
+  }
+
+  lldb::ThreadSP GetThreadSP() const {
+    return m_update_point.GetExecutionContextRef().GetThreadSP();
+  }
+
+  lldb::StackFrameSP GetFrameSP() const {
+    return m_update_point.GetExecutionContextRef().GetFrameSP();
+  }
+
+  void SetNeedsUpdate();
+
+  CompilerType GetCompilerType() { return MaybeCalculateCompleteType(); }
+
+  // this vends a TypeImpl that is useful at the SB API layer
+  virtual TypeImpl GetTypeImpl() { return TypeImpl(GetCompilerType()); }
+
+  virtual bool CanProvideValue();
+
+  // Subclasses must implement the functions below.
+  virtual std::optional<uint64_t> GetByteSize() = 0;
+
+  virtual lldb::ValueType GetValueType() const = 0;
+
+  // Subclasses can implement the functions below.
+  virtual ConstString GetTypeName() { return GetCompilerType().GetTypeName(); }
+
+  virtual ConstString GetDisplayTypeName() { return GetTypeName(); }
+
+  virtual ConstString GetQualifiedTypeName() {
+    return GetCompilerType().GetTypeName();
+  }
+
+  lldb::LanguageType GetObjectRuntimeLanguage() {
+    return GetCompilerType().GetMinimumLanguage();
+  }
+
+  uint32_t
+  GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr) {
+    return GetCompilerType().GetTypeInfo(pointee_or_element_compiler_type);
+  }
+
+  bool IsPointerType() { return GetCompilerType().IsPointerType(); }
+
+  bool IsArrayType() { return GetCompilerType().IsArrayType(); }
+
+  bool IsScalarType() { return GetCompilerType().IsScalarType(); }
+
+  bool IsPointerOrReferenceType() {
+    return GetCompilerType().IsPointerOrReferenceType();
+  }
+
+  bool IsPossibleDynamicType();
+
+  bool IsNilReference();
+
+  bool IsUninitializedReference();
+
+  virtual bool IsBaseClass() { return false; }
+
+  bool IsBaseClass(uint32_t &depth);
+
+  virtual bool IsDereferenceOfParent() { return false; }
+
+  bool IsIntegerType(bool &is_signed) {
+    return GetCompilerType().IsIntegerType(is_signed);
+  }
+
+  virtual void GetExpressionPath(
+      Stream &s,
+      GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers);
+
+  lldb::ValueObjectSP GetValueForExpressionPath(
+      llvm::StringRef expression,
+      ExpressionPathScanEndReason *reason_to_stop = nullptr,
+      ExpressionPathEndResultType *final_value_type = nullptr,
+      const GetValueForExpressionPathOptions &options =
+          GetValueForExpressionPathOptions::DefaultOptions(),
+      ExpressionPathAftermath *final_task_on_target = nullptr);
+
+  virtual bool IsInScope() { return true; }
+
+  virtual lldb::offset_t GetByteOffset() { return 0; }
+
+  virtual uint32_t GetBitfieldBitSize() { return 0; }
+
+  virtual uint32_t GetBitfieldBitOffset() { return 0; }
+
+  bool IsBitfield() {
+    return (GetBitfieldBitSize() != 0) || (GetBitfieldBitOffset() != 0);
+  }
+
+  virtual const char *GetValueAsCString();
+
+  virtual bool GetValueAsCString(const lldb_private::TypeFormatImpl &format,
+                                 std::string &destination);
+
+  bool GetValueAsCString(lldb::Format format, std::string &destination);
+
+  virtual uint64_t GetValueAsUnsigned(uint64_t fail_value,
+                                      bool *success = nullptr);
+
+  virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = nullptr);
+
+  /// If the current ValueObject is of an appropriate type, convert the
+  /// value to an APSInt and return that. Otherwise return an error.
+  llvm::Expected<llvm::APSInt> GetValueAsAPSInt();
+
+  /// If the current ValueObject is of an appropriate type, convert the
+  /// value to an APFloat and return that. Otherwise return an error.
+  llvm::Expected<llvm::APFloat> GetValueAsAPFloat();
+
+  /// If the current ValueObject is of an appropriate type, convert the
+  /// value to a boolean and return that. Otherwise return an error.
+  llvm::Expected<bool> GetValueAsBool();
+
+  /// Update an existing integer ValueObject with a new integer value. This
+  /// is only intended to be used with 'temporary' ValueObjects, i.e. ones that
+  /// are not associated with program variables. It does not update program
+  /// memory, registers, stack, etc.
+  void SetValueFromInteger(const llvm::APInt &value, Status &error);
+
+  /// Update an existing integer ValueObject with an integer value created
+  /// frome 'new_val_sp'.  This is only intended to be used with 'temporary'
+  /// ValueObjects, i.e. ones that are not associated with program variables.
+  /// It does not update program  memory, registers, stack, etc.
+  void SetValueFromInteger(lldb::ValueObjectSP new_val_sp, Status &error);
+
+  virtual bool SetValueFromCString(const char *value_str, Status &error);
+
+  /// Return the module associated with this value object in case the value is
+  /// from an executable file and might have its data in sections of the file.
+  /// This can be used for variables.
+  virtual lldb::ModuleSP GetModule();
+
+  ValueObject *GetRoot();
+
+  /// Given a ValueObject, loop over itself and its parent, and its parent's
+  /// parent, .. until either the given callback returns false, or you end up at
+  /// a null pointer
+  ValueObject *FollowParentChain(std::function<bool(ValueObject *)>);
+
+  virtual bool GetDeclaration(Declaration &decl);
+
+  // The functions below should NOT be modified by subclasses
+  const Status &GetError();
+
+  ConstString GetName() const { return m_name; }
+
+  /// Returns a unique id for this ValueObject.
+  lldb::user_id_t GetID() const { return m_id.GetID(); }
+
+  virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx,
+                                              bool can_create = true);
+
+  // The method always creates missing children in the path, if necessary.
+  lldb::ValueObjectSP GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names);
+
+  virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
+                                                     bool can_create = true);
+
+  virtual size_t GetIndexOfChildWithName(llvm::StringRef name);
+
+  llvm::Expected<uint32_t> GetNumChildren(uint32_t max = UINT32_MAX);
+  /// Like \c GetNumChildren but returns 0 on error.  You probably
+  /// shouldn't be using this function. It exists primarily to ease the
+  /// transition to more pervasive error handling while not all APIs
+  /// have been updated.
+  uint32_t GetNumChildrenIgnoringErrors(uint32_t max = UINT32_MAX);
+  bool HasChildren() { return GetNumChildrenIgnoringErrors() > 0; }
+
+  const Value &GetValue() const { return m_value; }
+
+  Value &GetValue() { return m_value; }
+
+  virtual bool ResolveValue(Scalar &scalar);
+
+  // return 'false' whenever you set the error, otherwise callers may assume
+  // true means everything is OK - this will break breakpoint conditions among
+  // potentially a few others
+  virtual bool IsLogicalTrue(Status &error);
+
+  virtual const char *GetLocationAsCString() {
+    return GetLocationAsCStringImpl(m_value, m_data);
+  }
+
+  const char *
+  GetSummaryAsCString(lldb::LanguageType lang = lldb::eLanguageTypeUnknown);
+
+  bool
+  GetSummaryAsCString(TypeSummaryImpl *summary_ptr, std::string &destination,
+                      lldb::LanguageType lang = lldb::eLanguageTypeUnknown);
+
+  bool GetSummaryAsCString(std::string &destination,
+                           const TypeSummaryOptions &options);
+
+  bool GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
+                           std::string &destination,
+                           const TypeSummaryOptions &options);
+
+  llvm::Expected<std::string> GetObjectDescription();
+
+  bool HasSpecialPrintableRepresentation(
+      ValueObjectRepresentationStyle val_obj_display,
+      lldb::Format custom_format);
+
+  enum class PrintableRepresentationSpecialCases : bool {
+    eDisable = false,
+    eAllow = true
+  };
+
+  bool
+  DumpPrintableRepresentation(Stream &s,
+                              ValueObjectRepresentationStyle val_obj_display =
+                                  eValueObjectRepresentationStyleSummary,
+                              lldb::Format custom_format = lldb::eFormatInvalid,
+                              PrintableRepresentationSpecialCases special =
+                                  PrintableRepresentationSpecialCases::eAllow,
+                              bool do_dump_error = true);
+  bool GetValueIsValid() const { return m_flags.m_value_is_valid; }
+
+  // If you call this on a newly created ValueObject, it will always return
+  // false.
+  bool GetValueDidChange() { return m_flags.m_value_did_change; }
+
+  bool UpdateValueIfNeeded(bool update_format = true);
+
+  bool UpdateFormatsIfNeeded();
+
+  lldb::ValueObjectSP GetSP() { return m_manager->GetSharedPointer(this); }
+
+  /// Change the name of the current ValueObject. Should *not* be used from a
+  /// synthetic child provider as it would change the name of the non synthetic
+  /// child as well.
+  void SetName(ConstString name) { m_name = name; }
+
+  virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
+                                    AddressType *address_type = nullptr);
+
+  lldb::addr_t GetPointerValue(AddressType *address_type = nullptr);
+
+  lldb::ValueObjectSP GetSyntheticChild(ConstString key) const;
+
+  lldb::ValueObjectSP GetSyntheticArrayMember(size_t index, bool can_create);
+
+  lldb::ValueObjectSP GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
+                                                bool can_create);
+
+  lldb::ValueObjectSP GetSyntheticExpressionPathChild(const char *expression,
+                                                      bool can_create);
+
+  virtual lldb::ValueObjectSP
+  GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type,
+                            bool can_create,
+                            ConstString name_const_str = ConstString());
+
+  virtual lldb::ValueObjectSP
+  GetSyntheticBase(uint32_t offset, const CompilerType &type, bool can_create,
+                   ConstString name_const_str = ConstString());
+
+  virtual lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType);
+
+  lldb::DynamicValueType GetDynamicValueType();
+
+  virtual lldb::ValueObjectSP GetStaticValue() { return GetSP(); }
+
+  virtual lldb::ValueObjectSP GetNonSyntheticValue() { return GetSP(); }
+
+  lldb::ValueObjectSP GetSyntheticValue();
+
+  virtual bool HasSyntheticValue();
+
+  virtual bool IsSynthetic() { return false; }
+
+  lldb::ValueObjectSP
+  GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue,
+                                        bool synthValue);
+
+  virtual lldb::ValueObjectSP CreateConstantValue(ConstString name);
+
+  virtual lldb::ValueObjectSP Dereference(Status &error);
+
+  /// Creates a copy of the ValueObject with a new name and setting the current
+  /// ValueObject as its parent. It should be used when we want to change the
+  /// name of a ValueObject without modifying the actual ValueObject itself
+  /// (e.g. sythetic child provider).
+  virtual lldb::ValueObjectSP Clone(ConstString new_name);
+
+  virtual lldb::ValueObjectSP AddressOf(Status &error);
+
+  virtual lldb::addr_t GetLiveAddress() { return LLDB_INVALID_ADDRESS; }
+
+  virtual void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
+                              AddressType address_type = eAddressTypeLoad) {}
+
+  lldb::ValueObjectSP Cast(const CompilerType &compiler_type);
+
+  virtual lldb::ValueObjectSP DoCast(const CompilerType &compiler_type);
+
+  virtual lldb::ValueObjectSP CastPointerType(const char *name,
+                                              CompilerType &ast_type);
+
+  virtual lldb::ValueObjectSP CastPointerType(const char *name,
+                                              lldb::TypeSP &type_sp);
+
+  /// Return the target load address associated with this value object.
+  lldb::addr_t GetLoadAddress();
+
+  /// Take a ValueObject whose type is an inherited class, and cast it to
+  /// 'type', which should be one of its base classes. 'base_type_indices'
+  /// contains the indices of direct base classes on the path from the
+  /// ValueObject's current type to 'type'
+  llvm::Expected<lldb::ValueObjectSP>
+  CastDerivedToBaseType(CompilerType type,
+                        const llvm::ArrayRef<uint32_t> &base_type_indices);
+
+  /// Take a ValueObject whose type is a base class, and cast it to 'type',
+  /// which should be one of its derived classes. 'base_type_indices'
+  /// contains the indices of direct base classes on the path from the
+  /// ValueObject's current type to 'type'
+  llvm::Expected<lldb::ValueObjectSP> CastBaseToDerivedType(CompilerType type,
+                                                            uint64_t offset);
+
+  // Take a ValueObject that contains a scalar, enum or pointer type, and
+  // cast it to a "basic" type (integer, float or boolean).
+  lldb::ValueObjectSP CastToBasicType(CompilerType type);
+
+  // Take a ValueObject that contain an integer, float or enum, and cast it
+  // to an enum.
+  lldb::ValueObjectSP CastToEnumType(CompilerType type);
+
+  /// If this object represents a C++ class with a vtable, return an object
+  /// that represents the virtual function table. If the object isn't a class
+  /// with a vtable, return a valid ValueObject with the error set correctly.
+  lldb::ValueObjectSP GetVTable();
+  // The backing bits of this value object were updated, clear any descriptive
+  // string, so we know we have to refetch them.
+  void ValueUpdated() {
+    ClearUserVisibleData(eClearUserVisibleDataItemsValue |
+                         eClearUserVisibleDataItemsSummary |
+                         eClearUserVisibleDataItemsDescription);
+  }
+
+  virtual bool IsDynamic() { return false; }
+
+  virtual bool DoesProvideSyntheticValue() { return false; }
+
+  virtual bool IsSyntheticChildrenGenerated() {
+    return m_flags.m_is_synthetic_children_generated;
+  }
+
+  virtual void SetSyntheticChildrenGenerated(bool b) {
+    m_flags.m_is_synthetic_children_generated = b;
+  }
+
+  virtual SymbolContextScope *GetSymbolContextScope();
+
+  llvm::Error Dump(Stream &s);
+
+  llvm::Error Dump(Stream &s, const DumpValueObjectOptions &options);
+
+  static lldb::ValueObjectSP
+  CreateValueObjectFromExpression(llvm::StringRef name,
+                                  llvm::StringRef expression,
+                                  const ExecutionContext &exe_ctx);
+
+  static lldb::ValueObjectSP
+  CreateValueObjectFromExpression(llvm::StringRef name,
+                                  llvm::StringRef expression,
+                                  const ExecutionContext &exe_ctx,
+                                  const EvaluateExpressionOptions &options);
+
+  /// Given an address either create a value object containing the value at
+  /// that address, or create a value object containing the address itself
+  /// (pointer value), depending on whether the parameter 'do_deref' is true or
+  /// false.
+  static lldb::ValueObjectSP
+  CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address,
+                               const ExecutionContext &exe_ctx,
+                               CompilerType type, bool do_deref = true);
+
+  static lldb::ValueObjectSP
+  CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data,
+                            const ExecutionContext &exe_ctx, CompilerType type);
+
+  /// Create a value object containing the given APInt value.
+  static lldb::ValueObjectSP CreateValueObjectFromAPInt(lldb::TargetSP target,
+                                                        const llvm::APInt &v,
+                                                        CompilerType type,
+                                                        llvm::StringRef name);
+
+  /// Create a value object containing the given APFloat value.
+  static lldb::ValueObjectSP
+  CreateValueObjectFromAPFloat(lldb::TargetSP target, const llvm::APFloat &v,
+                               CompilerType type, llvm::StringRef name);
+
+  /// Create a value object containing the given boolean value.
+  static lldb::ValueObjectSP CreateValueObjectFromBool(lldb::TargetSP target,
+                                                       bool value,
+                                                       llvm::StringRef name);
+
+  /// Create a nullptr value object with the specified type (must be a
+  /// nullptr type).
+  static lldb::ValueObjectSP CreateValueObjectFromNullptr(lldb::TargetSP target,
+                                                          CompilerType type,
+                                                          llvm::StringRef name);
+
+  lldb::ValueObjectSP Persist();
+
+  /// Returns true if this is a char* or a char[] if it is a char* and
+  /// check_pointer is true, it also checks that the pointer is valid.
+  bool IsCStringContainer(bool check_pointer = false);
+
+  std::pair<size_t, bool>
+  ReadPointedString(lldb::WritableDataBufferSP &buffer_sp, Status &error,
+                    bool honor_array);
+
+  virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
+                                uint32_t item_count = 1);
+
+  virtual uint64_t GetData(DataExtractor &data, Status &error);
+
+  virtual bool SetData(DataExtractor &data, Status &error);
+
+  virtual bool GetIsConstant() const { return m_update_point.IsConstant(); }
+
+  bool NeedsUpdating() {
+    const bool accept_invalid_exe_ctx =
+        (CanUpdateWithInvalidExecutionContext() == eLazyBoolYes);
+    return m_update_point.NeedsUpdating(accept_invalid_exe_ctx);
+  }
+
+  void SetIsConstant() { m_update_point.SetIsConstant(); }
+
+  lldb::Format GetFormat() const;
+
+  virtual void SetFormat(lldb::Format format) {
+    if (format != m_format)
+      ClearUserVisibleData(eClearUserVisibleDataItemsValue);
+    m_format = format;
+  }
+
+  virtual lldb::LanguageType GetPreferredDisplayLanguage();
+
+  void SetPreferredDisplayLanguage(lldb::LanguageType lt) {
+    m_preferred_display_language = lt;
+  }
+
+  lldb::TypeSummaryImplSP GetSummaryFormat() {
+    UpdateFormatsIfNeeded();
+    return m_type_summary_sp;
+  }
+
+  void SetSummaryFormat(lldb::TypeSummaryImplSP format) {
+    m_type_summary_sp = std::move(format);
+    ClearUserVisibleData(eClearUserVisibleDataItemsSummary);
+  }
+
+  void SetDerefValobj(ValueObject *deref) { m_deref_valobj = deref; }
+
+  ValueObject *GetDerefValobj() { return m_deref_valobj; }
+
+  void SetValueFormat(lldb::TypeFormatImplSP format) {
+    m_type_format_sp = std::move(format);
+    ClearUserVisibleData(eClearUserVisibleDataItemsValue);
+  }
+
+  lldb::TypeFormatImplSP GetValueFormat() {
+    UpdateFormatsIfNeeded();
+    return m_type_format_sp;
+  }
+
+  void SetSyntheticChildren(const lldb::SyntheticChildrenSP &synth_sp) {
+    if (synth_sp.get() == m_synthetic_children_sp.get())
+      return;
+    ClearUserVisibleData(eClearUserVisibleDataItemsSyntheticChildren);
+    m_synthetic_children_sp = synth_sp;
+  }
+
+  lldb::SyntheticChildrenSP GetSyntheticChildren() {
+    UpdateFormatsIfNeeded();
+    return m_synthetic_children_sp;
+  }
+
+  // Use GetParent for display purposes, but if you want to tell the parent to
+  // update itself then use m_parent.  The ValueObjectDynamicValue's parent is
+  // not the correct parent for displaying, they are really siblings, so for
+  // display it needs to route through to its grandparent.
+  virtual ValueObject *GetParent() { return m_parent; }
+
+  virtual const ValueObject *GetParent() const { return m_parent; }
+
+  ValueObject *GetNonBaseClassParent();
+
+  void SetAddressTypeOfChildren(AddressType at) {
+    m_address_type_of_ptr_or_ref_children = at;
+  }
+
+  AddressType GetAddressTypeOfChildren();
+
+  void SetHasCompleteType() {
+    m_flags.m_did_calculate_complete_objc_class_type = true;
+  }
+
+  /// Find out if a ValueObject might have children.
+  ///
+  /// This call is much more efficient than CalculateNumChildren() as
+  /// it doesn't need to complete the underlying type. This is designed
+  /// to be used in a UI environment in order to detect if the
+  /// disclosure triangle should be displayed or not.
+  ///
+  /// This function returns true for class, union, structure,
+  /// pointers, references, arrays and more. Again, it does so without
+  /// doing any expensive type completion.
+  ///
+  /// \return
+  ///     Returns \b true if the ValueObject might have children, or \b
+  ///     false otherwise.
+  virtual bool MightHaveChildren();
+
+  virtual lldb::VariableSP GetVariable() { return nullptr; }
+
+  virtual bool IsRuntimeSupportValue();
+
+  virtual uint64_t GetLanguageFlags() { return m_language_flags; }
+
+  virtual void SetLanguageFlags(uint64_t flags) { m_language_flags = flags; }
+
+protected:
+  typedef ClusterManager<ValueObject> ValueObjectManager;
+
+  class ChildrenManager {
+  public:
+    ChildrenManager() = default;
+
+    bool HasChildAtIndex(size_t idx) {
+      std::lock_guard<std::recursive_mutex> guard(m_mutex);
+      return (m_children.find(idx) != m_children.end());
+    }
+
+    ValueObject *GetChildAtIndex(uint32_t idx) {
+      std::lock_guard<std::recursive_mutex> guard(m_mutex);
+      const auto iter = m_children.find(idx);
+      return ((iter == m_children.end()) ? nullptr : iter->second);
+    }
+
+    void SetChildAtIndex(size_t idx, ValueObject *valobj) {
+      // we do not need to be mutex-protected to make a pair
+      ChildrenPair pair(idx, valobj);
+      std::lock_guard<std::recursive_mutex> guard(m_mutex);
+      m_children.insert(pair);
+    }
+
+    void SetChildrenCount(size_t count) { Clear(count); }
+
+    size_t GetChildrenCount() { return m_children_count; }
+
+    void Clear(size_t new_count = 0) {
+      std::lock_guard<std::recursive_mutex> guard(m_mutex);
+      m_children_count = new_count;
+      m_children.clear();
+    }
+
+  private:
+    typedef std::map<size_t, ValueObject *> ChildrenMap;
+    typedef ChildrenMap::iterator ChildrenIterator;
+    typedef ChildrenMap::value_type ChildrenPair;
+    std::recursive_mutex m_mutex;
+    ChildrenMap m_children;
+    size_t m_children_count = 0;
+  };
+
+  // Classes that inherit from ValueObject can see and modify these
+
+  /// The parent value object, or nullptr if this has no parent.
+  ValueObject *m_parent = nullptr;
+  /// The root of the hierarchy for this ValueObject (or nullptr if never
+  /// calculated).
+  ValueObject *m_root = nullptr;
+  /// Stores both the stop id and the full context at which this value was last
+  /// updated.  When we are asked to update the value object, we check whether
+  /// the context & stop id are the same before updating.
+  EvaluationPoint m_update_point;
+  /// The name of this object.
+  ConstString m_name;
+  /// A data extractor that can be used to extract the value.
+  DataExtractor m_data;
+  Value m_value;
+  /// An error object that can describe any errors that occur when updating
+  /// values.
+  Status m_error;
+  /// Cached value string that will get cleared if/when the value is updated.
+  std::string m_value_str;
+  /// Cached old value string from the last time the value was gotten
+  std::string m_old_value_str;
+  /// Cached location string that will get cleared if/when the value is updated.
+  std::string m_location_str;
+  /// Cached summary string that will get cleared if/when the value is updated.
+  std::string m_summary_str;
+  /// Cached result of the "object printer". This differs from the summary
+  /// in that the summary is consed up by us, the object_desc_string is builtin.
+  std::string m_object_desc_str;
+  /// If the type of the value object should be overridden, the type to impose.
+  CompilerType m_override_type;
+
+  /// This object is managed by the root object (any ValueObject that gets
+  /// created without a parent.) The manager gets passed through all the
+  /// generations of dependent objects, and will keep the whole cluster of
+  /// objects alive as long as a shared pointer to any of them has been handed
+  /// out. Shared pointers to value objects must always be made with the GetSP
+  /// method.
+  ValueObjectManager *m_manager = nullptr;
+
+  ChildrenManager m_children;
+  std::map<ConstString, ValueObject *> m_synthetic_children;
+
+  ValueObject *m_dynamic_value = nullptr;
+  ValueObject *m_synthetic_value = nullptr;
+  ValueObject *m_deref_valobj = nullptr;
+
+  /// We have to hold onto a shared  pointer to this one because it is created
+  /// as an independent ValueObjectConstResult, which isn't managed by us.
+  lldb::ValueObjectSP m_addr_of_valobj_sp;
+
+  lldb::Format m_format = lldb::eFormatDefault;
+  lldb::Format m_last_format = lldb::eFormatDefault;
+  uint32_t m_last_format_mgr_revision = 0;
+  lldb::TypeSummaryImplSP m_type_summary_sp;
+  lldb::TypeFormatImplSP m_type_format_sp;
+  lldb::SyntheticChildrenSP m_synthetic_children_sp;
+  ProcessModID m_user_id_of_forced_summary;
+  AddressType m_address_type_of_ptr_or_ref_children = eAddressTypeInvalid;
+
+  llvm::SmallVector<uint8_t, 16> m_value_checksum;
+
+  lldb::LanguageType m_preferred_display_language = lldb::eLanguageTypeUnknown;
+
+  uint64_t m_language_flags = 0;
+
+  /// Unique identifier for every value object.
+  UserID m_id;
+
+  // Utility class for initializing all bitfields in ValueObject's constructors.
+  // FIXME: This could be done via default initializers once we have C++20.
+  struct Bitflags {
+    bool m_value_is_valid : 1, m_value_did_change : 1,
+        m_children_count_valid : 1, m_old_value_valid : 1,
+        m_is_deref_of_parent : 1, m_is_array_item_for_pointer : 1,
+        m_is_bitfield_for_scalar : 1, m_is_child_at_offset : 1,
+        m_is_getting_summary : 1, m_did_calculate_complete_objc_class_type : 1,
+        m_is_synthetic_children_generated : 1;
+    Bitflags() {
+      m_value_is_valid = false;
+      m_value_did_change = false;
+      m_children_count_valid = false;
+      m_old_value_valid = false;
+      m_is_deref_of_parent = false;
+      m_is_array_item_for_pointer = false;
+      m_is_bitfield_for_scalar = false;
+      m_is_child_at_offset = false;
+      m_is_getting_summary = false;
+      m_did_calculate_complete_objc_class_type = false;
+      m_is_synthetic_children_generated = false;
+    }
+  } m_flags;
+
+  friend class ValueObjectChild;
+  friend class ExpressionVariable; // For SetName
+  friend class Target;             // For SetName
+  friend class ValueObjectConstResultImpl;
+  friend class ValueObjectSynthetic; // For ClearUserVisibleData
+
+  /// Use this constructor to create a "root variable object".  The ValueObject
+  /// will be locked to this context through-out its lifespan.
+  ValueObject(ExecutionContextScope *exe_scope, ValueObjectManager &manager,
+              AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad);
+
+  /// Use this constructor to create a ValueObject owned by another ValueObject.
+  /// It will inherit the ExecutionContext of its parent.
+  ValueObject(ValueObject &parent);
+
+  ValueObjectManager *GetManager() { return m_manager; }
+
+  virtual bool UpdateValue() = 0;
+
+  virtual LazyBool CanUpdateWithInvalidExecutionContext() {
+    return eLazyBoolCalculate;
+  }
+
+  virtual void CalculateDynamicValue(lldb::DynamicValueType use_dynamic);
+
+  virtual lldb::DynamicValueType GetDynamicValueTypeImpl() {
+    return lldb::eNoDynamicValues;
+  }
+
+  virtual bool HasDynamicValueTypeInfo() { return false; }
+
+  virtual void CalculateSyntheticValue();
+
+  /// Should only be called by ValueObject::GetChildAtIndex().
+  ///
+  /// \return A ValueObject managed by this ValueObject's manager.
+  virtual ValueObject *CreateChildAtIndex(size_t idx);
+
+  /// Should only be called by ValueObject::GetSyntheticArrayMember().
+  ///
+  /// \return A ValueObject managed by this ValueObject's manager.
+  virtual ValueObject *CreateSyntheticArrayMember(size_t idx);
+
+  /// Should only be called by ValueObject::GetNumChildren().
+  virtual llvm::Expected<uint32_t>
+  CalculateNumChildren(uint32_t max = UINT32_MAX) = 0;
+
+  void SetNumChildren(uint32_t num_children);
+
+  void SetValueDidChange(bool value_changed) {
+    m_flags.m_value_did_change = value_changed;
+  }
+
+  void SetValueIsValid(bool valid) { m_flags.m_value_is_valid = valid; }
+
+  void ClearUserVisibleData(
+      uint32_t items = ValueObject::eClearUserVisibleDataItemsAllStrings);
+
+  void AddSyntheticChild(ConstString key, ValueObject *valobj);
+
+  DataExtractor &GetDataExtractor();
+
+  void ClearDynamicTypeInformation();
+
+  // Subclasses must implement the functions below.
+
+  virtual CompilerType GetCompilerTypeImpl() = 0;
+
+  const char *GetLocationAsCStringImpl(const Value &value,
+                                       const DataExtractor &data);
+
+  bool IsChecksumEmpty() { return m_value_checksum.empty(); }
+
+  void SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType);
+
+protected:
+  virtual void DoUpdateChildrenAddressType(ValueObject &valobj) {};
+
+private:
+  virtual CompilerType MaybeCalculateCompleteType();
+  void UpdateChildrenAddressType() {
+    GetRoot()->DoUpdateChildrenAddressType(*this);
+  }
+
+  lldb::ValueObjectSP GetValueForExpressionPath_Impl(
+      llvm::StringRef expression_cstr,
+      ExpressionPathScanEndReason *reason_to_stop,
+      ExpressionPathEndResultType *final_value_type,
+      const GetValueForExpressionPathOptions &options,
+      ExpressionPathAftermath *final_task_on_target);
+
+  ValueObject(const ValueObject &) = delete;
+  const ValueObject &operator=(const ValueObject &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECT_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectCast.h b/lldb/include/lldb/ValueObject/ValueObjectCast.h
new file mode 100644
index 00000000000000..9d174ae5ca609d
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectCast.h
@@ -0,0 +1,66 @@
+//===-- ValueObjectCast.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_VALUEOBJECTCAST_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTCAST_H
+
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/ValueObject/ValueObject.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+
+namespace lldb_private {
+class ConstString;
+
+/// A ValueObject that represents a given value represented as a different type.
+class ValueObjectCast : public ValueObject {
+public:
+  ~ValueObjectCast() override;
+
+  static lldb::ValueObjectSP Create(ValueObject &parent, ConstString name,
+                                    const CompilerType &cast_type);
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  lldb::ValueType GetValueType() const override;
+
+  bool IsInScope() override;
+
+  ValueObject *GetParent() override {
+    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
+  }
+
+  const ValueObject *GetParent() const override {
+    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
+  }
+
+protected:
+  ValueObjectCast(ValueObject &parent, ConstString name,
+                  const CompilerType &cast_type);
+
+  bool UpdateValue() override;
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  CompilerType m_cast_type;
+
+private:
+  ValueObjectCast(const ValueObjectCast &) = delete;
+  const ValueObjectCast &operator=(const ValueObjectCast &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTCAST_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectChild.h b/lldb/include/lldb/ValueObject/ValueObjectChild.h
new file mode 100644
index 00000000000000..e8c974a3a10a76
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectChild.h
@@ -0,0 +1,91 @@
+//===-- ValueObjectChild.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_VALUEOBJECTCHILD_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTCHILD_H
+
+#include "lldb/ValueObject/ValueObject.h"
+
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+
+namespace lldb_private {
+
+/// A child of another ValueObject.
+class ValueObjectChild : public ValueObject {
+public:
+  ~ValueObjectChild() override;
+
+  std::optional<uint64_t> GetByteSize() override { return m_byte_size; }
+
+  lldb::offset_t GetByteOffset() override { return m_byte_offset; }
+
+  uint32_t GetBitfieldBitSize() override { return m_bitfield_bit_size; }
+
+  uint32_t GetBitfieldBitOffset() override { return m_bitfield_bit_offset; }
+
+  lldb::ValueType GetValueType() const override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  ConstString GetTypeName() override;
+
+  ConstString GetQualifiedTypeName() override;
+
+  ConstString GetDisplayTypeName() override;
+
+  bool IsInScope() override;
+
+  bool IsBaseClass() override { return m_is_base_class; }
+
+  bool IsDereferenceOfParent() override { return m_is_deref_of_parent; }
+
+protected:
+  bool UpdateValue() override;
+
+  LazyBool CanUpdateWithInvalidExecutionContext() override;
+
+  CompilerType GetCompilerTypeImpl() override { return m_compiler_type; }
+
+  CompilerType m_compiler_type;
+  ConstString m_type_name;
+  uint64_t m_byte_size;
+  int32_t m_byte_offset;
+  uint8_t m_bitfield_bit_size;
+  uint8_t m_bitfield_bit_offset;
+  bool m_is_base_class;
+  bool m_is_deref_of_parent;
+  std::optional<LazyBool> m_can_update_with_invalid_exe_ctx;
+
+  friend class ValueObject;
+  friend class ValueObjectConstResult;
+  friend class ValueObjectConstResultImpl;
+  friend class ValueObjectVTable;
+
+  ValueObjectChild(ValueObject &parent, const CompilerType &compiler_type,
+                   ConstString name, uint64_t byte_size, int32_t byte_offset,
+                   uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
+                   bool is_base_class, bool is_deref_of_parent,
+                   AddressType child_ptr_or_ref_addr_type,
+                   uint64_t language_flags);
+
+  ValueObjectChild(const ValueObjectChild &) = delete;
+  const ValueObjectChild &operator=(const ValueObjectChild &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTCHILD_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResult.h b/lldb/include/lldb/ValueObject/ValueObjectConstResult.h
new file mode 100644
index 00000000000000..e4ed1f399bf6bd
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectConstResult.h
@@ -0,0 +1,166 @@
+//===-- ValueObjectConstResult.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_VALUEOBJECTCONSTRESULT_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULT_H
+
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/ValueObject/ValueObject.h"
+#include "lldb/ValueObject/ValueObjectConstResultImpl.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+
+namespace lldb_private {
+class DataExtractor;
+class ExecutionContextScope;
+class Module;
+
+/// A frozen ValueObject copied into host memory.
+class ValueObjectConstResult : public ValueObject {
+public:
+  ~ValueObjectConstResult() override;
+
+  static lldb::ValueObjectSP
+  Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order,
+         uint32_t addr_byte_size, lldb::addr_t address = LLDB_INVALID_ADDRESS);
+
+  static lldb::ValueObjectSP
+  Create(ExecutionContextScope *exe_scope, const CompilerType &compiler_type,
+         ConstString name, const DataExtractor &data,
+         lldb::addr_t address = LLDB_INVALID_ADDRESS);
+
+  static lldb::ValueObjectSP
+  Create(ExecutionContextScope *exe_scope, const CompilerType &compiler_type,
+         ConstString name, const lldb::DataBufferSP &result_data_sp,
+         lldb::ByteOrder byte_order, uint32_t addr_size,
+         lldb::addr_t address = LLDB_INVALID_ADDRESS);
+
+  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
+                                    const CompilerType &compiler_type,
+                                    ConstString name, lldb::addr_t address,
+                                    AddressType address_type,
+                                    uint32_t addr_byte_size);
+
+  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
+                                    Value &value, ConstString name,
+                                    Module *module = nullptr);
+
+  // When an expression fails to evaluate, we return an error
+  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
+                                    Status &&error);
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  lldb::ValueType GetValueType() const override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  ConstString GetTypeName() override;
+
+  ConstString GetDisplayTypeName() override;
+
+  bool IsInScope() override;
+
+  void SetByteSize(size_t size);
+
+  lldb::ValueObjectSP Dereference(Status &error) override;
+
+  lldb::ValueObjectSP GetSyntheticChildAtOffset(
+      uint32_t offset, const CompilerType &type, bool can_create,
+      ConstString name_const_str = ConstString()) override;
+
+  lldb::ValueObjectSP AddressOf(Status &error) override;
+
+  lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
+                            AddressType *address_type = nullptr) override;
+
+  size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
+                        uint32_t item_count = 1) override;
+
+  lldb::addr_t GetLiveAddress() override { return m_impl.GetLiveAddress(); }
+
+  void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
+                      AddressType address_type = eAddressTypeLoad) override {
+    m_impl.SetLiveAddress(addr, address_type);
+  }
+
+  lldb::ValueObjectSP
+  GetDynamicValue(lldb::DynamicValueType valueType) override;
+
+  lldb::LanguageType GetPreferredDisplayLanguage() override;
+
+  lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
+
+protected:
+  bool UpdateValue() override;
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  ConstString m_type_name;
+  std::optional<uint64_t> m_byte_size;
+
+  ValueObjectConstResultImpl m_impl;
+
+private:
+  friend class ValueObjectConstResultImpl;
+
+  ValueObjectConstResult(ExecutionContextScope *exe_scope,
+                         ValueObjectManager &manager,
+                         lldb::ByteOrder byte_order, uint32_t addr_byte_size,
+                         lldb::addr_t address);
+
+  ValueObjectConstResult(ExecutionContextScope *exe_scope,
+                         ValueObjectManager &manager,
+                         const CompilerType &compiler_type, ConstString name,
+                         const DataExtractor &data, lldb::addr_t address);
+
+  ValueObjectConstResult(ExecutionContextScope *exe_scope,
+                         ValueObjectManager &manager,
+                         const CompilerType &compiler_type, ConstString name,
+                         const lldb::DataBufferSP &result_data_sp,
+                         lldb::ByteOrder byte_order, uint32_t addr_size,
+                         lldb::addr_t address);
+
+  ValueObjectConstResult(ExecutionContextScope *exe_scope,
+                         ValueObjectManager &manager,
+                         const CompilerType &compiler_type, ConstString name,
+                         lldb::addr_t address, AddressType address_type,
+                         uint32_t addr_byte_size);
+
+  ValueObjectConstResult(ExecutionContextScope *exe_scope,
+                         ValueObjectManager &manager, const Value &value,
+                         ConstString name, Module *module = nullptr);
+
+  ValueObjectConstResult(ExecutionContextScope *exe_scope,
+                         ValueObjectManager &manager, Status &&error);
+
+  ValueObject *CreateChildAtIndex(size_t idx) override {
+    return m_impl.CreateChildAtIndex(idx);
+  }
+  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
+    return m_impl.CreateSyntheticArrayMember(idx);
+  }
+
+  ValueObjectConstResult(const ValueObjectConstResult &) = delete;
+  const ValueObjectConstResult &
+  operator=(const ValueObjectConstResult &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULT_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultCast.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultCast.h
new file mode 100644
index 00000000000000..e786467eae6e26
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectConstResultCast.h
@@ -0,0 +1,75 @@
+//===-- ValueObjectConstResultCast.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_VALUEOBJECTCONSTRESULTCAST_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTCAST_H
+
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/ValueObject/ValueObjectCast.h"
+#include "lldb/ValueObject/ValueObjectConstResultImpl.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+#include <cstddef>
+#include <cstdint>
+
+namespace lldb_private {
+class DataExtractor;
+class Status;
+class ValueObject;
+
+class ValueObjectConstResultCast : public ValueObjectCast {
+public:
+  ValueObjectConstResultCast(ValueObject &parent, ConstString name,
+                             const CompilerType &cast_type,
+                             lldb::addr_t live_address = LLDB_INVALID_ADDRESS);
+
+  ~ValueObjectConstResultCast() override;
+
+  lldb::ValueObjectSP Dereference(Status &error) override;
+
+  virtual CompilerType GetCompilerType() {
+    return ValueObjectCast::GetCompilerType();
+  }
+
+  lldb::ValueObjectSP GetSyntheticChildAtOffset(
+      uint32_t offset, const CompilerType &type, bool can_create,
+      ConstString name_const_str = ConstString()) override;
+
+  lldb::ValueObjectSP AddressOf(Status &error) override;
+
+  size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
+                        uint32_t item_count = 1) override;
+
+  lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
+
+protected:
+  ValueObjectConstResultImpl m_impl;
+
+private:
+  friend class ValueObject;
+  friend class ValueObjectConstResult;
+  friend class ValueObjectConstResultImpl;
+
+  ValueObject *CreateChildAtIndex(size_t idx) override {
+    return m_impl.CreateChildAtIndex(idx);
+  }
+  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
+    return m_impl.CreateSyntheticArrayMember(idx);
+  }
+
+  ValueObjectConstResultCast(const ValueObjectConstResultCast &) = delete;
+  const ValueObjectConstResultCast &
+  operator=(const ValueObjectConstResultCast &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTCAST_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
new file mode 100644
index 00000000000000..ad97b885684ee5
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectConstResultChild.h
@@ -0,0 +1,81 @@
+//===-- ValueObjectConstResultChild.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_VALUEOBJECTCONSTRESULTCHILD_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTCHILD_H
+
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/ValueObject/ValueObjectChild.h"
+#include "lldb/ValueObject/ValueObjectConstResultImpl.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+#include <cstddef>
+#include <cstdint>
+
+namespace lldb_private {
+class DataExtractor;
+class Status;
+class ValueObject;
+
+// A child of a ValueObjectConstResult.
+class ValueObjectConstResultChild : public ValueObjectChild {
+public:
+  ValueObjectConstResultChild(
+      ValueObject &parent, const CompilerType &compiler_type, ConstString name,
+      uint32_t byte_size, int32_t byte_offset, uint32_t bitfield_bit_size,
+      uint32_t bitfield_bit_offset, bool is_base_class, bool is_deref_of_parent,
+      lldb::addr_t live_address, uint64_t language_flags);
+
+  ~ValueObjectConstResultChild() override;
+
+  lldb::ValueObjectSP Dereference(Status &error) override;
+
+  virtual CompilerType GetCompilerType() {
+    return ValueObjectChild::GetCompilerType();
+  }
+
+  lldb::ValueObjectSP GetSyntheticChildAtOffset(
+      uint32_t offset, const CompilerType &type, bool can_create,
+      ConstString name_const_str = ConstString()) override;
+
+  lldb::ValueObjectSP AddressOf(Status &error) override;
+
+  lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
+                            AddressType *address_type = nullptr) override;
+
+  size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
+                        uint32_t item_count = 1) override;
+
+  lldb::ValueObjectSP DoCast(const CompilerType &compiler_type) override;
+
+protected:
+  ValueObjectConstResultImpl m_impl;
+
+private:
+  friend class ValueObject;
+  friend class ValueObjectConstResult;
+  friend class ValueObjectConstResultImpl;
+
+  ValueObject *CreateChildAtIndex(size_t idx) override {
+    return m_impl.CreateChildAtIndex(idx);
+  }
+  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
+    return m_impl.CreateSyntheticArrayMember(idx);
+  }
+
+  ValueObjectConstResultChild(const ValueObjectConstResultChild &) = delete;
+  const ValueObjectConstResultChild &
+  operator=(const ValueObjectConstResultChild &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTCHILD_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
new file mode 100644
index 00000000000000..dbd68160acb4dc
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectConstResultImpl.h
@@ -0,0 +1,80 @@
+//===-- ValueObjectConstResultImpl.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_VALUEOBJECTCONSTRESULTIMPL_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTIMPL_H
+
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
+
+#include <cstddef>
+#include <cstdint>
+namespace lldb_private {
+class CompilerType;
+class DataExtractor;
+class Status;
+class ValueObject;
+} // namespace lldb_private
+
+namespace lldb_private {
+
+/// A class wrapping common implementation details for operations in
+/// ValueObjectConstResult ( & Child ) that may need to jump from the host
+/// memory space into the target's memory space.
+class ValueObjectConstResultImpl {
+public:
+  ValueObjectConstResultImpl(ValueObject *valobj,
+                             lldb::addr_t live_address = LLDB_INVALID_ADDRESS);
+
+  virtual ~ValueObjectConstResultImpl() = default;
+
+  lldb::ValueObjectSP Dereference(Status &error);
+
+  ValueObject *CreateChildAtIndex(size_t idx);
+  ValueObject *CreateSyntheticArrayMember(size_t idx);
+
+  lldb::ValueObjectSP
+  GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type,
+                            bool can_create,
+                            ConstString name_const_str = ConstString());
+
+  lldb::ValueObjectSP AddressOf(Status &error);
+
+  lldb::addr_t GetLiveAddress() { return m_live_address; }
+
+  lldb::ValueObjectSP Cast(const CompilerType &compiler_type);
+
+  void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
+                      AddressType address_type = eAddressTypeLoad) {
+    m_live_address = addr;
+    m_live_address_type = address_type;
+  }
+
+  virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
+                                    AddressType *address_type = nullptr);
+
+  virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
+                                uint32_t item_count = 1);
+
+private:
+  ValueObject *m_impl_backend;
+  lldb::addr_t m_live_address;
+  AddressType m_live_address_type;
+  lldb::ValueObjectSP m_address_of_backend;
+
+  ValueObjectConstResultImpl(const ValueObjectConstResultImpl &) = delete;
+  const ValueObjectConstResultImpl &
+  operator=(const ValueObjectConstResultImpl &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTCONSTRESULTIMPL_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectDynamicValue.h b/lldb/include/lldb/ValueObject/ValueObjectDynamicValue.h
new file mode 100644
index 00000000000000..145a46e2955667
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectDynamicValue.h
@@ -0,0 +1,129 @@
+//===-- ValueObjectDynamicValue.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_VALUEOBJECTDYNAMICVALUE_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTDYNAMICVALUE_H
+
+#include "lldb/Core/Address.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/ValueObject/ValueObject.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+
+namespace lldb_private {
+class DataExtractor;
+class Declaration;
+class Status;
+
+/// A ValueObject that represents memory at a given address, viewed as some
+/// set lldb type.
+class ValueObjectDynamicValue : public ValueObject {
+public:
+  ~ValueObjectDynamicValue() override = default;
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  ConstString GetTypeName() override;
+
+  ConstString GetQualifiedTypeName() override;
+
+  ConstString GetDisplayTypeName() override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  lldb::ValueType GetValueType() const override;
+
+  bool IsInScope() override;
+
+  bool IsDynamic() override { return true; }
+
+  bool IsBaseClass() override {
+    if (m_parent)
+      return m_parent->IsBaseClass();
+    return false;
+  }
+
+  bool GetIsConstant() const override { return false; }
+
+  ValueObject *GetParent() override {
+    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
+  }
+
+  const ValueObject *GetParent() const override {
+    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
+  }
+
+  lldb::ValueObjectSP GetStaticValue() override { return m_parent->GetSP(); }
+
+  bool SetValueFromCString(const char *value_str, Status &error) override;
+
+  bool SetData(DataExtractor &data, Status &error) override;
+
+  TypeImpl GetTypeImpl() override;
+
+  lldb::VariableSP GetVariable() override {
+    return m_parent ? m_parent->GetVariable() : nullptr;
+  }
+
+  lldb::LanguageType GetPreferredDisplayLanguage() override;
+
+  void SetPreferredDisplayLanguage(lldb::LanguageType);
+
+  bool IsSyntheticChildrenGenerated() override;
+
+  void SetSyntheticChildrenGenerated(bool b) override;
+
+  bool GetDeclaration(Declaration &decl) override;
+
+  uint64_t GetLanguageFlags() override;
+
+  void SetLanguageFlags(uint64_t flags) override;
+
+protected:
+  bool UpdateValue() override;
+
+  LazyBool CanUpdateWithInvalidExecutionContext() override {
+    return eLazyBoolYes;
+  }
+
+  lldb::DynamicValueType GetDynamicValueTypeImpl() override {
+    return m_use_dynamic;
+  }
+
+  bool HasDynamicValueTypeInfo() override { return true; }
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  Address m_address; ///< The variable that this value object is based upon
+  TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name
+  lldb::DynamicValueType m_use_dynamic;
+  TypeImpl m_type_impl;
+
+private:
+  friend class ValueObject;
+  friend class ValueObjectConstResult;
+  ValueObjectDynamicValue(ValueObject &parent,
+                          lldb::DynamicValueType use_dynamic);
+
+  ValueObjectDynamicValue(const ValueObjectDynamicValue &) = delete;
+  const ValueObjectDynamicValue &
+  operator=(const ValueObjectDynamicValue &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTDYNAMICVALUE_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectList.h b/lldb/include/lldb/ValueObject/ValueObjectList.h
new file mode 100644
index 00000000000000..5d63c65a96e5f3
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectList.h
@@ -0,0 +1,63 @@
+//===-- ValueObjectList.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_VALUEOBJECTLIST_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTLIST_H
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+#include <vector>
+
+#include <cstddef>
+
+namespace lldb_private {
+class ValueObject;
+
+/// A collection of ValueObject values that.
+class ValueObjectList {
+public:
+  const ValueObjectList &operator=(const ValueObjectList &rhs);
+
+  void Append(const lldb::ValueObjectSP &val_obj_sp);
+
+  void Append(const ValueObjectList &valobj_list);
+
+  lldb::ValueObjectSP FindValueObjectByPointer(ValueObject *valobj);
+
+  size_t GetSize() const;
+
+  void Resize(size_t size);
+
+  lldb::ValueObjectSP GetValueObjectAtIndex(size_t idx);
+
+  lldb::ValueObjectSP RemoveValueObjectAtIndex(size_t idx);
+
+  void SetValueObjectAtIndex(size_t idx, const lldb::ValueObjectSP &valobj_sp);
+
+  lldb::ValueObjectSP FindValueObjectByValueName(const char *name);
+
+  lldb::ValueObjectSP FindValueObjectByUID(lldb::user_id_t uid);
+
+  void Swap(ValueObjectList &value_object_list);
+
+  void Clear() { m_value_objects.clear(); }
+
+  const std::vector<lldb::ValueObjectSP> &GetObjects() const {
+    return m_value_objects;
+  }
+
+protected:
+  typedef std::vector<lldb::ValueObjectSP> collection;
+  // Classes that inherit from ValueObjectList can see and modify these
+  collection m_value_objects;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTLIST_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectMemory.h b/lldb/include/lldb/ValueObject/ValueObjectMemory.h
new file mode 100644
index 00000000000000..cfc36d0d610dba
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectMemory.h
@@ -0,0 +1,82 @@
+//===-- ValueObjectMemory.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_VALUEOBJECTMEMORY_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTMEMORY_H
+
+#include "lldb/Core/Address.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/ValueObject/ValueObject.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+
+namespace lldb_private {
+class ExecutionContextScope;
+
+/// A ValueObject that represents memory at a given address, viewed as some
+/// set lldb type.
+class ValueObjectMemory : public ValueObject {
+public:
+  ~ValueObjectMemory() override;
+
+  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
+                                    llvm::StringRef name,
+                                    const Address &address,
+                                    lldb::TypeSP &type_sp);
+
+  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
+                                    llvm::StringRef name,
+                                    const Address &address,
+                                    const CompilerType &ast_type);
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  ConstString GetTypeName() override;
+
+  ConstString GetDisplayTypeName() override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  lldb::ValueType GetValueType() const override;
+
+  bool IsInScope() override;
+
+  lldb::ModuleSP GetModule() override;
+
+protected:
+  bool UpdateValue() override;
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  Address m_address; ///< The variable that this value object is based upon
+  lldb::TypeSP m_type_sp;
+  CompilerType m_compiler_type;
+
+private:
+  ValueObjectMemory(ExecutionContextScope *exe_scope,
+                    ValueObjectManager &manager, llvm::StringRef name,
+                    const Address &address, lldb::TypeSP &type_sp);
+
+  ValueObjectMemory(ExecutionContextScope *exe_scope,
+                    ValueObjectManager &manager, llvm::StringRef name,
+                    const Address &address, const CompilerType &ast_type);
+  // For ValueObject only
+  ValueObjectMemory(const ValueObjectMemory &) = delete;
+  const ValueObjectMemory &operator=(const ValueObjectMemory &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTMEMORY_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectRegister.h b/lldb/include/lldb/ValueObject/ValueObjectRegister.h
new file mode 100644
index 00000000000000..fafbfd0341115c
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectRegister.h
@@ -0,0 +1,143 @@
+//===-- ValueObjectRegister.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_VALUEOBJECTREGISTER_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTREGISTER_H
+
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/ValueObject/ValueObject.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-types.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+
+namespace lldb_private {
+class DataExtractor;
+class Status;
+class ExecutionContextScope;
+class Scalar;
+class Stream;
+
+class ValueObjectRegisterSet : public ValueObject {
+public:
+  ~ValueObjectRegisterSet() override;
+
+  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
+                                    lldb::RegisterContextSP &reg_ctx_sp,
+                                    uint32_t set_idx);
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  lldb::ValueType GetValueType() const override {
+    return lldb::eValueTypeRegisterSet;
+  }
+
+  ConstString GetTypeName() override;
+
+  ConstString GetQualifiedTypeName() override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
+                                             bool can_create = true) override;
+
+  size_t GetIndexOfChildWithName(llvm::StringRef name) override;
+
+protected:
+  bool UpdateValue() override;
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  lldb::RegisterContextSP m_reg_ctx_sp;
+  const RegisterSet *m_reg_set;
+  uint32_t m_reg_set_idx;
+
+private:
+  friend class ValueObjectRegisterContext;
+
+  ValueObjectRegisterSet(ExecutionContextScope *exe_scope,
+                         ValueObjectManager &manager,
+                         lldb::RegisterContextSP &reg_ctx_sp, uint32_t set_idx);
+
+  ValueObject *CreateChildAtIndex(size_t idx) override;
+  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
+    return nullptr;
+  }
+
+  // For ValueObject only
+  ValueObjectRegisterSet(const ValueObjectRegisterSet &) = delete;
+  const ValueObjectRegisterSet &
+  operator=(const ValueObjectRegisterSet &) = delete;
+};
+
+class ValueObjectRegister : public ValueObject {
+public:
+  ~ValueObjectRegister() override;
+
+  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
+                                    lldb::RegisterContextSP &reg_ctx_sp,
+                                    const RegisterInfo *reg_info);
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  lldb::ValueType GetValueType() const override {
+    return lldb::eValueTypeRegister;
+  }
+
+  ConstString GetTypeName() override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  bool SetValueFromCString(const char *value_str, Status &error) override;
+
+  bool SetData(DataExtractor &data, Status &error) override;
+
+  bool ResolveValue(Scalar &scalar) override;
+
+  void
+  GetExpressionPath(Stream &s,
+                    GetExpressionPathFormat epformat =
+                        eGetExpressionPathFormatDereferencePointers) override;
+
+protected:
+  bool UpdateValue() override;
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  lldb::RegisterContextSP m_reg_ctx_sp;
+  RegisterInfo m_reg_info;
+  RegisterValue m_reg_value;
+  ConstString m_type_name;
+  CompilerType m_compiler_type;
+
+private:
+  void ConstructObject(const RegisterInfo *reg_info);
+
+  friend class ValueObjectRegisterSet;
+
+  ValueObjectRegister(ValueObject &parent, lldb::RegisterContextSP &reg_ctx_sp,
+                      const RegisterInfo *reg_info);
+  ValueObjectRegister(ExecutionContextScope *exe_scope,
+                      ValueObjectManager &manager,
+                      lldb::RegisterContextSP &reg_ctx_sp,
+                      const RegisterInfo *reg_info);
+
+  // For ValueObject only
+  ValueObjectRegister(const ValueObjectRegister &) = delete;
+  const ValueObjectRegister &operator=(const ValueObjectRegister &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTREGISTER_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectSyntheticFilter.h b/lldb/include/lldb/ValueObject/ValueObjectSyntheticFilter.h
new file mode 100644
index 00000000000000..2811658fd8f1f4
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectSyntheticFilter.h
@@ -0,0 +1,179 @@
+//===-- ValueObjectSyntheticFilter.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_VALUEOBJECTSYNTHETICFILTER_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTSYNTHETICFILTER_H
+
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/ValueObject/ValueObject.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+
+#include <cstddef>
+
+namespace lldb_private {
+class Declaration;
+class Status;
+class SyntheticChildrenFrontEnd;
+
+/// A ValueObject that obtains its children from some source other than
+/// real information.
+/// This is currently used to implement Python-based children and filters but
+/// you can bind it to any source of synthetic information and have it behave
+/// accordingly.
+class ValueObjectSynthetic : public ValueObject {
+public:
+  ~ValueObjectSynthetic() override;
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  ConstString GetTypeName() override;
+
+  ConstString GetQualifiedTypeName() override;
+
+  ConstString GetDisplayTypeName() override;
+
+  bool MightHaveChildren() override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  lldb::ValueType GetValueType() const override;
+
+  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx,
+                                      bool can_create = true) override;
+
+  lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name,
+                                             bool can_create = true) override;
+
+  size_t GetIndexOfChildWithName(llvm::StringRef name) override;
+
+  lldb::ValueObjectSP
+  GetDynamicValue(lldb::DynamicValueType valueType) override;
+
+  bool IsInScope() override;
+
+  bool HasSyntheticValue() override { return false; }
+
+  bool IsSynthetic() override { return true; }
+
+  void CalculateSyntheticValue() override {}
+
+  bool IsDynamic() override {
+    return ((m_parent != nullptr) ? m_parent->IsDynamic() : false);
+  }
+
+  lldb::ValueObjectSP GetStaticValue() override {
+    return ((m_parent != nullptr) ? m_parent->GetStaticValue() : GetSP());
+  }
+
+  virtual lldb::DynamicValueType GetDynamicValueType() {
+    return ((m_parent != nullptr) ? m_parent->GetDynamicValueType()
+                                  : lldb::eNoDynamicValues);
+  }
+
+  lldb::VariableSP GetVariable() override {
+    return m_parent != nullptr ? m_parent->GetVariable() : nullptr;
+  }
+
+  ValueObject *GetParent() override {
+    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
+  }
+
+  const ValueObject *GetParent() const override {
+    return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr);
+  }
+
+  lldb::ValueObjectSP GetNonSyntheticValue() override;
+
+  bool CanProvideValue() override;
+
+  bool DoesProvideSyntheticValue() override {
+    return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes);
+  }
+
+  bool GetIsConstant() const override { return false; }
+
+  bool SetValueFromCString(const char *value_str, Status &error) override;
+
+  void SetFormat(lldb::Format format) override;
+
+  lldb::LanguageType GetPreferredDisplayLanguage() override;
+
+  void SetPreferredDisplayLanguage(lldb::LanguageType);
+
+  bool IsSyntheticChildrenGenerated() override;
+
+  void SetSyntheticChildrenGenerated(bool b) override;
+
+  bool GetDeclaration(Declaration &decl) override;
+
+  uint64_t GetLanguageFlags() override;
+
+  void SetLanguageFlags(uint64_t flags) override;
+
+protected:
+  bool UpdateValue() override;
+
+  LazyBool CanUpdateWithInvalidExecutionContext() override {
+    return eLazyBoolYes;
+  }
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  virtual void CreateSynthFilter();
+
+  // we need to hold on to the SyntheticChildren because someone might delete
+  // the type binding while we are alive
+  lldb::SyntheticChildrenSP m_synth_sp;
+  std::unique_ptr<SyntheticChildrenFrontEnd> m_synth_filter_up;
+
+  typedef std::map<uint32_t, ValueObject *> ByIndexMap;
+  typedef std::map<const char *, uint32_t> NameToIndexMap;
+  typedef std::vector<lldb::ValueObjectSP> SyntheticChildrenCache;
+
+  typedef ByIndexMap::iterator ByIndexIterator;
+  typedef NameToIndexMap::iterator NameToIndexIterator;
+
+  std::mutex m_child_mutex;
+  /// Guarded by m_child_mutex;
+  ByIndexMap m_children_byindex;
+  /// Guarded by m_child_mutex;
+  NameToIndexMap m_name_toindex;
+  /// Guarded by m_child_mutex;
+  SyntheticChildrenCache m_synthetic_children_cache;
+
+  // FIXME: use the ValueObject's  ChildrenManager instead of a special purpose
+  // solution.
+  uint32_t m_synthetic_children_count;
+
+  ConstString m_parent_type_name;
+
+  LazyBool m_might_have_children;
+
+  LazyBool m_provides_value;
+
+private:
+  friend class ValueObject;
+  ValueObjectSynthetic(ValueObject &parent, lldb::SyntheticChildrenSP filter);
+
+  void CopyValueData(ValueObject *source);
+
+  ValueObjectSynthetic(const ValueObjectSynthetic &) = delete;
+  const ValueObjectSynthetic &operator=(const ValueObjectSynthetic &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTSYNTHETICFILTER_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectUpdater.h b/lldb/include/lldb/ValueObject/ValueObjectUpdater.h
new file mode 100644
index 00000000000000..3f1d887b47a7b6
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectUpdater.h
@@ -0,0 +1,43 @@
+//===-- ValueObjectUpdater.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_VALUEOBJECTUPDATER_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTUPDATER_H
+
+#include "lldb/ValueObject/ValueObject.h"
+
+namespace lldb_private {
+
+/// A value object class that is seeded with the static variable value
+/// and it vends the user facing value object. If the type is dynamic it can
+/// vend the dynamic type. If this user type also has a synthetic type
+/// associated with it, it will vend the synthetic type. The class watches the
+/// process' stop ID and will update the user type when needed.
+class ValueObjectUpdater {
+  /// The root value object is the static typed variable object.
+  lldb::ValueObjectSP m_root_valobj_sp;
+  /// The user value object is the value object the user wants to see.
+  lldb::ValueObjectSP m_user_valobj_sp;
+  /// The stop ID that m_user_valobj_sp is valid for.
+  uint32_t m_stop_id = UINT32_MAX;
+
+public:
+  ValueObjectUpdater(lldb::ValueObjectSP in_valobj_sp);
+
+  /// Gets the correct value object from the root object for a given process
+  /// stop ID. If dynamic values are enabled, or if synthetic children are
+  /// enabled, the value object that the user wants to see might change while
+  /// debugging.
+  lldb::ValueObjectSP GetSP();
+
+  lldb::ProcessSP GetProcessSP() const;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTUPDATER_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectVTable.h b/lldb/include/lldb/ValueObject/ValueObjectVTable.h
new file mode 100644
index 00000000000000..9cf13be093a8db
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectVTable.h
@@ -0,0 +1,107 @@
+//===-- ValueObjectVTable.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_VALUEOBJECTVTABLE_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTVTABLE_H
+
+#include "lldb/ValueObject/ValueObject.h"
+
+namespace lldb_private {
+
+/// A class that represents a virtual function table for a C++ class.
+///
+/// ValueObject::GetError() will be in the success state if this value
+/// represents a C++ class with a vtable, or an appropriate error describing
+/// that the object isn't a C++ class with a vtable or not a C++ class.
+///
+/// ValueObject::GetName() will be the demangled symbol name for the virtual
+/// function table like "vtable for <classname>".
+///
+/// ValueObject::GetValueAsCString() will be the address of the first vtable
+/// entry if the current ValueObject is a class with a vtable, or nothing the
+/// current ValueObject is not a C++ class or not a C++ class that has a
+/// vtable.
+///
+/// ValueObject::GetValueAtUnsigned(...) will return the address of the first
+/// vtable entry.
+///
+/// ValueObject::GetAddressOf() will return the address of the vtable pointer
+/// found in the parent ValueObject.
+///
+/// ValueObject::GetNumChildren() will return the number of virtual function
+/// pointers in the vtable, or zero on error.
+///
+/// ValueObject::GetChildAtIndex(...) will return each virtual function pointer
+/// as a ValueObject object.
+///
+/// The child ValueObjects will have the following values:
+///
+/// ValueObject::GetError() will indicate success if the vtable entry was
+/// successfully read from memory, or an error if not.
+///
+/// ValueObject::GetName() will be the vtable function index in the form "[%u]"
+/// where %u is the index.
+///
+/// ValueObject::GetValueAsCString() will be the virtual function pointer value
+///
+/// ValueObject::GetValueAtUnsigned(...) will return the virtual function
+/// pointer value.
+///
+/// ValueObject::GetAddressOf() will return the address of the virtual function
+/// pointer.
+///
+/// ValueObject::GetNumChildren() returns 0
+class ValueObjectVTable : public ValueObject {
+public:
+  ~ValueObjectVTable() override;
+
+  static lldb::ValueObjectSP Create(ValueObject &parent);
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  lldb::ValueType GetValueType() const override;
+
+  ConstString GetTypeName() override;
+
+  ConstString GetQualifiedTypeName() override;
+
+  ConstString GetDisplayTypeName() override;
+
+  bool IsInScope() override;
+
+protected:
+  bool UpdateValue() override;
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  /// The symbol for the C++ virtual function table.
+  const Symbol *m_vtable_symbol = nullptr;
+  /// Cache the number of vtable children when we update the value.
+  uint32_t m_num_vtable_entries = 0;
+  /// Cache the address size in bytes to avoid checking with the process to
+  /// many times.
+  uint32_t m_addr_size = 0;
+
+private:
+  ValueObjectVTable(ValueObject &parent);
+
+  ValueObject *CreateChildAtIndex(size_t idx) override;
+  ValueObject *CreateSyntheticArrayMember(size_t idx) override {
+    return nullptr;
+  }
+
+  // For ValueObject only
+  ValueObjectVTable(const ValueObjectVTable &) = delete;
+  const ValueObjectVTable &operator=(const ValueObjectVTable &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTVTABLE_H
diff --git a/lldb/include/lldb/ValueObject/ValueObjectVariable.h b/lldb/include/lldb/ValueObject/ValueObjectVariable.h
new file mode 100644
index 00000000000000..9f66af808425ab
--- /dev/null
+++ b/lldb/include/lldb/ValueObject/ValueObjectVariable.h
@@ -0,0 +1,93 @@
+//===-- ValueObjectVariable.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_VALUEOBJECTVARIABLE_H
+#define LLDB_VALUEOBJECT_VALUEOBJECTVARIABLE_H
+
+#include "lldb/ValueObject/ValueObject.h"
+
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+
+namespace lldb_private {
+class DataExtractor;
+class Declaration;
+class Status;
+class ExecutionContextScope;
+class SymbolContextScope;
+
+/// A ValueObject that contains a root variable that may or may not
+/// have children.
+class ValueObjectVariable : public ValueObject {
+public:
+  ~ValueObjectVariable() override;
+
+  static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
+                                    const lldb::VariableSP &var_sp);
+
+  std::optional<uint64_t> GetByteSize() override;
+
+  ConstString GetTypeName() override;
+
+  ConstString GetQualifiedTypeName() override;
+
+  ConstString GetDisplayTypeName() override;
+
+  llvm::Expected<uint32_t> CalculateNumChildren(uint32_t max) override;
+
+  lldb::ValueType GetValueType() const override;
+
+  bool IsInScope() override;
+
+  lldb::ModuleSP GetModule() override;
+
+  SymbolContextScope *GetSymbolContextScope() override;
+
+  bool GetDeclaration(Declaration &decl) override;
+
+  const char *GetLocationAsCString() override;
+
+  bool SetValueFromCString(const char *value_str, Status &error) override;
+
+  bool SetData(DataExtractor &data, Status &error) override;
+
+  lldb::VariableSP GetVariable() override { return m_variable_sp; }
+
+protected:
+  bool UpdateValue() override;
+
+  void DoUpdateChildrenAddressType(ValueObject &valobj) override;
+
+  CompilerType GetCompilerTypeImpl() override;
+
+  /// The variable that this value object is based upon.
+  lldb::VariableSP m_variable_sp;
+  ///< The value that DWARFExpression resolves this variable to before we patch
+  ///< it up.
+  Value m_resolved_value;
+
+private:
+  ValueObjectVariable(ExecutionContextScope *exe_scope,
+                      ValueObjectManager &manager,
+                      const lldb::VariableSP &var_sp);
+  // For ValueObject only
+  ValueObjectVariable(const ValueObjectVariable &) = delete;
+  const ValueObjectVariable &operator=(const ValueObjectVariable &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_VALUEOBJECT_VALUEOBJECTVARIABLE_H

>From f56c01986b6dc47d3e12ad02a57ada06603d4abb Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Tue, 4 Feb 2025 11:35:39 -0800
Subject: [PATCH 10/10] Remove unneeded include file & unused m_eof_token.

---
 lldb/include/lldb/ValueObject/DILLexer.h | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index fa0b5338834d78..e1182da5b20ab2 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -12,7 +12,6 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
 #include <cstdint>
-#include <limits.h>
 #include <memory>
 #include <string>
 #include <vector>
@@ -103,7 +102,7 @@ class DILLexer {
 private:
   DILLexer(llvm::StringRef dil_expr, std::vector<Token> lexed_tokens)
       : m_expr(dil_expr), m_lexed_tokens(std::move(lexed_tokens)),
-        m_tokens_idx(0), m_eof_token(Token(Token::eof, "", 0)) {}
+        m_tokens_idx(0) {}
 
   static llvm::Expected<Token> Lex(llvm::StringRef expr,
                                    llvm::StringRef &remainder);
@@ -117,9 +116,6 @@ class DILLexer {
   // Index into m_lexed_tokens; indicates which token the DIL parser is
   // currently trying to parse/handle.
   uint32_t m_tokens_idx;
-
-  // "eof" token; to be returned by lexer when 'look ahead' fails.
-  Token m_eof_token;
 };
 
 } // namespace lldb_private::dil



More information about the lldb-commits mailing list