13ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Copyright 2014 The Chromium Authors. All rights reserved.
23ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Use of this source code is governed by a BSD-style license that can be
33ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// found in the LICENSE file.
43ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
53ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Slightly adapted for inclusion in V8.
63ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Copyright 2014 the V8 project authors. All rights reserved.
73ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
83ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org#ifndef V8_BASE_SAFE_CONVERSIONS_IMPL_H_
93ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org#define V8_BASE_SAFE_CONVERSIONS_IMPL_H_
103ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
113ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org#include <limits>
123ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
13d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org#include "src/base/logging.h"
143ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org#include "src/base/macros.h"
153ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
163ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgnamespace v8 {
173ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgnamespace base {
183ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgnamespace internal {
193ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
203ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// The std library doesn't provide a binary max_exponent for integers, however
213ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// we can compute one by adding one to the number of non-sign bits. This allows
223ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// for accurate range comparisons between floating point and integer types.
233ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename NumericType>
243ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct MaxExponent {
253ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static const int value = std::numeric_limits<NumericType>::is_iec559
263ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                               ? std::numeric_limits<NumericType>::max_exponent
273ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                               : (sizeof(NumericType) * 8 + 1 -
283ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                  std::numeric_limits<NumericType>::is_signed);
293ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
303ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
313ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgenum IntegerRepresentation {
323ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  INTEGER_REPRESENTATION_UNSIGNED,
333ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  INTEGER_REPRESENTATION_SIGNED
343ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
353ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
363ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// A range for a given nunmeric Src type is contained for a given numeric Dst
373ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and
383ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true.
393ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// We implement this as template specializations rather than simple static
403ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// comparisons to ensure type correctness in our comparisons.
413ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgenum NumericRangeRepresentation {
423ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  NUMERIC_RANGE_NOT_CONTAINED,
433ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  NUMERIC_RANGE_CONTAINED
443ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
453ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
463ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Helper templates to statically determine if our destination type can contain
473ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// maximum and minimum values represented by the source type.
483ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
493ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <
503ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    typename Dst,
513ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    typename Src,
523ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
533ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                            ? INTEGER_REPRESENTATION_SIGNED
543ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                            : INTEGER_REPRESENTATION_UNSIGNED,
553ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    IntegerRepresentation SrcSign =
563ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        std::numeric_limits<Src>::is_signed
573ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org            ? INTEGER_REPRESENTATION_SIGNED
583ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org            : INTEGER_REPRESENTATION_UNSIGNED >
593ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct StaticDstRangeRelationToSrcRange;
603ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
613ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Same sign: Dst is guaranteed to contain Src only if its range is equal or
623ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// larger.
633ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst, typename Src, IntegerRepresentation Sign>
643ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign> {
653ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static const NumericRangeRepresentation value =
663ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org      MaxExponent<Dst>::value >= MaxExponent<Src>::value
673ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org          ? NUMERIC_RANGE_CONTAINED
683ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org          : NUMERIC_RANGE_NOT_CONTAINED;
693ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
703ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
713ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Unsigned to signed: Dst is guaranteed to contain source only if its range is
723ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// larger.
733ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst, typename Src>
743ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct StaticDstRangeRelationToSrcRange<Dst,
753ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                        Src,
763ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                        INTEGER_REPRESENTATION_SIGNED,
773ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                        INTEGER_REPRESENTATION_UNSIGNED> {
783ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static const NumericRangeRepresentation value =
793ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org      MaxExponent<Dst>::value > MaxExponent<Src>::value
803ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org          ? NUMERIC_RANGE_CONTAINED
813ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org          : NUMERIC_RANGE_NOT_CONTAINED;
823ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
833ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
843ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Signed to unsigned: Dst cannot be statically determined to contain Src.
853ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst, typename Src>
863ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct StaticDstRangeRelationToSrcRange<Dst,
873ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                        Src,
883ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                        INTEGER_REPRESENTATION_UNSIGNED,
893ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                        INTEGER_REPRESENTATION_SIGNED> {
903ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
913ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
923ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
933ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgenum RangeConstraint {
943ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  RANGE_VALID = 0x0,  // Value can be represented by the destination type.
953ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  RANGE_UNDERFLOW = 0x1,  // Value would overflow.
963ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  RANGE_OVERFLOW = 0x2,  // Value would underflow.
973ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW  // Invalid (i.e. NaN).
983ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
993ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1003ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Helper function for coercing an int back to a RangeContraint.
1013ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orginline RangeConstraint GetRangeConstraint(int integer_range_constraint) {
102e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(integer_range_constraint >= RANGE_VALID &&
103d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org         integer_range_constraint <= RANGE_INVALID);
1043ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  return static_cast<RangeConstraint>(integer_range_constraint);
1053ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org}
1063ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1073ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// This function creates a RangeConstraint from an upper and lower bound
1083ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// check by taking advantage of the fact that only NaN can be out of range in
1093ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// both directions at once.
1103ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orginline RangeConstraint GetRangeConstraint(bool is_in_upper_bound,
1113ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                   bool is_in_lower_bound) {
1123ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) |
1133ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                            (is_in_lower_bound ? 0 : RANGE_UNDERFLOW));
1143ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org}
1153ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1163ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <
1173ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    typename Dst,
1183ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    typename Src,
1193ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
1203ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                            ? INTEGER_REPRESENTATION_SIGNED
1213ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                            : INTEGER_REPRESENTATION_UNSIGNED,
1223ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
1233ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                            ? INTEGER_REPRESENTATION_SIGNED
1243ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                            : INTEGER_REPRESENTATION_UNSIGNED,
1253ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    NumericRangeRepresentation DstRange =
1263ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org        StaticDstRangeRelationToSrcRange<Dst, Src>::value >
1273ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct DstRangeRelationToSrcRangeImpl;
1283ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1293ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// The following templates are for ranges that must be verified at runtime. We
1303ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// split it into checks based on signedness to avoid confusing casts and
1313ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// compiler warnings on signed an unsigned comparisons.
1323ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1333ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Dst range is statically determined to contain Src: Nothing to check.
1343ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst,
1353ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org          typename Src,
1363ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org          IntegerRepresentation DstSign,
1373ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org          IntegerRepresentation SrcSign>
1383ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct DstRangeRelationToSrcRangeImpl<Dst,
1393ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      Src,
1403ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      DstSign,
1413ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      SrcSign,
1423ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      NUMERIC_RANGE_CONTAINED> {
1433ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static RangeConstraint Check(Src value) { return RANGE_VALID; }
1443ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
1453ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1463ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Signed to signed narrowing: Both the upper and lower boundaries may be
1473ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// exceeded.
1483ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst, typename Src>
1493ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct DstRangeRelationToSrcRangeImpl<Dst,
1503ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      Src,
1513ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      INTEGER_REPRESENTATION_SIGNED,
1523ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      INTEGER_REPRESENTATION_SIGNED,
1533ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      NUMERIC_RANGE_NOT_CONTAINED> {
1543ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static RangeConstraint Check(Src value) {
1553ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    return std::numeric_limits<Dst>::is_iec559
1563ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org               ? GetRangeConstraint(value <= std::numeric_limits<Dst>::max(),
1573ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                    value >= -std::numeric_limits<Dst>::max())
1583ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org               : GetRangeConstraint(value <= std::numeric_limits<Dst>::max(),
1593ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                    value >= std::numeric_limits<Dst>::min());
1603ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  }
1613ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
1623ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1633ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded.
1643ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst, typename Src>
1653ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct DstRangeRelationToSrcRangeImpl<Dst,
1663ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      Src,
1673ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      INTEGER_REPRESENTATION_UNSIGNED,
1683ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      INTEGER_REPRESENTATION_UNSIGNED,
1693ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      NUMERIC_RANGE_NOT_CONTAINED> {
1703ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static RangeConstraint Check(Src value) {
1713ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    return GetRangeConstraint(value <= std::numeric_limits<Dst>::max(), true);
1723ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  }
1733ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
1743ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1753ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Unsigned to signed: The upper boundary may be exceeded.
1763ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst, typename Src>
1773ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct DstRangeRelationToSrcRangeImpl<Dst,
1783ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      Src,
1793ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      INTEGER_REPRESENTATION_SIGNED,
1803ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      INTEGER_REPRESENTATION_UNSIGNED,
1813ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      NUMERIC_RANGE_NOT_CONTAINED> {
1823ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static RangeConstraint Check(Src value) {
1833ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    return sizeof(Dst) > sizeof(Src)
1843ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org               ? RANGE_VALID
1853ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org               : GetRangeConstraint(
1863ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                     value <= static_cast<Src>(std::numeric_limits<Dst>::max()),
1873ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                     true);
1883ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  }
1893ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
1903ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
1913ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst,
1923ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org// and any negative value exceeds the lower boundary.
1933ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst, typename Src>
1943ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgstruct DstRangeRelationToSrcRangeImpl<Dst,
1953ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      Src,
1963ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      INTEGER_REPRESENTATION_UNSIGNED,
1973ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      INTEGER_REPRESENTATION_SIGNED,
1983ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                                      NUMERIC_RANGE_NOT_CONTAINED> {
1993ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  static RangeConstraint Check(Src value) {
2003ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org    return (MaxExponent<Dst>::value >= MaxExponent<Src>::value)
2013ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org               ? GetRangeConstraint(true, value >= static_cast<Src>(0))
2023ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org               : GetRangeConstraint(
2033ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                     value <= static_cast<Src>(std::numeric_limits<Dst>::max()),
2043ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org                     value >= static_cast<Src>(0));
2053ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  }
2063ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org};
2073ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
2083ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orgtemplate <typename Dst, typename Src>
2093ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.orginline RangeConstraint DstRangeRelationToSrcRange(Src value) {
2103ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  // Both source and destination must be numeric.
2113ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  STATIC_ASSERT(std::numeric_limits<Src>::is_specialized);
2123ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  STATIC_ASSERT(std::numeric_limits<Dst>::is_specialized);
2133ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org  return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value);
2143ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org}
2153ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
2163ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org}  // namespace internal
2173ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org}  // namespace base
2183ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org}  // namespace v8
2193ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org
2203ee7a7ed19002e4a0efbf6cdb2a201f21763a80adanno@chromium.org#endif  // V8_BASE_SAFE_CONVERSIONS_IMPL_H_
221