diff options
Diffstat (limited to 'src/3rdparty/angle/src/common/third_party/base/anglebase')
13 files changed, 0 insertions, 2792 deletions
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/base_export.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/base_export.h deleted file mode 100644 index 1af5485336..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/base_export.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// Copyright 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// base_export.h: Compatiblity hacks for importing Chromium's base/SHA1. - -#ifndef ANGLEBASE_BASE_EXPORT_H_ -#define ANGLEBASE_BASE_EXPORT_H_ - -#define ANGLEBASE_EXPORT - -#endif // ANGLEBASE_BASE_EXPORT_H_
\ No newline at end of file diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/containers/mru_cache.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/containers/mru_cache.h deleted file mode 100644 index fe4fec5768..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/containers/mru_cache.h +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This file contains a template for a Most Recently Used cache that allows -// constant-time access to items using a key, but easy identification of the -// least-recently-used items for removal. Each key can only be associated with -// one payload item at a time. -// -// The key object will be stored twice, so it should support efficient copying. -// -// NOTE: While all operations are O(1), this code is written for -// legibility rather than optimality. If future profiling identifies this as -// a bottleneck, there is room for smaller values of 1 in the O(1). :] - -#ifndef ANGLEBASE_CONTAINERS_MRU_CACHE_H_ -#define ANGLEBASE_CONTAINERS_MRU_CACHE_H_ - -#include <stddef.h> - -#include <algorithm> -#include <functional> -#include <list> -#include <map> -#include <unordered_map> -#include <utility> - -#include "anglebase/logging.h" -#include "anglebase/macros.h" - -namespace angle -{ - -namespace base -{ - -// MRUCacheBase ---------------------------------------------------------------- - -// This template is used to standardize map type containers that can be used -// by MRUCacheBase. This level of indirection is necessary because of the way -// that template template params and default template params interact. -template <class KeyType, class ValueType, class CompareType> -struct MRUCacheStandardMap -{ - typedef std::map<KeyType, ValueType, CompareType> Type; -}; - -// Base class for the MRU cache specializations defined below. -template <class KeyType, - class PayloadType, - class HashOrCompareType, - template <typename, typename, typename> class MapType = MRUCacheStandardMap> -class MRUCacheBase -{ - public: - // The payload of the list. This maintains a copy of the key so we can - // efficiently delete things given an element of the list. - typedef std::pair<KeyType, PayloadType> value_type; - - private: - typedef std::list<value_type> PayloadList; - typedef - typename MapType<KeyType, typename PayloadList::iterator, HashOrCompareType>::Type KeyIndex; - - public: - typedef typename PayloadList::size_type size_type; - - typedef typename PayloadList::iterator iterator; - typedef typename PayloadList::const_iterator const_iterator; - typedef typename PayloadList::reverse_iterator reverse_iterator; - typedef typename PayloadList::const_reverse_iterator const_reverse_iterator; - - enum - { - NO_AUTO_EVICT = 0 - }; - - // The max_size is the size at which the cache will prune its members to when - // a new item is inserted. If the caller wants to manager this itself (for - // example, maybe it has special work to do when something is evicted), it - // can pass NO_AUTO_EVICT to not restrict the cache size. - explicit MRUCacheBase(size_type max_size) : max_size_(max_size) {} - - virtual ~MRUCacheBase() {} - - size_type max_size() const { return max_size_; } - - // Inserts a payload item with the given key. If an existing item has - // the same key, it is removed prior to insertion. An iterator indicating the - // inserted item will be returned (this will always be the front of the list). - // - // The payload will be forwarded. - template <typename Payload> - iterator Put(const KeyType &key, Payload &&payload) - { - // Remove any existing payload with that key. - typename KeyIndex::iterator index_iter = index_.find(key); - if (index_iter != index_.end()) - { - // Erase the reference to it. The index reference will be replaced in the - // code below. - Erase(index_iter->second); - } - else if (max_size_ != NO_AUTO_EVICT) - { - // New item is being inserted which might make it larger than the maximum - // size: kick the oldest thing out if necessary. - ShrinkToSize(max_size_ - 1); - } - - ordering_.emplace_front(key, std::forward<Payload>(payload)); - index_.emplace(key, ordering_.begin()); - return ordering_.begin(); - } - - // Retrieves the contents of the given key, or end() if not found. This method - // has the side effect of moving the requested item to the front of the - // recency list. - iterator Get(const KeyType &key) - { - typename KeyIndex::iterator index_iter = index_.find(key); - if (index_iter == index_.end()) - return end(); - typename PayloadList::iterator iter = index_iter->second; - - // Move the touched item to the front of the recency ordering. - ordering_.splice(ordering_.begin(), ordering_, iter); - return ordering_.begin(); - } - - // Retrieves the payload associated with a given key and returns it via - // result without affecting the ordering (unlike Get). - iterator Peek(const KeyType &key) - { - typename KeyIndex::const_iterator index_iter = index_.find(key); - if (index_iter == index_.end()) - return end(); - return index_iter->second; - } - - const_iterator Peek(const KeyType &key) const - { - typename KeyIndex::const_iterator index_iter = index_.find(key); - if (index_iter == index_.end()) - return end(); - return index_iter->second; - } - - // Exchanges the contents of |this| by the contents of the |other|. - void Swap(MRUCacheBase &other) - { - ordering_.swap(other.ordering_); - index_.swap(other.index_); - std::swap(max_size_, other.max_size_); - } - - // Erases the item referenced by the given iterator. An iterator to the item - // following it will be returned. The iterator must be valid. - iterator Erase(iterator pos) - { - index_.erase(pos->first); - return ordering_.erase(pos); - } - - // MRUCache entries are often processed in reverse order, so we add this - // convenience function (not typically defined by STL containers). - reverse_iterator Erase(reverse_iterator pos) - { - // We have to actually give it the incremented iterator to delete, since - // the forward iterator that base() returns is actually one past the item - // being iterated over. - return reverse_iterator(Erase((++pos).base())); - } - - // Shrinks the cache so it only holds |new_size| items. If |new_size| is - // bigger or equal to the current number of items, this will do nothing. - void ShrinkToSize(size_type new_size) - { - for (size_type i = size(); i > new_size; i--) - Erase(rbegin()); - } - - // Deletes everything from the cache. - void Clear() - { - index_.clear(); - ordering_.clear(); - } - - // Returns the number of elements in the cache. - size_type size() const - { - // We don't use ordering_.size() for the return value because - // (as a linked list) it can be O(n). - DCHECK(index_.size() == ordering_.size()); - return index_.size(); - } - - // Allows iteration over the list. Forward iteration starts with the most - // recent item and works backwards. - // - // Note that since these iterators are actually iterators over a list, you - // can keep them as you insert or delete things (as long as you don't delete - // the one you are pointing to) and they will still be valid. - iterator begin() { return ordering_.begin(); } - const_iterator begin() const { return ordering_.begin(); } - iterator end() { return ordering_.end(); } - const_iterator end() const { return ordering_.end(); } - - reverse_iterator rbegin() { return ordering_.rbegin(); } - const_reverse_iterator rbegin() const { return ordering_.rbegin(); } - reverse_iterator rend() { return ordering_.rend(); } - const_reverse_iterator rend() const { return ordering_.rend(); } - - bool empty() const { return ordering_.empty(); } - - private: - PayloadList ordering_; - KeyIndex index_; - - size_type max_size_; - - DISALLOW_COPY_AND_ASSIGN(MRUCacheBase); -}; - -// MRUCache -------------------------------------------------------------------- - -// A container that does not do anything to free its data. Use this when storing -// value types (as opposed to pointers) in the list. -template <class KeyType, class PayloadType, class CompareType = std::less<KeyType>> -class MRUCache : public MRUCacheBase<KeyType, PayloadType, CompareType> -{ - private: - using ParentType = MRUCacheBase<KeyType, PayloadType, CompareType>; - - public: - // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. - explicit MRUCache(typename ParentType::size_type max_size) : ParentType(max_size) {} - virtual ~MRUCache() {} - - private: - DISALLOW_COPY_AND_ASSIGN(MRUCache); -}; - -// HashingMRUCache ------------------------------------------------------------ - -template <class KeyType, class ValueType, class HashType> -struct MRUCacheHashMap -{ - typedef std::unordered_map<KeyType, ValueType, HashType> Type; -}; - -// This class is similar to MRUCache, except that it uses std::unordered_map as -// the map type instead of std::map. Note that your KeyType must be hashable to -// use this cache or you need to provide a hashing class. -template <class KeyType, class PayloadType, class HashType = std::hash<KeyType>> -class HashingMRUCache : public MRUCacheBase<KeyType, PayloadType, HashType, MRUCacheHashMap> -{ - private: - using ParentType = MRUCacheBase<KeyType, PayloadType, HashType, MRUCacheHashMap>; - - public: - // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT. - explicit HashingMRUCache(typename ParentType::size_type max_size) : ParentType(max_size) {} - virtual ~HashingMRUCache() {} - - private: - DISALLOW_COPY_AND_ASSIGN(HashingMRUCache); -}; - -} // namespace base - -} // namespace angle - -#endif // ANGLEBASE_CONTAINERS_MRU_CACHE_H_ diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/logging.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/logging.h deleted file mode 100644 index 85ad82b47d..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/logging.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright 2016 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// logging.h: Compatiblity hacks for importing Chromium's base/numerics. - -#ifndef ANGLEBASE_LOGGING_H_ -#define ANGLEBASE_LOGGING_H_ - -#include "common/debug.h" - -#ifndef DCHECK -#define DCHECK(X) ASSERT(X) -#endif - -#ifndef CHECK -#define CHECK(X) ASSERT(X) -#endif - -// Unfortunately ANGLE relies on ASSERT being an empty statement, which these libs don't respect. -#ifndef NOTREACHED -#define NOTREACHED() UNREACHABLE() -#endif - -#endif // ANGLEBASE_LOGGING_H_ diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/macros.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/macros.h deleted file mode 100644 index 06391784e4..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/macros.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// macros.h: Compatiblity hacks for importing Chromium's MRUCache. - -#ifndef ANGLEBASE_MACROS_H_ -#define ANGLEBASE_MACROS_H_ - -// A macro to disallow the copy constructor and operator= functions. -// This should be used in the private: declarations for a class. -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName &) = delete; \ - void operator=(const TypeName &) = delete - -#endif // ANGLEBASE_MACROS_H_ diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS deleted file mode 100644 index 41f35fc79b..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -jschuh@chromium.org -tsepez@chromium.org - diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h deleted file mode 100644 index 43babc31a8..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_ -#define ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_ - -#include <stddef.h> - -#include <limits> -#include <type_traits> - -#include "anglebase/logging.h" -#include "anglebase/numerics/safe_conversions_impl.h" - -namespace angle -{ - -namespace base -{ - -// Convenience function that returns true if the supplied value is in range -// for the destination type. -template <typename Dst, typename Src> -constexpr bool IsValueInRangeForNumericType(Src value) -{ - return internal::DstRangeRelationToSrcRange<Dst>(value) == internal::RANGE_VALID; -} - -// Convenience function for determining if a numeric value is negative without -// throwing compiler warnings on: unsigned(value) < 0. -template <typename T> -constexpr typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type IsValueNegative( - T value) -{ - static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric."); - return value < 0; -} - -template <typename T> -constexpr typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(T) -{ - static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric."); - return false; -} - -// checked_cast<> is analogous to static_cast<> for numeric types, -// except that it CHECKs that the specified numeric conversion will not -// overflow or underflow. NaN source will always trigger a CHECK. -template <typename Dst, typename Src> -inline Dst checked_cast(Src value) -{ - CHECK(IsValueInRangeForNumericType<Dst>(value)); - return static_cast<Dst>(value); -} - -// HandleNaN will cause this class to CHECK(false). -struct SaturatedCastNaNBehaviorCheck -{ - template <typename T> - static T HandleNaN() - { - CHECK(false); - return T(); - } -}; - -// HandleNaN will return 0 in this case. -struct SaturatedCastNaNBehaviorReturnZero -{ - template <typename T> - static constexpr T HandleNaN() - { - return T(); - } -}; - -namespace internal -{ -// This wrapper is used for C++11 constexpr support by avoiding the declaration -// of local variables in the saturated_cast template function. -template <typename Dst, class NaNHandler, typename Src> -constexpr Dst saturated_cast_impl(const Src value, const RangeConstraint constraint) -{ - return constraint == RANGE_VALID - ? static_cast<Dst>(value) - : (constraint == RANGE_UNDERFLOW - ? std::numeric_limits<Dst>::min() - : (constraint == RANGE_OVERFLOW - ? std::numeric_limits<Dst>::max() - : (constraint == RANGE_INVALID - ? NaNHandler::template HandleNaN<Dst>() - : (NOTREACHED(), static_cast<Dst>(value))))); -} -} // namespace internal - -// saturated_cast<> is analogous to static_cast<> for numeric types, except -// that the specified numeric conversion will saturate rather than overflow or -// underflow. NaN assignment to an integral will defer the behavior to a -// specified class. By default, it will return 0. -template <typename Dst, class NaNHandler = SaturatedCastNaNBehaviorReturnZero, typename Src> -constexpr Dst saturated_cast(Src value) -{ - return std::numeric_limits<Dst>::is_iec559 - ? static_cast<Dst>(value) // Floating point optimization. - : internal::saturated_cast_impl<Dst, NaNHandler>( - value, internal::DstRangeRelationToSrcRange<Dst>(value)); -} - -// strict_cast<> is analogous to static_cast<> for numeric types, except that -// it will cause a compile failure if the destination type is not large enough -// to contain any value in the source type. It performs no runtime checking. -template <typename Dst, typename Src> -constexpr Dst strict_cast(Src value) -{ - static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric."); - static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric."); - static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value == - internal::NUMERIC_RANGE_CONTAINED), - "The numeric conversion is out of range for this type. You " - "should probably use one of the following conversion " - "mechanisms on the value you want to pass:\n" - "- base::checked_cast\n" - "- base::saturated_cast\n" - "- base::CheckedNumeric"); - - return static_cast<Dst>(value); -} - -// StrictNumeric implements compile time range checking between numeric types by -// wrapping assignment operations in a strict_cast. This class is intended to be -// used for function arguments and return types, to ensure the destination type -// can always contain the source type. This is essentially the same as enforcing -// -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied -// incrementally at API boundaries, making it easier to convert code so that it -// compiles cleanly with truncation warnings enabled. -// This template should introduce no runtime overhead, but it also provides no -// runtime checking of any of the associated mathematical operations. Use -// CheckedNumeric for runtime range checks of the actual value being assigned. -template <typename T> -class StrictNumeric -{ - public: - typedef T type; - - constexpr StrictNumeric() : value_(0) {} - - // Copy constructor. - template <typename Src> - constexpr StrictNumeric(const StrictNumeric<Src> &rhs) : value_(strict_cast<T>(rhs.value_)) - { - } - - // This is not an explicit constructor because we implicitly upgrade regular - // numerics to StrictNumerics to make them easier to use. - template <typename Src> - constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value)) - { - } - - // The numeric cast operator basically handles all the magic. - template <typename Dst> - constexpr operator Dst() const - { - return strict_cast<Dst>(value_); - } - - private: - const T value_; -}; - -// Explicitly make a shorter size_t typedef for convenience. -typedef StrictNumeric<size_t> SizeT; - -} // namespace base - -} // namespace angle - -#endif // ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_ diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h deleted file mode 100644 index 10ed6c7a7f..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ -#define ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ - -#include <limits.h> -#include <stdint.h> - -#include <climits> -#include <limits> - -namespace angle -{ - -namespace base -{ -namespace internal -{ - -// The std library doesn't provide a binary max_exponent for integers, however -// we can compute one by adding one to the number of non-sign bits. This allows -// for accurate range comparisons between floating point and integer types. -template <typename NumericType> -struct MaxExponent -{ - static_assert(std::is_arithmetic<NumericType>::value, "Argument must be numeric."); - static const int value = - std::numeric_limits<NumericType>::is_iec559 - ? std::numeric_limits<NumericType>::max_exponent - : (sizeof(NumericType) * CHAR_BIT + 1 - std::numeric_limits<NumericType>::is_signed); -}; - -enum IntegerRepresentation -{ - INTEGER_REPRESENTATION_UNSIGNED, - INTEGER_REPRESENTATION_SIGNED -}; - -// A range for a given nunmeric Src type is contained for a given numeric Dst -// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and -// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true. -// We implement this as template specializations rather than simple static -// comparisons to ensure type correctness in our comparisons. -enum NumericRangeRepresentation -{ - NUMERIC_RANGE_NOT_CONTAINED, - NUMERIC_RANGE_CONTAINED -}; - -// Helper templates to statically determine if our destination type can contain -// maximum and minimum values represented by the source type. - -template <typename Dst, - typename Src, - IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed - ? INTEGER_REPRESENTATION_SIGNED - : INTEGER_REPRESENTATION_UNSIGNED, - IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed - ? INTEGER_REPRESENTATION_SIGNED - : INTEGER_REPRESENTATION_UNSIGNED> -struct StaticDstRangeRelationToSrcRange; - -// Same sign: Dst is guaranteed to contain Src only if its range is equal or -// larger. -template <typename Dst, typename Src, IntegerRepresentation Sign> -struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign> -{ - static const NumericRangeRepresentation value = - MaxExponent<Dst>::value >= MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED - : NUMERIC_RANGE_NOT_CONTAINED; -}; - -// Unsigned to signed: Dst is guaranteed to contain source only if its range is -// larger. -template <typename Dst, typename Src> -struct StaticDstRangeRelationToSrcRange<Dst, - Src, - INTEGER_REPRESENTATION_SIGNED, - INTEGER_REPRESENTATION_UNSIGNED> -{ - static const NumericRangeRepresentation value = - MaxExponent<Dst>::value > MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED - : NUMERIC_RANGE_NOT_CONTAINED; -}; - -// Signed to unsigned: Dst cannot be statically determined to contain Src. -template <typename Dst, typename Src> -struct StaticDstRangeRelationToSrcRange<Dst, - Src, - INTEGER_REPRESENTATION_UNSIGNED, - INTEGER_REPRESENTATION_SIGNED> -{ - static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED; -}; - -enum RangeConstraint : unsigned char -{ - RANGE_VALID = 0x0, // Value can be represented by the destination type. - RANGE_UNDERFLOW = 0x1, // Value would overflow. - RANGE_OVERFLOW = 0x2, // Value would underflow. - RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN). -}; - -// Helper function for coercing an int back to a RangeContraint. -constexpr RangeConstraint GetRangeConstraint(int integer_range_constraint) -{ - // TODO(jschuh): Once we get full C++14 support we want this - // assert(integer_range_constraint >= RANGE_VALID && - // integer_range_constraint <= RANGE_INVALID) - return static_cast<RangeConstraint>(integer_range_constraint); -} - -// This function creates a RangeConstraint from an upper and lower bound -// check by taking advantage of the fact that only NaN can be out of range in -// both directions at once. -constexpr inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, bool is_in_lower_bound) -{ - return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) | - (is_in_lower_bound ? 0 : RANGE_UNDERFLOW)); -} - -// The following helper template addresses a corner case in range checks for -// conversion from a floating-point type to an integral type of smaller range -// but larger precision (e.g. float -> unsigned). The problem is as follows: -// 1. Integral maximum is always one less than a power of two, so it must be -// truncated to fit the mantissa of the floating point. The direction of -// rounding is implementation defined, but by default it's always IEEE -// floats, which round to nearest and thus result in a value of larger -// magnitude than the integral value. -// Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX -// // is 4294967295u. -// 2. If the floating point value is equal to the promoted integral maximum -// value, a range check will erroneously pass. -// Example: (4294967296f <= 4294967295u) // This is true due to a precision -// // loss in rounding up to float. -// 3. When the floating point value is then converted to an integral, the -// resulting value is out of range for the target integral type and -// thus is implementation defined. -// Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0. -// To fix this bug we manually truncate the maximum value when the destination -// type is an integral of larger precision than the source floating-point type, -// such that the resulting maximum is represented exactly as a floating point. -template <typename Dst, typename Src> -struct NarrowingRange -{ - typedef typename std::numeric_limits<Src> SrcLimits; - typedef typename std::numeric_limits<Dst> DstLimits; - // The following logic avoids warnings where the max function is - // instantiated with invalid values for a bit shift (even though - // such a function can never be called). - static const int shift = (MaxExponent<Src>::value > MaxExponent<Dst>::value && - SrcLimits::digits < DstLimits::digits && - SrcLimits::is_iec559 && - DstLimits::is_integer) - ? (DstLimits::digits - SrcLimits::digits) - : 0; - - static constexpr Dst max() - { - // We use UINTMAX_C below to avoid compiler warnings about shifting floating - // points. Since it's a compile time calculation, it shouldn't have any - // performance impact. - return DstLimits::max() - static_cast<Dst>((UINTMAX_C(1) << shift) - 1); - } - - static constexpr Dst min() - { - return std::numeric_limits<Dst>::is_iec559 ? -DstLimits::max() : DstLimits::min(); - } -}; - -template <typename Dst, - typename Src, - IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed - ? INTEGER_REPRESENTATION_SIGNED - : INTEGER_REPRESENTATION_UNSIGNED, - IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed - ? INTEGER_REPRESENTATION_SIGNED - : INTEGER_REPRESENTATION_UNSIGNED, - NumericRangeRepresentation DstRange = StaticDstRangeRelationToSrcRange<Dst, Src>::value> -struct DstRangeRelationToSrcRangeImpl; - -// The following templates are for ranges that must be verified at runtime. We -// split it into checks based on signedness to avoid confusing casts and -// compiler warnings on signed an unsigned comparisons. - -// Dst range is statically determined to contain Src: Nothing to check. -template <typename Dst, typename Src, IntegerRepresentation DstSign, IntegerRepresentation SrcSign> -struct DstRangeRelationToSrcRangeImpl<Dst, Src, DstSign, SrcSign, NUMERIC_RANGE_CONTAINED> -{ - static constexpr RangeConstraint Check(Src value) { return RANGE_VALID; } -}; - -// Signed to signed narrowing: Both the upper and lower boundaries may be -// exceeded. -template <typename Dst, typename Src> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - INTEGER_REPRESENTATION_SIGNED, - INTEGER_REPRESENTATION_SIGNED, - NUMERIC_RANGE_NOT_CONTAINED> -{ - static constexpr RangeConstraint Check(Src value) - { - return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()), - (value >= NarrowingRange<Dst, Src>::min())); - } -}; - -// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded. -template <typename Dst, typename Src> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - INTEGER_REPRESENTATION_UNSIGNED, - INTEGER_REPRESENTATION_UNSIGNED, - NUMERIC_RANGE_NOT_CONTAINED> -{ - static constexpr RangeConstraint Check(Src value) - { - return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true); - } -}; - -// Unsigned to signed: The upper boundary may be exceeded. -template <typename Dst, typename Src> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - INTEGER_REPRESENTATION_SIGNED, - INTEGER_REPRESENTATION_UNSIGNED, - NUMERIC_RANGE_NOT_CONTAINED> -{ - static constexpr RangeConstraint Check(Src value) - { - return sizeof(Dst) > sizeof(Src) - ? RANGE_VALID - : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()), - true); - } -}; - -// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst, -// and any negative value exceeds the lower boundary. -template <typename Dst, typename Src> -struct DstRangeRelationToSrcRangeImpl<Dst, - Src, - INTEGER_REPRESENTATION_UNSIGNED, - INTEGER_REPRESENTATION_SIGNED, - NUMERIC_RANGE_NOT_CONTAINED> -{ - static constexpr RangeConstraint Check(Src value) - { - return (MaxExponent<Dst>::value >= MaxExponent<Src>::value) - ? GetRangeConstraint(true, value >= static_cast<Src>(0)) - : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()), - value >= static_cast<Src>(0)); - } -}; - -template <typename Dst, typename Src> -constexpr RangeConstraint DstRangeRelationToSrcRange(Src value) -{ - static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric."); - static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric."); - return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value); -} - -} // namespace internal -} // namespace base - -} // namespace angle - -#endif // ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_ diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h deleted file mode 100644 index 3af4db63f7..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ANGLEBASE_NUMERICS_SAFE_MATH_H_ -#define ANGLEBASE_NUMERICS_SAFE_MATH_H_ - -#include <stddef.h> - -#include <limits> -#include <type_traits> - -#include "anglebase/logging.h" -#include "anglebase/numerics/safe_math_impl.h" - -namespace angle -{ - -namespace base -{ - -namespace internal -{ - -// CheckedNumeric implements all the logic and operators for detecting integer -// boundary conditions such as overflow, underflow, and invalid conversions. -// The CheckedNumeric type implicitly converts from floating point and integer -// data types, and contains overloads for basic arithmetic operations (i.e.: +, -// -, *, /, %). -// -// The following methods convert from CheckedNumeric to standard numeric values: -// IsValid() - Returns true if the underlying numeric value is valid (i.e. has -// has not wrapped and is not the result of an invalid conversion). -// ValueOrDie() - Returns the underlying value. If the state is not valid this -// call will crash on a CHECK. -// ValueOrDefault() - Returns the current value, or the supplied default if the -// state is not valid. -// ValueFloating() - Returns the underlying floating point value (valid only -// only for floating point CheckedNumeric types). -// -// Bitwise operations are explicitly not supported, because correct -// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison -// operations are explicitly not supported because they could result in a crash -// on a CHECK condition. You should use patterns like the following for these -// operations: -// Bitwise operation: -// CheckedNumeric<int> checked_int = untrusted_input_value; -// int x = checked_int.ValueOrDefault(0) | kFlagValues; -// Comparison: -// CheckedNumeric<size_t> checked_size = untrusted_input_value; -// checked_size += HEADER LENGTH; -// if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) -// Do stuff... -template <typename T> -class CheckedNumeric -{ - static_assert(std::is_arithmetic<T>::value, "CheckedNumeric<T>: T must be a numeric type."); - - public: - typedef T type; - - CheckedNumeric() {} - - // Copy constructor. - template <typename Src> - CheckedNumeric(const CheckedNumeric<Src> &rhs) : state_(rhs.ValueUnsafe(), rhs.validity()) - { - } - - template <typename Src> - CheckedNumeric(Src value, RangeConstraint validity) : state_(value, validity) - { - } - - // This is not an explicit constructor because we implicitly upgrade regular - // numerics to CheckedNumerics to make them easier to use. - template <typename Src> - CheckedNumeric(Src value) // NOLINT(runtime/explicit) - : state_(value) - { - static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric."); - } - - // This is not an explicit constructor because we want a seamless conversion - // from StrictNumeric types. - template <typename Src> - CheckedNumeric(StrictNumeric<Src> value) // NOLINT(runtime/explicit) - : state_(static_cast<Src>(value)) - { - } - - // IsValid() is the public API to test if a CheckedNumeric is currently valid. - bool IsValid() const { return validity() == RANGE_VALID; } - - // ValueOrDie() The primary accessor for the underlying value. If the current - // state is not valid it will CHECK and crash. - T ValueOrDie() const - { - CHECK(IsValid()); - return state_.value(); - } - - // ValueOrDefault(T default_value) A convenience method that returns the - // current value if the state is valid, and the supplied default_value for - // any other state. - T ValueOrDefault(T default_value) const { return IsValid() ? state_.value() : default_value; } - - // ValueFloating() - Since floating point values include their validity state, - // we provide an easy method for extracting them directly, without a risk of - // crashing on a CHECK. - T ValueFloating() const - { - static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float."); - return CheckedNumeric<T>::cast(*this).ValueUnsafe(); - } - - // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for - // tests and to avoid a big matrix of friend operator overloads. But the - // values it returns are likely to change in the future. - // Returns: current validity state (i.e. valid, overflow, underflow, nan). - // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for - // saturation/wrapping so we can expose this state consistently and implement - // saturated arithmetic. - RangeConstraint validity() const { return state_.validity(); } - - // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now - // for tests and to avoid a big matrix of friend operator overloads. But the - // values it returns are likely to change in the future. - // Returns: the raw numeric value, regardless of the current state. - // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for - // saturation/wrapping so we can expose this state consistently and implement - // saturated arithmetic. - T ValueUnsafe() const { return state_.value(); } - - // Prototypes for the supported arithmetic operator overloads. - template <typename Src> - CheckedNumeric &operator+=(Src rhs); - template <typename Src> - CheckedNumeric &operator-=(Src rhs); - template <typename Src> - CheckedNumeric &operator*=(Src rhs); - template <typename Src> - CheckedNumeric &operator/=(Src rhs); - template <typename Src> - CheckedNumeric &operator%=(Src rhs); - - CheckedNumeric operator-() const - { - RangeConstraint validity; - T value = CheckedNeg(state_.value(), &validity); - // Negation is always valid for floating point. - if (std::numeric_limits<T>::is_iec559) - return CheckedNumeric<T>(value); - - validity = GetRangeConstraint(state_.validity() | validity); - return CheckedNumeric<T>(value, validity); - } - - CheckedNumeric Abs() const - { - RangeConstraint validity; - T value = CheckedAbs(state_.value(), &validity); - // Absolute value is always valid for floating point. - if (std::numeric_limits<T>::is_iec559) - return CheckedNumeric<T>(value); - - validity = GetRangeConstraint(state_.validity() | validity); - return CheckedNumeric<T>(value, validity); - } - - // This function is available only for integral types. It returns an unsigned - // integer of the same width as the source type, containing the absolute value - // of the source, and properly handling signed min. - CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const - { - return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>( - CheckedUnsignedAbs(state_.value()), state_.validity()); - } - - CheckedNumeric &operator++() - { - *this += 1; - return *this; - } - - CheckedNumeric operator++(int) - { - CheckedNumeric value = *this; - *this += 1; - return value; - } - - CheckedNumeric &operator--() - { - *this -= 1; - return *this; - } - - CheckedNumeric operator--(int) - { - CheckedNumeric value = *this; - *this -= 1; - return value; - } - - // These static methods behave like a convenience cast operator targeting - // the desired CheckedNumeric type. As an optimization, a reference is - // returned when Src is the same type as T. - template <typename Src> - static CheckedNumeric<T> cast( - Src u, - typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0) - { - return u; - } - - template <typename Src> - static CheckedNumeric<T> cast( - const CheckedNumeric<Src> &u, - typename std::enable_if<!std::is_same<Src, T>::value, int>::type = 0) - { - return u; - } - - static const CheckedNumeric<T> &cast(const CheckedNumeric<T> &u) { return u; } - - private: - template <typename NumericType> - struct UnderlyingType - { - using type = NumericType; - }; - - template <typename NumericType> - struct UnderlyingType<CheckedNumeric<NumericType>> - { - using type = NumericType; - }; - - CheckedNumericState<T> state_; -}; - -// This is the boilerplate for the standard arithmetic operator overloads. A -// macro isn't the prettiest solution, but it beats rewriting these five times. -// Some details worth noting are: -// * We apply the standard arithmetic promotions. -// * We skip range checks for floating points. -// * We skip range checks for destination integers with sufficient range. -// TODO(jschuh): extract these out into templates. -#define ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ - /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ - template <typename T> \ - CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \ - const CheckedNumeric<T> &lhs, const CheckedNumeric<T> &rhs) \ - { \ - typedef typename ArithmeticPromotion<T>::type Promotion; \ - /* Floating point always takes the fast path */ \ - if (std::numeric_limits<T>::is_iec559) \ - return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ - if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \ - return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ - GetRangeConstraint(rhs.validity() | lhs.validity())); \ - RangeConstraint validity = RANGE_VALID; \ - T result = \ - static_cast<T>(Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \ - static_cast<Promotion>(rhs.ValueUnsafe()), &validity)); \ - return CheckedNumeric<Promotion>( \ - result, GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \ - } \ - /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ - template <typename T> \ - template <typename Src> \ - CheckedNumeric<T> &CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) \ - { \ - *this = CheckedNumeric<T>::cast(*this) \ - OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \ - return *this; \ - } \ - /* Binary arithmetic operator for CheckedNumeric of different type. */ \ - template <typename T, typename Src> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - const CheckedNumeric<Src> &lhs, const CheckedNumeric<T> &rhs) \ - { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ - GetRangeConstraint(rhs.validity() | lhs.validity())); \ - return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \ - } \ - /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ - template <typename T, typename Src, \ - typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - const CheckedNumeric<T> &lhs, Src rhs) \ - { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, lhs.validity()); \ - return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \ - } \ - /* Binary arithmetic operator for left numeric and right CheckedNumeric. */ \ - template <typename T, typename Src, \ - typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - Src lhs, const CheckedNumeric<T> &rhs) \ - { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), rhs.validity()); \ - return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \ - } - -ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=) -ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=) -ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=) -ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=) -ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=) - -#undef ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS - -} // namespace internal - -using internal::CheckedNumeric; - -} // namespace base - -} // namespace angle - -#endif // ANGLEBASE_NUMERICS_SAFE_MATH_H_ diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h deleted file mode 100644 index 2831cc6ceb..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h +++ /dev/null @@ -1,575 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_ -#define ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <climits> -#include <cmath> -#include <cstdlib> -#include <limits> -#include <type_traits> - -#include "anglebase/numerics/safe_conversions.h" - -namespace angle -{ - -namespace base -{ -namespace internal -{ - -// Everything from here up to the floating point operations is portable C++, -// but it may not be fast. This code could be split based on -// platform/architecture and replaced with potentially faster implementations. - -// Integer promotion templates used by the portable checked integer arithmetic. -template <size_t Size, bool IsSigned> -struct IntegerForSizeAndSign; -template <> -struct IntegerForSizeAndSign<1, true> -{ - typedef int8_t type; -}; -template <> -struct IntegerForSizeAndSign<1, false> -{ - typedef uint8_t type; -}; -template <> -struct IntegerForSizeAndSign<2, true> -{ - typedef int16_t type; -}; -template <> -struct IntegerForSizeAndSign<2, false> -{ - typedef uint16_t type; -}; -template <> -struct IntegerForSizeAndSign<4, true> -{ - typedef int32_t type; -}; -template <> -struct IntegerForSizeAndSign<4, false> -{ - typedef uint32_t type; -}; -template <> -struct IntegerForSizeAndSign<8, true> -{ - typedef int64_t type; -}; -template <> -struct IntegerForSizeAndSign<8, false> -{ - typedef uint64_t type; -}; - -// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to -// support 128-bit math, then the ArithmeticPromotion template below will need -// to be updated (or more likely replaced with a decltype expression). - -template <typename Integer> -struct UnsignedIntegerForSize -{ - typedef - typename std::enable_if<std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type - type; -}; - -template <typename Integer> -struct SignedIntegerForSize -{ - typedef - typename std::enable_if<std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type - type; -}; - -template <typename Integer> -struct TwiceWiderInteger -{ - typedef typename std::enable_if< - std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign<sizeof(Integer) * 2, - std::numeric_limits<Integer>::is_signed>::type>::type type; -}; - -template <typename Integer> -struct PositionOfSignBit -{ - static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, size_t>::type - value = CHAR_BIT * sizeof(Integer) - 1; -}; - -// This is used for UnsignedAbs, where we need to support floating-point -// template instantiations even though we don't actually support the operations. -// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs, -// so the float versions will not compile. -template <typename Numeric, - bool IsInteger = std::numeric_limits<Numeric>::is_integer, - bool IsFloat = std::numeric_limits<Numeric>::is_iec559> -struct UnsignedOrFloatForSize; - -template <typename Numeric> -struct UnsignedOrFloatForSize<Numeric, true, false> -{ - typedef typename UnsignedIntegerForSize<Numeric>::type type; -}; - -template <typename Numeric> -struct UnsignedOrFloatForSize<Numeric, false, true> -{ - typedef Numeric type; -}; - -// Helper templates for integer manipulations. - -template <typename T> -constexpr bool HasSignBit(T x) -{ - // Cast to unsigned since right shift on signed is undefined. - return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >> - PositionOfSignBit<T>::value); -} - -// This wrapper undoes the standard integer promotions. -template <typename T> -constexpr T BinaryComplement(T x) -{ - return static_cast<T>(~x); -} - -// Here are the actual portable checked integer math implementations. -// TODO(jschuh): Break this code out from the enable_if pattern and find a clean -// way to coalesce things into the CheckedNumericState specializations below. - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type -CheckedAdd(T x, T y, RangeConstraint *validity) -{ - // Since the value of x+y is undefined if we have a signed type, we compute - // it using the unsigned type of the same size. - typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; - UnsignedDst ux = static_cast<UnsignedDst>(x); - UnsignedDst uy = static_cast<UnsignedDst>(y); - UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy); - // Addition is valid if the sign of (x + y) is equal to either that of x or - // that of y. - if (std::numeric_limits<T>::is_signed) - { - if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (uresult ^ uy))))) - { - *validity = RANGE_VALID; - } - else - { // Direction of wrap is inverse of result sign. - *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; - } - } - else - { // Unsigned is either valid or overflow. - *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW; - } - return static_cast<T>(uresult); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type -CheckedSub(T x, T y, RangeConstraint *validity) -{ - // Since the value of x+y is undefined if we have a signed type, we compute - // it using the unsigned type of the same size. - typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; - UnsignedDst ux = static_cast<UnsignedDst>(x); - UnsignedDst uy = static_cast<UnsignedDst>(y); - UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy); - // Subtraction is valid if either x and y have same sign, or (x-y) and x have - // the same sign. - if (std::numeric_limits<T>::is_signed) - { - if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (ux ^ uy))))) - { - *validity = RANGE_VALID; - } - else - { // Direction of wrap is inverse of result sign. - *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; - } - } - else - { // Unsigned is either valid or underflow. - *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW; - } - return static_cast<T>(uresult); -} - -// Integer multiplication is a bit complicated. In the fast case we just -// we just promote to a twice wider type, and range check the result. In the -// slow case we need to manually check that the result won't be truncated by -// checking with division against the appropriate bound. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && sizeof(T) * 2 <= sizeof(uintmax_t), - T>::type -CheckedMul(T x, T y, RangeConstraint *validity) -{ - typedef typename TwiceWiderInteger<T>::type IntermediateType; - IntermediateType tmp = static_cast<IntermediateType>(x) * static_cast<IntermediateType>(y); - *validity = DstRangeRelationToSrcRange<T>(tmp); - return static_cast<T>(tmp); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed && - (sizeof(T) * 2 > sizeof(uintmax_t)), - T>::type -CheckedMul(T x, T y, RangeConstraint *validity) -{ - // If either side is zero then the result will be zero. - if (!x || !y) - { - *validity = RANGE_VALID; - return static_cast<T>(0); - } - else if (x > 0) - { - if (y > 0) - *validity = x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW; - else - *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID : RANGE_UNDERFLOW; - } - else - { - if (y > 0) - *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID : RANGE_UNDERFLOW; - else - *validity = y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW; - } - - return static_cast<T>(x * y); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed && - (sizeof(T) * 2 > sizeof(uintmax_t)), - T>::type -CheckedMul(T x, T y, RangeConstraint *validity) -{ - *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) ? RANGE_VALID : RANGE_OVERFLOW; - return static_cast<T>(x * y); -} - -// Division just requires a check for an invalid negation on signed min/-1. -template <typename T> -T CheckedDiv(T x, - T y, - RangeConstraint *validity, - typename std::enable_if<std::numeric_limits<T>::is_integer, int>::type = 0) -{ - if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && - y == static_cast<T>(-1)) - { - *validity = RANGE_OVERFLOW; - return std::numeric_limits<T>::min(); - } - - *validity = RANGE_VALID; - return static_cast<T>(x / y); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, - T>::type -CheckedMod(T x, T y, RangeConstraint *validity) -{ - *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; - return static_cast<T>(x % y); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type -CheckedMod(T x, T y, RangeConstraint *validity) -{ - *validity = RANGE_VALID; - return static_cast<T>(x % y); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, - T>::type -CheckedNeg(T value, RangeConstraint *validity) -{ - *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; - // The negation of signed min is min, so catch that one. - return static_cast<T>(-value); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type -CheckedNeg(T value, RangeConstraint *validity) -{ - // The only legal unsigned negation is zero. - *validity = value ? RANGE_UNDERFLOW : RANGE_VALID; - return static_cast<T>(-static_cast<typename SignedIntegerForSize<T>::type>(value)); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, - T>::type -CheckedAbs(T value, RangeConstraint *validity) -{ - *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; - return static_cast<T>(std::abs(value)); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type -CheckedAbs(T value, RangeConstraint *validity) -{ - // T is unsigned, so |value| must already be positive. - *validity = RANGE_VALID; - return value; -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, - typename UnsignedIntegerForSize<T>::type>::type -CheckedUnsignedAbs(T value) -{ - typedef typename UnsignedIntegerForSize<T>::type UnsignedT; - return value == std::numeric_limits<T>::min() - ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1 - : static_cast<UnsignedT>(std::abs(value)); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type -CheckedUnsignedAbs(T value) -{ - // T is unsigned, so |value| must already be positive. - return static_cast<T>(value); -} - -// These are the floating point stubs that the compiler needs to see. Only the -// negation operation is ever called. -#define ANGLEBASE_FLOAT_ARITHMETIC_STUBS(NAME) \ - template <typename T> \ - typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type Checked##NAME( \ - T, T, RangeConstraint *) \ - { \ - NOTREACHED(); \ - return static_cast<T>(0); \ - } - -ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Add) -ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Sub) -ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Mul) -ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Div) -ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Mod) - -#undef ANGLEBASE_FLOAT_ARITHMETIC_STUBS - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedNeg(T value, - RangeConstraint *) -{ - return static_cast<T>(-value); -} - -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedAbs(T value, - RangeConstraint *) -{ - return static_cast<T>(std::abs(value)); -} - -// Floats carry around their validity state with them, but integers do not. So, -// we wrap the underlying value in a specialization in order to hide that detail -// and expose an interface via accessors. -enum NumericRepresentation -{ - NUMERIC_INTEGER, - NUMERIC_FLOATING, - NUMERIC_UNKNOWN -}; - -template <typename NumericType> -struct GetNumericRepresentation -{ - static const NumericRepresentation value = - std::numeric_limits<NumericType>::is_integer - ? NUMERIC_INTEGER - : (std::numeric_limits<NumericType>::is_iec559 ? NUMERIC_FLOATING : NUMERIC_UNKNOWN); -}; - -template <typename T, NumericRepresentation type = GetNumericRepresentation<T>::value> -class CheckedNumericState -{ -}; - -// Integrals require quite a bit of additional housekeeping to manage state. -template <typename T> -class CheckedNumericState<T, NUMERIC_INTEGER> -{ - private: - T value_; - RangeConstraint validity_ : CHAR_BIT; // Actually requires only two bits. - - public: - template <typename Src, NumericRepresentation type> - friend class CheckedNumericState; - - CheckedNumericState() : value_(0), validity_(RANGE_VALID) {} - - template <typename Src> - CheckedNumericState(Src value, RangeConstraint validity) - : value_(static_cast<T>(value)), - validity_(GetRangeConstraint(validity | DstRangeRelationToSrcRange<T>(value))) - { - static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric."); - } - - // Copy constructor. - template <typename Src> - CheckedNumericState(const CheckedNumericState<Src> &rhs) - : value_(static_cast<T>(rhs.value())), - validity_(GetRangeConstraint(rhs.validity() | DstRangeRelationToSrcRange<T>(rhs.value()))) - { - } - - template <typename Src> - explicit CheckedNumericState( - Src value, - typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0) - : value_(static_cast<T>(value)), validity_(DstRangeRelationToSrcRange<T>(value)) - { - } - - RangeConstraint validity() const { return validity_; } - T value() const { return value_; } -}; - -// Floating points maintain their own validity, but need translation wrappers. -template <typename T> -class CheckedNumericState<T, NUMERIC_FLOATING> -{ - private: - T value_; - - public: - template <typename Src, NumericRepresentation type> - friend class CheckedNumericState; - - CheckedNumericState() : value_(0.0) {} - - template <typename Src> - CheckedNumericState( - Src value, - RangeConstraint validity, - typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = 0) - { - switch (DstRangeRelationToSrcRange<T>(value)) - { - case RANGE_VALID: - value_ = static_cast<T>(value); - break; - - case RANGE_UNDERFLOW: - value_ = -std::numeric_limits<T>::infinity(); - break; - - case RANGE_OVERFLOW: - value_ = std::numeric_limits<T>::infinity(); - break; - - case RANGE_INVALID: - value_ = std::numeric_limits<T>::quiet_NaN(); - break; - - default: - NOTREACHED(); - } - } - - template <typename Src> - explicit CheckedNumericState( - Src value, - typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0) - : value_(static_cast<T>(value)) - { - } - - // Copy constructor. - template <typename Src> - CheckedNumericState(const CheckedNumericState<Src> &rhs) : value_(static_cast<T>(rhs.value())) - { - } - - RangeConstraint validity() const - { - return GetRangeConstraint(value_ <= std::numeric_limits<T>::max(), - value_ >= -std::numeric_limits<T>::max()); - } - T value() const { return value_; } -}; - -// For integers less than 128-bit and floats 32-bit or larger, we have the type -// with the larger maximum exponent take precedence. -enum ArithmeticPromotionCategory -{ - LEFT_PROMOTION, - RIGHT_PROMOTION -}; - -template <typename Lhs, - typename Rhs = Lhs, - ArithmeticPromotionCategory Promotion = - (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) ? LEFT_PROMOTION - : RIGHT_PROMOTION> -struct ArithmeticPromotion; - -template <typename Lhs, typename Rhs> -struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION> -{ - typedef Lhs type; -}; - -template <typename Lhs, typename Rhs> -struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION> -{ - typedef Rhs type; -}; - -// We can statically check if operations on the provided types can wrap, so we -// can skip the checked operations if they're not needed. So, for an integer we -// care if the destination type preserves the sign and is twice the width of -// the source. -template <typename T, typename Lhs, typename Rhs> -struct IsIntegerArithmeticSafe -{ - static const bool value = - !std::numeric_limits<T>::is_iec559 && - StaticDstRangeRelationToSrcRange<T, Lhs>::value == NUMERIC_RANGE_CONTAINED && - sizeof(T) >= (2 * sizeof(Lhs)) && - StaticDstRangeRelationToSrcRange<T, Rhs>::value != NUMERIC_RANGE_CONTAINED && - sizeof(T) >= (2 * sizeof(Rhs)); -}; - -} // namespace internal -} // namespace base - -} // namespace angle - -#endif // ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_ diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc deleted file mode 100644 index 052d850427..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc +++ /dev/null @@ -1,771 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include <limits> -#include <type_traits> - -#include "base/compiler_specific.h" -#include "base/numerics/safe_conversions.h" -#include "base/numerics/safe_math.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) -#include <mmintrin.h> -#endif - -using std::numeric_limits; -using base::CheckedNumeric; -using base::checked_cast; -using base::IsValueInRangeForNumericType; -using base::IsValueNegative; -using base::SizeT; -using base::StrictNumeric; -using base::saturated_cast; -using base::strict_cast; -using base::internal::MaxExponent; -using base::internal::RANGE_VALID; -using base::internal::RANGE_INVALID; -using base::internal::RANGE_OVERFLOW; -using base::internal::RANGE_UNDERFLOW; -using base::internal::SignedIntegerForSize; - -// These tests deliberately cause arithmetic overflows. If the compiler is -// aggressive enough, it can const fold these overflows. Disable warnings about -// overflows for const expressions. -#if defined(OS_WIN) -#pragma warning(disable : 4756) -#endif - -// This is a helper function for finding the maximum value in Src that can be -// wholy represented as the destination floating-point type. -template <typename Dst, typename Src> -Dst GetMaxConvertibleToFloat() -{ - typedef numeric_limits<Dst> DstLimits; - typedef numeric_limits<Src> SrcLimits; - static_assert(SrcLimits::is_specialized, "Source must be numeric."); - static_assert(DstLimits::is_specialized, "Destination must be numeric."); - CHECK(DstLimits::is_iec559); - - if (SrcLimits::digits <= DstLimits::digits && - MaxExponent<Src>::value <= MaxExponent<Dst>::value) - return SrcLimits::max(); - Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0); - while (max != static_cast<Src>(static_cast<Dst>(max))) - { - max /= 2; - } - return static_cast<Dst>(max); -} - -// Helper macros to wrap displaying the conversion types and line numbers. -#define TEST_EXPECTED_VALIDITY(expected, actual) \ - EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).IsValid()) \ - << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst << " on line " \ - << line; - -#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual) -#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual) - -#define TEST_EXPECTED_VALUE(expected, actual) \ - EXPECT_EQ(static_cast<Dst>(expected), CheckedNumeric<Dst>(actual).ValueUnsafe()) \ - << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst << " on line " \ - << line; - -// Signed integer arithmetic. -template <typename Dst> -static void TestSpecializedArithmetic( - const char *dst, - int line, - typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed, - int>::type = 0) -{ - typedef numeric_limits<Dst> DstLimits; - TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min())); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()).Abs()); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); - - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max()); - - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1); - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) - -1); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max()); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max()); - - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) * 2); - - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) / -1); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2); - - // Modulus is legal only for integers. - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1); - TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2); - // Test all the different modulus combinations. - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1); - CheckedNumeric<Dst> checked_dst = 1; - TEST_EXPECTED_VALUE(0, checked_dst %= 1); -} - -// Unsigned integer arithmetic. -template <typename Dst> -static void TestSpecializedArithmetic( - const char *dst, - int line, - typename std::enable_if<numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed, - int>::type = 0) -{ - typedef numeric_limits<Dst> DstLimits; - TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min())); - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs()); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2); - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs()); - TEST_EXPECTED_SUCCESS(CheckedNumeric<typename SignedIntegerForSize<Dst>::type>( - std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min()) - .UnsignedAbs()); - - // Modulus is legal only for integers. - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2); - // Test all the different modulus combinations. - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1); - CheckedNumeric<Dst> checked_dst = 1; - TEST_EXPECTED_VALUE(0, checked_dst %= 1); -} - -// Floating point arithmetic. -template <typename Dst> -void TestSpecializedArithmetic( - const char *dst, - int line, - typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) -{ - typedef numeric_limits<Dst> DstLimits; - TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min())); - - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs()); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs()); - - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1); - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max()); - - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max()); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max()); - - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2); - - TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2); - EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating()); -} - -// Generic arithmetic tests. -template <typename Dst> -static void TestArithmetic(const char *dst, int line) -{ - typedef numeric_limits<Dst> DstLimits; - - EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid()); - EXPECT_EQ( - false, - CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()).IsValid()); - EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie()); - EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1)); - EXPECT_EQ(static_cast<Dst>(1), - CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()) - .ValueOrDefault(1)); - - // Test the operator combinations. - TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1); - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1); - CheckedNumeric<Dst> checked_dst = 1; - TEST_EXPECTED_VALUE(2, checked_dst += 1); - checked_dst = 1; - TEST_EXPECTED_VALUE(0, checked_dst -= 1); - checked_dst = 1; - TEST_EXPECTED_VALUE(1, checked_dst *= 1); - checked_dst = 1; - TEST_EXPECTED_VALUE(1, checked_dst /= 1); - - // Generic negation. - TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>()); - TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1)); - TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1)); - TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1), - -CheckedNumeric<Dst>(DstLimits::max())); - - // Generic absolute value. - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs()); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs()); - TEST_EXPECTED_VALUE(DstLimits::max(), CheckedNumeric<Dst>(DstLimits::max()).Abs()); - - // Generic addition. - TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1)); - TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1)); - TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1)); - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + 1); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max()); - - // Generic subtraction. - TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1)); - TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1)); - TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1)); - TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1); - - // Generic multiplication. - TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1)); - TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1)); - TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2)); - TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0)); - TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0)); - TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1)); - TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()); - - // Generic division. - TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1); - TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1); - TEST_EXPECTED_VALUE(DstLimits::min() / 2, CheckedNumeric<Dst>(DstLimits::min()) / 2); - TEST_EXPECTED_VALUE(DstLimits::max() / 2, CheckedNumeric<Dst>(DstLimits::max()) / 2); - - TestSpecializedArithmetic<Dst>(dst, line); -} - -// Helper macro to wrap displaying the conversion types and line numbers. -#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__) - -TEST(SafeNumerics, SignedIntegerMath) -{ - TEST_ARITHMETIC(int8_t); - TEST_ARITHMETIC(int); - TEST_ARITHMETIC(intptr_t); - TEST_ARITHMETIC(intmax_t); -} - -TEST(SafeNumerics, UnsignedIntegerMath) -{ - TEST_ARITHMETIC(uint8_t); - TEST_ARITHMETIC(unsigned int); - TEST_ARITHMETIC(uintptr_t); - TEST_ARITHMETIC(uintmax_t); -} - -TEST(SafeNumerics, FloatingPointMath) -{ - TEST_ARITHMETIC(float); - TEST_ARITHMETIC(double); -} - -// Enumerates the five different conversions types we need to test. -enum NumericConversionType -{ - SIGN_PRESERVING_VALUE_PRESERVING, - SIGN_PRESERVING_NARROW, - SIGN_TO_UNSIGN_WIDEN_OR_EQUAL, - SIGN_TO_UNSIGN_NARROW, - UNSIGN_TO_SIGN_NARROW_OR_EQUAL, -}; - -// Template covering the different conversion tests. -template <typename Dst, typename Src, NumericConversionType conversion> -struct TestNumericConversion -{ -}; - -// EXPECT_EQ wrappers providing specific detail on test failures. -#define TEST_EXPECTED_RANGE(expected, actual) \ - EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \ - << "Conversion test: " << src << " value " << actual << " to " << dst << " on line " \ - << line; - -template <typename Dst, typename Src> -struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> -{ - static void Test(const char *dst, const char *src, int line) - { - typedef numeric_limits<Src> SrcLimits; - typedef numeric_limits<Dst> DstLimits; - // Integral to floating. - static_assert( - (DstLimits::is_iec559 && SrcLimits::is_integer) || - // Not floating to integral and... - (!(DstLimits::is_integer && SrcLimits::is_iec559) && - // Same sign, same numeric, source is narrower or same. - ((SrcLimits::is_signed == DstLimits::is_signed && sizeof(Dst) >= sizeof(Src)) || - // Or signed destination and source is smaller - (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))), - "Comparison must be sign preserving and value preserving"); - - const CheckedNumeric<Dst> checked_dst = SrcLimits::max(); - TEST_EXPECTED_SUCCESS(checked_dst); - if (MaxExponent<Dst>::value > MaxExponent<Src>::value) - { - if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) - { - // At least twice larger type. - TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst); - } - else - { // Larger, but not at least twice as large. - TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst); - TEST_EXPECTED_SUCCESS(checked_dst + 1); - } - } - else - { // Same width type. - TEST_EXPECTED_FAILURE(checked_dst + 1); - } - - TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); - if (SrcLimits::is_iec559) - { - TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1)); - TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); - TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); - } - else if (numeric_limits<Src>::is_signed) - { - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); - TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); - } - } -}; - -template <typename Dst, typename Src> -struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> -{ - static void Test(const char *dst, const char *src, int line) - { - typedef numeric_limits<Src> SrcLimits; - typedef numeric_limits<Dst> DstLimits; - static_assert(SrcLimits::is_signed == DstLimits::is_signed, - "Destination and source sign must be the same"); - static_assert(sizeof(Dst) < sizeof(Src) || (DstLimits::is_integer && SrcLimits::is_iec559), - "Destination must be narrower than source"); - - const CheckedNumeric<Dst> checked_dst; - TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); - TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); - TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max()); - - TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); - if (SrcLimits::is_iec559) - { - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); - TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); - TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); - if (DstLimits::is_integer) - { - if (SrcLimits::digits < DstLimits::digits) - { - TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max())); - } - else - { - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max())); - } - TEST_EXPECTED_RANGE(RANGE_VALID, - static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>())); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min())); - } - } - else if (SrcLimits::is_signed) - { - TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1)); - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); - } - else - { - TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1)); - TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); - } - } -}; - -template <typename Dst, typename Src> -struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> -{ - static void Test(const char *dst, const char *src, int line) - { - typedef numeric_limits<Src> SrcLimits; - typedef numeric_limits<Dst> DstLimits; - static_assert(sizeof(Dst) >= sizeof(Src), - "Destination must be equal or wider than source."); - static_assert(SrcLimits::is_signed, "Source must be signed"); - static_assert(!DstLimits::is_signed, "Destination must be unsigned"); - - const CheckedNumeric<Dst> checked_dst; - TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max()); - TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); - TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); - - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); - TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max()); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); - } -}; - -template <typename Dst, typename Src> -struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> -{ - static void Test(const char *dst, const char *src, int line) - { - typedef numeric_limits<Src> SrcLimits; - typedef numeric_limits<Dst> DstLimits; - static_assert( - (DstLimits::is_integer && SrcLimits::is_iec559) || (sizeof(Dst) < sizeof(Src)), - "Destination must be narrower than source."); - static_assert(SrcLimits::is_signed, "Source must be signed."); - static_assert(!DstLimits::is_signed, "Destination must be unsigned."); - - const CheckedNumeric<Dst> checked_dst; - TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); - TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); - TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1)); - TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max()); - - TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1)); - if (SrcLimits::is_iec559) - { - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1); - TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); - TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); - if (DstLimits::is_integer) - { - if (SrcLimits::digits < DstLimits::digits) - { - TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max())); - } - else - { - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max())); - } - TEST_EXPECTED_RANGE(RANGE_VALID, - static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>())); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min())); - } - } - else - { - TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); - } - } -}; - -template <typename Dst, typename Src> -struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> -{ - static void Test(const char *dst, const char *src, int line) - { - typedef numeric_limits<Src> SrcLimits; - typedef numeric_limits<Dst> DstLimits; - static_assert(sizeof(Dst) <= sizeof(Src), - "Destination must be narrower or equal to source."); - static_assert(!SrcLimits::is_signed, "Source must be unsigned."); - static_assert(DstLimits::is_signed, "Destination must be signed."); - - const CheckedNumeric<Dst> checked_dst; - TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1)); - TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max()); - TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min()); - - TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); - TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max()); - TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1)); - } -}; - -// Helper macro to wrap displaying the conversion types and line numbers -#define TEST_NUMERIC_CONVERSION(d, s, t) TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__) - -TEST(SafeNumerics, IntMinOperations) -{ - TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING); - - TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW); - TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW); - TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW); - - TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); - - TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW); - TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW); - TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW); - - TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); - TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); -} - -TEST(SafeNumerics, IntOperations) -{ - TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(unsigned int, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(unsigned int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING); - - TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW); - TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW); - TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW); - TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW); - - TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); - TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); - - TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW); - TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW); - TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW); - - TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); - TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); -} - -TEST(SafeNumerics, IntMaxOperations) -{ - TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(intmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING); - - TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW); - TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW); - - TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); - TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); - - TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW); - TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW); - - TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); -} - -TEST(SafeNumerics, FloatOperations) -{ - TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(float, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING); - - TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW); -} - -TEST(SafeNumerics, DoubleOperations) -{ - TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING); - TEST_NUMERIC_CONVERSION(double, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING); -} - -TEST(SafeNumerics, SizeTOperations) -{ - TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL); - TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL); -} - -TEST(SafeNumerics, CastTests) -{ -// MSVC catches and warns that we're forcing saturation in these tests. -// Since that's intentional, we need to shut this warning off. -#if defined(COMPILER_MSVC) -#pragma warning(disable : 4756) -#endif - - int small_positive = 1; - int small_negative = -1; - double double_small = 1.0; - double double_large = numeric_limits<double>::max(); - double double_infinity = numeric_limits<float>::infinity(); - double double_large_int = numeric_limits<int>::max(); - double double_small_int = numeric_limits<int>::min(); - - // Just test that the casts compile, since the other tests cover logic. - EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0))); - EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0))); - EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0))); - EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0))); - EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U))); - EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U))); - EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U))); - - EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid()); - EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid()); - EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid()); - - EXPECT_TRUE(IsValueNegative(-1)); - EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min())); - EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min())); - EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max())); - EXPECT_FALSE(IsValueNegative(0)); - EXPECT_FALSE(IsValueNegative(1)); - EXPECT_FALSE(IsValueNegative(0u)); - EXPECT_FALSE(IsValueNegative(1u)); - EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max())); - EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max())); - EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max())); - - // These casts and coercions will fail to compile: - // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0))); - // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0))); - // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1)); - // EXPECT_EQ(1, StrictNumeric<size_t>(1U)); - - // Test various saturation corner cases. - EXPECT_EQ(saturated_cast<int>(small_negative), static_cast<int>(small_negative)); - EXPECT_EQ(saturated_cast<int>(small_positive), static_cast<int>(small_positive)); - EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0)); - EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small)); - EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max()); - EXPECT_EQ(saturated_cast<float>(double_large), double_infinity); - EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity); - EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int)); - EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int)); - - float not_a_number = - std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity(); - EXPECT_TRUE(std::isnan(not_a_number)); - EXPECT_EQ(0, saturated_cast<int>(not_a_number)); -} - -#if GTEST_HAS_DEATH_TEST - -TEST(SafeNumerics, SaturatedCastChecks) -{ - float not_a_number = - std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity(); - EXPECT_TRUE(std::isnan(not_a_number)); - EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(not_a_number)), ""); -} - -#endif // GTEST_HAS_DEATH_TEST - -TEST(SafeNumerics, IsValueInRangeForNumericType) -{ - EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0)); - EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1)); - EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2)); - EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1)); - EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu)); - EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff))); - EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000))); - EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001))); - EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int32_t>::min())); - EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int64_t>::min())); - - EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0)); - EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1)); - EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2)); - EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1)); - EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff)); - EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu)); - EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u)); - EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu)); - EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000))); - EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff))); - EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000))); - EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int32_t>::min())); - EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>( - static_cast<int64_t>(std::numeric_limits<int32_t>::min()))); - EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>( - static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1)); - EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int64_t>::min())); - - EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0)); - EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1)); - EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2)); - EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1)); - EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu)); - EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff))); - EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000))); - EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001))); - EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int32_t>::min())); - EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1))); - EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int64_t>::min())); - - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0)); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1)); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2)); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1)); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff)); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu)); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u)); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu)); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000))); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff))); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000))); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff))); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff))); - EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000))); - EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff))); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int32_t>::min())); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>( - static_cast<int64_t>(std::numeric_limits<int32_t>::min()))); - EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int64_t>::min())); -} - -TEST(SafeNumerics, CompoundNumericOperations) -{ - CheckedNumeric<int> a = 1; - CheckedNumeric<int> b = 2; - CheckedNumeric<int> c = 3; - CheckedNumeric<int> d = 4; - a += b; - EXPECT_EQ(3, a.ValueOrDie()); - a -= c; - EXPECT_EQ(0, a.ValueOrDie()); - d /= b; - EXPECT_EQ(2, d.ValueOrDie()); - d *= d; - EXPECT_EQ(4, d.ValueOrDie()); - - CheckedNumeric<int> too_large = std::numeric_limits<int>::max(); - EXPECT_TRUE(too_large.IsValid()); - too_large += d; - EXPECT_FALSE(too_large.IsValid()); - too_large -= d; - EXPECT_FALSE(too_large.IsValid()); - too_large /= d; - EXPECT_FALSE(too_large.IsValid()); -} diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.cc b/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.cc deleted file mode 100644 index cb88ba06e1..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.cc +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "anglebase/sha1.h" - -#include <stddef.h> -#include <stdint.h> -#include <string.h> - -#include "anglebase/sys_byteorder.h" - -namespace angle -{ - -namespace base -{ - -// Implementation of SHA-1. Only handles data in byte-sized blocks, -// which simplifies the code a fair bit. - -// Identifier names follow notation in FIPS PUB 180-3, where you'll -// also find a description of the algorithm: -// http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf - -// Usage example: -// -// SecureHashAlgorithm sha; -// while(there is data to hash) -// sha.Update(moredata, size of data); -// sha.Final(); -// memcpy(somewhere, sha.Digest(), 20); -// -// to reuse the instance of sha, call sha.Init(); - -// TODO(jhawkins): Replace this implementation with a per-platform -// implementation using each platform's crypto library. See -// http://crbug.com/47218 - -class SecureHashAlgorithm -{ - public: - SecureHashAlgorithm() { Init(); } - - static const int kDigestSizeBytes; - - void Init(); - void Update(const void *data, size_t nbytes); - void Final(); - - // 20 bytes of message digest. - const unsigned char *Digest() const { return reinterpret_cast<const unsigned char *>(H); } - - private: - void Pad(); - void Process(); - - uint32_t A, B, C, D, E; - - uint32_t H[5]; - - union { - uint32_t W[80]; - uint8_t M[64]; - }; - - uint32_t cursor; - uint64_t l; -}; - -static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D) -{ - if (t < 20) - { - return (B & C) | ((~B) & D); - } - else if (t < 40) - { - return B ^ C ^ D; - } - else if (t < 60) - { - return (B & C) | (B & D) | (C & D); - } - else - { - return B ^ C ^ D; - } -} - -static inline uint32_t S(uint32_t n, uint32_t X) -{ - return (X << n) | (X >> (32 - n)); -} - -static inline uint32_t K(uint32_t t) -{ - if (t < 20) - { - return 0x5a827999; - } - else if (t < 40) - { - return 0x6ed9eba1; - } - else if (t < 60) - { - return 0x8f1bbcdc; - } - else - { - return 0xca62c1d6; - } -} - -const int SecureHashAlgorithm::kDigestSizeBytes = 20; - -void SecureHashAlgorithm::Init() -{ - A = 0; - B = 0; - C = 0; - D = 0; - E = 0; - cursor = 0; - l = 0; - H[0] = 0x67452301; - H[1] = 0xefcdab89; - H[2] = 0x98badcfe; - H[3] = 0x10325476; - H[4] = 0xc3d2e1f0; -} - -void SecureHashAlgorithm::Final() -{ - Pad(); - Process(); - - for (int t = 0; t < 5; ++t) - H[t] = ByteSwap(H[t]); -} - -void SecureHashAlgorithm::Update(const void *data, size_t nbytes) -{ - const uint8_t *d = reinterpret_cast<const uint8_t *>(data); - while (nbytes--) - { - M[cursor++] = *d++; - if (cursor >= 64) - Process(); - l += 8; - } -} - -void SecureHashAlgorithm::Pad() -{ - M[cursor++] = 0x80; - - if (cursor > 64 - 8) - { - // pad out to next block - while (cursor < 64) - M[cursor++] = 0; - - Process(); - } - - while (cursor < 64 - 8) - M[cursor++] = 0; - - M[cursor++] = (l >> 56) & 0xff; - M[cursor++] = (l >> 48) & 0xff; - M[cursor++] = (l >> 40) & 0xff; - M[cursor++] = (l >> 32) & 0xff; - M[cursor++] = (l >> 24) & 0xff; - M[cursor++] = (l >> 16) & 0xff; - M[cursor++] = (l >> 8) & 0xff; - M[cursor++] = l & 0xff; -} - -void SecureHashAlgorithm::Process() -{ - uint32_t t; - - // Each a...e corresponds to a section in the FIPS 180-3 algorithm. - - // a. - // - // W and M are in a union, so no need to memcpy. - // memcpy(W, M, sizeof(M)); - for (t = 0; t < 16; ++t) - W[t] = ByteSwap(W[t]); - - // b. - for (t = 16; t < 80; ++t) - W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); - - // c. - A = H[0]; - B = H[1]; - C = H[2]; - D = H[3]; - E = H[4]; - - // d. - for (t = 0; t < 80; ++t) - { - uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t); - E = D; - D = C; - C = S(30, B); - B = A; - A = TEMP; - } - - // e. - H[0] += A; - H[1] += B; - H[2] += C; - H[3] += D; - H[4] += E; - - cursor = 0; -} - -std::string SHA1HashString(const std::string &str) -{ - char hash[SecureHashAlgorithm::kDigestSizeBytes]; - SHA1HashBytes(reinterpret_cast<const unsigned char *>(str.c_str()), str.length(), - reinterpret_cast<unsigned char *>(hash)); - return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes); -} - -void SHA1HashBytes(const unsigned char *data, size_t len, unsigned char *hash) -{ - SecureHashAlgorithm sha; - sha.Update(data, len); - sha.Final(); - - memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes); -} - -} // namespace base - -} // namespace angle diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.h deleted file mode 100644 index a60908814f..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ANGLEBASE_SHA1_H_ -#define ANGLEBASE_SHA1_H_ - -#include <stddef.h> - -#include <string> - -#include "anglebase/base_export.h" - -namespace angle -{ - -namespace base -{ - -// These functions perform SHA-1 operations. - -static const size_t kSHA1Length = 20; // Length in bytes of a SHA-1 hash. - -// Computes the SHA-1 hash of the input string |str| and returns the full -// hash. -ANGLEBASE_EXPORT std::string SHA1HashString(const std::string &str); - -// Computes the SHA-1 hash of the |len| bytes in |data| and puts the hash -// in |hash|. |hash| must be kSHA1Length bytes long. -ANGLEBASE_EXPORT void SHA1HashBytes(const unsigned char *data, size_t len, unsigned char *hash); - -} // namespace base - -} // namespace angle - -#endif // ANGLEBASE_SHA1_H_ diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/sys_byteorder.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/sys_byteorder.h deleted file mode 100644 index 43d1777f26..0000000000 --- a/src/3rdparty/angle/src/common/third_party/base/anglebase/sys_byteorder.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// Copyright 2017 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// sys_byteorder.h: Compatiblity hacks for importing Chromium's base/SHA1. - -#ifndef ANGLEBASE_SYS_BYTEORDER_H_ -#define ANGLEBASE_SYS_BYTEORDER_H_ - -namespace angle -{ - -namespace base -{ - -// Returns a value with all bytes in |x| swapped, i.e. reverses the endianness. -inline uint16_t ByteSwap(uint16_t x) -{ -#if defined(_MSC_VER) - return _byteswap_ushort(x); -#else - return __builtin_bswap16(x); -#endif -} - -inline uint32_t ByteSwap(uint32_t x) -{ -#if defined(_MSC_VER) - return _byteswap_ulong(x); -#else - return __builtin_bswap32(x); -#endif -} - -inline uint64_t ByteSwap(uint64_t x) -{ -#if defined(_MSC_VER) - return _byteswap_uint64(x); -#else - return __builtin_bswap64(x); -#endif -} - -} // namespace base - -} // namespace angle - -#endif // ANGLEBASE_SYS_BYTEORDER_H_
\ No newline at end of file |