[PATCH 4/9] c++: C++26 Reflection [PR120775]

Jonathan Wakely jwakely@redhat.com
Sat Nov 15 08:47:10 GMT 2025


On Fri, 14 Nov 2025 at 19:37 -0500, Marek Polacek wrote:
>This contains the libstdc++ bits (including <meta>).

Excliting! A few small changes requested below ...

>-- >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
>       __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>

We could move all these headers after the #if below, so that we don't
include anything if this is going to be an empty file. I don't think
we're consistent about how we do that elsewhere though, so it's not
important to change now.

>+
>+#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,

Please put a newline before 'exception'

       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,

Ditto

>+			  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>

We need to avoid single letter names of the form _[A-Z] like _R
because they clash with ctype macros on some C libraries, so it should
be _Rg everywhere that you've used _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;

Should this be non-constant instead of returning a valid value?

>+#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();
>+    }
>+
>+_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

I think I'd prefer just one definition, with a conditional part:

   template<typename _Tp>
     struct is_fundamental
     : public __or_<is_arithmetic<_Tp>, is_void<_Tp>,
		   is_null_pointer<_Tp>
#if __cpp_impl_reflection >= 202500L
                    , is_reflection<_Tp>
#endif
                    >::type
     { };

That way if we need to add other traits to the list, or we can replace
is_arithmetic<_Tp> with a new __bool_constant<__is_arithmetic(_Tp)>
builtin, we don't need to edit two definitions of is_fundamental.

>   /// 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;

We could specialize this to avoid instantiating the is_reflection
class template, but that can be optimized later.

>+#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;

This is enough to export all the enumerators of this enum, right?

Hmm, we don't do this for other enums such as
std::filesystem::file_type, which might be a bug in the existing
exports...

>+    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.

We don't need the copyright and license header on these tests, they're
not doing anything legally significant that is copyrightable.

>+
>+#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>;

We should really rationalize our type_traits tests and stop having
three separate one-line tests for every individual trait :-\

That's not something to fix with this patch though, just reminding
myself to revisit it one day.

>+}
>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<>, "");
>
>



More information about the Libstdc++ mailing list