Skip to content

Commit 603c977

Browse files
authored
Removed forced unsigned int cast in type_def bit-shift operators (#1178)
* Removed UB in type_def bit-shift operators * Changed shift operators to allow both signed and unsigned operands for shifts This allows the library user to explicitly use unsigned values to avoid UB * Fixed constexpr errors for CPP11 * Changed is_arithmetic checks to use is_integral since valid shifts require integral operands * Removed need for CPP11 since changes are CPP03 compatible
1 parent db57df1 commit 603c977

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

include/etl/type_def.h

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,14 +290,18 @@ namespace etl
290290
}
291291

292292
//*********************************************************************
293-
ETL_CONSTEXPR14 type_def& operator <<=(int rhs) ETL_NOEXCEPT
293+
template <typename T>
294+
ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value, type_def&>::type
295+
operator <<=(T rhs) ETL_NOEXCEPT
294296
{
295297
value <<= rhs;
296298
return *this;
297299
}
298300

299301
//*********************************************************************
300-
ETL_CONSTEXPR14 type_def& operator >>=(int rhs) ETL_NOEXCEPT
302+
template <typename T>
303+
ETL_CONSTEXPR14 typename etl::enable_if<etl::is_integral<T>::value, type_def&>::type
304+
operator >>=(T rhs) ETL_NOEXCEPT
301305
{
302306
value >>= rhs;
303307
return *this;
@@ -589,19 +593,40 @@ namespace etl
589593
//*********************************************************************
590594
// << operator
591595
//*********************************************************************
592-
friend ETL_CONSTEXPR type_def operator <<(const type_def& lhs, int rhs) ETL_NOEXCEPT
596+
template <typename T>
597+
friend ETL_CONSTEXPR typename etl::enable_if<etl::is_integral<T>::value, type_def>::type
598+
operator <<(const type_def& lhs, T rhs) ETL_NOEXCEPT
593599
{
594600
return type_def(lhs.value << rhs);
595601
}
596602

603+
//*********************************************************************
604+
template <typename T>
605+
friend ETL_CONSTEXPR typename etl::enable_if<(etl::is_integral<T>::value && etl::is_integral<TValue>::value), T>::type
606+
operator <<(T lhs, const type_def& rhs) ETL_NOEXCEPT
607+
{
608+
return lhs << rhs.value;
609+
}
610+
597611
//*********************************************************************
598612
// >> operator
599613
//*********************************************************************
600-
friend ETL_CONSTEXPR type_def operator >>(const type_def& lhs, int rhs) ETL_NOEXCEPT
614+
template <typename T>
615+
friend ETL_CONSTEXPR typename etl::enable_if<etl::is_integral<T>::value, type_def>::type
616+
operator >>(const type_def& lhs, T rhs) ETL_NOEXCEPT
601617
{
602618
return type_def(lhs.value >> rhs);
603619
}
604620

621+
//*********************************************************************
622+
template <typename T>
623+
friend ETL_CONSTEXPR
624+
typename etl::enable_if<(etl::is_integral<T>::value && etl::is_integral<TValue>::value), T>::type
625+
operator >>(T lhs, const type_def& rhs) ETL_NOEXCEPT
626+
{
627+
return lhs >> rhs.value;
628+
}
629+
605630
//*********************************************************************
606631
// < operator
607632
//*********************************************************************

test/test_type_def.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@ namespace
179179
CHECK_EQUAL(i |= 0x003DU, uint32_t(t |= type_t(0x003DU)));
180180
CHECK_EQUAL(i ^= 0xAA55U, uint32_t(t ^= 0xAA55U));
181181
CHECK_EQUAL(i ^= 0xAA55U, uint32_t(t ^= type_t(0xAA55U)));
182+
CHECK_EQUAL(i <<= 2, uint32_t(t <<= 2));
182183
CHECK_EQUAL(i <<= 2U, uint32_t(t <<= 2U));
184+
CHECK_EQUAL(i >>= 2, uint32_t(t >>= 2));
183185
CHECK_EQUAL(i >>= 2U, uint32_t(t >>= 2U));
184186
CHECK_EQUAL(i %= 23, uint32_t(t %= 23));
185187

@@ -195,8 +197,10 @@ namespace
195197

196198
uint32_t i1 = 0x5A3DUL;
197199
uint32_t i2 = 0xB47AUL;
200+
uint32_t i3 = 3UL;
198201
type_t t1(0x5A3DUL);
199202
type_t t2(0xB47AUL);
203+
type_t t3(3UL);
200204

201205
CHECK_EQUAL(i1 + Two, t1 + Two);
202206
CHECK_EQUAL(Two + i1, Two + t1);
@@ -205,11 +209,11 @@ namespace
205209
CHECK_EQUAL(i1 - Two, t1 - Two);
206210
CHECK_EQUAL(i2 - i1, i2 - t1);
207211
CHECK_EQUAL(i2 - i1, t2 - t1);
208-
212+
209213
CHECK_EQUAL(i1 * Two, t1 * Two);
210214
CHECK_EQUAL(Two * i1, Two * t1);
211215
CHECK_EQUAL(i1 * i2, t1 * t2);
212-
216+
213217
CHECK_EQUAL(i1 / Two, t1 / Two);
214218
CHECK_EQUAL(i2 / i1, i2 / t1);
215219
CHECK_EQUAL(i2 / i1, t2 / t1);
@@ -227,7 +231,16 @@ namespace
227231
CHECK_EQUAL(uint32_t(0xAA55) ^ i1, type_t(0xAA55UL) ^ t1);
228232

229233
CHECK_EQUAL(i1 << 2, t1 << 2);
234+
CHECK_EQUAL(i1 << 2U, t1 << 2U);
235+
CHECK_EQUAL(2 << i3, 2 << t3);
236+
CHECK_EQUAL(2U << i3, 2U << t3);
237+
CHECK_EQUAL(i1 << i3, t1 << t3);
238+
230239
CHECK_EQUAL(i1 >> 2, t1 >> 2);
240+
CHECK_EQUAL(i1 >> 2U, t1 >> 2U);
241+
CHECK_EQUAL(42 >> i3, 42 >> t3);
242+
CHECK_EQUAL(42U >> i3, 42U >> t3);
243+
CHECK_EQUAL(i1 >> i3, t1 >> t3);
231244

232245
CHECK_EQUAL(i1 % uint32_t(23), t1 % uint32_t(23));
233246
CHECK_EQUAL(uint32_t(23) % i1, uint32_t(23) % t1);
@@ -313,7 +326,7 @@ namespace
313326

314327
return value;
315328
}
316-
329+
317330
TEST(test_arithmetic_constexpr)
318331
{
319332
constexpr arithmetic_type_t value_plus = CreatePlus();

0 commit comments

Comments
 (0)