Skip to content

Commit 1370a1c

Browse files
committed
[lldb] Add support for negative integer to {SB,}StructuredData
This patch refactors the `StructuredData::Integer` class to make it templated, makes it private and adds 2 public specialization for both `int64_t` & `uint64_t` with a public type aliases, respectively `SignedInteger` & `UnsignedInteger`. It adds new getter for signed and unsigned interger values to the `StructuredData::Object` base class and changes the implementation of `StructuredData::Array::GetItemAtIndexAsInteger` and `StructuredData::Dictionary::GetValueForKeyAsInteger` to support signed and unsigned integers. This patch also adds 2 new `Get{Signed,Unsigned}IntegerValue` to the `SBStructuredData` class and marks `GetIntegerValue` as deprecated. Finally, this patch audits all the caller of `StructuredData::Integer` or `StructuredData::GetIntegerValue` to use the proper type as well the various tests that uses `SBStructuredData.GetIntegerValue`. rdar://105575764 Differential Revision: https://reviews.llvm.org/D150485 Signed-off-by: Med Ismail Bennani <[email protected]>
1 parent 01c5ec3 commit 1370a1c

37 files changed

+365
-185
lines changed

lldb/include/lldb/API/SBStructuredData.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class SBStructuredData {
5757

5858
/// Fill keys with the keys in this object and return true if this data
5959
/// structure is a dictionary. Returns false otherwise.
60-
bool GetKeys(lldb::SBStringList &keys) const;
60+
bool GetKeys(lldb::SBStringList &keys) const;
6161

6262
/// Return the value corresponding to a key if this data structure
6363
/// is a dictionary type.
@@ -68,6 +68,12 @@ class SBStructuredData {
6868
lldb::SBStructuredData GetItemAtIndex(size_t idx) const;
6969

7070
/// Return the integer value if this data structure is an integer type.
71+
uint64_t GetUnsignedIntegerValue(uint64_t fail_value = 0) const;
72+
/// Return the integer value if this data structure is an integer type.
73+
int64_t GetSignedIntegerValue(int64_t fail_value = 0) const;
74+
75+
LLDB_DEPRECATED("Specify if the value is signed or unsigned",
76+
"uint64_t GetUnsignedIntegerValue(uint64_t fail_value = 0)")
7177
uint64_t GetIntegerValue(uint64_t fail_value = 0) const;
7278

7379
/// Return the floating point value if this data structure is a floating

lldb/include/lldb/Core/StructuredDataImpl.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,13 @@ class StructuredDataImpl {
129129
}
130130

131131
uint64_t GetIntegerValue(uint64_t fail_value = 0) const {
132-
return (m_data_sp ? m_data_sp->GetIntegerValue(fail_value) : fail_value);
132+
return (m_data_sp ? m_data_sp->GetUnsignedIntegerValue(fail_value)
133+
: fail_value);
134+
}
135+
136+
int64_t GetIntegerValue(int64_t fail_value = 0) const {
137+
return (m_data_sp ? m_data_sp->GetSignedIntegerValue(fail_value)
138+
: fail_value);
133139
}
134140

135141
double GetFloatValue(double fail_value = 0.0) const {

lldb/include/lldb/Utility/StructuredData.h

Lines changed: 96 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <string>
2727
#include <type_traits>
2828
#include <utility>
29+
#include <variant>
2930
#include <vector>
3031

3132
namespace lldb_private {
@@ -48,10 +49,13 @@ namespace lldb_private {
4849
/// that may be present.
4950

5051
class StructuredData {
52+
template <typename N> class Integer;
53+
5154
public:
5255
class Object;
5356
class Array;
54-
class Integer;
57+
using UnsignedInteger = Integer<uint64_t>;
58+
using SignedInteger = Integer<int64_t>;
5559
class Float;
5660
class Boolean;
5761
class String;
@@ -60,13 +64,16 @@ class StructuredData {
6064

6165
typedef std::shared_ptr<Object> ObjectSP;
6266
typedef std::shared_ptr<Array> ArraySP;
63-
typedef std::shared_ptr<Integer> IntegerSP;
67+
typedef std::shared_ptr<UnsignedInteger> UnsignedIntegerSP;
68+
typedef std::shared_ptr<SignedInteger> SignedIntegerSP;
6469
typedef std::shared_ptr<Float> FloatSP;
6570
typedef std::shared_ptr<Boolean> BooleanSP;
6671
typedef std::shared_ptr<String> StringSP;
6772
typedef std::shared_ptr<Dictionary> DictionarySP;
6873
typedef std::shared_ptr<Generic> GenericSP;
6974

75+
typedef std::variant<UnsignedIntegerSP, SignedIntegerSP> IntegerSP;
76+
7077
class Object : public std::enable_shared_from_this<Object> {
7178
public:
7279
Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid)
@@ -94,14 +101,28 @@ class StructuredData {
94101
: nullptr);
95102
}
96103

97-
Integer *GetAsInteger() {
98-
return ((m_type == lldb::eStructuredDataTypeInteger)
99-
? static_cast<Integer *>(this)
104+
UnsignedInteger *GetAsUnsignedInteger() {
105+
// NOTE: For backward compatibility, eStructuredDataTypeInteger is
106+
// the same as eStructuredDataTypeUnsignedInteger.
107+
return ((m_type == lldb::eStructuredDataTypeInteger ||
108+
m_type == lldb::eStructuredDataTypeUnsignedInteger)
109+
? static_cast<UnsignedInteger *>(this)
110+
: nullptr);
111+
}
112+
113+
SignedInteger *GetAsSignedInteger() {
114+
return ((m_type == lldb::eStructuredDataTypeSignedInteger)
115+
? static_cast<SignedInteger *>(this)
100116
: nullptr);
101117
}
102118

103-
uint64_t GetIntegerValue(uint64_t fail_value = 0) {
104-
Integer *integer = GetAsInteger();
119+
uint64_t GetUnsignedIntegerValue(uint64_t fail_value = 0) {
120+
UnsignedInteger *integer = GetAsUnsignedInteger();
121+
return ((integer != nullptr) ? integer->GetValue() : fail_value);
122+
}
123+
124+
int64_t GetSignedIntegerValue(int64_t fail_value = 0) {
125+
SignedInteger *integer = GetAsSignedInteger();
105126
return ((integer != nullptr) ? integer->GetValue() : fail_value);
106127
}
107128

@@ -202,9 +223,16 @@ class StructuredData {
202223
bool GetItemAtIndexAsInteger(size_t idx, IntType &result) const {
203224
ObjectSP value_sp = GetItemAtIndex(idx);
204225
if (value_sp.get()) {
205-
if (auto int_value = value_sp->GetAsInteger()) {
206-
result = static_cast<IntType>(int_value->GetValue());
207-
return true;
226+
if constexpr (std::numeric_limits<IntType>::is_signed) {
227+
if (auto signed_value = value_sp->GetAsSignedInteger()) {
228+
result = static_cast<IntType>(signed_value->GetValue());
229+
return true;
230+
}
231+
} else {
232+
if (auto unsigned_value = value_sp->GetAsUnsignedInteger()) {
233+
result = static_cast<IntType>(unsigned_value->GetValue());
234+
return true;
235+
}
208236
}
209237
}
210238
return false;
@@ -281,6 +309,26 @@ class StructuredData {
281309

282310
void AddItem(const ObjectSP &item) { m_items.push_back(item); }
283311

312+
template <typename T> void AddIntegerItem(T value) {
313+
static_assert(std::is_integral<T>::value ||
314+
std::is_floating_point<T>::value,
315+
"value type should be integral");
316+
if constexpr (std::numeric_limits<T>::is_signed)
317+
AddItem(std::make_shared<SignedInteger>(value));
318+
else
319+
AddItem(std::make_shared<UnsignedInteger>(value));
320+
}
321+
322+
void AddFloatItem(double value) { AddItem(std::make_shared<Float>(value)); }
323+
324+
void AddStringItem(llvm::StringRef value) {
325+
AddItem(std::make_shared<String>(std::move(value)));
326+
}
327+
328+
void AddBooleanItem(bool value) {
329+
AddItem(std::make_shared<Boolean>(value));
330+
}
331+
284332
void Serialize(llvm::json::OStream &s) const override;
285333

286334
void GetDescription(lldb_private::Stream &s) const override;
@@ -290,25 +338,36 @@ class StructuredData {
290338
collection m_items;
291339
};
292340

293-
class Integer : public Object {
294-
public:
295-
Integer(uint64_t i = 0)
296-
: Object(lldb::eStructuredDataTypeInteger), m_value(i) {}
341+
private:
342+
template <typename N> class Integer : public Object {
343+
static_assert(std::is_integral<N>::value, "N must be an integral type");
297344

345+
public:
346+
Integer(N i = 0)
347+
: Object(std::numeric_limits<N>::is_signed
348+
? lldb::eStructuredDataTypeSignedInteger
349+
: lldb::eStructuredDataTypeUnsignedInteger),
350+
m_value(i) {}
298351
~Integer() override = default;
299352

300-
void SetValue(uint64_t value) { m_value = value; }
353+
void SetValue(N value) { m_value = value; }
301354

302-
uint64_t GetValue() { return m_value; }
355+
N GetValue() { return m_value; }
303356

304-
void Serialize(llvm::json::OStream &s) const override;
357+
void Serialize(llvm::json::OStream &s) const override {
358+
s.value(static_cast<N>(m_value));
359+
}
305360

306-
void GetDescription(lldb_private::Stream &s) const override;
361+
void GetDescription(lldb_private::Stream &s) const override {
362+
s.Printf(std::numeric_limits<N>::is_signed ? "%" PRId64 : "%" PRIu64,
363+
static_cast<N>(m_value));
364+
}
307365

308366
protected:
309-
uint64_t m_value;
367+
N m_value;
310368
};
311369

370+
public:
312371
class Float : public Object {
313372
public:
314373
Float(double d = 0.0)
@@ -429,9 +488,16 @@ class StructuredData {
429488
bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
430489
ObjectSP value_sp = GetValueForKey(key);
431490
if (value_sp) {
432-
if (auto int_value = value_sp->GetAsInteger()) {
433-
result = static_cast<IntType>(int_value->GetValue());
434-
return true;
491+
if constexpr (std::numeric_limits<IntType>::is_signed) {
492+
if (auto signed_value = value_sp->GetAsSignedInteger()) {
493+
result = static_cast<IntType>(signed_value->GetValue());
494+
return true;
495+
}
496+
} else {
497+
if (auto unsigned_value = value_sp->GetAsUnsignedInteger()) {
498+
result = static_cast<IntType>(unsigned_value->GetValue());
499+
return true;
500+
}
435501
}
436502
}
437503
return false;
@@ -522,8 +588,14 @@ class StructuredData {
522588
m_dict[key_cs] = std::move(value_sp);
523589
}
524590

525-
void AddIntegerItem(llvm::StringRef key, uint64_t value) {
526-
AddItem(key, std::make_shared<Integer>(value));
591+
template <typename T> void AddIntegerItem(llvm::StringRef key, T value) {
592+
static_assert(std::is_integral<T>::value ||
593+
std::is_floating_point<T>::value,
594+
"value type should be integral");
595+
if constexpr (std::numeric_limits<T>::is_signed)
596+
AddItem(key, std::make_shared<SignedInteger>(value));
597+
else
598+
AddItem(key, std::make_shared<UnsignedInteger>(value));
527599
}
528600

529601
void AddFloatItem(llvm::StringRef key, double value) {

lldb/include/lldb/lldb-enumerations.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,9 @@ enum StructuredDataType {
819819
eStructuredDataTypeFloat,
820820
eStructuredDataTypeBoolean,
821821
eStructuredDataTypeString,
822-
eStructuredDataTypeDictionary
822+
eStructuredDataTypeDictionary,
823+
eStructuredDataTypeSignedInteger,
824+
eStructuredDataTypeUnsignedInteger = eStructuredDataTypeInteger,
823825
};
824826

825827
FLAGS_ENUM(TypeClass){

lldb/source/API/SBStructuredData.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/API/SBStructuredData.h"
10+
#include "lldb/Core/StructuredDataImpl.h"
1011
#include "lldb/Utility/Instrumentation.h"
1112

1213
#include "lldb/API/SBStream.h"
1314
#include "lldb/API/SBStringList.h"
14-
#include "lldb/Core/StructuredDataImpl.h"
1515
#include "lldb/Target/StructuredDataPlugin.h"
1616
#include "lldb/Utility/Event.h"
1717
#include "lldb/Utility/Status.h"
@@ -165,6 +165,18 @@ lldb::SBStructuredData SBStructuredData::GetItemAtIndex(size_t idx) const {
165165
uint64_t SBStructuredData::GetIntegerValue(uint64_t fail_value) const {
166166
LLDB_INSTRUMENT_VA(this, fail_value);
167167

168+
return GetUnsignedIntegerValue(fail_value);
169+
}
170+
171+
uint64_t SBStructuredData::GetUnsignedIntegerValue(uint64_t fail_value) const {
172+
LLDB_INSTRUMENT_VA(this, fail_value);
173+
174+
return m_impl_up->GetIntegerValue(fail_value);
175+
}
176+
177+
int64_t SBStructuredData::GetSignedIntegerValue(int64_t fail_value) const {
178+
LLDB_INSTRUMENT_VA(this, fail_value);
179+
168180
return m_impl_up->GetIntegerValue(fail_value);
169181
}
170182

lldb/source/API/SBThread.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
461461
success = true;
462462
}
463463
if (node->GetType() == eStructuredDataTypeInteger) {
464-
strm.Printf("0x%" PRIx64, node->GetAsInteger()->GetValue());
464+
strm.Printf("0x%" PRIx64, node->GetUnsignedIntegerValue());
465465
success = true;
466466
}
467467
if (node->GetType() == eStructuredDataTypeFloat) {

lldb/source/Breakpoint/BreakpointOptions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ std::unique_ptr<BreakpointOptions> BreakpointOptions::CreateFromStructuredData(
230230
bool enabled = true;
231231
bool one_shot = false;
232232
bool auto_continue = false;
233-
int32_t ignore_count = 0;
233+
uint32_t ignore_count = 0;
234234
llvm::StringRef condition_ref("");
235235
Flags set_options;
236236

lldb/source/Breakpoint/BreakpointResolver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ BreakpointResolverSP BreakpointResolver::CreateFromStructuredData(
102102
return result_sp;
103103
}
104104

105-
lldb::addr_t offset;
105+
lldb::offset_t offset;
106106
success = subclass_options->GetValueForKeyAsInteger(
107107
GetKey(OptionNames::Offset), offset);
108108
if (!success) {

lldb/source/Breakpoint/BreakpointResolverAddress.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData(
3434
const BreakpointSP &bkpt, const StructuredData::Dictionary &options_dict,
3535
Status &error) {
3636
llvm::StringRef module_name;
37-
lldb::addr_t addr_offset;
37+
lldb::offset_t addr_offset;
3838
FileSpec module_filespec;
3939
bool success;
4040

lldb/source/Breakpoint/BreakpointResolverName.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ BreakpointResolver *BreakpointResolverName::CreateFromStructuredData(
104104
}
105105
}
106106

107-
lldb::addr_t offset = 0;
107+
lldb::offset_t offset = 0;
108108
success =
109109
options_dict.GetValueForKeyAsInteger(GetKey(OptionNames::Offset), offset);
110110
if (!success) {
@@ -197,8 +197,8 @@ StructuredData::ObjectSP BreakpointResolverName::SerializeToStructuredData() {
197197
for (auto lookup : m_lookups) {
198198
names_sp->AddItem(StructuredData::StringSP(
199199
new StructuredData::String(lookup.GetName().GetStringRef())));
200-
name_masks_sp->AddItem(StructuredData::IntegerSP(
201-
new StructuredData::Integer(lookup.GetNameTypeMask())));
200+
name_masks_sp->AddItem(StructuredData::UnsignedIntegerSP(
201+
new StructuredData::UnsignedInteger(lookup.GetNameTypeMask())));
202202
}
203203
options_dict_sp->AddItem(GetKey(OptionNames::SymbolNameArray), names_sp);
204204
options_dict_sp->AddItem(GetKey(OptionNames::NameMaskArray), name_masks_sp);

lldb/source/Core/FormatEntity.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ static bool FormatThreadExtendedInfoRecurse(
10081008
const char *token_format = "0x%4.4" PRIx64;
10091009
if (!entry.printf_format.empty())
10101010
token_format = entry.printf_format.c_str();
1011-
s.Printf(token_format, value->GetAsInteger()->GetValue());
1011+
s.Printf(token_format, value->GetUnsignedIntegerValue());
10121012
return true;
10131013
} else if (value->GetType() == eStructuredDataTypeFloat) {
10141014
s.Printf("%f", value->GetAsFloat()->GetValue());

lldb/source/Host/common/XML.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ static StructuredData::ObjectSP CreatePlistValue(XMLNode node) {
490490
} else if (element_name == "integer") {
491491
uint64_t value = 0;
492492
node.GetElementTextAsUnsigned(value, 0, 0);
493-
return StructuredData::ObjectSP(new StructuredData::Integer(value));
493+
return StructuredData::ObjectSP(new StructuredData::UnsignedInteger(value));
494494
} else if ((element_name == "string") || (element_name == "data") ||
495495
(element_name == "date")) {
496496
std::string text;

lldb/source/Interpreter/OptionGroupPythonClassWithDict.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,26 @@ Status OptionGroupPythonClassWithDict::SetOptionValue(
102102
if (!m_dict_sp)
103103
m_dict_sp = std::make_shared<StructuredData::Dictionary>();
104104
if (!m_current_key.empty()) {
105-
m_dict_sp->AddStringItem(m_current_key, option_arg);
106-
m_current_key.clear();
105+
if (!option_arg.empty()) {
106+
double d = 0;
107+
std::string opt = option_arg.lower();
108+
109+
if (llvm::to_integer(option_arg, d)) {
110+
if (opt[0] == '-')
111+
m_dict_sp->AddIntegerItem(m_current_key, static_cast<int64_t>(d));
112+
else
113+
m_dict_sp->AddIntegerItem(m_current_key,
114+
static_cast<uint64_t>(d));
115+
} else if (llvm::to_float(option_arg, d)) {
116+
m_dict_sp->AddFloatItem(m_current_key, d);
117+
} else if (opt == "true" || opt == "false") {
118+
m_dict_sp->AddBooleanItem(m_current_key, opt == "true");
119+
} else {
120+
m_dict_sp->AddStringItem(m_current_key, option_arg);
121+
}
122+
}
123+
124+
m_current_key.clear();
107125
}
108126
else
109127
error.SetErrorStringWithFormat("Value: \"%s\" missing matching key.",

0 commit comments

Comments
 (0)