Bug 89102 - 'common_type' of single abominable function should not have a nested typename
Summary: 'common_type' of single abominable function should not have a nested typename
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 8.2.0
: P3 normal
Target Milestone: 8.4
Assignee: Jonathan Wakely
URL:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2019-01-29 13:42 UTC by Alisdair Meredith
Modified: 2021-03-29 20:04 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-02-06 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alisdair Meredith 2019-01-29 13:42:02 UTC
According to the formula for 'common_type', as an abominable function type does not have a valid return type for 'declval', the trait should not have a nested 'type' name.

The following program shows this is not the case (I have not tried to work out what the nested name aliases, probably the type itself):


template <typename TestType, typename = void>
inline constexpr bool DetectType = false;

template <typename TestType >
inline constexpr
bool DetectType<TestType, std::void_t<typename TestType::type>> = true;

// Quick proof detector works correctly
struct NoType {};
struct HasType { using type = HasType; };

static_assert( DetectType<HasType> );
static_assert(!DetectType<NoType> );


auto main() -> int {
   static_assert(!DetectType< std::common_type<int(   ) &         > >);
   static_assert(!DetectType< std::common_type<int(...) &         > >);
   static_assert(!DetectType< std::common_type<int(   ) & noexcept> >);
   static_assert(!DetectType< std::common_type<int(...) & noexcept> >);

   return 0;
}


I have also tested with gcc9 in development, but MacPorts stopped updating around October 2018, so my test environment is quite out of date - so only claiming the bug
against the latest release version I have tested.
Comment 1 Jonathan Wakely 2019-02-06 00:42:04 UTC
We implement the C++14 rules still, where common_type<T>::type is just decay<T>::type.
Comment 2 Jonathan Wakely 2019-02-06 00:50:30 UTC
That changed with P0548R1 (which is not a DR).
Comment 3 Jonathan Wakely 2019-02-06 17:26:02 UTC
Author: redi
Date: Wed Feb  6 17:25:26 2019
New Revision: 268586

URL: https://gcc.gnu.org/viewcvs?rev=268586&root=gcc&view=rev
Log:
PR libstdc++/89102 fix common_type<> and common_type<T> specializations

This is a partial implementation of the revised std::common_type rules
from P0435R1.

	PR libstdc++/89102 (partial)
	* include/std/type_traits (common_type<>): Define.
	(common_type<T>): Derive from common_type<T, T>.
	* testsuite/20_util/common_type/requirements/explicit_instantiation.cc:
	Test zero-length template argument list.
	* testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc:
	Test additional single argument cases.
	* testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc:
	Adjust expected error.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/std/type_traits
    trunk/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc
    trunk/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc
    trunk/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc
Comment 4 Jonathan Wakely 2019-02-06 19:37:30 UTC
Minimal fix committed to trunk, with a complete fix posted to https://gcc.gnu.org/ml/gcc-patches/2019-02/msg00346.html for stage 1.
Comment 5 Jakub Jelinek 2019-02-22 15:26:17 UTC
GCC 8.3 has been released.
Comment 6 Jonathan Wakely 2019-05-07 15:47:19 UTC
Author: redi
Date: Tue May  7 15:46:44 2019
New Revision: 270968

URL: https://gcc.gnu.org/viewcvs?rev=270968&root=gcc&view=rev
Log:
PR libstdc++/89102 fix common_type<> and common_type<T> specializations

This is a partial implementation of the revised std::common_type rules
from P0435R1.

Backport from mainline
2019-02-06  Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/89102 (partial)
	* include/std/type_traits (common_type<>): Define.
	(common_type<T>): Derive from common_type<T, T>.
	* testsuite/20_util/common_type/requirements/explicit_instantiation.cc:
	Test zero-length template argument list.
	* testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc:
	Test additional single argument cases.
	* testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc:
	Adjust expected error.

Modified:
    branches/gcc-8-branch/libstdc++-v3/ChangeLog
    branches/gcc-8-branch/libstdc++-v3/include/std/type_traits
    branches/gcc-8-branch/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc
    branches/gcc-8-branch/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc
    branches/gcc-8-branch/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc
Comment 7 Jonathan Wakely 2019-05-07 22:47:11 UTC
Author: redi
Date: Tue May  7 22:46:39 2019
New Revision: 270987

URL: https://gcc.gnu.org/viewcvs?rev=270987&root=gcc&view=rev
Log:
PR libstdc++/89102 implement new common_type rules (P0435R1, P0548R1)

This change ensures that std::common_type<> is a complete type (LWG
2408), and that std::common_type<T>, std::common_type<cv T1, cv T2>, and
std::common_type<T1, T2, R...> will use program-defined specializations
for std::common_type<T1, T2> (LWG 2465).

The implementation of common_type<T1, T2, R...> is changed to use
void_t, and the specializations for duration and time_point are modified
to also use void_t instead of depending on implementation details of
common_type.

	PR libstdc++/89102
	* doc/xml/manual/intro.xml: Document DR 2408 and 2465 changes.
	* include/std/chrono (__duration_common_type_wrapper): Replace with ...
	(__duration_common_type): New helper.
	(common_type<chrono::duration<R1, P2>, chrono::duration<R2, P2>>): Use
	__duration_common_type.
	(__timepoint_common_type_wrapper): Replace with ...
	(__timepoint_common_type): New helper.
	(common_type<chrono::time_point<C, D2>, chrono::time_point<C, D2>>):
	Use __time_point_common_type.
	* include/std/type_traits (common_type<>): Define, as per LWG 2408.
	(__common_type_impl): If either argument is transformed by decay,
	use the common_type of the decayed types.
	(__common_type_impl<_Tp, _Up, _Tp, _Up>): If the types are already
	decayed, use __do_common_type_impl to get the common_type.
	(common_type<_Tp>): Use common_type<_Tp, _Tp>.
	(__do_member_type_wrapper, __member_type_wrapper)
	(__expanded_common_type_wrapper): Remove.
	(__common_type_pack, __common_type_fold): New helpers.
	(common_type<_Tp, _Up, _Vp...>): Use new helpers instead of
	__member_type_wrapper and __expanded_common_type_wrapper.
	* testsuite/20_util/common_type/requirements/explicit_instantiation.cc:
	Test zero-length template argument list.
	* testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc:
	Test single argument cases and argument types that should decay.
	* testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc:
	Adjust expected error.
	* testsuite/20_util/duration/literals/range_neg.cc: Use zero for
	dg-error lineno.
	* testsuite/20_util/duration/requirements/typedefs_neg1.cc: Likewise.
	* testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise.
	* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Likewise.

Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/doc/xml/manual/intro.xml
    trunk/libstdc++-v3/include/std/chrono
    trunk/libstdc++-v3/include/std/type_traits
    trunk/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc
    trunk/libstdc++-v3/testsuite/20_util/duration/literals/range_neg.cc
    trunk/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc
    trunk/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc
    trunk/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg3.cc
Comment 8 Jonathan Wakely 2019-05-07 22:55:25 UTC
The abominable function types handling is fixed for gcc 8.4 and the full C++2a common_type spec is implemented on trunk now.
Comment 9 GCC Commits 2020-08-27 21:40:37 UTC
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:82030d51017323c5706d58d8c8626324ece007e4

commit r11-2913-g82030d51017323c5706d58d8c8626324ece007e4
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Aug 27 22:36:03 2020 +0100

    libstdc++: Make std::chrono::duration use reduced ratio for period
    
    This implements the changes from P0548 "common_type and duration". That
    was a change for C++17, but as it corrects some issues introduced by DRs
    I'm also treating it as a DR and changing it for all modes from C++11
    up.
    
    The main change is that duration<R,P>::period no longer denotes P, but
    rather P::type, the reduced ratio. The unary operator+ and operator-
    members of duration should now return a duration using that reduced
    ratio.
    
    The requirement that common_type<T>::type is the same type as
    common_type<T, T>::type (rather than simply T) was already implemented
    for PR 89102.
    
    The standard says that duration::operator+() and duration::operator-()
    should return common_type_t<duration>, but that seems unnecessarily
    expensive to compute. This change just uses duration<rep, period> which
    is the same type, so we don't need to instantiate common_type.
    
    As an optimization, this also adds partial specializations of
    common_type for two durations of the same type, a single duration, two
    time_points of the same type, and a single time_point. These
    specializations avoid instantiating other specializations of common_type
    and one or both of __duration_common_type or __timepoint_common_type for
    the cases where the answer is trivial to obtain.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/chrono (__duration_common_type): Ensure the
            reduced ratio is used. Remove unused partial specialization
            using __failure_type.
            (common_type): Pass reduced ratios to __duration_common_type.
            Add partial specializations for simple cases involving a single
            duration or time_point type.
            (duration::period): Use reduced ratio.
            (duration::operator+(), duration::operator-()): Return duration
            type using the reduced ratio.
            * testsuite/20_util/duration/requirements/typedefs_neg2.cc:
            Adjust expected errors.
            * testsuite/20_util/duration/requirements/reduced_period.cc: New test.
Comment 10 GCC Commits 2021-03-29 20:04:39 UTC
The releases/gcc-10 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:7dea2f84f26d454331d34b8536c261b6e96205d7

commit r10-9608-g7dea2f84f26d454331d34b8536c261b6e96205d7
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Aug 27 22:36:03 2020 +0100

    libstdc++: Make std::chrono::duration use reduced ratio for period
    
    This implements the changes from P0548 "common_type and duration". That
    was a change for C++17, but as it corrects some issues introduced by DRs
    I'm also treating it as a DR and changing it for all modes from C++11
    up.
    
    The main change is that duration<R,P>::period no longer denotes P, but
    rather P::type, the reduced ratio. The unary operator+ and operator-
    members of duration should now return a duration using that reduced
    ratio.
    
    The requirement that common_type<T>::type is the same type as
    common_type<T, T>::type (rather than simply T) was already implemented
    for PR 89102.
    
    The standard says that duration::operator+() and duration::operator-()
    should return common_type_t<duration>, but that seems unnecessarily
    expensive to compute. This uses duration<common_type_t<rep>, period>
    which is the same type, so we avoid a common_type specialization.
    
    As an optimization, this also adds partial specializations of
    common_type for two durations of the same type, a single duration, two
    time_points of the same type, and a single time_point. These
    specializations avoid instantiating other specializations of common_type
    and one or both of __duration_common_type or __timepoint_common_type for
    the cases where the answer is trivial to obtain.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/chrono (__duration_common_type): Ensure the
            reduced ratio is used. Remove unused partial specialization
            using __failure_type.
            (common_type): Pass reduced ratios to __duration_common_type.
            Add partial specializations for simple cases involving a single
            duration or time_point type.
            (duration::period): Use reduced ratio.
            (duration::operator+(), duration::operator-()): Return duration
            type using the reduced ratio.
            * testsuite/20_util/duration/requirements/typedefs_neg2.cc:
            Adjust expected errors.
            * testsuite/20_util/duration/requirements/reduced_period.cc: New test.
    
    (cherry picked from commit 82030d51017323c5706d58d8c8626324ece007e4)