Index: llvm/include/llvm/Support/JSON.h =================================================================== --- llvm/include/llvm/Support/JSON.h +++ llvm/include/llvm/Support/JSON.h @@ -234,7 +234,7 @@ /// Each Value is one of the JSON kinds: /// null (nullptr_t) /// boolean (bool) -/// number (double or int64) +/// number (double, int64 or uint64) /// string (StringRef) /// array (json::Array) /// object (json::Object) @@ -342,9 +342,18 @@ Value(T B) : Type(T_Boolean) { create(B); } - // Integers (except boolean). Must be non-narrowing convertible to int64_t. + + // Unsigned 64-bit long integers. + template ::value>, + bool = false, bool = false> + Value(T V) : Type(T_UINT64) { create(uint64_t{V}); } + + // Integers (except boolean and uint64_t). + // Must be non-narrowing convertible to int64_t. template ::value>, - typename = std::enable_if_t::value>> + typename = std::enable_if_t::value>, + typename = std::enable_if_t::value>> Value(T I) : Type(T_Integer) { create(int64_t{I}); } @@ -382,6 +391,7 @@ return Boolean; case T_Double: case T_Integer: + case T_UINT64: return Number; case T_String: case T_StringRef: @@ -410,6 +420,8 @@ return as(); if (LLVM_LIKELY(Type == T_Integer)) return as(); + if (LLVM_LIKELY(Type == T_UINT64)) + return as(); return llvm::None; } // Succeeds if the Value is a Number, and exactly representable as int64_t. @@ -425,6 +437,11 @@ } return llvm::None; } + llvm::Optional getAsUINT64() const { + if (Type == T_UINT64) + return as(); + return llvm::None; + } llvm::Optional getAsString() const { if (Type == T_String) return llvm::StringRef(as()); @@ -467,11 +484,12 @@ friend class OStream; - enum ValueType : char { + enum ValueType : char16_t { T_Null, T_Boolean, T_Double, T_Integer, + T_UINT64, T_StringRef, T_String, T_Object, @@ -479,8 +497,9 @@ }; // All members mutable, see moveFrom(). mutable ValueType Type; - mutable llvm::AlignedCharArrayUnion + mutable llvm::AlignedCharArrayUnion Union; friend bool operator==(const Value &, const Value &); }; @@ -683,6 +702,14 @@ P.report("expected boolean"); return false; } +inline bool fromJSON(const Value &E, uint64_t &Out, Path P) { + if (auto S = E.getAsUINT64()) { + Out = *S; + return true; + } + P.report("expected uint64_t"); + return false; +} inline bool fromJSON(const Value &E, std::nullptr_t &Out, Path P) { if (auto S = E.getAsNull()) { Out = *S; Index: llvm/lib/Support/JSON.cpp =================================================================== --- llvm/lib/Support/JSON.cpp +++ llvm/lib/Support/JSON.cpp @@ -109,6 +109,7 @@ case T_Boolean: case T_Double: case T_Integer: + case T_UINT64: memcpy(&Union, &M.Union, sizeof(Union)); break; case T_StringRef: @@ -133,6 +134,7 @@ case T_Boolean: case T_Double: case T_Integer: + case T_UINT64: memcpy(&Union, &M.Union, sizeof(Union)); break; case T_StringRef: @@ -159,6 +161,7 @@ case T_Boolean: case T_Double: case T_Integer: + case T_UINT64: break; case T_StringRef: as().~StringRef(); @@ -750,6 +753,8 @@ valueBegin(); if (V.Type == Value::T_Integer) OS << *V.getAsInteger(); + else if (V.Type == Value::T_UINT64) + OS << *V.getAsUINT64(); else OS << format("%.*g", std::numeric_limits::max_digits10, *V.getAsNumber()); Index: llvm/unittests/Support/JSONTest.cpp =================================================================== --- llvm/unittests/Support/JSONTest.cpp +++ llvm/unittests/Support/JSONTest.cpp @@ -356,6 +356,13 @@ } } +// Simple uint64_t testing. +TEST(JSONTest, U64Integers) { + Value Val = uint64_t{3100100100}; + uint64_t Var = 3100100100; + EXPECT_EQ(Val, Var); +} + // Sample struct with typical JSON-mapping rules. struct CustomStruct { CustomStruct() : B(false) {}