]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix up extract_ref [PR125111]
authorJakub Jelinek <jakub@redhat.com>
Thu, 7 May 2026 06:54:21 +0000 (08:54 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 7 May 2026 06:54:21 +0000 (08:54 +0200)
https://eel.is/c++draft/meta.reflection.extract#5.2 requests that
is_convertible_v<remove_reference_t<U>(*)[], remove_reference_t<T>(*)[]>
is tested and if it not true, the function throws.
If U/T are references to function/method/array[], we try to build
array of types which are not valid in arrays and ICE shortly after that.
The following patch makes sure we don't create arrays in that case
and instead just throw the exception.  We can't have references to void
or references to references, so I think the other problematic cases
of creating arrays can't trigger.

2026-05-07  Jakub Jelinek  <jakub@redhat.com>

PR c++/125111
* reflect.cc (extract_ref): Throw instead of trying to build
arrays of functions, methods or arrays with NULL TYPE_DOMAIN.

* g++.dg/reflect/extract12.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/reflect.cc
gcc/testsuite/g++.dg/reflect/extract12.C [new file with mode: 0644]

index 816950d43edee0f41cc55588dfcd56011e5c009f..bcbb5980c9f31abffb0d9dde3dedd23206109773 100644 (file)
@@ -7453,6 +7453,10 @@ extract_ref (location_t loc, const constexpr_ctx *ctx, tree T, tree r,
     {
       if (TYPE_REF_P (type))
        type = TREE_TYPE (type);
+      if (FUNC_OR_METHOD_TYPE_P (type)
+         || (TREE_CODE (type) == ARRAY_TYPE
+             && TYPE_DOMAIN (type) == NULL_TREE))
+       return error_mark_node;
       type = build_cplus_array_type (type, NULL_TREE);
       return build_pointer_type (type);
     };
@@ -7462,7 +7466,11 @@ extract_ref (location_t loc, const constexpr_ctx *ctx, tree T, tree r,
     {
       /* The wording is saying that U is the type of r.  */
       tree U = TREE_TYPE (r);
-      if (is_convertible (adjust_type (U), adjust_type (T))
+      tree adju = adjust_type (U);
+      tree adjt = adjust_type (T);
+      if (adju != error_mark_node
+         && adjt != error_mark_node
+         && is_convertible (adju, adjt)
          && (!var_p || is_constant_expression (r)))
        {
          if (TYPE_REF_P (TREE_TYPE (r)))
diff --git a/gcc/testsuite/g++.dg/reflect/extract12.C b/gcc/testsuite/g++.dg/reflect/extract12.C
new file mode 100644 (file)
index 0000000..cc5c856
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/125111
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+using A = void ();
+extern A &a;
+constexpr auto b = ^^a;
+constexpr auto c = std::meta::extract <A &> (b);       // { dg-error "uncaught exception of type 'std::meta::exception'; 'what\\\(\\\)': 'value cannot be extracted'" }
+using B = int [];
+extern B &d;
+constexpr auto e = ^^d;
+constexpr auto f = std::meta::extract <B &> (e);       // { dg-error "uncaught exception of type 'std::meta::exception'; 'what\\\(\\\)': 'value cannot be extracted'" }