[llvm] 9e3aa50 - [support] Provide overload to PrintNumber that use C++ types

Paul Kirth via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 12 10:59:30 PDT 2023


Author: Paul Kirth
Date: 2023-04-12T17:59:22Z
New Revision: 9e3aa50d39fa208998360cb45793df1e39188d4c

URL: https://github.com/llvm/llvm-project/commit/9e3aa50d39fa208998360cb45793df1e39188d4c
DIFF: https://github.com/llvm/llvm-project/commit/9e3aa50d39fa208998360cb45793df1e39188d4c.diff

LOG: [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

Added: 
    

Modified: 
    llvm/include/llvm/Support/JSON.h
    llvm/include/llvm/Support/ScopedPrinter.h
    llvm/tools/llvm-readobj/ELFDumper.cpp
    llvm/unittests/Support/JSONTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/JSON.h b/llvm/include/llvm/Support/JSON.h
index 97f32dffb4f6e..2c97cde059f91 100644
--- a/llvm/include/llvm/Support/JSON.h
+++ b/llvm/include/llvm/Support/JSON.h
@@ -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 @@ class Value {
     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 @@ class Value {
   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 &&

diff  --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h
index 4aa695418f226..aaaed3f5ceac6 100644
--- a/llvm/include/llvm/Support/ScopedPrinter.h
+++ b/llvm/include/llvm/Support/ScopedPrinter.h
@@ -198,36 +198,48 @@ class ScopedPrinter {
     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, unsigned int Value) {
+    startLine() << Label << ": " << Value << "\n";
   }
 
-  virtual void printNumber(StringRef Label, int64_t Value) {
+  virtual void printNumber(StringRef Label, long Value) {
     startLine() << Label << ": " << Value << "\n";
   }
 
-  virtual void printNumber(StringRef Label, int32_t Value) {
+  virtual void printNumber(StringRef Label, unsigned long Value) {
     startLine() << Label << ": " << Value << "\n";
   }
 
-  virtual void printNumber(StringRef Label, int16_t Value) {
+  virtual void printNumber(StringRef Label, long long Value) {
     startLine() << Label << ": " << Value << "\n";
   }
 
-  virtual void printNumber(StringRef Label, int8_t Value) {
-    startLine() << Label << ": " << int(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 @@ class JSONScopedPrinter : public ScopedPrinter {
     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, signed char Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, unsigned char Value) override {
+    JOS.attribute(Label, Value);
+  }
+
+  void printNumber(StringRef Label, short Value) override {
     JOS.attribute(Label, Value);
   }
 
-  void printNumber(StringRef Label, uint32_t Value) override {
+  void printNumber(StringRef Label, unsigned short Value) override {
     JOS.attribute(Label, Value);
   }
 
-  void printNumber(StringRef Label, uint16_t Value) override {
+  void printNumber(StringRef Label, int Value) override {
     JOS.attribute(Label, Value);
   }
 
-  void printNumber(StringRef Label, uint8_t Value) override {
+  void printNumber(StringRef Label, unsigned int Value) override {
     JOS.attribute(Label, Value);
   }
 
-  void printNumber(StringRef Label, int64_t Value) override {
+  void printNumber(StringRef Label, long Value) override {
     JOS.attribute(Label, Value);
   }
 
-  void printNumber(StringRef Label, int32_t Value) override {
+  void printNumber(StringRef Label, unsigned long Value) override {
     JOS.attribute(Label, Value);
   }
 
-  void printNumber(StringRef Label, int16_t Value) override {
+  void printNumber(StringRef Label, long long Value) override {
     JOS.attribute(Label, Value);
   }
 
-  void printNumber(StringRef Label, int8_t Value) override {
+  void printNumber(StringRef Label, unsigned long long Value) override {
     JOS.attribute(Label, Value);
   }
 

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 1d0c795c3a205..3199188f30c83 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -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);
   }

diff  --git a/llvm/unittests/Support/JSONTest.cpp b/llvm/unittests/Support/JSONTest.cpp
index 392a9532b660e..8aa42a28ee92a 100644
--- a/llvm/unittests/Support/JSONTest.cpp
+++ b/llvm/unittests/Support/JSONTest.cpp
@@ -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) {}


        


More information about the llvm-commits mailing list