[support] Provide overload to PrintNumber that use C++ types
This attempts to address an issue with overload resolution for `PrintNumber` with `size_t` parameters on Darwin, brought up in https://reviews.llvm.org/D146492. On Aarch64 Darwin, `uint64_t` has a different typedef than `size_t` (e.g., `unsigned long long` vs. `unsigned long`), whereas on Linux and Windows they are the same. This commit also reverts the static_cast's added in 064e2497e2ebe9ac30ac96923a26a52484300fdf, since they are no longer needed. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D146771
This commit is contained in:
parent
99ab3d9861
commit
9e3aa50d39
@ -74,6 +74,11 @@ namespace json {
|
||||
// - When retrieving strings from Values (e.g. asString()), the result will
|
||||
// always be valid UTF-8.
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_uint_64_bit_v =
|
||||
std::is_integral_v<T> && std::is_unsigned_v<T> &&
|
||||
sizeof(T) == sizeof(uint64_t);
|
||||
|
||||
/// Returns true if \p S is valid UTF-8, which is required for use as JSON.
|
||||
/// If it returns false, \p Offset is set to a byte offset near the first error.
|
||||
bool isUTF8(llvm::StringRef S, size_t *ErrOffset = nullptr);
|
||||
@ -336,19 +341,17 @@ public:
|
||||
create<bool>(B);
|
||||
}
|
||||
|
||||
// Unsigned 64-bit long integers.
|
||||
template <typename T,
|
||||
typename = std::enable_if_t<std::is_same<T, uint64_t>::value>,
|
||||
bool = false, bool = false>
|
||||
// Unsigned 64-bit integers.
|
||||
template <typename T, typename = std::enable_if_t<is_uint_64_bit_v<T>>>
|
||||
Value(T V) : Type(T_UINT64) {
|
||||
create<uint64_t>(uint64_t{V});
|
||||
}
|
||||
|
||||
// Integers (except boolean and uint64_t).
|
||||
// Must be non-narrowing convertible to int64_t.
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>,
|
||||
typename = std::enable_if_t<!std::is_same<T, bool>::value>,
|
||||
typename = std::enable_if_t<!std::is_same<T, uint64_t>::value>>
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>,
|
||||
typename = std::enable_if_t<!std::is_same_v<T, bool>>,
|
||||
typename = std::enable_if_t<!is_uint_64_bit_v<T>>>
|
||||
Value(T I) : Type(T_Integer) {
|
||||
create<int64_t>(int64_t{I});
|
||||
}
|
||||
@ -424,6 +427,12 @@ public:
|
||||
std::optional<int64_t> getAsInteger() const {
|
||||
if (LLVM_LIKELY(Type == T_Integer))
|
||||
return as<int64_t>();
|
||||
if (LLVM_LIKELY(Type == T_UINT64)) {
|
||||
uint64_t U = as<uint64_t>();
|
||||
if (LLVM_LIKELY(U <= uint64_t(std::numeric_limits<int64_t>::max()))) {
|
||||
return U;
|
||||
}
|
||||
}
|
||||
if (LLVM_LIKELY(Type == T_Double)) {
|
||||
double D = as<double>();
|
||||
if (LLVM_LIKELY(std::modf(D, &D) == 0.0 &&
|
||||
|
@ -198,36 +198,48 @@ public:
|
||||
printFlagsImpl(Label, hex(Value), SetFlags);
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, uint64_t Value) {
|
||||
virtual void printNumber(StringRef Label, char Value) {
|
||||
startLine() << Label << ": " << static_cast<int>(Value) << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, signed char Value) {
|
||||
startLine() << Label << ": " << static_cast<int>(Value) << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, unsigned char Value) {
|
||||
startLine() << Label << ": " << static_cast<unsigned>(Value) << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, short Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, uint32_t Value) {
|
||||
virtual void printNumber(StringRef Label, unsigned short Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, uint16_t Value) {
|
||||
virtual void printNumber(StringRef Label, int Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, uint8_t Value) {
|
||||
startLine() << Label << ": " << unsigned(Value) << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, int64_t Value) {
|
||||
virtual void printNumber(StringRef Label, unsigned int Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, int32_t Value) {
|
||||
virtual void printNumber(StringRef Label, long Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, int16_t Value) {
|
||||
virtual void printNumber(StringRef Label, unsigned long Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, int8_t Value) {
|
||||
startLine() << Label << ": " << int(Value) << "\n";
|
||||
virtual void printNumber(StringRef Label, long long Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, unsigned long long Value) {
|
||||
startLine() << Label << ": " << Value << "\n";
|
||||
}
|
||||
|
||||
virtual void printNumber(StringRef Label, const APSInt &Value) {
|
||||
@ -562,35 +574,47 @@ public:
|
||||
return SP->getKind() == ScopedPrinter::ScopedPrinterKind::JSON;
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, uint64_t Value) override {
|
||||
void printNumber(StringRef Label, char Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, uint32_t Value) override {
|
||||
void printNumber(StringRef Label, signed char Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, uint16_t Value) override {
|
||||
void printNumber(StringRef Label, unsigned char Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, uint8_t Value) override {
|
||||
void printNumber(StringRef Label, short Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, int64_t Value) override {
|
||||
void printNumber(StringRef Label, unsigned short Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, int32_t Value) override {
|
||||
void printNumber(StringRef Label, int Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, int16_t Value) override {
|
||||
void printNumber(StringRef Label, unsigned int Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, int8_t Value) override {
|
||||
void printNumber(StringRef Label, long Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, unsigned long Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, long long Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
void printNumber(StringRef Label, unsigned long long Value) override {
|
||||
JOS.attribute(Label, Value);
|
||||
}
|
||||
|
||||
|
@ -7275,14 +7275,14 @@ void LLVMELFDumper<ELFT>::printHashHistogramStats(size_t NBucket,
|
||||
StringRef BucketName = IsGnu ? "Bucket" : "Chain";
|
||||
StringRef ListName = IsGnu ? "Buckets" : "Chains";
|
||||
DictScope Outer(W, HistName);
|
||||
W.printNumber("TotalBuckets", static_cast<uint64_t>(NBucket));
|
||||
W.printNumber("TotalBuckets", NBucket);
|
||||
ListScope Buckets(W, ListName);
|
||||
size_t CumulativeNonZero = 0;
|
||||
for (size_t I = 0; I < MaxChain; ++I) {
|
||||
CumulativeNonZero += Count[I] * I;
|
||||
DictScope Bucket(W, BucketName);
|
||||
W.printNumber("Length", static_cast<uint64_t>(I));
|
||||
W.printNumber("Count", static_cast<uint64_t>(Count[I]));
|
||||
W.printNumber("Length", I);
|
||||
W.printNumber("Count", Count[I]);
|
||||
W.printNumber("Percentage", (float)(Count[I] * 100.0) / NBucket);
|
||||
W.printNumber("Coverage", (float)(CumulativeNonZero * 100.0) / TotalSyms);
|
||||
}
|
||||
|
@ -442,6 +442,39 @@ TEST(JSONTest, U64Integers) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void checkCppIntegers() {
|
||||
Value Val = T{10};
|
||||
T Var = 10;
|
||||
EXPECT_EQ(Val, Var);
|
||||
|
||||
Val = T{std::numeric_limits<T>::max()};
|
||||
Var = std::numeric_limits<T>::max();
|
||||
EXPECT_EQ(Val, Var);
|
||||
|
||||
Val = T{std::numeric_limits<T>::min()};
|
||||
Var = std::numeric_limits<T>::min();
|
||||
EXPECT_EQ(Val, Var);
|
||||
}
|
||||
|
||||
// Test that underlying C++ integer types behave as expected.
|
||||
TEST(JSONTest, CppIntegers) {
|
||||
checkCppIntegers<char>();
|
||||
checkCppIntegers<signed char>();
|
||||
checkCppIntegers<unsigned char>();
|
||||
|
||||
checkCppIntegers<short>();
|
||||
checkCppIntegers<unsigned short>();
|
||||
|
||||
checkCppIntegers<int>();
|
||||
checkCppIntegers<unsigned int>();
|
||||
|
||||
checkCppIntegers<long>();
|
||||
checkCppIntegers<unsigned long>();
|
||||
|
||||
checkCppIntegers<long long>();
|
||||
checkCppIntegers<unsigned long long>();
|
||||
}
|
||||
|
||||
// Sample struct with typical JSON-mapping rules.
|
||||
struct CustomStruct {
|
||||
CustomStruct() : B(false) {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user