On Mon, Nov 17, 2025 at 10:30 AM Tomasz Kaminski <[email protected]> wrote:
> > > On Sat, Nov 15, 2025 at 1:44 AM Marek Polacek <[email protected]> wrote: > >> This contains the libstdc++ bits (including <meta>). >> >> -- >8 -- >> diff --git a/libstdc++-v3/include/Makefile.am >> b/libstdc++-v3/include/Makefile.am >> index ae7a7ca9073..5fff459a779 100644 >> --- a/libstdc++-v3/include/Makefile.am >> +++ b/libstdc++-v3/include/Makefile.am >> @@ -89,6 +89,7 @@ std_headers = \ >> ${std_srcdir}/locale \ >> ${std_srcdir}/map \ >> ${std_srcdir}/memory_resource \ >> + ${std_srcdir}/meta \ >> ${std_srcdir}/mutex \ >> ${std_srcdir}/ostream \ >> ${std_srcdir}/print \ >> diff --git a/libstdc++-v3/include/Makefile.in >> b/libstdc++-v3/include/Makefile.in >> index f07e2326816..d364d046267 100644 >> --- a/libstdc++-v3/include/Makefile.in >> +++ b/libstdc++-v3/include/Makefile.in >> @@ -448,6 +448,7 @@ std_freestanding = \ >> @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/locale \ >> @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/map \ >> @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/memory_resource \ >> +@GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/meta \ >> @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/mutex \ >> @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/ostream \ >> @GLIBCXX_HOSTED_TRUE@ ${std_srcdir}/print \ >> diff --git a/libstdc++-v3/include/bits/iterator_concepts.h >> b/libstdc++-v3/include/bits/iterator_concepts.h >> index fd91b22d75a..61cf3c510c3 100644 >> --- a/libstdc++-v3/include/bits/iterator_concepts.h >> +++ b/libstdc++-v3/include/bits/iterator_concepts.h >> @@ -1008,7 +1008,7 @@ namespace ranges >> // for use by __range_iter_t below. >> template<typename _Tp> >> requires is_array_v<_Tp> || __member_begin<_Tp&> || >> __adl_begin<_Tp&> >> - auto >> + constexpr auto >> > This change seem like a fix for a pre-existing bug, and I would prefer to > land it as a separate commit, > using range_iter_t on any type with consteval begin/end members would > cause the same issue, I believe. > OK, this does not seem to be revelant until consteval only types are involved. > __begin(_Tp& __t) >> { >> if constexpr (is_array_v<_Tp>) >> diff --git a/libstdc++-v3/include/bits/version.def >> b/libstdc++-v3/include/bits/version.def >> index 29ecf15c7e3..c59dc09c6d8 100644 >> --- a/libstdc++-v3/include/bits/version.def >> +++ b/libstdc++-v3/include/bits/version.def >> @@ -2191,6 +2191,15 @@ ftms = { >> }; >> }; >> >> +ftms = { >> + name = reflection; >> + values = { >> + v = 202506; >> + cxxmin = 26; >> + extra_cond = "__cpp_impl_reflection >= 202506L"; >> + }; >> +}; >> + >> ftms = { >> name = is_implicit_lifetime; >> values = { >> diff --git a/libstdc++-v3/include/bits/version.h >> b/libstdc++-v3/include/bits/version.h >> index 5901d27113d..b947ee3c953 100644 >> --- a/libstdc++-v3/include/bits/version.h >> +++ b/libstdc++-v3/include/bits/version.h >> @@ -2465,4 +2465,14 @@ >> #endif /* !defined(__cpp_lib_is_implicit_lifetime) */ >> #undef __glibcxx_want_is_implicit_lifetime >> >> +#if !defined(__cpp_lib_reflection) >> +# if (__cplusplus > 202302L) && (__cpp_impl_reflection >= 202506L) >> +# define __glibcxx_reflection 202506L >> +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_reflection) >> +# define __cpp_lib_reflection 202506L >> +# endif >> +# endif >> +#endif /* !defined(__cpp_lib_reflection) */ >> +#undef __glibcxx_want_reflection >> + >> #undef __glibcxx_want_all >> diff --git a/libstdc++-v3/include/precompiled/stdc++.h >> b/libstdc++-v3/include/precompiled/stdc++.h >> index 54baed43a5e..30de85d8c37 100644 >> --- a/libstdc++-v3/include/precompiled/stdc++.h >> +++ b/libstdc++-v3/include/precompiled/stdc++.h >> @@ -234,6 +234,7 @@ >> #if __cplusplus > 202302L >> #include <debugging> >> #include <inplace_vector> >> +#include <meta> >> #include <text_encoding> >> #include <stdbit.h> >> #include <stdckdint.h> >> diff --git a/libstdc++-v3/include/std/meta b/libstdc++-v3/include/std/meta >> new file mode 100644 >> index 00000000000..13c79358bc9 >> --- /dev/null >> +++ b/libstdc++-v3/include/std/meta >> @@ -0,0 +1,651 @@ >> +// <meta> -*- C++ -*- >> + >> +// 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. >> + >> +// Under Section 7 of GPL version 3, you are granted additional >> +// permissions described in the GCC Runtime Library Exception, version >> +// 3.1, as published by the Free Software Foundation. >> + >> +// You should have received a copy of the GNU General Public License and >> +// a copy of the GCC Runtime Library Exception along with this program; >> +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see >> +// <http://www.gnu.org/licenses/>. >> + >> +/** @file include/meta >> + * This is a Standard C++ Library header. >> + */ >> + >> +#ifndef _GLIBCXX_META >> +#define _GLIBCXX_META 1 >> + >> +#ifdef _GLIBCXX_SYSHDR >> +#pragma GCC system_header >> +#endif >> + >> +#include <array> >> +#include <initializer_list> >> +#include <optional> >> +#include <source_location> >> +#include <span> >> +#include <string> >> +#include <string_view> >> +#include <vector> >> + >> +#define __glibcxx_want_reflection >> +#include <bits/version.h> >> + >> +#if __glibcxx_reflection >= 202506L // C++ >= 26 && __cpp_impl_reflection >> + >> +namespace std _GLIBCXX_VISIBILITY(default) >> +{ >> +_GLIBCXX_BEGIN_NAMESPACE_VERSION >> + >> +#if __has_builtin(__builtin_is_string_literal) >> + // [meta.string.literal], checking string literals >> + consteval bool is_string_literal(const char* __p) >> + { >> + return __builtin_is_string_literal(__p); >> + } >> + >> + consteval bool is_string_literal(const wchar_t* __p) >> + { >> + return __builtin_is_string_literal(__p); >> + } >> + >> +#ifdef _GLIBCXX_USE_CHAR8_T >> + consteval bool is_string_literal(const char8_t* __p) >> + { >> + return __builtin_is_string_literal(__p); >> + } >> +#endif >> + >> + consteval bool is_string_literal(const char16_t* __p) >> + { >> + return __builtin_is_string_literal(__p); >> + } >> + >> + consteval bool is_string_literal(const char32_t* __p) >> + { >> + return __builtin_is_string_literal(__p); >> + } >> +#endif >> + >> + namespace meta >> + { >> + using info = decltype(^^int); >> + >> + // [meta.reflection.exception], class exception >> + class exception : public std::exception { >> + private: >> + string _M_what; >> + u8string _M_u8what; >> + info _M_from; >> + source_location _M_where; >> + >> + public: >> + consteval exception(u8string_view __what, info __from, >> + source_location __where >> + = source_location::current()) noexcept >> + : _M_what{_S_exception_cvt_from_utf8(__what)}, _M_u8what{__what}, >> + _M_from{__from}, _M_where{__where} {} >> + >> + consteval exception(string_view __what, info __from, >> + source_location __where >> + = source_location::current()) noexcept >> + : _M_what{__what}, _M_u8what{_S_exception_cvt_to_utf8(__what)}, >> + _M_from{__from}, _M_where{__where} {} >> + >> + exception(const exception&) = default; >> + exception(exception&&) = default; >> + >> + exception& operator=(const exception&) = default; >> + exception& operator=(exception&&) = default; >> + >> + consteval const char *what() const noexcept override >> + { >> + // If u8string is not empty and string is empty, conversion >> + // from UTF-8 to ordinary literal encoding failed. >> + // In that case what() should be non-constant. >> + if (_M_what.size() == 0 && _M_u8what.size() != 0) >> + asm(""); >> + return _M_what.c_str(); >> + } >> + consteval u8string_view u8what() const noexcept { return >> _M_u8what; } >> + consteval info from() const noexcept { return _M_from; } >> + consteval source_location where() const noexcept { return >> _M_where; } >> + private: >> + // Helper special template metafunctions to convert from UTF-8 to >> + // ordinary literal encoding and vice versa. On conversion failure >> + // they just return an empty {,u8}string_view. >> + template<ranges::input_range _R> >> + static consteval u8string_view _S_exception_cvt_to_utf8(_R&&); >> + template<ranges::input_range _R> >> + static consteval string_view _S_exception_cvt_from_utf8(_R&&); >> + }; >> + >> + // [meta.reflection.operators], operator representations >> + enum class operators { >> + op_new = 1, >> + op_delete, >> + op_array_new, >> + op_array_delete, >> + op_co_await, >> + op_parentheses, >> + op_square_brackets, >> + op_arrow, >> + op_arrow_star, >> + op_tilde, >> + op_exclamation, >> + op_plus, >> + op_minus, >> + op_star, >> + op_slash, >> + op_percent, >> + op_caret, >> + op_ampersand, >> + op_equals, >> + op_pipe, >> + op_plus_equals, >> + op_minus_equals, >> + op_star_equals, >> + op_slash_equals, >> + op_percent_equals, >> + op_caret_equals, >> + op_ampersand_equals, >> + op_pipe_equals, >> + op_equals_equals, >> + op_exclamation_equals, >> + op_less, >> + op_greater, >> + op_less_equals, >> + op_greater_equals, >> + op_spaceship, >> + op_ampersand_ampersand, >> + op_pipe_pipe, >> + op_less_less, >> + op_greater_greater, >> + op_less_less_equals, >> + op_greater_greater_equals, >> + op_plus_plus, >> + op_minus_minus, >> + op_comma >> + }; >> + using enum operators; >> + consteval operators operator_of(info); >> + consteval string_view symbol_of(operators); >> + consteval u8string_view u8symbol_of(operators); >> + >> + // [meta.reflection.names], reflection names and locations >> + consteval bool has_identifier(info); >> + >> + consteval string_view identifier_of(info); >> + consteval u8string_view u8identifier_of(info); >> + >> + consteval string_view display_string_of(info); >> + consteval u8string_view u8display_string_of(info); >> + >> + consteval source_location source_location_of(info); >> + >> + // [meta.reflection.queries], reflection queries >> + consteval info type_of(info); >> + consteval info object_of(info); >> + consteval info constant_of(info); >> + >> + consteval bool is_public(info); >> + consteval bool is_protected(info); >> + consteval bool is_private(info); >> + >> + consteval bool is_virtual(info); >> + consteval bool is_pure_virtual(info); >> + consteval bool is_override(info); >> + consteval bool is_final(info); >> + >> + consteval bool is_deleted(info); >> + consteval bool is_defaulted(info); >> + consteval bool is_user_provided(info); >> + consteval bool is_user_declared(info); >> + consteval bool is_explicit(info); >> + consteval bool is_noexcept(info); >> + >> + consteval bool is_bit_field(info); >> + consteval bool is_enumerator(info); >> + consteval bool is_annotation(info); >> + >> + consteval bool is_const(info); >> + consteval bool is_volatile(info); >> + consteval bool is_mutable_member(info); >> + consteval bool is_lvalue_reference_qualified(info); >> + consteval bool is_rvalue_reference_qualified(info); >> + >> + consteval bool has_static_storage_duration(info); >> + consteval bool has_thread_storage_duration(info); >> + consteval bool has_automatic_storage_duration(info); >> + >> + consteval bool has_internal_linkage(info); >> + consteval bool has_module_linkage(info); >> + consteval bool has_external_linkage(info); >> + consteval bool has_c_language_linkage(info); >> + consteval bool has_linkage(info); >> + >> + consteval bool is_complete_type(info); >> + consteval bool is_enumerable_type(info); >> + >> + consteval bool is_variable(info); >> + consteval bool is_type(info); >> + consteval bool is_namespace(info); >> + consteval bool is_type_alias(info); >> + consteval bool is_namespace_alias(info); >> + >> + consteval bool is_function(info); >> + consteval bool is_conversion_function(info); >> + consteval bool is_operator_function(info); >> + consteval bool is_literal_operator(info); >> + consteval bool is_special_member_function(info); >> + consteval bool is_constructor(info); >> + consteval bool is_default_constructor(info); >> + consteval bool is_copy_constructor(info); >> + consteval bool is_move_constructor(info); >> + consteval bool is_assignment(info); >> + consteval bool is_copy_assignment(info); >> + consteval bool is_move_assignment(info); >> + consteval bool is_destructor(info); >> + >> + consteval bool is_function_parameter(info); >> + consteval bool is_explicit_object_parameter(info); >> + consteval bool has_default_argument(info); >> + consteval bool has_ellipsis_parameter(info); >> + >> + consteval bool is_template(info); >> + consteval bool is_function_template(info); >> + consteval bool is_variable_template(info); >> + consteval bool is_class_template(info); >> + consteval bool is_alias_template(info); >> + consteval bool is_conversion_function_template(info); >> + consteval bool is_operator_function_template(info); >> + consteval bool is_literal_operator_template(info); >> + consteval bool is_constructor_template(info); >> + consteval bool is_concept(info); >> + >> + consteval bool is_value(info); >> + consteval bool is_object(info); >> + >> + consteval bool is_structured_binding(info); >> + >> + consteval bool is_class_member(info); >> + consteval bool is_namespace_member(info); >> + consteval bool is_nonstatic_data_member(info); >> + consteval bool is_static_member(info); >> + consteval bool is_base(info); >> + >> + consteval bool has_default_member_initializer(info); >> + >> + consteval bool has_parent(info); >> + consteval info parent_of(info); >> + >> + consteval info dealias(info); >> + >> + consteval bool has_template_arguments(info); >> + consteval info template_of(info); >> + consteval vector<info> template_arguments_of(info); >> + consteval vector<info> parameters_of(info); >> + consteval info variable_of(info); >> + consteval info return_type_of(info); >> + >> + // [meta.reflection.access.context], access control context >> + struct access_context { >> + private: >> + consteval access_context(info __scope, info __designating_class) >> noexcept >> + : _M_scope{__scope}, _M_designating_class{__designating_class} { } >> + public: >> + access_context() = delete; >> + consteval access_context(const access_context &) = default; >> + consteval access_context(access_context &&) = default; >> + >> + consteval info scope() const { return _M_scope; } >> + consteval info designating_class() const { return >> _M_designating_class; } >> + >> + static consteval access_context current() noexcept; >> + static consteval access_context unprivileged() noexcept >> + { return access_context { ^^::, info {} }; } >> + static consteval access_context unchecked() noexcept >> + { return access_context { info {}, info {} }; } >> + consteval access_context via(info) const; >> + >> + info _M_scope; >> + info _M_designating_class; >> + }; >> + >> + // [meta.reflection.access.queries], member accessibility queries >> + consteval bool is_accessible(info, access_context); >> + consteval bool has_inaccessible_nonstatic_data_members(info, >> + >> access_context); >> + consteval bool has_inaccessible_bases(info, access_context); >> + consteval bool has_inaccessible_subobjects(info, access_context); >> + >> + // [meta.reflection.member.queries], reflection member queries >> + consteval vector<info> members_of(info, access_context); >> + consteval vector<info> bases_of(info, access_context); >> + consteval vector<info> static_data_members_of(info, access_context); >> + consteval vector<info> nonstatic_data_members_of(info, >> access_context); >> + consteval vector<info> subobjects_of(info, access_context); >> + consteval vector<info> enumerators_of(info); >> + >> + // [meta.reflection.layout], reflection layout queries >> + struct member_offset { >> + ptrdiff_t bytes; >> + ptrdiff_t bits; >> + >> + constexpr ptrdiff_t >> + total_bits() const >> + { return bytes * __CHAR_BIT__ + bits; } >> + >> + auto operator<=>(const member_offset&) const = default; >> + }; >> + >> + consteval member_offset offset_of(info); >> + consteval size_t size_of(info); >> + consteval size_t alignment_of(info); >> + consteval size_t bit_size_of(info); >> + >> + // [meta.reflection.extract], value extraction >> + template<class _Tp> >> + consteval _Tp extract(info); >> + >> + // [meta.reflection.substitute], reflection substitution >> + template<class _R> >> + concept reflection_range = ranges::input_range<_R> >> + && same_as<ranges::range_value_t<_R>, info> >> + && same_as<remove_cvref_t<ranges::range_reference_t<_R>>, info>; >> + >> + template<reflection_range _R = initializer_list<info>> >> + consteval bool can_substitute(info, _R&&); >> + template<reflection_range _R = initializer_list<info>> >> + consteval info substitute(info, _R&&); >> + >> + // [meta.reflection.result], expression result reflection >> + template<typename _Tp> >> + requires (is_copy_constructible_v<_Tp>) >> + consteval info reflect_constant(_Tp); >> + template<typename _Tp> >> + requires (!is_function_v<remove_reference_t<_Tp>>) >> + consteval info reflect_object(_Tp&); >> + template<typename _Tp> >> + requires (is_function_v<remove_reference_t<_Tp>>) >> + consteval info reflect_function(_Tp&); >> + >> + // [meta.reflection.array], promoting to static storage arrays >> + template<ranges::input_range _R> >> + consteval info reflect_constant_string(_R&&); >> + >> + template<ranges::input_range _R> >> + consteval info reflect_constant_array(_R&&); >> + >> + // [meta.reflection.define.aggregate], class definition generation >> + struct data_member_options { >> + struct _Name { >> + template<class _Tp> >> + requires constructible_from<u8string, _Tp> >> + consteval _Name(_Tp&& __n) : _M_is_u8(true), _M_u8s((_Tp&&) >> __n) {} >> + >> + template<class _Tp> >> + requires constructible_from<string, _Tp> >> + consteval _Name(_Tp&& __n) : _M_is_u8(false), _M_s((_Tp&&) __n) >> {} >> + >> + private: >> + bool _M_is_u8; >> + u8string _M_u8s; >> + string _M_s; >> + info _M_unused = {}; >> + }; >> + >> + optional<_Name> name; >> + optional<int> alignment; >> + optional<int> bit_width; >> + bool no_unique_address = false; >> + }; >> + consteval info data_member_spec(info, data_member_options); >> + consteval bool is_data_member_spec(info); >> + template<reflection_range _R = initializer_list<info>> >> + consteval info define_aggregate(info, _R&&); >> + >> + // associated with [meta.unary.cat], primary type categories >> + consteval bool is_void_type(info); >> + consteval bool is_null_pointer_type(info); >> + consteval bool is_integral_type(info); >> + consteval bool is_floating_point_type(info); >> + consteval bool is_array_type(info); >> + consteval bool is_pointer_type(info); >> + consteval bool is_lvalue_reference_type(info); >> + consteval bool is_rvalue_reference_type(info); >> + consteval bool is_member_object_pointer_type(info); >> + consteval bool is_member_function_pointer_type(info); >> + consteval bool is_enum_type(info); >> + consteval bool is_union_type(info); >> + consteval bool is_class_type(info); >> + consteval bool is_function_type(info); >> + consteval bool is_reflection_type(info); >> + >> + // associated with [meta.unary.comp], composite type categories >> + consteval bool is_reference_type(info); >> + consteval bool is_arithmetic_type(info); >> + consteval bool is_fundamental_type(info); >> + consteval bool is_object_type(info); >> + consteval bool is_scalar_type(info); >> + consteval bool is_compound_type(info); >> + consteval bool is_member_pointer_type(info); >> + >> + // associated with [meta.unary.prop], type properties >> + consteval bool is_const_type(info); >> + consteval bool is_volatile_type(info); >> + consteval bool is_trivially_copyable_type(info); >> + consteval bool is_standard_layout_type(info); >> + consteval bool is_empty_type(info); >> + consteval bool is_polymorphic_type(info); >> + consteval bool is_abstract_type(info); >> + consteval bool is_final_type(info); >> + consteval bool is_aggregate_type(info); >> + consteval bool is_consteval_only_type(info); >> + consteval bool is_signed_type(info); >> + consteval bool is_unsigned_type(info); >> + consteval bool is_bounded_array_type(info); >> + consteval bool is_unbounded_array_type(info); >> + consteval bool is_scoped_enum_type(info); >> + >> + template<reflection_range _R = initializer_list<info>> >> + consteval bool is_constructible_type(info, _R&&); >> + consteval bool is_default_constructible_type(info); >> + consteval bool is_copy_constructible_type(info); >> + consteval bool is_move_constructible_type(info); >> + >> + consteval bool is_assignable_type(info, info); >> + consteval bool is_copy_assignable_type(info); >> + consteval bool is_move_assignable_type(info); >> + >> + consteval bool is_swappable_with_type(info, info); >> + consteval bool is_swappable_type(info); >> + >> + consteval bool is_destructible_type(info); >> + >> + template<reflection_range _R = initializer_list<info>> >> + consteval bool is_trivially_constructible_type(info, _R&&); >> + consteval bool is_trivially_default_constructible_type(info); >> + consteval bool is_trivially_copy_constructible_type(info); >> + consteval bool is_trivially_move_constructible_type(info); >> + >> + consteval bool is_trivially_assignable_type(info, info); >> + consteval bool is_trivially_copy_assignable_type(info); >> + consteval bool is_trivially_move_assignable_type(info); >> + consteval bool is_trivially_destructible_type(info); >> + >> + template<reflection_range _R = initializer_list<info>> >> + consteval bool is_nothrow_constructible_type(info, _R&&); >> + consteval bool is_nothrow_default_constructible_type(info); >> + consteval bool is_nothrow_copy_constructible_type(info); >> + consteval bool is_nothrow_move_constructible_type(info); >> + >> + consteval bool is_nothrow_assignable_type(info, info); >> + consteval bool is_nothrow_copy_assignable_type(info); >> + consteval bool is_nothrow_move_assignable_type(info); >> + >> + consteval bool is_nothrow_swappable_with_type(info, info); >> + consteval bool is_nothrow_swappable_type(info); >> + >> + consteval bool is_nothrow_destructible_type(info); >> + >> + consteval bool is_implicit_lifetime_type(info); >> + >> + consteval bool has_virtual_destructor(info); >> + >> + consteval bool has_unique_object_representations(info); >> + >> + consteval bool reference_constructs_from_temporary(info, info); >> + consteval bool reference_converts_from_temporary(info, info); >> + >> + // associated with [meta.unary.prop.query], type property queries >> + consteval size_t rank(info); >> + consteval size_t extent(info, unsigned = 0); >> + >> + // associated with [meta.rel], type relations >> + consteval bool is_same_type(info, info); >> + consteval bool is_base_of_type(info, info); >> + consteval bool is_virtual_base_of_type(info, info); >> + consteval bool is_convertible_type(info, info); >> + consteval bool is_nothrow_convertible_type(info, info); >> + consteval bool is_layout_compatible_type(info, info); >> + consteval bool is_pointer_interconvertible_base_of_type(info, info); >> + >> + template<reflection_range _R = initializer_list<info>> >> + consteval bool is_invocable_type(info, _R&&); >> + template<reflection_range _R = initializer_list<info>> >> + consteval bool is_invocable_r_type(info, info, _R&&); >> + >> + template<reflection_range _R = initializer_list<info>> >> + consteval bool is_nothrow_invocable_type(info, _R&&); >> + template<reflection_range _R = initializer_list<info>> >> + consteval bool is_nothrow_invocable_r_type(info, info, _R&&); >> + >> + // associated with [meta.trans.cv], const-volatile modifications >> + consteval info remove_const(info); >> + consteval info remove_volatile(info); >> + consteval info remove_cv(info); >> + consteval info add_const(info); >> + consteval info add_volatile(info); >> + consteval info add_cv(info); >> + >> + // associated with [meta.trans.ref], reference modifications >> + consteval info remove_reference(info); >> + consteval info add_lvalue_reference(info); >> + consteval info add_rvalue_reference(info); >> + >> + // associated with [meta.trans.sign], sign modifications >> + consteval info make_signed(info); >> + consteval info make_unsigned(info); >> + >> + // associated with [meta.trans.arr], array modifications >> + consteval info remove_extent(info); >> + consteval info remove_all_extents(info); >> + >> + // associated with [meta.trans.ptr], pointer modifications >> + consteval info remove_pointer(info); >> + consteval info add_pointer(info); >> + >> + // associated with [meta.trans.other], other transformations >> + consteval info remove_cvref(info); >> + consteval info decay(info); >> + template<reflection_range _R = initializer_list<info>> >> + consteval info common_type(_R&&); >> + template<reflection_range _R = initializer_list<info>> >> + consteval info common_reference(_R&&); >> + consteval info underlying_type(info); >> + template<reflection_range _R = initializer_list<info>> >> + consteval info invoke_result(info, _R&&); >> + consteval info unwrap_reference(info); >> + consteval info unwrap_ref_decay(info); >> + >> + consteval size_t tuple_size(info); >> + consteval info tuple_element(size_t, info); >> + >> + consteval size_t variant_size(info); >> + consteval info variant_alternative(size_t, info); >> + >> + consteval strong_ordering type_order(info, info); >> + >> + // [meta.reflection.annotation], annotation reflection >> + consteval vector<info> annotations_of(info); >> + consteval vector<info> annotations_of_with_type(info, info); >> + >> + consteval access_context >> + access_context::via(info __cls) const >> + { >> + if (__cls != info {} >> + && (!std::meta::is_class_type(__cls) >> + || !std::meta::is_complete_type(__cls))) >> + { >> +#if __cpp_exceptions >> + throw std::meta::exception(u8"via argument other than null " >> + "or complete class type >> reflection", >> + ^^access_context::via); >> +#else >> + return *this; >> +#endif >> + } >> + return access_context { _M_scope, __cls }; >> + } >> + >> + } // namespace meta >> + >> + // [meta.define.static], promoting to static storage strings >> + template<ranges::input_range _R> >> + consteval const ranges::range_value_t<_R>* >> + define_static_string(_R&& __r) >> + { >> + auto __str = meta::reflect_constant_string(__r); >> + return meta::extract<const ranges::range_value_t<_R>*>(__str); >> + } >> + >> + template<ranges::input_range _R> >> + consteval span<const ranges::range_value_t<_R>> >> + define_static_array(_R&& __r) >> + { >> + using _Tp = ranges::range_value_t<_R>; >> + auto __array = meta::reflect_constant_array(__r); >> + auto __type = meta::type_of(__array); >> + if (meta::is_array_type(__type)) >> + return span<const _Tp>(meta::extract<const _Tp*>(__array), >> + meta::extent(__type, 0U)); >> + else >> + return span<const _Tp>(); >> + } >> + >> + template<class _Tp> >> + consteval const remove_cvref_t<_Tp>* >> + define_static_object(_Tp&& __t) >> + { >> + using _Up = remove_cvref_t<_Tp>; >> + if constexpr (meta::is_class_type(^^_Up)) >> + { >> + auto __cst = meta::reflect_constant(std::forward<_Tp>(__t)); >> + return std::addressof(meta::extract<const _Up&>(__cst)); >> + } >> + else >> + return std::define_static_array(span<const >> _Up>(std::addressof(__t), >> + 1)).data(); >> > I think I would prefer a symmetric branch to one above: > auto cst = meta::reflect_constant_array(std::forward<_Tp>(__t)); > return std::addressof(meta::extract<const _Up&>(__cst)); > >> + } >> + >> +_GLIBCXX_END_NAMESPACE_VERSION >> +} // namespace std >> + >> +#endif // C++26 >> + >> +#endif // _GLIBCXX_META >> diff --git a/libstdc++-v3/include/std/type_traits >> b/libstdc++-v3/include/std/type_traits >> index d28b077398b..75859e11ebf 100644 >> --- a/libstdc++-v3/include/std/type_traits >> +++ b/libstdc++-v3/include/std/type_traits >> @@ -695,6 +695,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> : public false_type { }; >> #endif >> >> +#if __cpp_impl_reflection >= 202500L // C++ >= 26 >> + /// is_reflection >> + template<typename _Tp> >> + struct is_reflection >> + : public false_type { }; >> + >> + template<> >> + struct is_reflection<decltype(^^int)> >> + : public true_type { }; >> + >> + template<> >> + struct is_reflection<const decltype(^^int)> >> + : public true_type { }; >> + >> + template<> >> + struct is_reflection<volatile decltype(^^int)> >> + : public true_type { }; >> + >> + template<> >> + struct is_reflection<const volatile decltype(^^int)> >> + : public true_type { }; >> +#endif >> + >> #ifdef __cpp_lib_is_null_pointer // C++ >= 11 >> /// is_null_pointer (LWG 2247). >> template<typename _Tp> >> @@ -757,11 +780,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> { }; >> >> /// is_fundamental >> +#if __cpp_impl_reflection >= 202500L >> + template<typename _Tp> >> + struct is_fundamental >> + : public __or_<is_arithmetic<_Tp>, is_void<_Tp>, >> + is_null_pointer<_Tp>, is_reflection<_Tp>>::type >> + { }; >> +#else >> template<typename _Tp> >> struct is_fundamental >> : public __or_<is_arithmetic<_Tp>, is_void<_Tp>, >> is_null_pointer<_Tp>>::type >> { }; >> +#endif >> >> /// is_object >> #if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object) >> @@ -3519,6 +3550,12 @@ template <typename _Tp> >> is_member_function_pointer<_Tp>::value; >> #endif >> >> +#if __cpp_impl_reflection >= 202500L // C++ >= 26 >> +template <typename _Tp> >> + inline constexpr bool is_reflection_v = >> + is_reflection<_Tp>::value; >> +#endif >> + >> template <typename _Tp> >> inline constexpr bool is_enum_v = __is_enum(_Tp); >> template <typename _Tp> >> @@ -3851,6 +3888,24 @@ template<typename _Ret, typename _Fn, typename... >> _Args> >> # endif >> #endif >> >> +#if __cpp_impl_reflection >= 202500L \ >> + && _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_is_consteval_only) // C++ >= >> 26 >> + /// is_consteval_only - true if the type is consteval-only. >> + /// @since C++26 >> + template<typename _Tp> >> + struct is_consteval_only >> + : bool_constant<__builtin_is_consteval_only(_Tp)> >> + { }; >> + >> + /** is_consteval_only_v - true if the type is consteval-only. >> + * @ingroup variable_templates >> + * @since C++26 >> + */ >> + template<typename _Tp> >> + inline constexpr bool is_consteval_only_v >> + = __builtin_is_consteval_only(_Tp); >> +#endif >> + >> /** * Remove references and cv-qualifiers. >> * @since C++20 >> * @{ >> diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/ >> std.cc.in >> index 27d83f1ba1b..a75db1fe0a0 100644 >> --- a/libstdc++-v3/src/c++23/std.cc.in >> +++ b/libstdc++-v3/src/c++23/std.cc.in >> @@ -2035,6 +2035,261 @@ export namespace std::pmr >> using std::pmr::unsynchronized_pool_resource; >> } >> >> +// <meta> >> +#if __glibcxx_reflection >= 202506L >> +export namespace std >> +{ >> +#if __has_builtin(__builtin_is_string_literal) >> + using std::is_string_literal; >> +#endif >> + using std::define_static_string; >> + using std::define_static_array; >> + using std::define_static_object; >> + namespace meta >> + { >> + using std::meta::info; >> + using std::meta::exception; >> + using std::meta::operators; >> + using enum std::meta::operators; >> + using std::meta::operator_of; >> + using std::meta::symbol_of; >> + using std::meta::u8symbol_of; >> + using std::meta::has_identifier; >> + using std::meta::identifier_of; >> + using std::meta::u8identifier_of; >> + using std::meta::display_string_of; >> + using std::meta::u8display_string_of; >> + using std::meta::source_location_of; >> + using std::meta::type_of; >> + using std::meta::object_of; >> + using std::meta::constant_of; >> + using std::meta::is_public; >> + using std::meta::is_protected; >> + using std::meta::is_private; >> + using std::meta::is_virtual; >> + using std::meta::is_pure_virtual; >> + using std::meta::is_override; >> + using std::meta::is_final; >> + using std::meta::is_deleted; >> + using std::meta::is_defaulted; >> + using std::meta::is_user_provided; >> + using std::meta::is_user_declared; >> + using std::meta::is_explicit; >> + using std::meta::is_noexcept; >> + using std::meta::is_bit_field; >> + using std::meta::is_enumerator; >> + using std::meta::is_annotation; >> + using std::meta::is_const; >> + using std::meta::is_volatile; >> + using std::meta::is_mutable_member; >> + using std::meta::is_lvalue_reference_qualified; >> + using std::meta::is_rvalue_reference_qualified; >> + using std::meta::has_static_storage_duration; >> + using std::meta::has_thread_storage_duration; >> + using std::meta::has_automatic_storage_duration; >> + using std::meta::has_internal_linkage; >> + using std::meta::has_module_linkage; >> + using std::meta::has_external_linkage; >> + using std::meta::has_c_language_linkage; >> + using std::meta::has_linkage; >> + using std::meta::is_complete_type; >> + using std::meta::is_enumerable_type; >> + using std::meta::is_variable; >> + using std::meta::is_type; >> + using std::meta::is_namespace; >> + using std::meta::is_type_alias; >> + using std::meta::is_namespace_alias; >> + using std::meta::is_function; >> + using std::meta::is_conversion_function; >> + using std::meta::is_operator_function; >> + using std::meta::is_literal_operator; >> + using std::meta::is_special_member_function; >> + using std::meta::is_constructor; >> + using std::meta::is_default_constructor; >> + using std::meta::is_copy_constructor; >> + using std::meta::is_move_constructor; >> + using std::meta::is_assignment; >> + using std::meta::is_copy_assignment; >> + using std::meta::is_move_assignment; >> + using std::meta::is_destructor; >> + using std::meta::is_function_parameter; >> + using std::meta::is_explicit_object_parameter; >> + using std::meta::has_default_argument; >> + using std::meta::has_ellipsis_parameter; >> + using std::meta::is_template; >> + using std::meta::is_function_template; >> + using std::meta::is_variable_template; >> + using std::meta::is_class_template; >> + using std::meta::is_alias_template; >> + using std::meta::is_conversion_function_template; >> + using std::meta::is_operator_function_template; >> + using std::meta::is_literal_operator_template; >> + using std::meta::is_constructor_template; >> + using std::meta::is_concept; >> + using std::meta::is_value; >> + using std::meta::is_object; >> + using std::meta::is_structured_binding; >> + using std::meta::is_class_member; >> + using std::meta::is_namespace_member; >> + using std::meta::is_nonstatic_data_member; >> + using std::meta::is_static_member; >> + using std::meta::is_base; >> + using std::meta::has_default_member_initializer; >> + using std::meta::has_parent; >> + using std::meta::parent_of; >> + using std::meta::dealias; >> + using std::meta::has_template_arguments; >> + using std::meta::template_of; >> + using std::meta::template_arguments_of; >> + using std::meta::parameters_of; >> + using std::meta::variable_of; >> + using std::meta::return_type_of; >> + using std::meta::access_context; >> + using std::meta::is_accessible; >> + using std::meta::has_inaccessible_nonstatic_data_members; >> + using std::meta::has_inaccessible_bases; >> + using std::meta::has_inaccessible_subobjects; >> + using std::meta::members_of; >> + using std::meta::bases_of; >> + using std::meta::static_data_members_of; >> + using std::meta::nonstatic_data_members_of; >> + using std::meta::subobjects_of; >> + using std::meta::enumerators_of; >> + using std::meta::member_offset; >> + using std::meta::offset_of; >> + using std::meta::size_of; >> + using std::meta::alignment_of; >> + using std::meta::bit_size_of; >> + using std::meta::extract; >> + using std::meta::reflection_range; >> + using std::meta::can_substitute; >> + using std::meta::substitute; >> + using std::meta::reflect_constant; >> + using std::meta::reflect_object; >> + using std::meta::reflect_function; >> + using std::meta::reflect_constant_string; >> + using std::meta::reflect_constant_array; >> + using std::meta::data_member_options; >> + using std::meta::data_member_spec; >> + using std::meta::is_data_member_spec; >> + using std::meta::define_aggregate; >> + using std::meta::is_void_type; >> + using std::meta::is_null_pointer_type; >> + using std::meta::is_integral_type; >> + using std::meta::is_floating_point_type; >> + using std::meta::is_array_type; >> + using std::meta::is_pointer_type; >> + using std::meta::is_lvalue_reference_type; >> + using std::meta::is_rvalue_reference_type; >> + using std::meta::is_member_object_pointer_type; >> + using std::meta::is_member_function_pointer_type; >> + using std::meta::is_enum_type; >> + using std::meta::is_union_type; >> + using std::meta::is_class_type; >> + using std::meta::is_function_type; >> + using std::meta::is_reflection_type; >> + using std::meta::is_reference_type; >> + using std::meta::is_arithmetic_type; >> + using std::meta::is_fundamental_type; >> + using std::meta::is_object_type; >> + using std::meta::is_scalar_type; >> + using std::meta::is_compound_type; >> + using std::meta::is_member_pointer_type; >> + using std::meta::is_const_type; >> + using std::meta::is_volatile_type; >> + using std::meta::is_trivially_copyable_type; >> + using std::meta::is_standard_layout_type; >> + using std::meta::is_empty_type; >> + using std::meta::is_polymorphic_type; >> + using std::meta::is_abstract_type; >> + using std::meta::is_final_type; >> + using std::meta::is_aggregate_type; >> + using std::meta::is_consteval_only_type; >> + using std::meta::is_signed_type; >> + using std::meta::is_unsigned_type; >> + using std::meta::is_bounded_array_type; >> + using std::meta::is_unbounded_array_type; >> + using std::meta::is_scoped_enum_type; >> + using std::meta::is_constructible_type; >> + using std::meta::is_default_constructible_type; >> + using std::meta::is_copy_constructible_type; >> + using std::meta::is_move_constructible_type; >> + using std::meta::is_assignable_type; >> + using std::meta::is_copy_assignable_type; >> + using std::meta::is_move_assignable_type; >> + using std::meta::is_swappable_with_type; >> + using std::meta::is_swappable_type; >> + using std::meta::is_destructible_type; >> + using std::meta::is_trivially_constructible_type; >> + using std::meta::is_trivially_default_constructible_type; >> + using std::meta::is_trivially_copy_constructible_type; >> + using std::meta::is_trivially_move_constructible_type; >> + using std::meta::is_trivially_assignable_type; >> + using std::meta::is_trivially_copy_assignable_type; >> + using std::meta::is_trivially_move_assignable_type; >> + using std::meta::is_trivially_destructible_type; >> + using std::meta::is_nothrow_constructible_type; >> + using std::meta::is_nothrow_default_constructible_type; >> + using std::meta::is_nothrow_copy_constructible_type; >> + using std::meta::is_nothrow_move_constructible_type; >> + using std::meta::is_nothrow_assignable_type; >> + using std::meta::is_nothrow_copy_assignable_type; >> + using std::meta::is_nothrow_move_assignable_type; >> + using std::meta::is_nothrow_swappable_with_type; >> + using std::meta::is_nothrow_swappable_type; >> + using std::meta::is_nothrow_destructible_type; >> + using std::meta::is_implicit_lifetime_type; >> + using std::meta::has_virtual_destructor; >> + using std::meta::has_unique_object_representations; >> + using std::meta::reference_constructs_from_temporary; >> + using std::meta::reference_converts_from_temporary; >> + using std::meta::rank; >> + using std::meta::extent; >> + using std::meta::is_same_type; >> + using std::meta::is_base_of_type; >> + using std::meta::is_virtual_base_of_type; >> + using std::meta::is_convertible_type; >> + using std::meta::is_nothrow_convertible_type; >> + using std::meta::is_layout_compatible_type; >> + using std::meta::is_pointer_interconvertible_base_of_type; >> + using std::meta::is_invocable_type; >> + using std::meta::is_invocable_r_type; >> + using std::meta::is_nothrow_invocable_type; >> + using std::meta::is_nothrow_invocable_r_type; >> + using std::meta::remove_const; >> + using std::meta::remove_volatile; >> + using std::meta::remove_cv; >> + using std::meta::add_const; >> + using std::meta::add_volatile; >> + using std::meta::add_cv; >> + using std::meta::remove_reference; >> + using std::meta::add_lvalue_reference; >> + using std::meta::add_rvalue_reference; >> + using std::meta::make_signed; >> + using std::meta::make_unsigned; >> + using std::meta::remove_extent; >> + using std::meta::remove_all_extents; >> + using std::meta::remove_pointer; >> + using std::meta::add_pointer; >> + using std::meta::remove_cvref; >> + using std::meta::decay; >> + using std::meta::common_type; >> + using std::meta::common_reference; >> + using std::meta::underlying_type; >> + using std::meta::invoke_result; >> + using std::meta::unwrap_reference; >> + using std::meta::unwrap_ref_decay; >> + using std::meta::tuple_size; >> + using std::meta::tuple_element; >> + using std::meta::variant_size; >> + using std::meta::variant_alternative; >> + using std::meta::type_order; >> + using std::meta::annotations_of; >> + using std::meta::annotations_of_with_type; >> + } >> +} >> +#endif >> + >> // <mutex> >> export namespace std >> { >> diff --git >> a/libstdc++-v3/testsuite/20_util/is_consteval_only/requirements/explicit_instantiation.cc >> b/libstdc++-v3/testsuite/20_util/is_consteval_only/requirements/explicit_instantiation.cc >> new file mode 100644 >> index 00000000000..3680730bd45 >> --- /dev/null >> +++ >> b/libstdc++-v3/testsuite/20_util/is_consteval_only/requirements/explicit_instantiation.cc >> @@ -0,0 +1,29 @@ >> +// { dg-do compile { target c++26 } } >> +// { dg-additional-options "-freflection" } >> + >> +// 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/>. >> + >> +// NB: This file is for testing type_traits with NO OTHER INCLUDES. >> + >> +#include <type_traits> >> + >> +namespace std >> +{ >> + typedef short test_type; >> + template struct is_consteval_only<test_type>; >> +} >> diff --git >> a/libstdc++-v3/testsuite/20_util/is_consteval_only/requirements/typedefs.cc >> b/libstdc++-v3/testsuite/20_util/is_consteval_only/requirements/typedefs.cc >> new file mode 100644 >> index 00000000000..39a55baeb3f >> --- /dev/null >> +++ >> b/libstdc++-v3/testsuite/20_util/is_consteval_only/requirements/typedefs.cc >> @@ -0,0 +1,34 @@ >> +// { dg-do compile { target c++26 } } >> +// { dg-additional-options "-freflection" } >> + >> +// 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/>. >> + >> +// >> +// NB: This file is for testing type_traits with NO OTHER INCLUDES. >> + >> +#include <type_traits> >> + >> +void test01() >> +{ >> + // Check for required typedefs >> + typedef std::is_consteval_only<decltype (^^int)> test_type; >> + typedef test_type::value_type value_type; >> + typedef test_type::type type; >> + typedef test_type::type::value_type type_value_type; >> + typedef test_type::type::type type_type; >> +} >> diff --git a/libstdc++-v3/testsuite/20_util/is_consteval_only/value.cc >> b/libstdc++-v3/testsuite/20_util/is_consteval_only/value.cc >> new file mode 100644 >> index 00000000000..d391ac79c34 >> --- /dev/null >> +++ b/libstdc++-v3/testsuite/20_util/is_consteval_only/value.cc >> @@ -0,0 +1,47 @@ >> +// { dg-do compile { target c++26 } } >> +// { dg-additional-options "-freflection" } >> + >> +// 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/>. >> + >> +#include <type_traits> >> +#include <testsuite_tr1.h> >> + >> +void test01() >> +{ >> + using std::is_consteval_only; >> + using namespace __gnu_test; >> + int v = 1; >> + struct S1 { decltype(^^long) a; }; >> + union U2 { int a; decltype(^^test01) b; }; >> + struct S3 { const decltype(^^__gnu_test) *c; }; >> + struct S4 : public S3 {}; >> + struct S5 { int a; long *b; }; >> + >> + static_assert(test_category<is_consteval_only, >> decltype(^^long)>(true), ""); >> + static_assert(test_category<is_consteval_only, const >> decltype(^^test01)>(true), ""); >> + static_assert(test_category<is_consteval_only, volatile >> decltype(^^__gnu_test)>(true), ""); >> + static_assert(test_category<is_consteval_only, const volatile >> decltype(^^v)>(true), ""); >> + static_assert(test_category<is_consteval_only, const S1>(true), ""); >> + static_assert(test_category<is_consteval_only, U2>(true), ""); >> + static_assert(test_category<is_consteval_only, S3>(true), ""); >> + static_assert(test_category<is_consteval_only, S4>(true), ""); >> + >> + // Sanity check. >> + static_assert(test_category<is_consteval_only, int>(false), ""); >> + static_assert(test_category<is_consteval_only, S5>(false), ""); >> +} >> diff --git >> a/libstdc++-v3/testsuite/20_util/is_reflection/requirements/explicit_instantiation.cc >> b/libstdc++-v3/testsuite/20_util/is_reflection/requirements/explicit_instantiation.cc >> new file mode 100644 >> index 00000000000..952574a8567 >> --- /dev/null >> +++ >> b/libstdc++-v3/testsuite/20_util/is_reflection/requirements/explicit_instantiation.cc >> @@ -0,0 +1,29 @@ >> +// { dg-do compile { target c++26 } } >> +// { dg-additional-options "-freflection" } >> + >> +// 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/>. >> + >> +// NB: This file is for testing type_traits with NO OTHER INCLUDES. >> + >> +#include <type_traits> >> + >> +namespace std >> +{ >> + typedef short test_type; >> + template struct is_reflection<test_type>; >> +} >> diff --git >> a/libstdc++-v3/testsuite/20_util/is_reflection/requirements/typedefs.cc >> b/libstdc++-v3/testsuite/20_util/is_reflection/requirements/typedefs.cc >> new file mode 100644 >> index 00000000000..04cdb0a56be >> --- /dev/null >> +++ >> b/libstdc++-v3/testsuite/20_util/is_reflection/requirements/typedefs.cc >> @@ -0,0 +1,34 @@ >> +// { dg-do compile { target c++26 } } >> +// { dg-additional-options "-freflection" } >> + >> +// 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/>. >> + >> +// >> +// NB: This file is for testing type_traits with NO OTHER INCLUDES. >> + >> +#include <type_traits> >> + >> +void test01() >> +{ >> + // Check for required typedefs >> + typedef std::is_reflection<decltype (^^int)> test_type; >> + typedef test_type::value_type value_type; >> + typedef test_type::type type; >> + typedef test_type::type::value_type type_value_type; >> + typedef test_type::type::type type_type; >> +} >> diff --git a/libstdc++-v3/testsuite/20_util/is_reflection/value.cc >> b/libstdc++-v3/testsuite/20_util/is_reflection/value.cc >> new file mode 100644 >> index 00000000000..ec820751faf >> --- /dev/null >> +++ b/libstdc++-v3/testsuite/20_util/is_reflection/value.cc >> @@ -0,0 +1,37 @@ >> +// { dg-do compile { target c++26 } } >> +// { dg-additional-options "-freflection" } >> + >> +// 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/>. >> + >> +#include <type_traits> >> +#include <testsuite_tr1.h> >> + >> +void test01() >> +{ >> + using std::is_reflection; >> + using namespace __gnu_test; >> + int v = 1; >> + >> + static_assert(test_category<is_reflection, decltype(^^long)>(true), >> ""); >> + static_assert(test_category<is_reflection, const >> decltype(^^test01)>(true), ""); >> + static_assert(test_category<is_reflection, volatile >> decltype(^^__gnu_test)>(true), ""); >> + static_assert(test_category<is_reflection, const volatile >> decltype(^^v)>(true), ""); >> + >> + // Sanity check. >> + static_assert(test_category<is_reflection, int>(false), ""); >> +} >> diff --git >> a/libstdc++-v3/testsuite/20_util/variable_templates_for_traits.cc >> b/libstdc++-v3/testsuite/20_util/variable_templates_for_traits.cc >> index b48958746e1..0efc533f25b 100644 >> --- a/libstdc++-v3/testsuite/20_util/variable_templates_for_traits.cc >> +++ b/libstdc++-v3/testsuite/20_util/variable_templates_for_traits.cc >> @@ -1,5 +1,6 @@ >> // { dg-additional-options "-Wno-deprecated-declarations" { target c++2a >> } } >> // { dg-do compile { target c++17 } } >> +// { dg-additional-options "-freflection" { target c++26 } } >> >> // Copyright (C) 2014-2025 Free Software Foundation, Inc. >> // >> @@ -330,6 +331,12 @@ static_assert(is_convertible_v<int&, const int&> >> static_assert(!is_convertible_v<const int&, int&> >> && !is_convertible<const int&, int&>::value, ""); >> >> +#if __cpp_impl_reflection >= 202500L >> +static_assert(is_reflection_v<decltype(^^int)> >> + && is_reflection<decltype(^^int)>::value, ""); >> +static_assert(!is_reflection_v<int> && !is_reflection<int>::value, ""); >> +#endif >> + >> static_assert(negation_v<false_type>, ""); >> static_assert(!negation_v<true_type>, ""); >> static_assert(conjunction_v<>, ""); >> >>
