On Tue, Sep 23, 2025 at 9:14 AM Tomasz Kaminski <[email protected]> wrote:
> The library side looks good to me, with two small comments:
> * removing version.cc file, that duplicates tests
> * removing copyright notice from second test (to be confirmed by
> Jonathan).
> The test covers all cases, that I could think of.
>
I have realized that version.cc adds { dg-add-options no_pch }, so I would
keep the
file and remove the duplicated check from value.cc.
>
> On Fri, Aug 29, 2025 at 12:22 PM Jakub Jelinek <[email protected]> wrote:
>
>> On Fri, Aug 29, 2025 at 11:40:10AM +0200, Jason Merrill wrote:
>> > > --- gcc/cp/semantics.cc.jj 2025-08-28 10:50:43.432763513 +0200
>> > > +++ gcc/cp/semantics.cc 2025-08-28 16:52:48.006806831 +0200
>> > > @@ -13591,6 +13591,38 @@ trait_expr_value (cp_trait_kind kind, tr
>> > > case CPTK_IS_FUNCTION:
>> > > return type_code1 == FUNCTION_TYPE;
>> > > + case CPTK_IS_IMPLICIT_LIFETIME:
>> >
>> > Please factor this into a predicate (e.g. implicit_lifetime_type_p)
>> that can
>> > be used elsewhere in the compiler.
>>
>> Done.
>>
>> > This is an interesting way to approach "has at least one trivial
>> eligible
>> > constructor"; I would expect a loop over CLASSTYPE_CONSTRUCTORS checking
>> > eligible_special_memfn_p (which doesn't exist yet) && trivial_fn_p.
>> But I
>> > guess your approach should work, too.
>>
>> This came from the paper's chapter 2,
>> template<typename T>
>> struct is_implicit_lifetime : std::disjunction<
>> std::is_scalar<T>,
>> std::is_array<T>,
>> std::is_aggregate<T>,
>> std::conjunction<
>> std::is_trivially_destructible<T>,
>> std::disjunction<
>> std::is_trivially_default_constructible<T>,
>> std::is_trivially_copy_constructible<T>,
>> std::is_trivially_move_constructible<T>>>> {};
>> except that the is_aggregate part is more complex and can't be done purely
>> on the library side since CWG2605.
>>
>> > For the rvalue case you can just use type1, and build_stub_object will
>> add
>> > the rvalue reference.
>>
>> Done.
>>
>> 2025-08-29 Jakub Jelinek <[email protected]>
>>
>> gcc/cp/
>> * cp-tree.h: Implement C++23 P2674R1 - A trait for implicit
>> lifetime
>> types.
>> (implicit_lifetime_type_p): Declare.
>> * tree.cc (implicit_lifetime_type_p): New function.
>> * cp-trait.def (IS_IMPLICIT_LIFETIME): New unary trait.
>> * semantics.cc (trait_expr_value): Handle
>> CPTK_IS_IMPLICIT_LIFETIME.
>> (finish_trait_expr): Likewise.
>> * constraint.cc (diagnose_trait_expr): Likewise.
>> gcc/testsuite/
>> * g++.dg/ext/is_implicit_lifetime.C: New test.
>> libstdc++-v3/
>> * include/bits/version.def (is_implicit_lifetime): New.
>> * include/bits/version.h: Regenerate.
>> * include/std/type_traits (std::is_implicit_lifetime,
>> std::is_implicit_lifetime_v): New trait.
>> * src/c++23/std.cc.in (std::is_implicit_lifetime,
>> std::is_implicit_lifetime_v): Export.
>> * testsuite/20_util/is_implicit_lifetime/version.cc: New test.
>> * testsuite/20_util/is_implicit_lifetime/value.cc: New test.
>>
>> --- gcc/cp/cp-tree.h.jj 2025-08-23 15:00:04.190788945 +0200
>> +++ gcc/cp/cp-tree.h 2025-08-29 12:04:55.294023368 +0200
>> @@ -8369,6 +8369,7 @@ extern bool std_layout_type_p
>> (const_t
>> extern bool trivial_type_p (const_tree);
>> extern bool trivially_relocatable_type_p (tree);
>> extern bool replaceable_type_p (tree);
>> +extern bool implicit_lifetime_type_p (tree);
>> extern bool trivially_copyable_p (const_tree);
>> extern bool type_has_unique_obj_representations (const_tree);
>> extern bool scalarish_type_p (const_tree);
>> --- gcc/cp/tree.cc.jj 2025-08-23 15:00:04.291787603 +0200
>> +++ gcc/cp/tree.cc 2025-08-29 12:08:47.617979696 +0200
>> @@ -5070,6 +5070,42 @@ replaceable_type_p (tree t)
>> return true;
>> }
>>
>> +/* Returns 1 iff type T is an implicit-lifetime type, as defined in
>> + [basic.types.general] and [class.prop]. */
>> +
>> +bool
>> +implicit_lifetime_type_p (tree t)
>> +{
>> + if (SCALAR_TYPE_P (t)
>> + || (TREE_CODE (t) == ARRAY_TYPE
>> + && !(TYPE_SIZE (t) && integer_zerop (TYPE_SIZE (t))))
>> + /* GNU extension. */
>> + || TREE_CODE (t) == VECTOR_TYPE)
>> + return true;
>> + if (!CLASS_TYPE_P (t))
>> + return false;
>> + t = TYPE_MAIN_VARIANT (t);
>> + if (CP_AGGREGATE_TYPE_P (t)
>> + && (!CLASSTYPE_DESTRUCTOR (t)
>> + || !user_provided_p (CLASSTYPE_DESTRUCTOR (t))))
>> + return true;
>> + if (is_trivially_xible (BIT_NOT_EXPR, t, NULL_TREE))
>> + {
>> + if (is_trivially_xible (INIT_EXPR, t, make_tree_vec (0)))
>> + return true;
>> + tree arg = make_tree_vec (1);
>> + tree ct
>> + = cp_build_qualified_type (t, (cp_type_quals (t) |
>> TYPE_QUAL_CONST));
>> + TREE_VEC_ELT (arg, 0) = cp_build_reference_type (ct,
>> /*rval=*/false);
>> + if (is_trivially_xible (INIT_EXPR, t, arg))
>> + return true;
>> + TREE_VEC_ELT (arg, 0) = t;
>> + if (is_trivially_xible (INIT_EXPR, t, arg))
>> + return true;
>> + }
>> + return false;
>> +}
>> +
>> /* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
>>
>> bool
>> --- gcc/cp/cp-trait.def.jj 2025-08-29 11:14:27.657997703 +0200
>> +++ gcc/cp/cp-trait.def 2025-08-29 11:53:46.940123903 +0200
>> @@ -76,6 +76,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1
>> DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
>> DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
>> DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
>> +DEFTRAIT_EXPR (IS_IMPLICIT_LIFETIME, "__builtin_is_implicit_lifetime", 1)
>> DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
>> DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
>> DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
>> --- gcc/cp/semantics.cc.jj 2025-08-29 11:14:27.687997312 +0200
>> +++ gcc/cp/semantics.cc 2025-08-29 12:06:08.162068723 +0200
>> @@ -13591,6 +13591,9 @@ trait_expr_value (cp_trait_kind kind, tr
>> case CPTK_IS_FUNCTION:
>> return type_code1 == FUNCTION_TYPE;
>>
>> + case CPTK_IS_IMPLICIT_LIFETIME:
>> + return implicit_lifetime_type_p (type1);
>> +
>> case CPTK_IS_INVOCABLE:
>> return !error_operand_p (build_invoke (type1, type2, tf_none));
>>
>> @@ -13910,6 +13913,7 @@ finish_trait_expr (location_t loc, cp_tr
>> type to know whether an array is an aggregate, so use kind=4
>> here. */
>> case CPTK_IS_AGGREGATE:
>> case CPTK_IS_FINAL:
>> + case CPTK_IS_IMPLICIT_LIFETIME:
>> if (!check_trait_type (type1, /* kind = */ 4))
>> return error_mark_node;
>> break;
>> --- gcc/cp/constraint.cc.jj 2025-08-29 11:14:27.645997860 +0200
>> +++ gcc/cp/constraint.cc 2025-08-29 11:53:46.943123862 +0200
>> @@ -3170,6 +3170,9 @@ diagnose_trait_expr (location_t loc, tre
>> case CPTK_IS_FUNCTION:
>> inform (loc, "%qT is not a function", t1);
>> break;
>> + case CPTK_IS_IMPLICIT_LIFETIME:
>> + inform (decl_loc, "%qT is not an implicit lifetime type", t1);
>> + break;
>> case CPTK_IS_INVOCABLE:
>> {
>> if (!TREE_VEC_LENGTH (t2))
>> --- gcc/testsuite/g++.dg/ext/is_implicit_lifetime.C.jj 2025-08-28
>> 14:14:33.475719420 +0200
>> +++ gcc/testsuite/g++.dg/ext/is_implicit_lifetime.C 2025-08-28
>> 20:36:08.805719765 +0200
>> @@ -0,0 +1,139 @@
>> +// { dg-do compile { target c++11 } }
>> +// { dg-options "" }
>> +// { dg-add-options float16 }
>> +// { dg-add-options float32 }
>> +// { dg-add-options float64 }
>> +// { dg-add-options float128 }
>> +
>> +struct A { int a, b, c; };
>> +class B { static int a; private: static int b; public: int c; };
>> +struct C { C () {} int a, b, c; };
>> +struct D { explicit D (int) {} int a, b, c; };
>> +struct E : public A { int d, e, f; };
>> +struct F : public C { using C::C; int d, e, f; };
>> +class G { int a, b; };
>> +struct H { private: int a, b; };
>> +struct I { protected: int a, b; };
>> +struct J { int a, b; void foo (); };
>> +struct K { int a, b; virtual void foo (); };
>> +struct L : virtual public A { int d, e; };
>> +struct M : protected A { int d, e; };
>> +struct N : private A { int d, e; };
>> +struct O { O () = delete; int a, b, c; };
>> +struct P { P () = default; int a, b, c; };
>> +struct Q { Q (); Q (const Q &); int a, b, c; };
>> +struct R { R (); R (const R &); R (R &&) = default; int a, b, c; };
>> +struct S { S (); ~S (); int a, b, c; };
>> +struct T { T (); ~T () = default; int a, b, c; };
>> +struct U { U (); U (const U &) = default; int a, b, c; };
>> +struct V { V () = default; V (const V &); int a, b, c; };
>> +enum W { W1 };
>> +enum class X : int { X1 };
>> +struct Y { int g; int foo (int); };
>> +struct Z;
>> +struct AA { Q a; Q b; };
>> +struct AB { Q a; Q b; ~AB () = default; };
>> +struct AC { Q a; Q b; ~AC () {} };
>> +struct AD : public Q {};
>> +struct AE : public Q { ~AE () = default; };
>> +struct AF : public Q { ~AF () {} };
>> +
>> +#define SA(X) static_assert ((X), #X)
>> +
>> +SA (!__builtin_is_implicit_lifetime (void));
>> +SA (!__builtin_is_implicit_lifetime (const void));
>> +SA (!__builtin_is_implicit_lifetime (volatile void));
>> +SA (__builtin_is_implicit_lifetime (char));
>> +SA (__builtin_is_implicit_lifetime (signed char));
>> +SA (__builtin_is_implicit_lifetime (const unsigned char));
>> +SA (__builtin_is_implicit_lifetime (short));
>> +SA (__builtin_is_implicit_lifetime (volatile unsigned short));
>> +SA (__builtin_is_implicit_lifetime (int));
>> +SA (__builtin_is_implicit_lifetime (unsigned int));
>> +SA (__builtin_is_implicit_lifetime (const volatile long));
>> +SA (__builtin_is_implicit_lifetime (unsigned long));
>> +SA (__builtin_is_implicit_lifetime (long long));
>> +SA (__builtin_is_implicit_lifetime (unsigned long long));
>> +#ifdef __SIZEOF_INT128__
>> +SA (__builtin_is_implicit_lifetime (__int128));
>> +SA (__builtin_is_implicit_lifetime (unsigned __int128));
>> +#endif
>> +SA (__builtin_is_implicit_lifetime (float));
>> +SA (__builtin_is_implicit_lifetime (double));
>> +SA (__builtin_is_implicit_lifetime (long double volatile));
>> +#ifdef __STDCPP_FLOAT16_T__
>> +SA (__builtin_is_implicit_lifetime (_Float16));
>> +#endif
>> +#ifdef __STDCPP_FLOAT32_T__
>> +SA (__builtin_is_implicit_lifetime (_Float32));
>> +#endif
>> +#ifdef __STDCPP_FLOAT64_T__
>> +SA (__builtin_is_implicit_lifetime (const _Float64));
>> +#endif
>> +#ifdef __STDCPP_FLOAT128_T__
>> +SA (__builtin_is_implicit_lifetime (_Float128));
>> +#endif
>> +#ifdef __STDCPP_BFLOAT16_T__
>> +SA (__builtin_is_implicit_lifetime (decltype(0.bf16)));
>> +#endif
>> +SA (__builtin_is_implicit_lifetime (W));
>> +SA (__builtin_is_implicit_lifetime (const volatile X));
>> +SA (__builtin_is_implicit_lifetime (int *));
>> +SA (__builtin_is_implicit_lifetime (int (*) (int)));
>> +SA (__builtin_is_implicit_lifetime (int (Y::*)));
>> +SA (__builtin_is_implicit_lifetime (int (Y::*) (int)));
>> +SA (!__builtin_is_implicit_lifetime (int &));
>> +SA (!__builtin_is_implicit_lifetime (char &&));
>> +SA (__builtin_is_implicit_lifetime (int []));
>> +SA (!__builtin_is_implicit_lifetime (int [0]));
>> +SA (__builtin_is_implicit_lifetime (int [1]));
>> +SA (__builtin_is_implicit_lifetime (const Y [42]));
>> +SA (!__builtin_is_implicit_lifetime (int ()));
>> +SA (!__builtin_is_implicit_lifetime (int () &));
>> +SA (!__builtin_is_implicit_lifetime (int () const));
>> +SA (!__builtin_is_implicit_lifetime (int (&) ()));
>> +SA (!__builtin_is_implicit_lifetime (Z)); // { dg-error
>> "invalid use of incomplete type 'struct Z'" }
>> +SA (__builtin_is_implicit_lifetime (Z []));
>> +SA (__builtin_is_implicit_lifetime (Z [5]));
>> +SA (__builtin_is_implicit_lifetime (A));
>> +SA (__builtin_is_implicit_lifetime (B));
>> +SA (__builtin_is_implicit_lifetime (C));
>> +SA (__builtin_is_implicit_lifetime (D));
>> +SA (__builtin_is_implicit_lifetime (E));
>> +SA (__builtin_is_implicit_lifetime (F));
>> +SA (__builtin_is_implicit_lifetime (G));
>> +SA (__builtin_is_implicit_lifetime (H));
>> +SA (__builtin_is_implicit_lifetime (I));
>> +SA (__builtin_is_implicit_lifetime (J));
>> +SA (!__builtin_is_implicit_lifetime (K));
>> +SA (!__builtin_is_implicit_lifetime (L));
>> +SA (__builtin_is_implicit_lifetime (M));
>> +SA (__builtin_is_implicit_lifetime (N));
>> +SA (__builtin_is_implicit_lifetime (O));
>> +SA (__builtin_is_implicit_lifetime (P));
>> +SA (!__builtin_is_implicit_lifetime (Q));
>> +SA (__builtin_is_implicit_lifetime (R));
>> +SA (!__builtin_is_implicit_lifetime (S));
>> +SA (__builtin_is_implicit_lifetime (S [3]));
>> +SA (__builtin_is_implicit_lifetime (T));
>> +SA (__builtin_is_implicit_lifetime (U));
>> +SA (__builtin_is_implicit_lifetime (V));
>> +SA (__builtin_is_implicit_lifetime (_Complex double));
>> +SA (__builtin_is_implicit_lifetime (int [[gnu::vector_size (4 * sizeof
>> (int))]]));
>> +SA (__builtin_is_implicit_lifetime (AA));
>> +SA (__builtin_is_implicit_lifetime (AB));
>> +SA (!__builtin_is_implicit_lifetime (AC));
>> +#if __cplusplus >= 201703L
>> +SA (__builtin_is_implicit_lifetime (AD));
>> +SA (__builtin_is_implicit_lifetime (AE));
>> +#else
>> +SA (!__builtin_is_implicit_lifetime (AD));
>> +SA (!__builtin_is_implicit_lifetime (AE));
>> +#endif
>> +SA (!__builtin_is_implicit_lifetime (AF));
>> +
>> +void
>> +foo (int n)
>> +{
>> + SA (__builtin_is_implicit_lifetime (char [n]));
>> +}
>> --- libstdc++-v3/include/bits/version.def.jj 2025-08-23
>> 15:00:05.175775859 +0200
>> +++ libstdc++-v3/include/bits/version.def 2025-08-28
>> 17:06:44.190031458 +0200
>> @@ -2091,6 +2091,15 @@ ftms = {
>> };
>> };
>>
>> +ftms = {
>> + name = is_implicit_lifetime;
>> + values = {
>> + v = 202302;
>> + cxxmin = 23;
>> + extra_cond = "__has_builtin(__builtin_is_implicit_lifetime)";
>> + };
>> +};
>> +
>> // Standard test specifications.
>> stds[97] = ">= 199711L";
>> stds[03] = ">= 199711L";
>> --- libstdc++-v3/include/bits/version.h.jj 2025-08-23
>> 15:00:05.176775846 +0200
>> +++ libstdc++-v3/include/bits/version.h 2025-08-28 17:06:49.160883915
>> +0200
>> @@ -2343,4 +2343,14 @@
>> #endif /* !defined(__cpp_lib_constexpr_exceptions) &&
>> defined(__glibcxx_want_constexpr_exceptions) */
>> #undef __glibcxx_want_constexpr_exceptions
>>
>> +#if !defined(__cpp_lib_is_implicit_lifetime)
>> +# if (__cplusplus >= 202100L) &&
>> (__has_builtin(__builtin_is_implicit_lifetime))
>> +# define __glibcxx_is_implicit_lifetime 202302L
>> +# if defined(__glibcxx_want_all) ||
>> defined(__glibcxx_want_is_implicit_lifetime)
>> +# define __cpp_lib_is_implicit_lifetime 202302L
>> +# endif
>> +# endif
>> +#endif /* !defined(__cpp_lib_is_implicit_lifetime) &&
>> defined(__glibcxx_want_is_implicit_lifetime) */
>> +#undef __glibcxx_want_is_implicit_lifetime
>> +
>> #undef __glibcxx_want_all
>> --- libstdc++-v3/include/std/type_traits.jj 2025-07-16
>> 13:10:11.054411335 +0200
>> +++ libstdc++-v3/include/std/type_traits 2025-08-28
>> 17:36:11.404329402 +0200
>> @@ -46,6 +46,7 @@
>> #define __glibcxx_want_is_aggregate
>> #define __glibcxx_want_is_constant_evaluated
>> #define __glibcxx_want_is_final
>> +#define __glibcxx_want_is_implicit_lifetime
>> #define __glibcxx_want_is_invocable
>> #define __glibcxx_want_is_layout_compatible
>> #define __glibcxx_want_is_nothrow_convertible
>> @@ -4052,6 +4053,22 @@ template<typename _Ret, typename _Fn, ty
>> # endif
>> #endif
>>
>> +#ifdef __cpp_lib_is_implicit_lifetime // C++ >= 23
>> + /// True if the type is an implicit-lifetime type.
>> + /// @since C++23
>> +
>> + template<typename _Tp>
>> + struct is_implicit_lifetime
>> + : bool_constant<__builtin_is_implicit_lifetime(_Tp)>
>> + { };
>> +
>> + /// @ingroup variable_templates
>> + /// @since C++23
>> + template<typename _Tp>
>> + inline constexpr bool is_implicit_lifetime_v
>> + = __builtin_is_implicit_lifetime(_Tp);
>> +#endif
>> +
>> #ifdef __cpp_lib_reference_from_temporary // C++ >= 23 &&
>> ref_{converts,constructs}_from_temp
>> /// True if _Tp is a reference type, a _Up value can be bound to _Tp in
>> /// direct-initialization, and a temporary object would be bound to
>> --- libstdc++-v3/src/c++23/std.cc.in.jj 2025-08-23 15:00:05.209775407
>> +0200
>> +++ libstdc++-v3/src/c++23/std.cc.in 2025-08-28 17:10:43.784942152
>> +0200
>> @@ -3216,6 +3216,10 @@ export namespace std
>> using std::is_scoped_enum;
>> using std::is_scoped_enum_v;
>> #endif
>> +#if __cpp_lib_is_implicit_lifetime
>> + using std::is_implicit_lifetime;
>> + using std::is_implicit_lifetime_v;
>> +#endif
>> }
>>
>> // <typeindex>
>> --- libstdc++-v3/testsuite/20_util/is_implicit_lifetime/version.cc.jj
>> 2025-08-28 17:16:17.590650275 +0200
>> +++ libstdc++-v3/testsuite/20_util/is_implicit_lifetime/version.cc
>> 2025-08-28 17:17:07.215014852 +0200
>> @@ -0,0 +1,27 @@
>> +// Copyright (C) 2025 Free Software Foundation, Inc.
>> +//
>> +// This file is part of the GNU ISO C++ Library. This library is free
>> +// software; you can redistribute it and/or modify it under the
>> +// terms of the GNU General Public License as published by the
>> +// Free Software Foundation; either version 3, or (at your option)
>> +// any later version.
>> +
>> +// This library is distributed in the hope that it will be useful,
>> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> +// GNU General Public License for more details.
>> +
>> +// You should have received a copy of the GNU General Public License
>> along
>> +// with this library; see the file COPYING3. If not see
>> +// <http://www.gnu.org/licenses/>.
>> +
>> +// { dg-do compile { target c++23 } }
>> +// { dg-add-options no_pch }
>> +
>> +#include <version>
>> +
>> +#ifndef __cpp_lib_is_implicit_lifetime
>> +# error "Feature test macro for is_implicit_lifetime is missing in
>> <version>"
>> +#elif __cpp_lib_is_implicit_lifetime < 202302L
>> +# error "Feature test macro for is_implicit_lifetime has wrong value in
>> <version>"
>> +#endif
>>
> The same check is already included in valuce.cc, so I would simply remove
> thsi file.
>
>
>> --- libstdc++-v3/testsuite/20_util/is_implicit_lifetime/value.cc.jj
>> 2025-08-28 17:16:20.746609864 +0200
>> +++ libstdc++-v3/testsuite/20_util/is_implicit_lifetime/value.cc
>> 2025-08-28 20:33:41.480591119 +0200
>> @@ -0,0 +1,129 @@
>> +// Copyright (C) 2025 Free Software Foundation, Inc.
>> +//
>> +// This file is part of the GNU ISO C++ Library. This library is free
>> +// software; you can redistribute it and/or modify it under the
>> +// terms of the GNU General Public License as published by the
>> +// Free Software Foundation; either version 3, or (at your option)
>> +// any later version.
>> +
>> +// This library is distributed in the hope that it will be useful,
>> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> +// GNU General Public License for more details.
>> +
>> +// You should have received a copy of the GNU General Public License
>> along
>> +// with this library; see the file COPYING3. If not see
>> +// <http://www.gnu.org/licenses/>.
>>
> I haven't seen a copyright notice in the recent libstdc++ test files which
> I believe is
> done intentionally.
>
>> +
>> +// { dg-do compile { target c++23 } }
>> +// { dg-add-options no_pch }
>> +
>> +#include <type_traits>
>> +
>> +#ifndef __cpp_lib_is_implicit_lifetime
>> +# error "Feature test macro for is_implicit_lifetime is missing in
>> <type_traits>"
>> +#elif __cpp_lib_is_implicit_lifetime < 202302L
>> +# error "Feature test macro for is_implicit_lifetime has wrong value in
>> <type_traits>"
>> +#endif
>> +
>> +#include <testsuite_tr1.h>
>> +
>> +template<typename T>
>> + concept Is_implicit_lifetime
>> + = __gnu_test::test_category<std::is_implicit_lifetime, T>(true);
>> +
>> +static_assert( ! Is_implicit_lifetime<void> );
>> +static_assert( ! Is_implicit_lifetime<const void> );
>> +static_assert( ! Is_implicit_lifetime<volatile void> );
>> +static_assert( Is_implicit_lifetime<char> );
>> +static_assert( Is_implicit_lifetime<signed char> );
>> +static_assert( Is_implicit_lifetime<const unsigned char> );
>> +static_assert( Is_implicit_lifetime<short> );
>> +static_assert( Is_implicit_lifetime<volatile unsigned short> );
>> +static_assert( Is_implicit_lifetime<int> );
>> +static_assert( Is_implicit_lifetime<unsigned int> );
>> +static_assert( Is_implicit_lifetime<const volatile long> );
>> +static_assert( Is_implicit_lifetime<unsigned long> );
>> +static_assert( Is_implicit_lifetime<long long> );
>> +static_assert( Is_implicit_lifetime<unsigned long long> );
>> +static_assert( Is_implicit_lifetime<float> );
>> +static_assert( Is_implicit_lifetime<double> );
>> +static_assert( Is_implicit_lifetime<long double volatile> );
>> +enum W { W1 };
>> +static_assert( Is_implicit_lifetime<W> );
>> +enum class X : int { X1 };
>> +static_assert( Is_implicit_lifetime<const volatile X> );
>> +static_assert( Is_implicit_lifetime<int *> );
>> +static_assert( Is_implicit_lifetime<int (*) (int)> );
>> +struct Y { int g; int foo (int); };
>> +static_assert( Is_implicit_lifetime<int (Y::*)> );
>> +static_assert( Is_implicit_lifetime<int (Y::*) (int)> );
>> +static_assert( ! Is_implicit_lifetime<int &> );
>> +static_assert( ! Is_implicit_lifetime<char &&> );
>> +static_assert( Is_implicit_lifetime<int []> );
>> +static_assert( Is_implicit_lifetime<int [1]> );
>> +static_assert( Is_implicit_lifetime<const Y [42]> );
>> +static_assert( ! Is_implicit_lifetime<int ()> );
>> +static_assert( ! Is_implicit_lifetime<int () &> );
>> +static_assert( ! Is_implicit_lifetime<int () const> );
>> +static_assert( ! Is_implicit_lifetime<int (&) ()> );
>> +struct Z;
>> +static_assert( Is_implicit_lifetime<Z []> );
>> +static_assert( Is_implicit_lifetime<Z [5]> );
>> +struct A { int a, b, c; };
>> +static_assert( Is_implicit_lifetime<A> );
>> +class B { static int a; private: static int b; public: int c; };
>> +static_assert( Is_implicit_lifetime<B> );
>> +struct C { C () {} int a, b, c; };
>> +static_assert( Is_implicit_lifetime<C> );
>> +struct D { explicit D (int) {} int a, b, c; };
>> +static_assert( Is_implicit_lifetime<D> );
>> +struct E : public A { int d, e, f; };
>> +static_assert( Is_implicit_lifetime<E> );
>> +struct F : public C { using C::C; int d, e, f; };
>> +static_assert( Is_implicit_lifetime<F> );
>> +class G { int a, b; };
>> +static_assert( Is_implicit_lifetime<G> );
>> +struct H { private: int a, b; };
>> +static_assert( Is_implicit_lifetime<H> );
>> +struct I { protected: int a, b; };
>> +static_assert( Is_implicit_lifetime<I> );
>> +struct J { int a, b; void foo (); };
>> +static_assert( Is_implicit_lifetime<J> );
>> +struct K { int a, b; virtual void foo (); };
>> +static_assert( ! Is_implicit_lifetime<K> );
>> +struct L : virtual public A { int d, e; };
>> +static_assert( ! Is_implicit_lifetime<L> );
>> +struct M : protected A { int d, e; };
>> +static_assert( Is_implicit_lifetime<M> );
>> +struct N : private A { int d, e; };
>> +static_assert( Is_implicit_lifetime<N> );
>> +struct O { O () = delete; int a, b, c; };
>> +static_assert( Is_implicit_lifetime<O> );
>> +struct P { P () = default; int a, b, c; };
>> +static_assert( Is_implicit_lifetime<P> );
>> +struct Q { Q (); Q (const Q &); int a, b, c; };
>> +static_assert( ! Is_implicit_lifetime<Q> );
>> +struct R { R (); R (const R &); R (R &&) = default; int a, b, c; };
>> +static_assert( Is_implicit_lifetime<R> );
>> +struct S { S (); ~S (); int a, b, c; };
>> +static_assert( ! Is_implicit_lifetime<S> );
>> +static_assert( Is_implicit_lifetime<S [3]> );
>> +struct T { T (); ~T () = default; int a, b, c; };
>> +static_assert( Is_implicit_lifetime<T> );
>> +struct U { U (); U (const U &) = default; int a, b, c; };
>> +static_assert( Is_implicit_lifetime<U> );
>> +struct V { V () = default; V (const V &); int a, b, c; };
>> +static_assert( Is_implicit_lifetime<V> );
>> +struct AA { Q a; Q b; };
>> +static_assert( Is_implicit_lifetime<AA> );
>> +struct AB { Q a; Q b; ~AB () = default; };
>> +static_assert( Is_implicit_lifetime<AB> );
>> +struct AC { Q a; Q b; ~AC () {} };
>> +static_assert( ! Is_implicit_lifetime<AC> );
>> +struct AD : public Q {};
>> +static_assert( Is_implicit_lifetime<AD> );
>> +struct AE : public Q { ~AE () = default; };
>> +static_assert( Is_implicit_lifetime<AE> );
>> +struct AF : public Q { ~AF () {} };
>> +static_assert( ! Is_implicit_lifetime<AF> );
>>
>>
>> Jakub
>>
>>