mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-03 04:26:55 +00:00
131 lines
5.7 KiB
Diff
131 lines
5.7 KiB
Diff
|
From e3b59e5461c81f03b608f24388af716c1983e2d0 Mon Sep 17 00:00:00 2001
|
||
|
From: Simon Marchi <simon.marchi@efficios.com>
|
||
|
Date: Thu, 23 Feb 2023 17:35:40 +0000
|
||
|
Subject: [PATCH] gdbsupport: ignore -Wenum-constexpr-conversion in
|
||
|
enum-flags.h
|
||
|
|
||
|
When building with clang 16, we get:
|
||
|
|
||
|
CXX gdb.o
|
||
|
In file included from /home/smarchi/src/binutils-gdb/gdb/gdb.c:19:
|
||
|
In file included from /home/smarchi/src/binutils-gdb/gdb/defs.h:65:
|
||
|
/home/smarchi/src/binutils-gdb/gdb/../gdbsupport/enum-flags.h:95:52: error: integer value -1 is outside the valid range of values [0, 15] for this enumeration type [-Wenum-constexpr-conversion]
|
||
|
integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type
|
||
|
^
|
||
|
|
||
|
The error message does not make it clear in the context of which enum
|
||
|
flag this fails (i.e. what is T in this context), but it doesn't really
|
||
|
matter, we have similar warning/errors for many of them, if we let the
|
||
|
build go through.
|
||
|
|
||
|
clang is right that the value -1 is invalid for the enum type we cast -1
|
||
|
to. However, we do need this expression in order to select an integer
|
||
|
type with the appropriate signedness. That is, with the same signedness
|
||
|
as the underlying type of the enum.
|
||
|
|
||
|
I first wondered if that was really needed, if we couldn't use
|
||
|
std::underlying_type for that. It turns out that the comment just above
|
||
|
says:
|
||
|
|
||
|
/* Note that std::underlying_type<enum_type> is not what we want here,
|
||
|
since that returns unsigned int even when the enum decays to signed
|
||
|
int. */
|
||
|
|
||
|
I was surprised, because std::is_signed<std::underlying_type<enum_type>>
|
||
|
returns the right thing. So I tried replacing all this with
|
||
|
std::underlying_type, see if that would work. Doing so causes some
|
||
|
build failures in unittests/enum-flags-selftests.c:
|
||
|
|
||
|
CXX unittests/enum-flags-selftests.o
|
||
|
/home/smarchi/src/binutils-gdb/gdb/unittests/enum-flags-selftests.c:254:1: error: static assertion failed due to requirement 'gdb::is_same<selftests::enum_flags_tests::check_valid_expr254::archetype<enum_flags<s
|
||
|
elftests::enum_flags_tests::RE>, selftests::enum_flags_tests::RE, enum_flags<selftests::enum_flags_tests::RE2>, selftests::enum_flags_tests::RE2, enum_flags<selftests::enum_flags_tests::URE>, selftests::enum_fla
|
||
|
gs_tests::URE, int>, selftests::enum_flags_tests::check_valid_expr254::archetype<enum_flags<selftests::enum_flags_tests::RE>, selftests::enum_flags_tests::RE, enum_flags<selftests::enum_flags_tests::RE2>, selfte
|
||
|
sts::enum_flags_tests::RE2, enum_flags<selftests::enum_flags_tests::URE>, selftests::enum_flags_tests::URE, unsigned int>>::value == true':
|
||
|
CHECK_VALID (true, int, true ? EF () : EF2 ())
|
||
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
/home/smarchi/src/binutils-gdb/gdb/unittests/enum-flags-selftests.c:91:3: note: expanded from macro 'CHECK_VALID'
|
||
|
CHECK_VALID_EXPR_6 (EF, RE, EF2, RE2, UEF, URE, VALID, EXPR_TYPE, EXPR)
|
||
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
/home/smarchi/src/binutils-gdb/gdb/../gdbsupport/valid-expr.h:105:3: note: expanded from macro 'CHECK_VALID_EXPR_6'
|
||
|
CHECK_VALID_EXPR_INT (ESC_PARENS (typename T1, typename T2, \
|
||
|
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
/home/smarchi/src/binutils-gdb/gdb/../gdbsupport/valid-expr.h:66:3: note: expanded from macro 'CHECK_VALID_EXPR_INT'
|
||
|
static_assert (gdb::is_detected_exact<archetype<TYPES, EXPR_TYPE>, \
|
||
|
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
This is a bit hard to decode, but basically enumerations have the
|
||
|
following funny property that they decay into a signed int, even if
|
||
|
their implicit underlying type is unsigned. This code:
|
||
|
|
||
|
enum A {};
|
||
|
enum B {};
|
||
|
|
||
|
int main() {
|
||
|
std::cout << std::is_signed<std::underlying_type<A>::type>::value
|
||
|
<< std::endl;
|
||
|
std::cout << std::is_signed<std::underlying_type<B>::type>::value
|
||
|
<< std::endl;
|
||
|
auto result = true ? A() : B();
|
||
|
std::cout << std::is_signed<decltype(result)>::value << std::endl;
|
||
|
}
|
||
|
|
||
|
produces:
|
||
|
|
||
|
0
|
||
|
0
|
||
|
1
|
||
|
|
||
|
So, the "CHECK_VALID" above checks that this property works for enum flags the
|
||
|
same way as it would if you were using their underlying enum types. And
|
||
|
somehow, changing integer_for_size to use std::underlying_type breaks that.
|
||
|
|
||
|
Since the current code does what we want, and I don't see any way of doing it
|
||
|
differently, ignore -Wenum-constexpr-conversion around it.
|
||
|
|
||
|
Change-Id: Ibc82ae7bbdb812102ae3f1dd099fc859dc6f3cc2
|
||
|
---
|
||
|
gdbsupport/enum-flags.h | 3 +++
|
||
|
include/diagnostics.h | 9 +++++++++
|
||
|
2 files changed, 12 insertions(+)
|
||
|
|
||
|
--- a/gdbsupport/enum-flags.h
|
||
|
+++ b/gdbsupport/enum-flags.h
|
||
|
@@ -91,9 +91,12 @@ template<> struct integer_for_size<8, 1>
|
||
|
template<typename T>
|
||
|
struct enum_underlying_type
|
||
|
{
|
||
|
+ DIAGNOSTIC_PUSH
|
||
|
+ DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
|
||
|
typedef typename
|
||
|
integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type
|
||
|
type;
|
||
|
+ DIAGNOSTIC_POP
|
||
|
};
|
||
|
|
||
|
namespace enum_flags_detail
|
||
|
--- a/include/diagnostics.h
|
||
|
+++ b/include/diagnostics.h
|
||
|
@@ -66,6 +66,11 @@
|
||
|
# define DIAGNOSTIC_ERROR_SWITCH \
|
||
|
DIAGNOSTIC_ERROR ("-Wswitch")
|
||
|
|
||
|
+# if __has_warning ("-Wenum-constexpr-conversion")
|
||
|
+# define DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION \
|
||
|
+ DIAGNOSTIC_IGNORE ("-Wenum-constexpr-conversion")
|
||
|
+# endif
|
||
|
+
|
||
|
#elif defined (__GNUC__) /* GCC */
|
||
|
|
||
|
# if __GNUC__ >= 7
|
||
|
@@ -96,6 +101,10 @@
|
||
|
# define DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
|
||
|
#endif
|
||
|
|
||
|
+#ifndef DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
|
||
|
+# define DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
|
||
|
+#endif
|
||
|
+
|
||
|
#ifndef DIAGNOSTIC_IGNORE_DEPRECATED_REGISTER
|
||
|
# define DIAGNOSTIC_IGNORE_DEPRECATED_REGISTER
|
||
|
#endif
|