Gave a more consistent behavior to the Value::isFoo methods. See
NEWS.txt for more details.
diff --git a/NEWS.txt b/NEWS.txt
index e53b880..ac7c856 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,3 +1,23 @@
+  New in SVN:
+  -----------
+
+* Value
+
+  - Updated the Value::isFoo methods to work as follows:
+
+      * isInt, isInt64, isUInt, and isUInt64 return true if and only if the
+	value can be exactly representable as that type. In particular, a value
+	constructed with a double like 17.0 will now return true for all of
+	these methods.
+
+      * isDouble and isFloat now return true for all numeric values, since all
+	numeric values can be converted to a double or float without
+	truncation. Note that the conversion may not be exact -- for example,
+	doubles cannot exactly represent integers above 2^53.
+
+      * isBool, isNull, isString, isArray, and isObject now return true if and
+	only if the value is of that type.
+
   New in JsonCpp 0.6.0:
   ---------------------
 
diff --git a/include/json/value.h b/include/json/value.h
index e3869e5..b013c9b 100644
--- a/include/json/value.h
+++ b/include/json/value.h
@@ -280,7 +280,9 @@
       bool isNull() const;
       bool isBool() const;
       bool isInt() const;
+      bool isInt64() const;
       bool isUInt() const;
+      bool isUInt64() const;
       bool isIntegral() const;
       bool isDouble() const;
       bool isNumeric() const;
diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp
index 0819f3e..35ec41d 100644
--- a/src/lib_json/json_value.cpp
+++ b/src/lib_json/json_value.cpp
@@ -11,6 +11,7 @@
 #  include "json_batchallocator.h"
 # endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
 #endif // if !defined(JSON_IS_AMALGAMATION)
+#include <math.h>
 #include <iostream>
 #include <utility>
 #include <stdexcept>
@@ -539,6 +540,7 @@
 }
 
 
+// TODO(jacobsa): Check this for correctness given the new type-coallescing API.
 bool 
 Value::operator <( const Value &other ) const
 {
@@ -601,6 +603,7 @@
    return other < *this;
 }
 
+// TODO(jacobsa): Check this for correctness given the new type-coallescing API.
 bool 
 Value::operator ==( const Value &other ) const
 {
@@ -694,59 +697,38 @@
 Value::Int 
 Value::asInt() const
 {
+   JSON_ASSERT_MESSAGE(isInt(), "Value is not convertible to Int");
    switch ( type_ )
    {
-   case nullValue:
-      return 0;
    case intValue:
-      JSON_ASSERT_MESSAGE( value_.int_ >= minInt  &&  value_.int_ <= maxInt, "unsigned integer out of signed int range" );
       return Int(value_.int_);
    case uintValue:
-      JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" );
       return Int(value_.uint_);
    case realValue:
-      JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
       return Int( value_.real_ );
-   case booleanValue:
-      return value_.bool_ ? 1 : 0;
-   case stringValue:
-   case arrayValue:
-   case objectValue:
-      JSON_FAIL_MESSAGE( "Type is not convertible to int" );
    default:
-      JSON_ASSERT_UNREACHABLE;
+      break;
    }
-   return 0; // unreachable;
+   JSON_ASSERT_UNREACHABLE;
+   return 0;
 }
 
 
 Value::UInt 
 Value::asUInt() const
 {
+   JSON_ASSERT_MESSAGE(isUInt(), "Value is not convertible to UInt");
    switch ( type_ )
    {
-   case nullValue:
-      return 0;
    case intValue:
-      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
-      JSON_ASSERT_MESSAGE( UInt(value_.int_) <= maxUInt, "signed integer out of UInt range" );
       return UInt(value_.int_);
    case uintValue:
-      JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" );
       return UInt(value_.uint_);
    case realValue:
-      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
       return UInt( value_.real_ );
-   case booleanValue:
-      return value_.bool_ ? 1 : 0;
-   case stringValue:
-   case arrayValue:
-   case objectValue:
-      JSON_FAIL_MESSAGE( "Type is not convertible to uint" );
-   default:
-      JSON_ASSERT_UNREACHABLE;
    }
-   return 0; // unreachable;
+   JSON_ASSERT_UNREACHABLE;
+   return 0;
 }
 
 
@@ -755,55 +737,40 @@
 Value::Int64
 Value::asInt64() const
 {
+   JSON_ASSERT_MESSAGE(isInt64(), "Value is not convertible to Int64");
    switch ( type_ )
    {
-   case nullValue:
-      return 0;
    case intValue:
-      return value_.int_;
+      return Int64(value_.int_);
    case uintValue:
-      JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" );
-      return value_.uint_;
+      return Int64(value_.uint_);
    case realValue:
-      JSON_ASSERT_MESSAGE( value_.real_ >= minInt64  &&  value_.real_ <= maxInt64, "Real out of Int64 range" );
       return Int64( value_.real_ );
-   case booleanValue:
-      return value_.bool_ ? 1 : 0;
-   case stringValue:
-   case arrayValue:
-   case objectValue:
-      JSON_FAIL_MESSAGE( "Type is not convertible to Int64" );
    default:
-      JSON_ASSERT_UNREACHABLE;
+      break;
    }
-   return 0; // unreachable;
+   JSON_ASSERT_UNREACHABLE;
+   return 0;
 }
 
 
 Value::UInt64
 Value::asUInt64() const
 {
+   JSON_ASSERT_MESSAGE(isUInt64(), "Value is not convertible to UInt64");
    switch ( type_ )
    {
-   case nullValue:
-      return 0;
    case intValue:
-      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" );
-      return value_.int_;
+      return UInt64(value_.int_);
    case uintValue:
-      return value_.uint_;
+      return UInt64(value_.uint_);
    case realValue:
-      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt64,  "Real out of UInt64 range" );
       return UInt64( value_.real_ );
-   case booleanValue:
-      return value_.bool_ ? 1 : 0;
-   case stringValue:
-   case arrayValue:
-   case objectValue:
-      JSON_FAIL_MESSAGE( "Type is not convertible to UInt64" );
    default:
-      JSON_ASSERT_UNREACHABLE;
+      break;
    }
+   JSON_ASSERT_UNREACHABLE;
+   return 0;
    return 0; // unreachable;
 }
 # endif // if defined(JSON_HAS_INT64)
@@ -836,8 +803,6 @@
 {
    switch ( type_ )
    {
-   case nullValue:
-      return 0.0;
    case intValue:
       return static_cast<double>( value_.int_ );
    case uintValue:
@@ -848,12 +813,12 @@
 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
    case realValue:
       return value_.real_;
+   case nullValue:
    case booleanValue:
-      return value_.bool_ ? 1.0 : 0.0;
    case stringValue:
    case arrayValue:
    case objectValue:
-      JSON_FAIL_MESSAGE( "Type is not convertible to double" );
+      JSON_FAIL_MESSAGE( "Value is not a double" );
    default:
       JSON_ASSERT_UNREACHABLE;
    }
@@ -865,8 +830,6 @@
 {
    switch ( type_ )
    {
-   case nullValue:
-      return 0.0f;
    case intValue:
       return static_cast<float>( value_.int_ );
    case uintValue:
@@ -877,12 +840,12 @@
 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
    case realValue:
       return static_cast<float>( value_.real_ );
+   case nullValue:
    case booleanValue:
-      return value_.bool_ ? 1.0f : 0.0f;
    case stringValue:
    case arrayValue:
    case objectValue:
-      JSON_FAIL_MESSAGE( "Type is not convertible to float" );
+      JSON_FAIL_MESSAGE( "Value is not a float" );
    default:
       JSON_ASSERT_UNREACHABLE;
    }
@@ -894,20 +857,16 @@
 {
    switch ( type_ )
    {
-   case nullValue:
-      return false;
-   case intValue:
-   case uintValue:
-      return value_.int_ != 0;
-   case realValue:
-      return value_.real_ != 0.0;
    case booleanValue:
       return value_.bool_;
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
    case stringValue:
-      return value_.string_  &&  value_.string_[0] != 0;
    case arrayValue:
    case objectValue:
-      return value_.map_->size() != 0;
+      JSON_FAIL_MESSAGE( "Value is not a bool" );
    default:
       JSON_ASSERT_UNREACHABLE;
    }
@@ -1366,6 +1325,11 @@
 //
 //# endif
 
+static bool IsIntegral(double d) {
+  double integral_part;
+  return modf(d, &integral_part) == 0.0;
+}
+
 
 bool
 Value::isNull() const
@@ -1384,30 +1348,106 @@
 bool 
 Value::isInt() const
 {
-   return type_ == intValue;
+   switch ( type_ )
+   {
+   case intValue:
+      return value_.int_ >= minInt  &&  value_.int_ <= maxInt;
+   case uintValue:
+      return value_.uint_ <= UInt(maxInt);
+   case realValue:
+      return value_.real_ >= minInt &&
+             value_.real_ <= maxInt &&
+             IsIntegral(value_.real_);
+   default:
+      break;
+   }
+   return false;
 }
 
 
 bool 
 Value::isUInt() const
 {
-   return type_ == uintValue;
+   switch ( type_ )
+   {
+   case intValue:
+      return value_.int_ >= 0 && value_.int_ <= maxUInt;
+   case uintValue:
+      return value_.uint_ <= maxUInt;
+   case realValue:
+      return value_.real_ >= 0 &&
+             value_.real_ <= maxUInt &&
+             IsIntegral(value_.real_);
+   default:
+      break;
+   }
+   return false;
+}
+
+bool 
+Value::isInt64() const
+{
+# if defined(JSON_HAS_INT64)
+   switch ( type_ )
+   {
+   case intValue:
+     return true;
+   case uintValue:
+      return value_.uint_ <= UInt64(maxInt64);
+   case realValue:
+      // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
+      // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
+      // require the value to be strictly less than the limit.
+      return value_.real_ >= double(minInt64) &&
+             value_.real_ < double(maxInt64) &&
+             IsIntegral(value_.real_);
+   default:
+      break;
+   }
+# endif  // JSON_HAS_INT64
+   return false;
+}
+
+bool 
+Value::isUInt64() const
+{
+# if defined(JSON_HAS_INT64)
+   switch ( type_ )
+   {
+   case intValue:
+     return value_.int_ >= 0;
+   case uintValue:
+      return true;
+   case realValue:
+      // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+      // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+      // require the value to be strictly less than the limit.
+      return value_.real_ >= 0 &&
+             value_.real_ < double(maxUInt64) &&
+             IsIntegral(value_.real_);
+   default:
+      break;
+   }
+# endif  // JSON_HAS_INT64
+   return false;
 }
 
 
 bool 
 Value::isIntegral() const
 {
-   return type_ == intValue  
-          ||  type_ == uintValue  
-          ||  type_ == booleanValue;
+#if defined(JSON_HAS_INT64)
+  return isInt64() || isUInt64();
+#else
+  return isInt() || isUInt();
+#endif
 }
 
 
 bool 
 Value::isDouble() const
 {
-   return type_ == realValue;
+   return type_ == realValue || isIntegral();
 }
 
 
@@ -1428,14 +1468,14 @@
 bool 
 Value::isArray() const
 {
-   return type_ == nullValue  ||  type_ == arrayValue;
+   return type_ == arrayValue;
 }
 
 
 bool 
 Value::isObject() const
 {
-   return type_ == nullValue  ||  type_ == objectValue;
+   return type_ == objectValue;
 }
 
 
diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp
index 07b1495..0684c90 100644
--- a/src/test_lib_json/main.cpp
+++ b/src/test_lib_json/main.cpp
@@ -74,13 +74,16 @@
       bool isObject_;
       bool isArray_;
       bool isBool_;
-      bool isDouble_;
-      bool isInt_;
-      bool isUInt_;
-      bool isIntegral_;
-      bool isNumeric_;
       bool isString_;
       bool isNull_;
+
+      bool isInt_;
+      bool isInt64_;
+      bool isUInt_;
+      bool isUInt64_;
+      bool isIntegral_;
+      bool isDouble_;
+      bool isNumeric_;
    };
 
    void checkConstMemberCount( const Json::Value &value, unsigned int expectedCount );
@@ -120,6 +123,8 @@
    JSONTEST_ASSERT_PRED( checkIs( emptyObject_, checks ) );
    JSONTEST_ASSERT_PRED( checkIs( object1_, checks ) );
 
+   JSONTEST_ASSERT_EQUAL( Json::objectValue, emptyObject_.type());
+
    // Access through const reference
    const Json::Value &constObject = object1_;
 
@@ -145,6 +150,8 @@
    JSONTEST_ASSERT_PRED( checkIs( emptyArray_, checks ) );
    JSONTEST_ASSERT_PRED( checkIs( array1_, checks ) );
 
+   JSONTEST_ASSERT_EQUAL( Json::arrayValue, array1_.type());
+
    // Access through const reference
    const Json::Value &constArray = array1_;
    JSONTEST_ASSERT( Json::Value(1234) == constArray[index0] );
@@ -162,16 +169,18 @@
 
 JSONTEST_FIXTURE( ValueTest, null )
 {
+   JSONTEST_ASSERT_EQUAL( Json::nullValue, null_.type());
+
    IsCheck checks;
    checks.isNull_ = true;
-   checks.isObject_ = true;
-   checks.isArray_ = true;
    JSONTEST_ASSERT_PRED( checkIs( null_, checks ) );
 }
 
 
 JSONTEST_FIXTURE( ValueTest, strings )
 {
+   JSONTEST_ASSERT_EQUAL( Json::stringValue, string1_.type());
+
    IsCheck checks;
    checks.isString_ = true;
    JSONTEST_ASSERT_PRED( checkIs( emptyString_, checks ) );
@@ -185,10 +194,10 @@
 
 JSONTEST_FIXTURE( ValueTest, bools )
 {
+   JSONTEST_ASSERT_EQUAL( Json::booleanValue, false_.type());
+
    IsCheck checks;
    checks.isBool_ = true;
-   checks.isIntegral_ = true;
-   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( false_, checks ) );
    JSONTEST_ASSERT_PRED( checkIs( true_, checks ) );
 
@@ -209,8 +218,12 @@
 
    checks = IsCheck();
    checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( 0 == val.asInt());
@@ -226,9 +239,35 @@
    JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type());
 
    checks = IsCheck();
+   checks.isInt_ = true;
+   checks.isInt64_ = true;
    checks.isUInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
+   JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
+
+   JSONTEST_ASSERT( 0 == val.asInt());
+   JSONTEST_ASSERT( 0 == val.asLargestInt());
+   JSONTEST_ASSERT( 0 == val.asUInt());
+   JSONTEST_ASSERT( 0 == val.asLargestUInt());
+   JSONTEST_ASSERT( 0.0 == val.asDouble());
+   JSONTEST_ASSERT( 0.0 == val.asFloat());
+
+   // Default real
+   val = Json::Value(Json::realValue);
+
+   JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
+
+   checks = IsCheck();
+   checks.isInt_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt_ = true;
+   checks.isUInt64_ = true;
+   checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( 0 == val.asInt());
@@ -241,10 +280,16 @@
    // Zero (signed constructor arg)
    val = Json::Value(0);
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
    checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( 0 == val.asInt());
@@ -257,10 +302,16 @@
    // Zero (unsigned constructor arg)
    val = Json::Value(0u);
 
+   JSONTEST_ASSERT_EQUAL( Json::uintValue, val.type());
+
    checks = IsCheck();
+   checks.isInt_ = true;
+   checks.isInt64_ = true;
    checks.isUInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( 0 == val.asInt());
@@ -273,7 +324,14 @@
    // Zero (floating-point constructor arg)
    val = Json::Value(0.0);
 
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
    checks = IsCheck();
+   checks.isInt_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt_ = true;
+   checks.isUInt64_ = true;
+   checks.isIntegral_ = true;
    checks.isDouble_ = true;
    checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
@@ -288,10 +346,16 @@
    // 2^20 (signed constructor arg)
    val = Json::Value(1 << 20);
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
    checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( (1 << 20) == val.asInt());
@@ -304,10 +368,16 @@
    // 2^20 (unsigned constructor arg)
    val = Json::Value(1u << 20);
 
+   JSONTEST_ASSERT_EQUAL( Json::uintValue, val.type());
+
    checks = IsCheck();
+   checks.isInt_ = true;
+   checks.isInt64_ = true;
    checks.isUInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( (1 << 20) == val.asInt());
@@ -320,7 +390,14 @@
    // 2^20 (floating-point constructor arg)
    val = Json::Value((1 << 20) / 1.0);
 
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
    checks = IsCheck();
+   checks.isInt_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt_ = true;
+   checks.isUInt64_ = true;
+   checks.isIntegral_ = true;
    checks.isDouble_ = true;
    checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
@@ -335,10 +412,14 @@
    // -2^20
    val = Json::Value(-(1 << 20));
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
    checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( -(1 << 20) == val.asInt());
@@ -349,10 +430,16 @@
    // int32 max
    val = Json::Value(kint32max);
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
    checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( kint32max == val.asInt());
@@ -365,10 +452,14 @@
    // int32 min
    val = Json::Value(kint32min);
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
    checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( kint32min == val.asInt());
@@ -379,10 +470,15 @@
    // uint32 max
    val = Json::Value(kuint32max);
 
+   JSONTEST_ASSERT_EQUAL( Json::uintValue, val.type());
+
    checks = IsCheck();
+   checks.isInt64_ = true;
    checks.isUInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
 #ifndef JSON_NO_INT64
@@ -397,6 +493,8 @@
    // int64 max
    val = Json::Value(double(kint64max));
 
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
    checks = IsCheck();
    checks.isDouble_ = true;
    checks.isNumeric_ = true;
@@ -408,6 +506,8 @@
    // int64 min
    val = Json::Value(double(kint64min));
 
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
    checks = IsCheck();
    checks.isDouble_ = true;
    checks.isNumeric_ = true;
@@ -419,6 +519,8 @@
    // uint64 max
    val = Json::Value(double(kuint64max));
 
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
    checks = IsCheck();
    checks.isDouble_ = true;
    checks.isNumeric_ = true;
@@ -430,10 +532,14 @@
    // 2^40 (signed constructor arg)
    val = Json::Value(1LL << 40);
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
-   checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( (1LL << 40) == val.asInt64());
@@ -446,10 +552,14 @@
    // 2^40 (unsigned constructor arg)
    val = Json::Value(1ULL << 40);
 
+   JSONTEST_ASSERT_EQUAL( Json::uintValue, val.type());
+
    checks = IsCheck();
-   checks.isUInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( (1LL << 40) == val.asInt64());
@@ -462,7 +572,12 @@
    // 2^40 (floating-point constructor arg)
    val = Json::Value((1LL << 40) / 1.0);
 
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
    checks = IsCheck();
+   checks.isInt64_ = true;
+   checks.isUInt64_ = true;
+   checks.isIntegral_ = true;
    checks.isDouble_ = true;
    checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
@@ -477,10 +592,13 @@
    // -2^40
    val = Json::Value(-(1LL << 40));
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
-   checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( -(1LL << 40) == val.asInt64());
@@ -491,10 +609,14 @@
    // int64 max
    val = Json::Value(Json::Int64(kint64max));
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
-   checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( kint64max == val.asInt64());
@@ -504,13 +626,34 @@
    JSONTEST_ASSERT( double(kint64max) == val.asDouble());
    JSONTEST_ASSERT( float(kint64max) == val.asFloat());
 
+   // int64 max (floating point constructor). Note that kint64max is not exactly
+   // representable as a double, and will be rounded up to be higher.
+   val = Json::Value(double(kint64max));
+
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
+   checks = IsCheck();
+   checks.isUInt64_ = true;
+   checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
+   JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
+
+   JSONTEST_ASSERT( 9223372036854775808ULL == val.asUInt64());
+   JSONTEST_ASSERT( 9223372036854775808ULL == val.asLargestUInt());
+   JSONTEST_ASSERT( 9223372036854775808ULL == val.asDouble());
+   JSONTEST_ASSERT( 9223372036854775808ULL == val.asFloat());
+
    // int64 min
    val = Json::Value(Json::Int64(kint64min));
 
+   JSONTEST_ASSERT_EQUAL( Json::intValue, val.type());
+
    checks = IsCheck();
-   checks.isInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( kint64min == val.asInt64());
@@ -518,19 +661,54 @@
    JSONTEST_ASSERT( double(kint64min) == val.asDouble());
    JSONTEST_ASSERT( float(kint64min) == val.asFloat());
 
+   // int64 min (floating point constructor). Note that kint64min *is* exactly
+   // representable as a double.
+   val = Json::Value(double(kint64min));
+
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
+   checks = IsCheck();
+   checks.isInt64_ = true;
+   checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
+   JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
+
+   JSONTEST_ASSERT( -9223372036854775808LL == val.asInt64());
+   JSONTEST_ASSERT( -9223372036854775808LL == val.asLargestInt());
+   JSONTEST_ASSERT( -9223372036854775808.0 == val.asDouble());
+   JSONTEST_ASSERT( -9223372036854775808.0 == val.asFloat());
+
    // uint64 max
    val = Json::Value(Json::UInt64(kuint64max));
 
+   JSONTEST_ASSERT_EQUAL( Json::uintValue, val.type());
+
    checks = IsCheck();
-   checks.isUInt_ = true;
-   checks.isNumeric_ = true;
+   checks.isUInt64_ = true;
    checks.isIntegral_ = true;
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
    JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
 
    JSONTEST_ASSERT( kuint64max == val.asUInt64());
    JSONTEST_ASSERT( kuint64max == val.asLargestUInt());
    JSONTEST_ASSERT( double(kuint64max) == val.asDouble());
    JSONTEST_ASSERT( float(kuint64max) == val.asFloat());
+
+   // uint64 max (floating point constructor). Note that kuint64max is not
+   // exactly representable as a double, and will be rounded up to be higher.
+   val = Json::Value(double(kuint64max));
+
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
+   checks = IsCheck();
+   checks.isDouble_ = true;
+   checks.isNumeric_ = true;
+   JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
+
+   JSONTEST_ASSERT( 18446744073709551616.0 == val.asDouble());
+   JSONTEST_ASSERT( 18446744073709551616.0 == val.asFloat());
 #endif
 }
 
@@ -540,26 +718,11 @@
    IsCheck checks;
    Json::Value val;
 
-   // Default real
-   val = Json::Value(Json::realValue);
-
-   JSONTEST_ASSERT_EQUAL(Json::realValue, val.type());
-
-   checks = IsCheck();
-   checks.isDouble_ = true;
-   checks.isNumeric_ = true;
-   JSONTEST_ASSERT_PRED( checkIs( val, checks ) );
-
-   JSONTEST_ASSERT( 0 == val.asInt());
-   JSONTEST_ASSERT( 0 == val.asLargestInt());
-   JSONTEST_ASSERT( 0 == val.asUInt());
-   JSONTEST_ASSERT( 0 == val.asLargestUInt());
-   JSONTEST_ASSERT( 0.0 == val.asDouble());
-   JSONTEST_ASSERT( 0.0 == val.asFloat());
-
    // Positive number
    val = Json::Value(0.25);
 
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
    checks = IsCheck();
    checks.isDouble_ = true;
    checks.isNumeric_ = true;
@@ -571,6 +734,8 @@
    // Negative number
    val = Json::Value(-0.25);
 
+   JSONTEST_ASSERT_EQUAL( Json::realValue, val.type());
+
    checks = IsCheck();
    checks.isDouble_ = true;
    checks.isNumeric_ = true;
@@ -614,13 +779,15 @@
    : isObject_( false )
    , isArray_( false )
    , isBool_( false )
-   , isDouble_( false )
-   , isInt_( false )
-   , isUInt_( false )
-   , isIntegral_( false )
-   , isNumeric_( false )
    , isString_( false )
    , isNull_( false )
+   , isInt_( false )
+   , isInt64_( false )
+   , isUInt_( false )
+   , isUInt64_( false )
+   , isIntegral_( false )
+   , isDouble_( false )
+   , isNumeric_( false )
 {
 }
 
@@ -633,7 +800,9 @@
    JSONTEST_ASSERT_EQUAL( check.isBool_, value.isBool() );
    JSONTEST_ASSERT_EQUAL( check.isDouble_, value.isDouble() );
    JSONTEST_ASSERT_EQUAL( check.isInt_, value.isInt() );
+   JSONTEST_ASSERT_EQUAL( check.isInt64_, value.isInt64() );
    JSONTEST_ASSERT_EQUAL( check.isUInt_, value.isUInt() );
+   JSONTEST_ASSERT_EQUAL( check.isUInt64_, value.isUInt64() );
    JSONTEST_ASSERT_EQUAL( check.isIntegral_, value.isIntegral() );
    JSONTEST_ASSERT_EQUAL( check.isNumeric_, value.isNumeric() );
    JSONTEST_ASSERT_EQUAL( check.isString_, value.isString() );