add way to get the address of variable
This commit is contained in:
@@ -1824,14 +1824,16 @@ std::optional<std::pair<uint16_t, size_t>>
|
|||||||
return check_single_res_changed(std::move(res_node));
|
return check_single_res_changed(std::move(res_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res_idx = this->build_nodes_for_var(var, data_res);
|
auto res_idx = this->build_nodes_for_var(var, data_res,
|
||||||
|
info.address_of_or_pointer);
|
||||||
if (!res_idx)
|
if (!res_idx)
|
||||||
{
|
{
|
||||||
return check_single_res_changed(std::move(res_node));
|
return check_single_res_changed(std::move(res_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Got res for %s: %u (%u)\n", info.expr_path.c_str(), *res_idx,
|
spdlog::trace(
|
||||||
_data_res[*res_idx]->node.type_id.type);
|
"Got res for {}: {} ({})", info.expr_path, *res_idx,
|
||||||
|
static_cast<uint8_t>(_data_res[*res_idx]->node.type_id.type));
|
||||||
res_node.success = true;
|
res_node.success = true;
|
||||||
res_node.children.push_back(*res_idx);
|
res_node.children.push_back(*res_idx);
|
||||||
return check_single_res_changed(std::move(res_node));
|
return check_single_res_changed(std::move(res_node));
|
||||||
@@ -2133,7 +2135,7 @@ std::optional<std::pair<uint16_t, size_t>>
|
|||||||
}
|
}
|
||||||
printf("Got local %s\n", name);
|
printf("Got local %s\n", name);
|
||||||
|
|
||||||
auto res_idx = this->build_nodes_for_var(var, data_res);
|
auto res_idx = this->build_nodes_for_var(var, data_res, false);
|
||||||
if (!res_idx)
|
if (!res_idx)
|
||||||
{
|
{
|
||||||
printf("No result\n");
|
printf("No result\n");
|
||||||
@@ -2958,7 +2960,8 @@ bool LLDBBackend::is_type_equal(data::type_info::TypeID type_id,
|
|||||||
|
|
||||||
std::optional<dbgui::data::result::NodeIdx>
|
std::optional<dbgui::data::result::NodeIdx>
|
||||||
LLDBBackend::build_nodes_for_var(lldb::SBValue &val,
|
LLDBBackend::build_nodes_for_var(lldb::SBValue &val,
|
||||||
std::vector<data::result::Node> &to_send)
|
std::vector<data::result::Node> &to_send,
|
||||||
|
bool address_of_or_pointer)
|
||||||
{
|
{
|
||||||
using namespace lldb;
|
using namespace lldb;
|
||||||
using namespace data;
|
using namespace data;
|
||||||
@@ -2983,7 +2986,8 @@ std::optional<dbgui::data::result::NodeIdx>
|
|||||||
for (auto i = 0; i < _var_cache.size(); ++i)
|
for (auto i = 0; i < _var_cache.size(); ++i)
|
||||||
{
|
{
|
||||||
auto &entry = _var_cache[i];
|
auto &entry = _var_cache[i];
|
||||||
if (!entry.global_or_static)
|
if (!entry.global_or_static
|
||||||
|
|| entry.address_of_or_pointer != address_of_or_pointer)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3012,7 +3016,8 @@ std::optional<dbgui::data::result::NodeIdx>
|
|||||||
for (auto i = 0; i < _var_cache.size(); ++i)
|
for (auto i = 0; i < _var_cache.size(); ++i)
|
||||||
{
|
{
|
||||||
auto &entry = _var_cache[i];
|
auto &entry = _var_cache[i];
|
||||||
if (entry.global_or_static)
|
if (entry.global_or_static
|
||||||
|
|| entry.address_of_or_pointer != address_of_or_pointer)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3084,12 +3089,14 @@ std::optional<dbgui::data::result::NodeIdx>
|
|||||||
}
|
}
|
||||||
auto node_idx = *_var_cache[*cache_entry].cached_node;
|
auto node_idx = *_var_cache[*cache_entry].cached_node;
|
||||||
_var_cache[*cache_entry].used = true;
|
_var_cache[*cache_entry].used = true;
|
||||||
this->build_nodes_for_var_cached(val, node_idx, to_send);
|
this->build_nodes_for_var_cached(val, node_idx, to_send,
|
||||||
|
address_of_or_pointer);
|
||||||
|
|
||||||
return node_idx;
|
return node_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto idx = this->build_nodes_for_var_uncached(val, to_send);
|
auto idx =
|
||||||
|
this->build_nodes_for_var_uncached(val, to_send, address_of_or_pointer);
|
||||||
_var_cache.push_back(
|
_var_cache.push_back(
|
||||||
VarCacheEntry{.lldb_val = val,
|
VarCacheEntry{.lldb_val = val,
|
||||||
.sym_ctx = val.GetFrame().GetSymbolContext(true),
|
.sym_ctx = val.GetFrame().GetSymbolContext(true),
|
||||||
@@ -3101,7 +3108,8 @@ std::optional<dbgui::data::result::NodeIdx>
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached(
|
dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached(
|
||||||
lldb::SBValue &val, std::vector<data::result::Node> &to_send)
|
lldb::SBValue &val, std::vector<data::result::Node> &to_send,
|
||||||
|
bool address_of_or_pointer)
|
||||||
{
|
{
|
||||||
auto lldb_type = val.GetType();
|
auto lldb_type = val.GetType();
|
||||||
auto type_id = this->build_type_from_lldb_type(lldb_type);
|
auto type_id = this->build_type_from_lldb_type(lldb_type);
|
||||||
@@ -3131,45 +3139,77 @@ dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached(
|
|||||||
|
|
||||||
// TODO: error handling
|
// TODO: error handling
|
||||||
auto err = lldb::SBError{};
|
auto err = lldb::SBError{};
|
||||||
switch (no_alias_type.type)
|
if (address_of_or_pointer)
|
||||||
{
|
{
|
||||||
using enum data::type_info::Type;
|
if (no_alias_type.type == data::type_info::Type::ptr)
|
||||||
|
|
||||||
case _bool:
|
|
||||||
case u8:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt8(err, 0));
|
|
||||||
break;
|
|
||||||
case u16:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt16(err, 0));
|
|
||||||
break;
|
|
||||||
case u32:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt32(err, 0));
|
|
||||||
break;
|
|
||||||
case u64:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt64(err, 0));
|
|
||||||
break;
|
|
||||||
case i8:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt8(err, 0));
|
|
||||||
break;
|
|
||||||
case i16:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt16(err, 0));
|
|
||||||
break;
|
|
||||||
case i32:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt32(err, 0));
|
|
||||||
break;
|
|
||||||
case i64:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt64(err, 0));
|
|
||||||
break;
|
|
||||||
case f32: res_node.data = var_data.GetFloat(err, 0); break;
|
|
||||||
case f64: res_node.data = var_data.GetDouble(err, 0); break;
|
|
||||||
default:
|
|
||||||
{
|
{
|
||||||
res_node.data = std::vector<uint8_t>{};
|
res_node.data = static_cast<uint64_t>(var_data.GetAddress(err, 0));
|
||||||
auto &vec = res_node.vec_data();
|
} else
|
||||||
auto size = var_data.GetByteSize();
|
{
|
||||||
vec.resize(size);
|
// so we don't need to create a new type for the pointer i think so just replace the node type
|
||||||
var_data.ReadRawData(err, 0, vec.data(), size);
|
res_node.type_id =
|
||||||
break;
|
data::type_info::TypeID{.type = data::type_info::Type::ptr,
|
||||||
|
.sub_type = type_id.type,
|
||||||
|
.idx = type_id.idx};
|
||||||
|
auto addr_of = val.AddressOf();
|
||||||
|
auto data = addr_of.GetData();
|
||||||
|
if (!data.IsValid())
|
||||||
|
{
|
||||||
|
// copypasted from above
|
||||||
|
to_send.push_back(res_node);
|
||||||
|
_data_res[res_idx] =
|
||||||
|
CachedDataRes{.node = std::move(res_node),
|
||||||
|
.no_delete_on_src_delete = true,
|
||||||
|
.src_id = std::numeric_limits<size_t>::max()};
|
||||||
|
return res_idx;
|
||||||
|
}
|
||||||
|
res_node.data = static_cast<uint64_t>(data.GetAddress(err, 0));
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
switch (no_alias_type.type)
|
||||||
|
{
|
||||||
|
using enum data::type_info::Type;
|
||||||
|
|
||||||
|
case _bool:
|
||||||
|
case u8:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt8(err, 0));
|
||||||
|
break;
|
||||||
|
case u16:
|
||||||
|
res_node.data =
|
||||||
|
static_cast<uint64_t>(var_data.GetUnsignedInt16(err, 0));
|
||||||
|
break;
|
||||||
|
case u32:
|
||||||
|
res_node.data =
|
||||||
|
static_cast<uint64_t>(var_data.GetUnsignedInt32(err, 0));
|
||||||
|
break;
|
||||||
|
case u64:
|
||||||
|
res_node.data =
|
||||||
|
static_cast<uint64_t>(var_data.GetUnsignedInt64(err, 0));
|
||||||
|
break;
|
||||||
|
case i8:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt8(err, 0));
|
||||||
|
break;
|
||||||
|
case i16:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt16(err, 0));
|
||||||
|
break;
|
||||||
|
case i32:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt32(err, 0));
|
||||||
|
break;
|
||||||
|
case i64:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt64(err, 0));
|
||||||
|
break;
|
||||||
|
case f32: res_node.data = var_data.GetFloat(err, 0); break;
|
||||||
|
case f64: res_node.data = var_data.GetDouble(err, 0); break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
res_node.data = std::vector<uint8_t>{};
|
||||||
|
auto &vec = res_node.vec_data();
|
||||||
|
auto size = var_data.GetByteSize();
|
||||||
|
vec.resize(size);
|
||||||
|
var_data.ReadRawData(err, 0, vec.data(), size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3188,7 +3228,7 @@ dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached(
|
|||||||
|
|
||||||
void LLDBBackend::build_nodes_for_var_cached(
|
void LLDBBackend::build_nodes_for_var_cached(
|
||||||
lldb::SBValue &val, data::result::NodeIdx cache_idx,
|
lldb::SBValue &val, data::result::NodeIdx cache_idx,
|
||||||
std::vector<data::result::Node> &to_send)
|
std::vector<data::result::Node> &to_send, bool address_of_or_pointer)
|
||||||
{
|
{
|
||||||
auto lldb_type = val.GetType();
|
auto lldb_type = val.GetType();
|
||||||
// auto type_id = this->build_type_from_lldb_type(lldb_type);
|
// auto type_id = this->build_type_from_lldb_type(lldb_type);
|
||||||
@@ -3216,47 +3256,81 @@ void LLDBBackend::build_nodes_for_var_cached(
|
|||||||
_types[no_alias_type.idx]->second.member_types);
|
_types[no_alias_type.idx]->second.member_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this is copypasted from build_nodes_for_var_uncached so that should be consolidated in the future
|
||||||
// TODO: error handling
|
// TODO: error handling
|
||||||
auto err = lldb::SBError{};
|
auto err = lldb::SBError{};
|
||||||
switch (no_alias_type.type)
|
|
||||||
{
|
|
||||||
using enum data::type_info::Type;
|
|
||||||
|
|
||||||
case _bool:
|
if (address_of_or_pointer)
|
||||||
case u8:
|
{
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt8(err, 0));
|
if (no_alias_type.type == data::type_info::Type::ptr)
|
||||||
break;
|
|
||||||
case u16:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt16(err, 0));
|
|
||||||
break;
|
|
||||||
case u32:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt32(err, 0));
|
|
||||||
break;
|
|
||||||
case u64:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt64(err, 0));
|
|
||||||
break;
|
|
||||||
case i8:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt8(err, 0));
|
|
||||||
break;
|
|
||||||
case i16:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt16(err, 0));
|
|
||||||
break;
|
|
||||||
case i32:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt32(err, 0));
|
|
||||||
break;
|
|
||||||
case i64:
|
|
||||||
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt64(err, 0));
|
|
||||||
break;
|
|
||||||
case f32: res_node.data = var_data.GetFloat(err, 0); break;
|
|
||||||
case f64: res_node.data = var_data.GetDouble(err, 0); break;
|
|
||||||
default:
|
|
||||||
{
|
{
|
||||||
res_node.data = std::vector<uint8_t>{};
|
res_node.data = static_cast<uint64_t>(var_data.GetAddress(err, 0));
|
||||||
auto &vec = res_node.vec_data();
|
} else
|
||||||
auto size = var_data.GetByteSize();
|
{
|
||||||
vec.resize(size);
|
// so we don't need to create a new type for the pointer i think so just replace the node type
|
||||||
var_data.ReadRawData(err, 0, vec.data(), size);
|
res_node.type_id =
|
||||||
break;
|
data::type_info::TypeID{.type = data::type_info::Type::ptr,
|
||||||
|
.sub_type = type_id.type,
|
||||||
|
.idx = type_id.idx};
|
||||||
|
auto addr_of = val.AddressOf();
|
||||||
|
auto data = addr_of.GetData();
|
||||||
|
if (!data.IsValid())
|
||||||
|
{
|
||||||
|
// copypasted from above
|
||||||
|
if (_data_res[cache_idx]->node.success)
|
||||||
|
{
|
||||||
|
to_send.push_back(res_node);
|
||||||
|
_data_res[cache_idx]->node.success = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res_node.data = static_cast<uint64_t>(data.GetAddress(err, 0));
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
switch (no_alias_type.type)
|
||||||
|
{
|
||||||
|
using enum data::type_info::Type;
|
||||||
|
|
||||||
|
case _bool:
|
||||||
|
case u8:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt8(err, 0));
|
||||||
|
break;
|
||||||
|
case u16:
|
||||||
|
res_node.data =
|
||||||
|
static_cast<uint64_t>(var_data.GetUnsignedInt16(err, 0));
|
||||||
|
break;
|
||||||
|
case u32:
|
||||||
|
res_node.data =
|
||||||
|
static_cast<uint64_t>(var_data.GetUnsignedInt32(err, 0));
|
||||||
|
break;
|
||||||
|
case u64:
|
||||||
|
res_node.data =
|
||||||
|
static_cast<uint64_t>(var_data.GetUnsignedInt64(err, 0));
|
||||||
|
break;
|
||||||
|
case i8:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt8(err, 0));
|
||||||
|
break;
|
||||||
|
case i16:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt16(err, 0));
|
||||||
|
break;
|
||||||
|
case i32:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt32(err, 0));
|
||||||
|
break;
|
||||||
|
case i64:
|
||||||
|
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt64(err, 0));
|
||||||
|
break;
|
||||||
|
case f32: res_node.data = var_data.GetFloat(err, 0); break;
|
||||||
|
case f64: res_node.data = var_data.GetDouble(err, 0); break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
res_node.data = std::vector<uint8_t>{};
|
||||||
|
auto &vec = res_node.vec_data();
|
||||||
|
auto size = var_data.GetByteSize();
|
||||||
|
vec.resize(size);
|
||||||
|
var_data.ReadRawData(err, 0, vec.data(), size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ namespace dbgui::backend
|
|||||||
bool used;
|
bool used;
|
||||||
bool
|
bool
|
||||||
global_or_static; // need to only compare compilation unit and module
|
global_or_static; // need to only compare compilation unit and module
|
||||||
|
bool address_of_or_pointer;
|
||||||
std::optional<data::result::NodeIdx> cached_node;
|
std::optional<data::result::NodeIdx> cached_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,13 +136,16 @@ namespace dbgui::backend
|
|||||||
|
|
||||||
std::optional<data::result::NodeIdx>
|
std::optional<data::result::NodeIdx>
|
||||||
build_nodes_for_var(lldb::SBValue &val,
|
build_nodes_for_var(lldb::SBValue &val,
|
||||||
std::vector<data::result::Node> &to_send);
|
std::vector<data::result::Node> &to_send,
|
||||||
|
bool address_of_or_pointer);
|
||||||
data::result::NodeIdx
|
data::result::NodeIdx
|
||||||
build_nodes_for_var_uncached(lldb::SBValue &,
|
build_nodes_for_var_uncached(lldb::SBValue &,
|
||||||
std::vector<data::result::Node> &to_send);
|
std::vector<data::result::Node> &to_send,
|
||||||
|
bool address_of_or_pointer);
|
||||||
void build_nodes_for_var_cached(lldb::SBValue &,
|
void build_nodes_for_var_cached(lldb::SBValue &,
|
||||||
data::result::NodeIdx cache_idx,
|
data::result::NodeIdx cache_idx,
|
||||||
std::vector<data::result::Node> &to_send);
|
std::vector<data::result::Node> &to_send,
|
||||||
|
bool address_of_or_pointer);
|
||||||
|
|
||||||
void clear_unused_vars_from_cache();
|
void clear_unused_vars_from_cache();
|
||||||
|
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ namespace dbgui::data
|
|||||||
Type type;
|
Type type;
|
||||||
TypeID enum_base;
|
TypeID enum_base;
|
||||||
uint64_t byte_size;
|
uint64_t byte_size;
|
||||||
|
// TODO: maybe we want a string array somewhere else? Harder to garbage collect but we save some space here
|
||||||
std::string display_name;
|
std::string display_name;
|
||||||
std::string internal_name;
|
std::string internal_name;
|
||||||
// sike, lldb doesnt give this to us
|
// sike, lldb doesnt give this to us
|
||||||
@@ -324,6 +325,8 @@ namespace dbgui::data
|
|||||||
struct Variable
|
struct Variable
|
||||||
{
|
{
|
||||||
std::string expr_path;
|
std::string expr_path;
|
||||||
|
// if this is set we want the address of whatever we got or the pointer value in case what we have is a pointer
|
||||||
|
bool address_of_or_pointer = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
|
|||||||
@@ -1119,13 +1119,15 @@ bool WatchWindow::draw(Frontend &frontend)
|
|||||||
if (slot.buf[0] != '\0')
|
if (slot.buf[0] != '\0')
|
||||||
{
|
{
|
||||||
frontend.target->backend->remove_data_node(slot.id);
|
frontend.target->backend->remove_data_node(slot.id);
|
||||||
|
|
||||||
using namespace data::source;
|
using namespace data::source;
|
||||||
frontend.target->backend->add_data_node(Node{
|
frontend.target->backend->add_data_node(
|
||||||
.id = slot.id,
|
Node{.id = slot.id,
|
||||||
.type = Node::Type::source,
|
.type = Node::Type::source,
|
||||||
.data =
|
.data = Source{.type = Source::Type::variable,
|
||||||
Source{.type = Source::Type::variable,
|
.data = Source::Variable{
|
||||||
.data = Source::Variable{.expr_path = slot.buf}}});
|
.expr_path = slot.buf,
|
||||||
|
.address_of_or_pointer = false}}});
|
||||||
}
|
}
|
||||||
|
|
||||||
slot.bak = slot.buf;
|
slot.bak = slot.buf;
|
||||||
@@ -1172,14 +1174,23 @@ bool WatchWindow::draw(Frontend &frontend)
|
|||||||
{
|
{
|
||||||
if (this->add_slot_buf[0] != '\0')
|
if (this->add_slot_buf[0] != '\0')
|
||||||
{
|
{
|
||||||
auto id = frontend.target->data_node_id++;
|
auto id = frontend.target->data_node_id++;
|
||||||
|
const auto *expr_path_buf = this->add_slot_buf;
|
||||||
|
bool address_of_or_pointer = false;
|
||||||
|
if (expr_path_buf[0] == '+')
|
||||||
|
{
|
||||||
|
address_of_or_pointer = true;
|
||||||
|
++expr_path_buf;
|
||||||
|
}
|
||||||
|
|
||||||
using namespace data::source;
|
using namespace data::source;
|
||||||
frontend.target->backend->add_data_node(Node{
|
frontend.target->backend->add_data_node(Node{
|
||||||
.id = id,
|
.id = id,
|
||||||
.type = Node::Type::source,
|
.type = Node::Type::source,
|
||||||
.data =
|
.data = Source{.type = Source::Type::variable,
|
||||||
Source{.type = Source::Type::variable,
|
.data = Source::Variable{.expr_path = expr_path_buf,
|
||||||
.data = Source::Variable{.expr_path = this->add_slot_buf}}});
|
.address_of_or_pointer =
|
||||||
|
address_of_or_pointer}}});
|
||||||
extra_slots.push_back(ExtraSlot{.id = id, .bak = this->add_slot_buf});
|
extra_slots.push_back(ExtraSlot{.id = id, .bak = this->add_slot_buf});
|
||||||
memcpy(extra_slots.back().buf, this->add_slot_buf,
|
memcpy(extra_slots.back().buf, this->add_slot_buf,
|
||||||
sizeof(this->add_slot_buf));
|
sizeof(this->add_slot_buf));
|
||||||
@@ -1402,8 +1413,11 @@ void WatchWindow::draw_value(Frontend &frontend,
|
|||||||
for (size_t i = 0; i < el_count; ++i)
|
for (size_t i = 0; i < el_count; ++i)
|
||||||
{
|
{
|
||||||
std::snprintf(buf, sizeof(buf), "[%lu]", i);
|
std::snprintf(buf, sizeof(buf), "[%lu]", i);
|
||||||
|
auto expr_path_size = expr_path.size();
|
||||||
|
expr_path.back().array_idx = i;
|
||||||
this->draw_value(frontend, member_ty_id, buf, node_idx,
|
this->draw_value(frontend, member_ty_id, buf, node_idx,
|
||||||
off + member_off, expr_path);
|
off + member_off, expr_path);
|
||||||
|
assert(expr_path.size() == expr_path_size);
|
||||||
member_off += member_size;
|
member_off += member_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -139,8 +139,9 @@ namespace dbgui::frontend
|
|||||||
struct ExprPathPart
|
struct ExprPathPart
|
||||||
{
|
{
|
||||||
std::string_view ident;
|
std::string_view ident;
|
||||||
bool deref = false;
|
bool deref = false;
|
||||||
bool array = false;
|
bool array = false;
|
||||||
|
uint64_t array_idx = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool draw(Frontend &);
|
bool draw(Frontend &);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct MyType {
|
struct MyType {
|
||||||
int data;
|
int data[3];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11,11 +11,11 @@ void helper_fn();
|
|||||||
void helper_fn2();
|
void helper_fn2();
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
MyType tmp = MyType{10};
|
MyType tmp = MyType{{10, 5, 19}};
|
||||||
while (tmp.data != 0) {
|
while (tmp.data[0] != 0) {
|
||||||
helper_fn();
|
helper_fn();
|
||||||
helper_fn2();
|
helper_fn2();
|
||||||
tmp.data--;
|
tmp.data[0]--;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user