Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Mullvad Browser
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
The Tor Project
Applications
Mullvad Browser
Commits
0758dd98
Commit
0758dd98
authored
2 years ago
by
Stanca Serban
Browse files
Options
Downloads
Patches
Plain Diff
Backed out changeset 39cfeb7cffda (bug 646323) for causing bustages in Casting.h. CLOSED TREE
parent
3155509b
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
mfbt/Casting.h
+124
-102
124 additions, 102 deletions
mfbt/Casting.h
mfbt/tests/TestCasting.cpp
+0
-156
0 additions, 156 deletions
mfbt/tests/TestCasting.cpp
with
124 additions
and
258 deletions
mfbt/Casting.h
+
124
−
102
View file @
0758dd98
...
...
@@ -12,9 +12,8 @@
#include
"mozilla/Assertions.h"
#include
<cstring>
#include
<limits.h>
#include
<type_traits>
#include
<limits>
#include
<cmath>
namespace
mozilla
{
...
...
@@ -66,133 +65,156 @@ inline To BitwiseCast(const From aFrom) {
namespace
detail
{
template
<
typename
T
>
constexpr
int64_t
safe_integer
()
{
static_assert
(
std
::
is_floating_point_v
<
T
>
);
return
std
::
pow
(
2
,
std
::
numeric_limits
<
T
>::
digits
);
}
enum
ToSignedness
{
ToIsSigned
,
ToIsUnsigned
};
enum
FromSignedness
{
FromIsSigned
,
FromIsUnsigned
};
template
<
typename
From
,
typename
To
,
FromSignedness
=
std
::
is_signed_v
<
From
>
?
FromIsSigned
:
FromIsUnsigned
,
ToSignedness
=
std
::
is_signed_v
<
To
>
?
ToIsSigned
:
ToIsUnsigned
>
struct
BoundsCheckImpl
;
// Implicit conversions on operands to binary operations make this all a bit
// hard to verify. Attempt to ease the pain below by *only* comparing values
// that are obviously the same type (and will undergo no further conversions),
// even when it's not strictly necessary, for explicitness.
enum
UUComparison
{
FromIsBigger
,
FromIsNotBigger
};
// Unsigned-to-unsigned range check
template
<
typename
From
,
typename
To
,
UUComparison
=
(
sizeof
(
From
)
>
sizeof
(
To
))
?
FromIsBigger
:
FromIsNotBigger
>
struct
UnsignedUnsignedCheck
;
template
<
typename
From
,
typename
To
>
struct
UnsignedUnsignedCheck
<
From
,
To
,
FromIsBigger
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
return
aFrom
<=
From
(
To
(
-
1
));
}
};
template
<
typename
From
,
typename
To
>
struct
UnsignedUnsignedCheck
<
From
,
To
,
FromIsNotBigger
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
return
true
;
}
};
template
<
typename
From
,
typename
To
>
struct
BoundsCheckImpl
<
From
,
To
,
FromIsUnsigned
,
ToIsUnsigned
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
return
UnsignedUnsignedCheck
<
From
,
To
>::
checkBounds
(
aFrom
);
}
};
template
<
typename
T
>
constexpr
uint64_t
safe_integer_unsigned
()
{
static_assert
(
std
::
is_floating_point_v
<
T
>
);
return
std
::
pow
(
2
,
std
::
numeric_limits
<
T
>::
digits
);
}
// Signed-to-unsigned range check
// This is working around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81676,
// fixed in gcc-10
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
template
<
typename
In
,
typename
Out
>
bool
IsInBounds
(
In
aIn
)
{
constexpr
bool
inSigned
=
std
::
is_signed_v
<
In
>
;
constexpr
bool
outSigned
=
std
::
is_signed_v
<
Out
>
;
constexpr
bool
bothSigned
=
inSigned
&&
outSigned
;
constexpr
bool
bothUnsigned
=
!
inSigned
&&
!
outSigned
;
constexpr
bool
inFloat
=
std
::
is_floating_point_v
<
In
>
;
constexpr
bool
outFloat
=
std
::
is_floating_point_v
<
Out
>
;
constexpr
bool
bothFloat
=
inFloat
&&
outFloat
;
constexpr
bool
noneFloat
=
!
inFloat
&&
!
outFloat
;
constexpr
Out
outMax
=
std
::
numeric_limits
<
Out
>::
max
();
constexpr
Out
outMin
=
std
::
numeric_limits
<
Out
>::
lowest
();
// This selects the widest of two types, and is used to cast throughout.
using
select_widest
=
std
::
conditional_t
<
(
sizeof
(
In
)
>
sizeof
(
Out
)),
In
,
Out
>
;
if
constexpr
(
bothFloat
)
{
if
(
aIn
>
select_widest
(
outMax
)
||
aIn
<
select_widest
(
outMin
))
{
return
false
;
}
}
// Normal casting applies, the floating point number is floored.
if
constexpr
(
inFloat
&&
!
outFloat
)
{
static_assert
(
sizeof
(
aIn
)
<=
sizeof
(
int64_t
));
// Check if the input floating point is larger than the output bounds. This
// catches situations where the input is a float larger than the max of the
// output type.
if
(
aIn
<
static_cast
<
double
>
(
outMin
)
||
aIn
>
static_cast
<
double
>
(
outMax
))
{
template
<
typename
From
,
typename
To
>
struct
BoundsCheckImpl
<
From
,
To
,
FromIsSigned
,
ToIsUnsigned
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
if
(
aFrom
<
0
)
{
return
false
;
}
// At this point we know that the input can be converted to an integer.
// Check if it's larger than the bounds of the target integer.
if
(
outSigned
)
{
int64_t
asInteger
=
static_cast
<
int64_t
>
(
aIn
);
if
(
asInteger
<
outMin
||
asInteger
>
outMax
)
{
return
false
;
}
}
else
{
uint64_t
asInteger
=
static_cast
<
uint64_t
>
(
aIn
);
if
(
asInteger
<
0
||
asInteger
>
outMax
)
{
return
false
;
}
if
(
sizeof
(
To
)
>=
sizeof
(
From
))
{
return
true
;
}
return
aFrom
<=
From
(
To
(
-
1
));
}
};
// Checks if the integer is representable exactly as a floating point value of
// a specific width.
if
constexpr
(
!
inFloat
&&
outFloat
)
{
if
constexpr
(
inSigned
)
{
if
(
aIn
<
-
safe_integer
<
Out
>
()
||
aIn
>
safe_integer
<
Out
>
())
{
return
false
;
}
}
else
{
if
(
aIn
>=
safe_integer_unsigned
<
Out
>
())
{
return
false
;
}
}
// Unsigned-to-signed range check
enum
USComparison
{
FromIsSmaller
,
FromIsNotSmaller
};
template
<
typename
From
,
typename
To
,
USComparison
=
(
sizeof
(
From
)
<
sizeof
(
To
))
?
FromIsSmaller
:
FromIsNotSmaller
>
struct
UnsignedSignedCheck
;
template
<
typename
From
,
typename
To
>
struct
UnsignedSignedCheck
<
From
,
To
,
FromIsSmaller
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
return
true
;
}
};
template
<
typename
From
,
typename
To
>
struct
UnsignedSignedCheck
<
From
,
To
,
FromIsNotSmaller
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
const
To
MaxValue
=
To
((
1ULL
<<
(
CHAR_BIT
*
sizeof
(
To
)
-
1
))
-
1
);
return
aFrom
<=
From
(
MaxValue
);
}
};
if
constexpr
(
noneFloat
)
{
if
constexpr
(
bothUnsigned
)
{
if
(
aIn
>
select_widest
(
outMax
))
{
return
false
;
}
}
if
constexpr
(
bothSigned
)
{
if
(
aIn
>
select_widest
(
outMax
)
||
aIn
<
select_widest
(
outMin
))
{
return
false
;
}
}
if
constexpr
(
inSigned
&&
!
outSigned
)
{
if
(
aIn
<
0
||
std
::
make_unsigned_t
<
In
>
(
aIn
)
>
outMax
)
{
return
false
;
}
}
if
constexpr
(
!
inSigned
&&
outSigned
)
{
if
(
aIn
>
select_widest
(
outMax
))
{
return
false
;
}
template
<
typename
From
,
typename
To
>
struct
BoundsCheckImpl
<
From
,
To
,
FromIsUnsigned
,
ToIsSigned
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
return
UnsignedSignedCheck
<
From
,
To
>::
checkBounds
(
aFrom
);
}
};
// Signed-to-signed range check
template
<
typename
From
,
typename
To
>
struct
BoundsCheckImpl
<
From
,
To
,
FromIsSigned
,
ToIsSigned
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
if
(
sizeof
(
From
)
<=
sizeof
(
To
))
{
return
true
;
}
const
To
MaxValue
=
To
((
1ULL
<<
(
CHAR_BIT
*
sizeof
(
To
)
-
1
))
-
1
);
const
To
MinValue
=
-
MaxValue
-
To
(
1
);
return
From
(
MinValue
)
<=
aFrom
&&
From
(
aFrom
)
<=
From
(
MaxValue
);
}
};
template
<
typename
From
,
typename
To
,
bool
TypesAreIntegral
=
std
::
is_integral_v
<
From
>
&&
std
::
is_integral_v
<
To
>>
class
BoundsChecker
;
template
<
typename
From
>
class
BoundsChecker
<
From
,
From
,
true
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
return
true
;
}
};
template
<
typename
From
,
typename
To
>
class
BoundsChecker
<
From
,
To
,
true
>
{
public:
static
bool
checkBounds
(
const
From
aFrom
)
{
return
BoundsCheckImpl
<
From
,
To
>::
checkBounds
(
aFrom
);
}
return
true
;
};
template
<
typename
From
,
typename
To
>
inline
bool
IsInBounds
(
const
From
aFrom
)
{
return
BoundsChecker
<
From
,
To
>::
checkBounds
(
aFrom
);
}
#pragma GCC diagnostic pop
}
// namespace detail
/**
* Cast a value of type |From| to a value of type |To|, asserting that the cast
* will be a safe cast per C++ (that is, that |to| is in the range of values
* permitted for the type |From|).
* In particular, this will fail if a integer cannot be represented exactly as a
* floating point value, because it's too large.
* Cast a value of integral type |From| to a value of integral type |To|,
* asserting that the cast will be a safe cast per C++ (that is, that |to| is in
* the range of values permitted for the type |From|).
*/
template
<
typename
To
,
typename
From
>
inline
To
AssertedCast
(
const
From
aFrom
)
{
static_assert
(
std
::
is_arithmetic_v
<
To
>
&&
std
::
is_arithmetic_v
<
From
>
);
MOZ_ASSERT
((
detail
::
IsInBounds
<
From
,
To
>
(
aFrom
)));
return
static_cast
<
To
>
(
aFrom
);
}
/**
* Cast a value of numeric type |From| to a value of numeric type |To|, release
* asserting that the cast will be a safe cast per C++ (that is, that |to| is in
* the range of values permitted for the type |From|).
* In particular, this will fail if a integer cannot be represented exactly as a
* floating point value, because it's too large.
* Cast a value of integral type |From| to a value of integral type |To|,
* release asserting that the cast will be a safe cast per C++ (that is, that
* |to| is in the range of values permitted for the type |From|).
*/
template
<
typename
To
,
typename
From
>
inline
To
ReleaseAssertedCast
(
const
From
aFrom
)
{
static_assert
(
std
::
is_arithmetic_v
<
To
>
&&
std
::
is_arithmetic_v
<
From
>
);
MOZ_RELEASE_ASSERT
((
detail
::
IsInBounds
<
From
,
To
>
(
aFrom
)));
return
static_cast
<
To
>
(
aFrom
);
}
...
...
This diff is collapsed.
Click to expand it.
mfbt/tests/TestCasting.cpp
+
0
−
156
View file @
0758dd98
...
...
@@ -5,20 +5,12 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include
"mozilla/Casting.h"
#include
"mozilla/ThreadSafety.h"
#include
<stdint.h>
#include
<cstdint>
#include
<limits>
#include
<type_traits>
using
mozilla
::
AssertedCast
;
using
mozilla
::
BitwiseCast
;
using
mozilla
::
detail
::
IsInBounds
;
static
const
uint8_t
floatMantissaBitsPlusOne
=
24
;
static
const
uint8_t
doubleMantissaBitsPlusOne
=
53
;
template
<
typename
Uint
,
typename
Ulong
,
bool
=
(
sizeof
(
Uint
)
==
sizeof
(
Ulong
))>
struct
UintUlongBitwiseCast
;
...
...
@@ -96,160 +88,12 @@ static void TestToSmallerSize() {
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
int64_t
,
uint32_t
>
(
int64_t
(
UINT32_MAX
)
+
1
)));
}
template
<
typename
In
,
typename
Out
>
void
checkBoundariesFloating
(
In
aEpsilon
=
{},
Out
aIntegerOffset
=
{})
{
// Check the max value of the input float can't be represented as an integer.
// This is true for all floating point and integer width.
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
In
,
Out
>
(
std
::
numeric_limits
<
In
>::
max
())));
// Check that the max value of the integer, as a float, minus an offset that
// depends on the magnitude, can be represented as an integer.
MOZ_RELEASE_ASSERT
((
IsInBounds
<
In
,
Out
>
(
static_cast
<
In
>
(
std
::
numeric_limits
<
Out
>::
max
()
-
aIntegerOffset
))));
// Check that the max value of the integer, plus a number that depends on the
// magnitude of the number, can't be represented as this integer (because it
// becomes too big).
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
In
,
Out
>
(
aEpsilon
+
static_cast
<
In
>
(
std
::
numeric_limits
<
Out
>::
max
()))));
if
constexpr
(
std
::
is_signed_v
<
In
>
)
{
// Same for negative numbers.
MOZ_RELEASE_ASSERT
(
(
!
IsInBounds
<
In
,
Out
>
(
std
::
numeric_limits
<
In
>::
lowest
())));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
In
,
Out
>
(
static_cast
<
In
>
(
std
::
numeric_limits
<
Out
>::
lowest
()))));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
In
,
Out
>
(
static_cast
<
In
>
(
std
::
numeric_limits
<
Out
>::
lowest
())
-
aEpsilon
)));
}
else
{
// Check for negative floats and unsigned integer types.
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
In
,
Out
>
(
static_cast
<
In
>
(
-
1
))));
}
}
void
TestFloatConversion
()
{
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
uint64_t
,
float
>
(
UINT64_MAX
)));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
uint32_t
,
float
>
(
UINT32_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
uint16_t
,
float
>
(
UINT16_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
uint8_t
,
float
>
(
UINT8_MAX
)));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
int64_t
,
float
>
(
INT64_MAX
)));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
int64_t
,
float
>
(
INT64_MIN
)));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
int32_t
,
float
>
(
INT32_MAX
)));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
int32_t
,
float
>
(
INT32_MIN
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int16_t
,
float
>
(
INT16_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int16_t
,
float
>
(
INT16_MIN
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int8_t
,
float
>
(
INT8_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int8_t
,
float
>
(
INT8_MIN
)));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
uint64_t
,
double
>
(
UINT64_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
uint32_t
,
double
>
(
UINT32_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
uint16_t
,
double
>
(
UINT16_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
uint8_t
,
double
>
(
UINT8_MAX
)));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
int64_t
,
double
>
(
INT64_MAX
)));
MOZ_RELEASE_ASSERT
((
!
IsInBounds
<
int64_t
,
double
>
(
INT64_MIN
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int32_t
,
double
>
(
INT32_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int32_t
,
double
>
(
INT32_MIN
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int16_t
,
double
>
(
INT16_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int16_t
,
double
>
(
INT16_MIN
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int8_t
,
double
>
(
INT8_MAX
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int8_t
,
double
>
(
INT8_MIN
)));
// Floor check
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
uint64_t
>
(
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
uint64_t
>
(
4.3
f
)
==
4u
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
uint32_t
>
(
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
uint32_t
>
(
4.3
f
)
==
4u
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
uint16_t
>
(
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
uint16_t
>
(
4.3
f
)
==
4u
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
uint8_t
>
(
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
uint8_t
>
(
4.3
f
)
==
4u
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
int64_t
>
(
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
int64_t
>
(
4.3
f
)
==
4u
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
int32_t
>
(
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
int32_t
>
(
4.3
f
)
==
4u
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
int16_t
>
(
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
int16_t
>
(
4.3
f
)
==
4u
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
int8_t
>
(
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
int8_t
>
(
4.3
f
)
==
4u
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
int64_t
>
(
-
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
int64_t
>
(
-
4.3
f
)
==
-
4
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
int32_t
>
(
-
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
int32_t
>
(
-
4.3
f
)
==
-
4
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
int16_t
>
(
-
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
int16_t
>
(
-
4.3
f
)
==
-
4
));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
float
,
int8_t
>
(
-
4.3
)));
MOZ_RELEASE_ASSERT
((
AssertedCast
<
int8_t
>
(
-
4.3
f
)
==
-
4
));
// Bound check for float to unsigned integer conversion. The parameters are
// espilons and offsets allowing to check boundaries, that depend on the
// magnitude of the numbers.
checkBoundariesFloating
<
double
,
uint64_t
>
(
2049.
);
checkBoundariesFloating
<
double
,
uint32_t
>
(
1.
);
checkBoundariesFloating
<
double
,
uint16_t
>
(
1.
);
checkBoundariesFloating
<
double
,
uint8_t
>
(
1.
);
// Large number because of the lack of precision of floats at this magnitude
checkBoundariesFloating
<
float
,
uint64_t
>
(
1.1e12
f
);
checkBoundariesFloating
<
float
,
uint32_t
>
(
1.
f
,
128u
);
checkBoundariesFloating
<
float
,
uint16_t
>
(
1.
f
);
checkBoundariesFloating
<
float
,
uint8_t
>
(
1.
f
);
checkBoundariesFloating
<
double
,
int64_t
>
(
1025.
);
checkBoundariesFloating
<
double
,
int32_t
>
(
1.
);
checkBoundariesFloating
<
double
,
int16_t
>
(
1.
);
checkBoundariesFloating
<
double
,
int8_t
>
(
1.
);
// Large number because of the lack of precision of floats at this magnitude
checkBoundariesFloating
<
float
,
int64_t
>
(
1.1e12
f
);
checkBoundariesFloating
<
float
,
int32_t
>
(
256.
f
,
64u
);
checkBoundariesFloating
<
float
,
int16_t
>
(
1.
f
);
checkBoundariesFloating
<
float
,
int8_t
>
(
1.
f
);
// Integer to floating point, boundary cases
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
int64_t
,
float
>
(
int64_t
(
std
::
pow
(
2
,
floatMantissaBitsPlusOne
))
+
1
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int64_t
,
float
>
(
int64_t
(
std
::
pow
(
2
,
floatMantissaBitsPlusOne
)))));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int64_t
,
float
>
(
int64_t
(
std
::
pow
(
2
,
floatMantissaBitsPlusOne
))
-
1
)));
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
int64_t
,
float
>
(
int64_t
(
-
std
::
pow
(
2
,
floatMantissaBitsPlusOne
))
-
1
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int64_t
,
float
>
(
int64_t
(
-
std
::
pow
(
2
,
floatMantissaBitsPlusOne
)))));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int64_t
,
float
>
(
int64_t
(
-
std
::
pow
(
2
,
floatMantissaBitsPlusOne
))
+
1
)));
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
int64_t
,
double
>
(
uint64_t
(
std
::
pow
(
2
,
doubleMantissaBitsPlusOne
))
+
1
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int64_t
,
double
>
(
uint64_t
(
std
::
pow
(
2
,
doubleMantissaBitsPlusOne
)))));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int64_t
,
double
>
(
uint64_t
(
std
::
pow
(
2
,
doubleMantissaBitsPlusOne
))
-
1
)));
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
int64_t
,
double
>
(
int64_t
(
-
std
::
pow
(
2
,
doubleMantissaBitsPlusOne
))
-
1
)));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int64_t
,
double
>
(
int64_t
(
-
std
::
pow
(
2
,
doubleMantissaBitsPlusOne
)))));
MOZ_RELEASE_ASSERT
((
IsInBounds
<
int64_t
,
double
>
(
int64_t
(
-
std
::
pow
(
2
,
doubleMantissaBitsPlusOne
))
+
1
)));
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
uint64_t
,
double
>
(
UINT64_MAX
)));
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
int64_t
,
double
>
(
INT64_MAX
)));
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
int64_t
,
double
>
(
INT64_MIN
)));
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
double
,
float
>
(
std
::
numeric_limits
<
double
>::
max
())));
MOZ_RELEASE_ASSERT
(
!
(
IsInBounds
<
double
,
float
>
(
-
std
::
numeric_limits
<
double
>::
max
())));
}
int
main
()
{
TestBitwiseCast
();
TestSameSize
();
TestToBiggerSize
();
TestToSmallerSize
();
TestFloatConversion
();
return
0
;
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment