Make CompilerType::getBitSize() / getByteSize() return an optional result. NFC
The code in LLDB assumes that CompilerType and friends use the size 0
as a sentinel value to signal an error. This works for C++, where no
zero-sized type exists, but in many other programming languages
(including I believe C) types of size zero are possible and even
common. This is a particular pain point in swift-lldb, where extra
code exists to double-check that a type is *really* of size zero and
not an error at various locations.
To remedy this situation, this patch starts by converting
CompilerType::getBitSize() and getByteSize() to return an optional
result. To avoid wasting space, I hand-rolled my own optional data
type assuming that no type is larger than what fits into 63
bits. Follow-up patches would make similar changes to the ValueObject
hierarchy.
rdar://problem/47178964
Differential Revision: https://reviews.llvm.org/D56688
llvm-svn: 351214
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index b0dd04a..1965d70 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -756,10 +756,12 @@
ExecutionContext exe_ctx(GetExecutionContextRef());
- const uint64_t item_type_size = pointee_or_element_compiler_type.GetByteSize(
+ auto item_type_size = pointee_or_element_compiler_type.GetByteSize(
exe_ctx.GetBestExecutionContextScope());
- const uint64_t bytes = item_count * item_type_size;
- const uint64_t offset = item_idx * item_type_size;
+ if (!item_type_size)
+ return 0;
+ const uint64_t bytes = item_count * *item_type_size;
+ const uint64_t offset = item_idx * *item_type_size;
if (item_idx == 0 && item_count == 1) // simply a deref
{
@@ -822,10 +824,10 @@
}
} break;
case eAddressTypeHost: {
- const uint64_t max_bytes =
+ auto max_bytes =
GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
- if (max_bytes > offset) {
- size_t bytes_read = std::min<uint64_t>(max_bytes - offset, bytes);
+ if (max_bytes && *max_bytes > offset) {
+ size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);
addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
break;
@@ -1818,14 +1820,15 @@
return synthetic_child_sp;
if (!can_create)
- return ValueObjectSP();
+ return {};
ExecutionContext exe_ctx(GetExecutionContextRef());
-
- ValueObjectChild *synthetic_child = new ValueObjectChild(
- *this, type, name_const_str,
- type.GetByteSize(exe_ctx.GetBestExecutionContextScope()), offset, 0, 0,
- false, false, eAddressTypeInvalid, 0);
+ auto size = type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
+ if (!size)
+ return {};
+ ValueObjectChild *synthetic_child =
+ new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
+ false, false, eAddressTypeInvalid, 0);
if (synthetic_child) {
AddSyntheticChild(name_const_str, synthetic_child);
synthetic_child_sp = synthetic_child->GetSP();
@@ -1856,16 +1859,17 @@
return synthetic_child_sp;
if (!can_create)
- return ValueObjectSP();
+ return {};
const bool is_base_class = true;
ExecutionContext exe_ctx(GetExecutionContextRef());
-
- ValueObjectChild *synthetic_child = new ValueObjectChild(
- *this, type, name_const_str,
- type.GetByteSize(exe_ctx.GetBestExecutionContextScope()), offset, 0, 0,
- is_base_class, false, eAddressTypeInvalid, 0);
+ auto size = type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
+ if (!size)
+ return {};
+ ValueObjectChild *synthetic_child =
+ new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
+ is_base_class, false, eAddressTypeInvalid, 0);
if (synthetic_child) {
AddSyntheticChild(name_const_str, synthetic_child);
synthetic_child_sp = synthetic_child->GetSP();