[pushed v2 3/4] Rewrite valid-expr.h's internals in terms of the detection idiom (C++17/N4502)
Luis Machado
luis.machado@linaro.org
Thu Sep 17 16:23:15 GMT 2020
Ok. Even though 14.04 is no longer supported, I suspect GCC 6.4.1 is
still fairly recent that we shouldn't be seeing this.
On 9/17/20 1:10 PM, Vaseeharan Vinayagamoorthy wrote:
> I observe this error when building on an aarch64-none-linux-gnu machine, running ubuntu 14.04.5.
> The compiler it is using is aarch64-none-linux-gnu-gcc version 6.4.1.
>
>
> On 17/09/2020, 11:58, "Gdb-patches on behalf of Vaseeharan Vinayagamoorthy" <gdb-patches-bounces@sourceware.org on behalf of Vaseeharan.Vinayagamoorthy@arm.com> wrote:
>
> Relevant to this patch, I am seeing error: type/value mismatch from valid-expr.h:65:20 when building GDB with:
> Build: aarch64-none-linux-gnu
> Host: aarch64-none-linux-gnu
> Target: aarch64-none-linux-gnu
>
>
> In file included from binutils-gdb--gdb/gdb/unittests/offset-type-selftests.c:24:0:
> /binutils-gdb--gdb/gdb/unittests/offset-type-selftests.c: In substitution of 'template<class Expected, template<class ...> class Op, class ... Args> using is_detected_exact = std::is_same<Expected, typename gdb::detection_detail::detector<gdb::nonesuch, void, Op, Args ...>::type> [with Expected = selftests::offset_type::off_A&; Op = selftests::offset_type::check_valid_expr75::archetype; Args = {selftests::offset_type::off_A, selftests::offset_type::off_B}]':
>
> /binutils-gdb--gdb/gdb/unittests/offset-type-selftests.c:75:1: required from here
> /binutils-gdb--gdb/gdb/../gdbsupport/valid-expr.h:65:20: error: type/value mismatch at argument 2 in template parameter list for 'template<class Expected, template<class ...> class Op, class ... Args> using is_detected_exact = std::is_same<Expected, typename gdb::detection_detail::detector<gdb::nonesuch, void, Op, Args ...>::type>'
> archetype, TYPES>::value == VALID, \
> ^
> /binutils-gdb--gdb/gdb/../gdbsupport/valid-expr.h:79:3: note: in expansion of macro 'CHECK_VALID_EXPR_INT'
> CHECK_VALID_EXPR_INT (ESC_PARENS(typename T1, typename T2), \
> ^~~~~~~~~~~~~~~~~~~~
> /binutils-gdb--gdb/gdb/unittests/offset-type-selftests.c:42:3: note: in expansion of macro 'CHECK_VALID_EXPR_2'
> CHECK_VALID_EXPR_2 (off_A, off_B, VALID, EXPR_TYPE, EXPR)
> ^~~~~~~~~~~~~~~~~~
>
>
>
> Regards,
> Vasee
>
>
>
>
> On 14/09/2020, 22:31, "Gdb-patches on behalf of Pedro Alves" <gdb-patches-bounces@sourceware.org on behalf of pedro@palves.net> wrote:
>
> An earlier attempt at doing this had failed (wouldn't work in GCCs
> around 4.8, IIRC), but now that I try again, it works. I suspect that
> my previous attempt did not use the pre C++14-safe void_t (in
> traits.h).
>
> I want to switch to this model because:
>
> - It's the standard detection idiom that folks will learn starting
> with C++17.
>
> - In the enum_flags unit tests, I have a static_assert that triggers
> a warning (resulting in build error), which GCC does not suppress
> because the warning is not being triggered in the SFINAE context.
> Switching to the detection idiom fixes that. Alternatively,
> switching to the C++03-style expression-validity checking with a
> varargs overload would allow addressing that, but I think that
> would be going backwards idiomatically speaking.
>
> - While this patch shows a net increase of lines of code, the magic
> being added to traits.h can be removed in a few years when we start
> requiring C++17.
>
> gdbsupport/ChangeLog:
>
> * traits.h (struct nonesuch, struct detector, detected_or)
> (detected_or_t, is_detected, detected_t, detected_or)
> (detected_or_t, is_detected_exact, is_detected_convertible): New.
> * valid-expr.h (CHECK_VALID_EXPR_INT): Use gdb::is_detected_exact.
> ---
> gdbsupport/ChangeLog | 7 ++++++
> gdbsupport/traits.h | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
> gdbsupport/valid-expr.h | 20 +++------------
> 3 files changed, 77 insertions(+), 17 deletions(-)
>
> diff --git a/gdbsupport/ChangeLog b/gdbsupport/ChangeLog
> index 6cda6050f9..4858cc6b56 100644
> --- a/gdbsupport/ChangeLog
> +++ b/gdbsupport/ChangeLog
> @@ -1,3 +1,10 @@
> +2020-09-14 Pedro Alves <pedro@palves.net>
> +
> + * traits.h (struct nonesuch, struct detector, detected_or)
> + (detected_or_t, is_detected, detected_t, detected_or)
> + (detected_or_t, is_detected_exact, is_detected_convertible): New.
> + * valid-expr.h (CHECK_VALID_EXPR_INT): Use gdb::is_detected_exact.
> +
> 2020-09-10 Kamil Rytarowski <n54@gmx.com>
>
> * eintr.h: New file.
> diff --git a/gdbsupport/traits.h b/gdbsupport/traits.h
> index 2a6f00654c..93b609ac10 100644
> --- a/gdbsupport/traits.h
> +++ b/gdbsupport/traits.h
> @@ -52,6 +52,73 @@ struct make_void { typedef void type; };
> template<typename... Ts>
> using void_t = typename make_void<Ts...>::type;
>
> +/* Implementation of the detection idiom:
> +
> + - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf
> + - http://en.cppreference.com/w/cpp/experimental/is_detected
> +
> +*/
> +
> +struct nonesuch
> +{
> + nonesuch () = delete;
> + ~nonesuch () = delete;
> + nonesuch (const nonesuch &) = delete;
> + void operator= (const nonesuch &) = delete;
> +};
> +
> +namespace detection_detail {
> +/* Implementation of the detection idiom (negative case). */
> +template<typename Default, typename AlwaysVoid,
> + template<typename...> class Op, typename... Args>
> +struct detector
> +{
> + using value_t = std::false_type;
> + using type = Default;
> +};
> +
> +/* Implementation of the detection idiom (positive case). */
> +template<typename Default, template<typename...> class Op, typename... Args>
> +struct detector<Default, void_t<Op<Args...>>, Op, Args...>
> +{
> + using value_t = std::true_type;
> + using type = Op<Args...>;
> +};
> +
> +/* Detect whether Op<Args...> is a valid type, use Default if not. */
> +template<typename Default, template<typename...> class Op,
> + typename... Args>
> +using detected_or = detector<Default, void, Op, Args...>;
> +
> +/* Op<Args...> if that is a valid type, otherwise Default. */
> +template<typename Default, template<typename...> class Op,
> + typename... Args>
> +using detected_or_t
> + = typename detected_or<Default, Op, Args...>::type;
> +
> +} /* detection_detail */
> +
> +template<template<typename...> class Op, typename... Args>
> +using is_detected
> + = typename detection_detail::detector<nonesuch, void, Op, Args...>::value_t;
> +
> +template<template<typename...> class Op, typename... Args>
> +using detected_t
> + = typename detection_detail::detector<nonesuch, void, Op, Args...>::type;
> +
> +template<typename Default, template<typename...> class Op, typename... Args>
> +using detected_or = detection_detail::detected_or<Default, Op, Args...>;
> +
> +template<typename Default, template<typename...> class Op, typename... Args>
> +using detected_or_t = typename detected_or<Default, Op, Args...>::type;
> +
> +template<typename Expected, template<typename...> class Op, typename... Args>
> +using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
> +
> +template<typename To, template<typename...> class Op, typename... Args>
> +using is_detected_convertible
> + = std::is_convertible<detected_t<Op, Args...>, To>;
> +
> /* A few trait helpers, mainly stolen from libstdc++. Uppercase
> because "and/or", etc. are reserved keywords. */
>
> diff --git a/gdbsupport/valid-expr.h b/gdbsupport/valid-expr.h
> index b1c8446814..a22fa61134 100644
> --- a/gdbsupport/valid-expr.h
> +++ b/gdbsupport/valid-expr.h
> @@ -58,26 +58,12 @@
> #define CHECK_VALID_EXPR_INT(TYPENAMES, TYPES, VALID, EXPR_TYPE, EXPR) \
> namespace CONCAT (check_valid_expr, __LINE__) { \
> \
> - template<typename, typename, typename = void> \
> - struct is_valid_expression \
> - : std::false_type {}; \
> - \
> template <TYPENAMES> \
> - struct is_valid_expression<TYPES, gdb::void_t<decltype (EXPR)>> \
> - : std::true_type {}; \
> + using archetype = decltype (EXPR); \
> \
> - static_assert (is_valid_expression<TYPES>::value == VALID, \
> + static_assert (gdb::is_detected_exact<EXPR_TYPE, \
> + archetype, TYPES>::value == VALID, \
> ""); \
> - \
> - template<TYPENAMES, typename = void> \
> - struct is_same_type \
> - : std::is_same<EXPR_TYPE, void> {}; \
> - \
> - template <TYPENAMES> \
> - struct is_same_type<TYPES, gdb::void_t<decltype (EXPR)>> \
> - : std::is_same<EXPR_TYPE, decltype (EXPR)> {}; \
> - \
> - static_assert (is_same_type<TYPES>::value, ""); \
> } /* namespace */
>
> /* A few convenience macros that support expressions involving a
> --
> 2.14.5
>
>
>
More information about the Gdb-patches
mailing list