Skip to content

Commit 1808310

Browse files
committed
Make sure bytes::to[U]Int returns runtime integers.
A user was using code like function make(): tuple<uint64> { return (b"\x00\x00".to_uint(spicy::ByteOrder::Big), ); } Before this patch this would generate a tuple constructor from an an naked `uint64_t` which failed in the conversion to the expected safe integer at C++ compilation time with a pretty cryptic C++ compiler error /spicy/hilti/runtime/include/hilti/rt/3rdparty/SafeInt/SafeInt.hpp:5538:52: error: incomplete definition of type 'GetCastMethod<unsigned long long, std::tuple<std::optional<unsigned long long>>>' 5538 | SafeCastHelper< T, U, GetCastMethod< T, U >::method >::template CastThrow< E >( i, m_int ); | ~~~~~~~~~~~~~~~~~~~~~^~ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk/usr/include/c++/v1/optional:337:9: note: in instantiation of function template specialization 'SafeInt<unsigned long long, hilti::rt::integer::det ail::SafeIntException>::SafeInt<std::tuple<std::optional<unsigned long long>>>' requested here 337 | : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} | ^ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk/usr/include/c++/v1/optional:686:57: note: in instantiation of function template specialization 'std::__optional_destruct_base<SafeInt<unsigned lon g long, hilti::rt::integer::detail::SafeIntException>>::__optional_destruct_base<std::tuple<std::optional<unsigned long long>>>' requested here 686 | _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {} | ^ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk/usr/include/c++/v1/optional:686:57: note: (skipping 1 context in backtrace; use -ftemplate-backtrace-limit=0 to see all) /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk/usr/include/c++/v1/tuple:345:9: note: in instantiation of function template specialization 'std::optional<SafeInt<unsigned long long, hilti::rt::i nteger::detail::SafeIntException>>::optional<std::tuple<std::optional<unsigned long long>>, 0>' requested here 345 | : __value_(std::forward<_Tp>(__t)) { | ^ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk/usr/include/c++/v1/tuple:473:9: note: in instantiation of function template specialization 'std::__tuple_leaf<0, std::optional<SafeInt<unsigned lo ng long, hilti::rt::integer::detail::SafeIntException>>>::__tuple_leaf<std::tuple<std::optional<unsigned long long>>, void>' requested here 473 | : __tuple_leaf<_Uf, _Tf>(std::forward<_Up>(__u))..., __tuple_leaf<_Ul, _Tl>()... {} | ^ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk/usr/include/c++/v1/tuple:620:9: note: in instantiation of function template specialization 'std::__tuple_impl<std::__tuple_indices<0>, std::option al<SafeInt<unsigned long long, hilti::rt::integer::detail::SafeIntException>>>::__tuple_impl<0UL, std::optional<SafeInt<unsigned long long, hilti::rt::integer::detail::SafeIntException>>, std::tuple<std::optional<unsigned long long>>>' requeste$ here 620 | : __base_(typename __make_tuple_indices<sizeof...(_Up)>::type(), | ^ /private/var/folders/ht/vtb0rkbd4ws15vx02xdb84zw0000gn/T/foo_5591707596a5ab7-1743e21b33c7da2.cc:36:12: note: in instantiation of function template specialization 'std::tuple<std::optional<SafeInt<unsigned long long, hilti::rt::integer::detail::S afeIntException>>>::tuple<std::tuple<std::optional<unsigned long long>>, 0>' requested here 36 | return hilti::rt::tuple::make_from_optionals(hilti::rt::tuple::wrap_expression([&]() { return "\000\000"_b.toUInt(::hilti::rt::ByteOrder{::hilti::rt::ByteOrder::Big}); })); | ^ The only way to work around that would have been to explicitly create a temporary integer and use that, e.g., function make(): tuple<uint64> { local x = b"\x00\x00".to_uint(spicy::ByteOrder::Big); return (x, ); } With this patch this works like expected. (cherry picked from commit 94a4441)
1 parent 84c3404 commit 1808310

File tree

2 files changed

+5
-5
lines changed

2 files changed

+5
-5
lines changed

hilti/runtime/include/types/bytes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ class Bytes : protected std::string {
477477
* @param byte_order byte order that the integer is encoded in
478478
* @return converted integer value
479479
*/
480-
int64_t toInt(hilti::rt::ByteOrder byte_order) const;
480+
integer::safe<int64_t> toInt(hilti::rt::ByteOrder byte_order) const;
481481

482482
/**
483483
* Interprets the data as an binary representation of an unsigned
@@ -486,7 +486,7 @@ class Bytes : protected std::string {
486486
* @param byte_order byte order that the integer is encoded in
487487
* @return converted integer value
488488
*/
489-
uint64_t toUInt(hilti::rt::ByteOrder byte_order) const;
489+
integer::safe<uint64_t> toUInt(hilti::rt::ByteOrder byte_order) const;
490490

491491
/**
492492
* Interprets the data as an ASCII representation of a floating point value

hilti/runtime/src/types/bytes.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ integer::safe<uint64_t> Bytes::toUInt(uint64_t base) const {
171171
throw RuntimeError("cannot parse bytes as unsigned integer");
172172
}
173173

174-
int64_t Bytes::toInt(ByteOrder byte_order) const {
175-
auto i = toUInt(byte_order); // throws on size == 0 or size > 8
174+
integer::safe<int64_t> Bytes::toInt(ByteOrder byte_order) const {
175+
auto i = toUInt(byte_order).Ref(); // throws on size == 0 or size > 8
176176
auto size_ = static_cast<uint64_t>(size());
177177

178178
if ( i & (UINT64_C(1) << (size_ * 8 - 1)) ) {
@@ -185,7 +185,7 @@ int64_t Bytes::toInt(ByteOrder byte_order) const {
185185
return static_cast<int64_t>(i);
186186
}
187187

188-
uint64_t Bytes::toUInt(ByteOrder byte_order) const {
188+
integer::safe<uint64_t> Bytes::toUInt(ByteOrder byte_order) const {
189189
switch ( byte_order.value() ) {
190190
case ByteOrder::Undef: throw InvalidArgument("cannot convert value to undefined byte order");
191191
case ByteOrder::Host: return toInt(systemByteOrder());

0 commit comments

Comments
 (0)