-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[libc] -Wshift-count-overflow in libc/src/__support/UInt.h #74623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@llvm/issue-subscribers-libc Author: Nick Desaulniers (nickdesaulniers)
```
[692/693] Building CXX object projects/libc/src/stdio/prin...s/libc.src.stdio.printf_core.converter.dir/converter.cpp.o
In file included from /android0/llvm-project/libc/src/__support/UInt128.h:12,
from /android0/llvm-project/libc/src/__support/FPUtil/FloatProperties.h:12,
from /android0/llvm-project/libc/src/__support/FPUtil/FPBits.h:17,
from /android0/llvm-project/libc/src/stdio/printf_core/core_structs.h:13,
from /android0/llvm-project/libc/src/stdio/printf_core/converter.h:12,
from /android0/llvm-project/libc/src/stdio/printf_core/converter.cpp:9:
/android0/llvm-project/libc/src/__support/UInt.h: In instantiation of ‘constexpr __llvm_libc_18_0_0_git::cpp::BigInt<Bits, Signed>::operator T() const [with T = unsigned int; <template-parameter-2-2> = void; long unsigned int Bits = 320; bool Signed = false]’:
/android0/llvm-project/libc/src/__support/float_to_string.h:381:57: required from here
/android0/llvm-project/libc/src/__support/UInt.h:125:53: warning: left shift count >= width of type [-Wshift-count-overflow]
125 | return static_cast<T>((static_cast<T>(val[1]) << 64) + lo);
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
```
I'm trying to get -Werror re-enabled in https://github.com//pull/74506; building with GCC flags the above warning.
|
@lntue is there any way we can use SFINAE to split I'd imagine we could have the implementation when return static_cast<T>(val[0]); then the existing implementation (when sizeof(T) > 8) be: // T is 128-bit.
T lo = static_cast<T>(val[0]);
if constexpr (Bits == 64) {
if constexpr (Signed) {
// Extend sign for negative numbers.
return (val[0] >> 63) ? ((T(-1) << 64) + lo) : lo;
} else {
return lo;
}
} else {
return static_cast<T>((static_cast<T>(val[1]) << 64) + lo);
} my SFINAE skills aren't great; so not sure if that's possible... |
You can split the template into 2 with SFINAE as follow:
|
That's what I would have thought. I have: diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h
index 3bec2e3a4713..5d9049186b82 100644
--- a/libc/src/__support/UInt.h
+++ b/libc/src/__support/UInt.h
@@ -104,12 +104,15 @@ template <size_t Bits, bool Signed> struct BigInt {
}
template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T> &&
- sizeof(T) <= 16 &&
+ sizeof(T) <= 8 &&
!cpp::is_same_v<T, bool>>>
LIBC_INLINE constexpr explicit operator T() const {
- if constexpr (sizeof(T) <= 8)
- return static_cast<T>(val[0]);
+ return static_cast<T>(val[0]);
+ }
+ template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T> &&
+ sizeof(T) == 16>>
+ LIBC_INLINE constexpr explicit operator T() const {
// T is 128-bit.
T lo = static_cast<T>(val[0]);
@@ -121,7 +124,6 @@ template <size_t Bits, bool Signed> struct BigInt {
return lo;
}
} else {
- // TODO: silence shift warning
return static_cast<T>((static_cast<T>(val[1]) << 64) + lo);
}
} but I observe the error with GCC:
I thought the usage of |
How about this one:
|
gah, you beat me to it! I have this working for either g++ or clang++: diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h
index 3bec2e3a4713..16a1fcc7d807 100644
--- a/libc/src/__support/UInt.h
+++ b/libc/src/__support/UInt.h
@@ -103,13 +103,21 @@ template <size_t Bits, bool Signed> struct BigInt {
val[i] = words[i];
}
- template <typename T, typename = cpp::enable_if_t<cpp::is_integral_v<T> &&
- sizeof(T) <= 16 &&
- !cpp::is_same_v<T, bool>>>
+
+
+ template<typename T>
LIBC_INLINE constexpr explicit operator T() const {
- if constexpr (sizeof(T) <= 8)
- return static_cast<T>(val[0]);
+ return to<T>();
+ }
+ template <typename T>
+ LIBC_INLINE constexpr
+ cpp::enable_if_t<cpp::is_integral_v<T> && sizeof(T) <= 8 && !cpp::is_same_v<T, bool>, T> to() const {
+ return static_cast<T>(val[0]);
+ }
+ template <typename T>
+ LIBC_INLINE constexpr
+ cpp::enable_if_t<cpp::is_integral_v<T> && sizeof(T) == 16, T> to() const {
// T is 128-bit.
T lo = static_cast<T>(val[0]);
@@ -121,7 +129,6 @@ template <size_t Bits, bool Signed> struct BigInt {
return lo;
}
} else {
- // TODO: silence shift warning
return static_cast<T>((static_cast<T>(val[1]) << 64) + lo);
}
} I guess what I was missing was the use of the |
Not that I'm very good at SFINAE, but it seems that conversion operators are perhaps difficult to compose with SFINAE. I saw an example that used one layer of indirection to have an explicit return type that could then be used with enable_if_t. Link: https://stackoverflow.com/a/7604580 Fixes: llvm#74623
Not that I'm very good at SFINAE, but it seems that conversion operators are perhaps difficult to compose with SFINAE. I saw an example that used one layer of indirection to have an explicit return type that could then be used with enable_if_t. Link: https://stackoverflow.com/a/7604580 Fixes: #74623
I'm trying to get -Werror re-enabled in #74506; building with GCC flags the above warning.
The text was updated successfully, but these errors were encountered: