https://gcc.gnu.org/g:127bd0f40827d7472cebacd2093d3379ec25dbd7

commit r17-4197-g127bd0f40827d7472cebacd2093d3379ec25dbd7
Author: Marek Polacek <[email protected]>
Date:   Tue Aug 4 16:10:55 2026 -0400

    c++/reflection: P4101, Consteval-only values [PR125820]
    
    <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4101r1.html>
    changes the consteval-only type model to a consteval-only values model.
    A null reflection is no longer consteval-only.
    
    So, for instance, this is now OK:
    
      std::meta::info i;
      auto foo (std::meta::info i) { return i; } // not consteval
    
    but
    
      std::meta::info type = ^^int;
    
    is still ill-formed, provided it's not in an immediate function context
    
    I suppose for users the change is not that dramatic, but our
    implementation had to change quite a bit.
    
    For one thing, we now need to be able to handle null reflections in the
    ME.  This is done by removing META_TYPE and using LANG_TYPE instead.
    In dwarf2out, LANG_TYPE already maps to DW_TAG_unspecified_type
    so we should get "decltype(^^int)" in debug info.
    
    To be able to detect invalid code like the bare:
    
      ^^int;
    
    and to allow code like:
    
      int i = (^^int, 42); // namespace scope
    
    convert_to_void no longer throws away discarded-value expressions.  But
    the modules and analyzer code sort of depended on these being
    discarded.  Obviously, first we have to check for consteval-only values
    and only then can we discard them.  But we need to do the discarding
    before maybe_save_constexpr_fundef; otherwise we'd have to add a separate
    walk for the copy.  I moved the discarding into cp_fold_r.  Consteval-only
    values are now checked right before the discarding and in cp_genericize_r.
    
    As mentioned above, a null reflection can get into the ME, but REFLECT_EXPR
    still can't.  rewrite_null_reflection rewrites REFLECT_EXPRs representing
    a null reflection to zero.
    
    The gcov-24.C change is arguably a fix, caused by adding a location to
    the CONVERT_EXPR in convert_to_void.  genericize_c_loop has
    
      location_t incr_locus = expr_loc_or_loc (incr, start_locus);
      protected_set_expr_location_if_unset (incr, start_locus);
    
    where incr is the CONVERT_EXPR.  Previously its location was 
UNKNOWN_LOCATION
    so _if_unset set start_locus, but now the increment stays on line 41.
    
    Taking the address of a consteval function is no longer prohibited outside
    an immediate function context, provided the result initializes a constexpr
    variable.  I didn't want to inflate the patch with testsuite changes for all
    the consteval tests that will need to be updated once this is resolved.
    
            PR c++/125820
            PR c++/124249
            PR c++/124414
    
    gcc/cp/ChangeLog:
    
            * constexpr.cc (cxx_eval_binary_expression): Check
            REFLECTION_TYPE_P instead of REFLECT_EXPR_P.
            (check_bit_cast_type): Also detect REFLECTION_TYPE_P.
            (cxx_eval_outermost_constant_expr): Delete consteval-only
            smuggling detection code.
            (potential_constant_expression_1) <case CONVERT_EXPR>: Recurse
            with want_rval=false for discarded-value expressions.
            * constraint.cc (satisfy_atom): Check require_constant_expression
            before calling cxx_constant_value.  Set result to error_mark_node
            otherwise.
            * cp-gimplify.cc (cp_gimplify_expr) <case CALL_EXPR>: Don't call
            consteval_only_p and check_out_of_consteval_use.
            (wipe_consteval_only_r): Remove.
            (cp_fold_immediate_r): Don't detect invalid uses of consteval-only
            types here.  Set *stmt_p to error_mark_node if the consteval call
            was invalid.
            <case IF_STMT>: Don't call wipe_consteval_only_r.
            (cp_fold_r) <case CONVERT_EXPR>: New, remove discarded-value
            expressions.
            (cp_genericize_r) <case ADDR_EXPR>: Call check_out_of_consteval_use.
            <case BIND_EXPR>: Call rewrite_null_reflection before pruning.
            <case REFLECT_EXPR>: Detect invalid uses of consteval-only
            expressions.
            * cp-objcp-common.cc (cp_common_init_ts): Remove the META_TYPE
            marking.
            * cp-tree.def (META_TYPE): Remove.
            * cp-tree.h (REFLECTION_TYPE_P): Adjust to check if TYPE is
            meta_info_type_node.
            (rewrite_null_reflection): Declare.
            (consteval_only_p): No longer pure.
            (check_consteval_only_fn): Remove.
            * cvt.cc (convert_to_void): Don't call check_out_of_consteval_use
            here.  Don't remove discarded-value expressions here.  Use a
            location when building the CONVERT_EXPR.
            * cxx-pretty-print.cc (cxx_pretty_printer::simple_type_specifier)
            <case META_TYPE>: Remove.
            <case LANG_TYPE>: New.
            (cxx_pretty_printer::type_id) <case META_TYPE>: Remove.
            <case LANG_TYPE>: New.
            * decl.cc (wrapup_namespace_globals): Call
            rewrite_null_reflection on each element of statics.
            (cp_finish_decl): Don't call check_out_of_consteval_use.  Assert
            !consteval_only_p.
            (grokfndecl): Don't call check_consteval_only_fn.
            * decl2.cc (maybe_make_one_only): Don't return early for
            consteval_only_p.
            (mark_needed): Likewise.
            (prune_vars_needing_no_initialization): Don't prune
            consteval_only_p variables.
            (c_parse_final_cleanups): Call rewrite_null_reflection.
            * error.cc (dump_type) <case LANG_TYPE>: Handle
            REFLECTION_TYPE_P.
            <case META_TYPE>: Remove.
            (dump_type_prefix) <case META_TYPE>: Remove.
            (dump_type_suffix) <case META_TYPE>: Remove.
            (dump_expr): Use REFLECTION_TYPE_P.
            * init.cc (perform_member_init): Don't call
            check_out_of_consteval_use.
            * mangle.cc (write_type) <case META_TYPE>: Remove.
            <case LANG_TYPE>: Handle REFLECTION_TYPE_P.
            * module.cc (trees_out::type_node) <case META_TYPE>: Remove.
            <case LANG_TYPE>: New.
            (trees_in::tree_node) <case META_TYPE>: Remove.
            <case LANG_TYPE>: New.
            * name-lookup.cc (name_lookup::adl_type): Move the
            REFLECTION_TYPE_P handling to case LANG_TYPE.
            * pt.cc (tsubst) <case META_TYPE>: Remove.
            (unify) <case META_TYPE>: Remove.
            <case LANG_TYPE>: New.
            (instantiate_body): Don't call check_consteval_only_fn.
            * reflect.cc (init_reflection): Use LANG_TYPE instead of
            META_TYPE for meta_info_type_node.
            (null_reflection_p): Also accept the rewritten form.
            (rewrite_null_reflection): New.
            (consteval_only_p): Rewrite for P4101.
            (struct consteval_only_p_walker): Remove.
            (consteval_only_value_p): New.
            (consteval_only_p_walker::walk): Remove.
            (check_out_of_consteval_use_r): Walk INIT_EXPR.  Handle EXPR_STMT
            specially.
            (check_out_of_consteval_use): Remove the special VAR_P handling.
            (compare_reflections): Deal with null reflections first.
            (check_consteval_only_fn): Remove.
            * search.cc (check_final_overrider): Don't check
            consteval_only_p.
            * semantics.cc (cp_build_bit_cast): Likewise.
            * tree.cc (type_has_unique_obj_representations) <case LANG_TYPE>:
            New, handle REFLECTION_TYPE_P.
            * typeck.cc (cp_build_binary_op): Use REFLECTION_TYPE_P.
            (check_return_expr): Don't call check_out_of_consteval_use.
            * typeck2.cc (store_init_value): Check that an immediate object
            is associated with a constexpr variable.
    
    gcc/ChangeLog:
    
            * expr.cc (count_type_elements) <case LANG_TYPE>: Return 1.
            * tree.cc (wide_int_to_tree_1) <case LANG_TYPE>: New.
            (cache_integer_cst) <case LANG_TYPE>: New.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/meta (std::meta::exception::what): Change it to
            constexpr.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp2a/concepts-uneval3.C: Add a dg-error.
            * g++.dg/gcov/gcov-24.C: Adjust expected output.
            * g++.dg/reflect/bit_cast.C: Remove dg-error.  Extend.
            * g++.dg/reflect/crash12.C: Remove dg-error.
            * g++.dg/reflect/crash18.C: Likewise.
            * g++.dg/reflect/diag3.C: Adjust expected output.
            * g++.dg/reflect/expr11.C: Likewise.
            * g++.dg/reflect/expr12.C: Likewise.
            * g++.dg/reflect/init10.C: Likewise.
            * g++.dg/reflect/init11.C: Likewise.
            * g++.dg/reflect/init12.C: Remove dg-error.
            * g++.dg/reflect/init16.C: Adjust expected output.
            * g++.dg/reflect/init19.C: Remove dg-error.
            * g++.dg/reflect/init4.C: Add an XFAIL.
            * g++.dg/reflect/init5.C: Remove dg-error.
            * g++.dg/reflect/init6.C: Adjust expected output.
            * g++.dg/reflect/init7.C: Likewise.
            * g++.dg/reflect/init9.C: Likewise.
            * g++.dg/reflect/override1.C: Likewise.
            * g++.dg/reflect/p2996-15.C: Remove dg-error.
            * g++.dg/reflect/parm3.C: Adjust expected output.
            * g++.dg/reflect/parm4.C: Likewise.
            * g++.dg/reflect/pr124012.C: Remove dg-error.
            * g++.dg/reflect/type12.C: Likewise.
            * g++.dg/reflect/type2.C: Adjust expected output.
            * g++.dg/reflect/bit_cast2.C: New test.
            * g++.dg/reflect/expr19.C: New test.
            * g++.dg/reflect/null7.C: New test.
            * g++.dg/reflect/type_trait19.C: New test.
            * g++.dg/reflect/typeinfo1.C: New test.
            * g++.dg/reflect/value1.C: New test.
            * g++.dg/reflect/value2.C: New test.
            * g++.dg/reflect/value3.C: New test.
            * g++.dg/reflect/value4.C: New test.
            * g++.dg/reflect/value5.C: New test.
            * g++.dg/reflect/value6.C: New test.
            * g++.dg/reflect/value7.C: New test.
            * g++.dg/reflect/value8.C: New test.
            * g++.dg/reflect/vector2.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/constexpr.cc                           |  56 ++-
 gcc/cp/constraint.cc                          |   5 +-
 gcc/cp/cp-gimplify.cc                         | 111 +++---
 gcc/cp/cp-objcp-common.cc                     |   1 -
 gcc/cp/cp-tree.def                            |   3 -
 gcc/cp/cp-tree.h                              |   7 +-
 gcc/cp/cvt.cc                                 |  12 +-
 gcc/cp/cxx-pretty-print.cc                    |  19 +-
 gcc/cp/decl.cc                                |  22 +-
 gcc/cp/decl2.cc                               |  20 +-
 gcc/cp/error.cc                               |  14 +-
 gcc/cp/init.cc                                |   3 -
 gcc/cp/mangle.cc                              |  11 +-
 gcc/cp/module.cc                              |   8 +-
 gcc/cp/name-lookup.cc                         |  14 +-
 gcc/cp/pt.cc                                  |   5 +-
 gcc/cp/reflect.cc                             | 286 +++++++-------
 gcc/cp/search.cc                              |  10 +-
 gcc/cp/semantics.cc                           |   6 -
 gcc/cp/tree.cc                                |  10 +
 gcc/cp/typeck.cc                              |   8 +-
 gcc/cp/typeck2.cc                             |  36 ++
 gcc/expr.cc                                   |   3 +-
 gcc/testsuite/g++.dg/cpp2a/concepts-uneval3.C |   2 +-
 gcc/testsuite/g++.dg/gcov/gcov-24.C           |   6 +-
 gcc/testsuite/g++.dg/reflect/bit_cast.C       |  20 +-
 gcc/testsuite/g++.dg/reflect/bit_cast2.C      |  16 +
 gcc/testsuite/g++.dg/reflect/crash12.C        |   2 +-
 gcc/testsuite/g++.dg/reflect/crash18.C        |   2 +-
 gcc/testsuite/g++.dg/reflect/diag3.C          |  18 +-
 gcc/testsuite/g++.dg/reflect/expr11.C         |  20 +-
 gcc/testsuite/g++.dg/reflect/expr12.C         |  14 +-
 gcc/testsuite/g++.dg/reflect/expr19.C         |   8 +
 gcc/testsuite/g++.dg/reflect/init10.C         |   8 +-
 gcc/testsuite/g++.dg/reflect/init11.C         |   5 +-
 gcc/testsuite/g++.dg/reflect/init12.C         |   2 +-
 gcc/testsuite/g++.dg/reflect/init16.C         |   4 +-
 gcc/testsuite/g++.dg/reflect/init19.C         |   2 +-
 gcc/testsuite/g++.dg/reflect/init4.C          |   2 +-
 gcc/testsuite/g++.dg/reflect/init5.C          |   4 +-
 gcc/testsuite/g++.dg/reflect/init6.C          |  12 +-
 gcc/testsuite/g++.dg/reflect/init7.C          |  22 +-
 gcc/testsuite/g++.dg/reflect/init9.C          |  22 +-
 gcc/testsuite/g++.dg/reflect/null7.C          |  32 ++
 gcc/testsuite/g++.dg/reflect/override1.C      |   8 +-
 gcc/testsuite/g++.dg/reflect/p2996-15.C       |   4 +-
 gcc/testsuite/g++.dg/reflect/parm3.C          |  12 +-
 gcc/testsuite/g++.dg/reflect/parm4.C          |  22 +-
 gcc/testsuite/g++.dg/reflect/pr124012.C       |   8 +-
 gcc/testsuite/g++.dg/reflect/type12.C         |   2 +-
 gcc/testsuite/g++.dg/reflect/type2.C          |  14 +-
 gcc/testsuite/g++.dg/reflect/type_trait19.C   |  15 +
 gcc/testsuite/g++.dg/reflect/typeinfo1.C      |   7 +
 gcc/testsuite/g++.dg/reflect/value1.C         | 543 ++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/reflect/value2.C         |  32 ++
 gcc/testsuite/g++.dg/reflect/value3.C         |  63 +++
 gcc/testsuite/g++.dg/reflect/value4.C         |  24 ++
 gcc/testsuite/g++.dg/reflect/value5.C         |  40 ++
 gcc/testsuite/g++.dg/reflect/value6.C         |  41 ++
 gcc/testsuite/g++.dg/reflect/value7.C         |  52 +++
 gcc/testsuite/g++.dg/reflect/value8.C         |  64 +++
 gcc/testsuite/g++.dg/reflect/vector2.C        |  26 ++
 gcc/tree.cc                                   |   4 +
 libstdc++-v3/include/std/meta                 |   2 +-
 64 files changed, 1410 insertions(+), 466 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index b934df86a8a0..7219c55c9ceb 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -5755,7 +5755,8 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, 
tree t,
        lhs = cplus_expand_constant (lhs);
       else if (TREE_CODE (rhs) == PTRMEM_CST)
        rhs = cplus_expand_constant (rhs);
-      else if (REFLECT_EXPR_P (lhs) && REFLECT_EXPR_P (rhs))
+      else if (REFLECTION_TYPE_P (TREE_TYPE (lhs))
+              && REFLECTION_TYPE_P (TREE_TYPE (rhs)))
        {
          const bool eq = compare_reflections (lhs, rhs);
          r = constant_boolean_node (eq == is_code_eq, type);
@@ -6834,7 +6835,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t,
    Check [bit.cast]/3 rules, bit_cast is constexpr only if the To and From
    types and types of all subobjects have is_union_v<T>, is_pointer_v<T>,
    is_member_pointer_v<T>, is_volatile_v<T> false and has no non-static
-   data members of reference type.  */
+   data members of reference or std::meta::info type.  */
 
 static bool
 check_bit_cast_type (const constexpr_ctx *ctx, location_t loc, tree type,
@@ -6911,6 +6912,20 @@ check_bit_cast_type (const constexpr_ctx *ctx, 
location_t loc, tree type,
        }
       return true;
     }
+  if (REFLECTION_TYPE_P (type))
+    {
+      if (!ctx->quiet)
+       {
+         if (type == orig_type)
+           error_at (loc, "%qs is not a constant expression because its "
+                          "type is %qs", "__builtin_bit_cast", 
"std::meta::info");
+         else
+           error_at (loc, "%qs is not a constant expression because %qT "
+                          "contains %qs type",
+                     "__builtin_bit_cast", orig_type, "std::meta::info");
+       }
+      return true;
+    }
   if (TREE_CODE (type) == RECORD_TYPE)
     for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
       if (TREE_CODE (field) == FIELD_DECL
@@ -11762,37 +11777,6 @@ cxx_eval_outermost_constant_expr (tree t, bool 
allow_non_constant,
       non_constant_p = true;
     }
 
-  /* Detect consteval-only smuggling: turning a consteval-only object
-     into one that is not.  For instance, in
-       struct B { };
-       struct D : B { info r; };
-       constexpr D d{^^::};
-       constexpr const B &b = d; // #1
-     #1 is wrong because D is a consteval-only type but B is not.  */
-  if (flag_reflection
-      && !non_constant_p
-      && object
-      && POINTER_TYPE_P (TREE_TYPE (object))
-      && !consteval_only_p (object)
-      && check_out_of_consteval_use (r, /*complain=*/false))
-    {
-      if (!allow_non_constant)
-       {
-         if (TYPE_REF_P (TREE_TYPE (object)))
-           error_at (cp_expr_loc_or_input_loc (t),
-                     "reference into an object of consteval-only type is "
-                     "not a constant expression unless it also has "
-                     "consteval-only type");
-         else
-           error_at (cp_expr_loc_or_input_loc (t),
-                     "pointer into an object of consteval-only type is "
-                     "not a constant expression unless it also has "
-                     "consteval-only type");
-       }
-      r = t;
-      non_constant_p = true;
-    }
-
   if (!non_constant_p && !constexpr_dtor)
     verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
 
@@ -12882,7 +12866,11 @@ potential_constant_expression_1 (tree t, bool 
want_rval, bool strict, bool now,
                return false;
              }
          }
-        return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
+       /* convert_to_void used to fold these away to void_node, because they
+          are a discarded-value expression.  */
+       if (TREE_CODE (t) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (t)))
+         return RECUR (from, /*want_rval=*/false);
+       return RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR);
       }
 
     case ADDRESSOF_EXPR:
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index d0d39da79799..a5ac77dad63d 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2553,7 +2553,10 @@ satisfy_atom (tree t, tree args, sat_info info)
   if (info.noisy ())
     {
       iloc_sentinel ils (EXPR_LOCATION (result));
-      result = cxx_constant_value (result);
+      if (require_constant_expression (result))
+       result = cxx_constant_value (result);
+      else
+       result = error_mark_node;
     }
   else
     {
diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index e79499f51b9c..c8f40413891b 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -860,13 +860,6 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, 
gimple_seq *post_p)
 
     case CALL_EXPR:
       ret = GS_OK;
-      /* At this point any function that takes/returns a consteval-only
-        expression is a problem.  */
-      for (int i = 0; i < call_expr_nargs (*expr_p); ++i)
-       if (check_out_of_consteval_use (CALL_EXPR_ARG (*expr_p, i)))
-         ret = GS_ERROR;
-      if (consteval_only_p (TREE_TYPE (*expr_p)))
-       ret = GS_ERROR;
       if (flag_strong_eval_order == 2
          && CALL_EXPR_FN (*expr_p)
          && !CALL_EXPR_OPERATOR_SYNTAX (*expr_p)
@@ -1374,23 +1367,6 @@ cp_build_init_expr_for_ctor (tree call, tree init)
   return init;
 }
 
-/* For every DECL_EXPR check if it declares a consteval-only variable and
-   if so, overwrite it with a no-op.  The point here is not to leak
-   consteval-only variables into the middle end.  */
-
-static tree
-wipe_consteval_only_r (tree *stmt_p, int *, void *)
-{
-  if (TREE_CODE (*stmt_p) == DECL_EXPR)
-    {
-      tree d = DECL_EXPR_DECL (*stmt_p);
-      if (VAR_P (d) && consteval_only_p (d))
-       /* Wipe the DECL_EXPR so that it doesn't get into gimple.  */
-       *stmt_p = void_node;
-    }
-  return NULL_TREE;
-}
-
 /* A walk_tree callback for cp_fold_function and cp_fully_fold_init to handle
    immediate functions.  */
 
@@ -1418,17 +1394,6 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, 
void *data_)
       return NULL_TREE;
     }
 
-  /* Most invalid uses of consteval-only types should have been already
-     detected at this point.  And the valid ones won't be needed
-     anymore.  */
-  if (flag_reflection
-      && complain
-      && (data->flags & ff_genericize)
-      && TREE_CODE (stmt) == STATEMENT_LIST)
-    for (tree s : tsi_range (stmt))
-      if (check_out_of_consteval_use (s))
-       *stmt_p = void_node;
-
   tree decl = NULL_TREE;
   bool call_p = false;
 
@@ -1462,15 +1427,8 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, 
void *data_)
       if (IF_STMT_CONSTEVAL_P (stmt))
        {
          if (!data->pset.add (stmt))
-           {
-             cp_walk_tree (&ELSE_CLAUSE (stmt), cp_fold_immediate_r, data_,
-                           nullptr);
-             if (flag_reflection)
-               /* Check & clear consteval-only DECL_EXPRs even here,
-                  because we wouldn't be walking this subtree otherwise.  */
-               cp_walk_tree (&THEN_CLAUSE (stmt), wipe_consteval_only_r,
-                             data_, nullptr);
-           }
+           cp_walk_tree (&ELSE_CLAUSE (stmt), cp_fold_immediate_r, data_,
+                         nullptr);
          *walk_subtrees = 0;
          return NULL_TREE;
        }
@@ -1529,7 +1487,8 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, 
void *data_)
                  error_at (loc, "call to consteval function %qE is "
                            "not a constant expression", stmt);
                  /* Explain why it's not a constant expression.  */
-                 *stmt_p = cxx_constant_value (stmt, complain);
+                 cxx_constant_value (stmt, complain);
+                 *stmt_p = error_mark_node;
                  maybe_explain_promoted_consteval (loc, decl);
                }
              else if (!data->pset.add (stmt))
@@ -1544,21 +1503,6 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, 
void *data_)
          *walk_subtrees = 0;
          return stmt;
        }
-      /* If we called a consteval function and it evaluated to a consteval-only
-        expression, it could be a problem if we are outside a manifestly
-        constant-evaluated context.  */
-      else if ((data->flags & ff_genericize)
-              && check_out_of_consteval_use (e, complain))
-       {
-         *stmt_p = void_node;
-         if (complain & tf_error)
-           return NULL_TREE;
-         else
-           {
-             *walk_subtrees = 0;
-             return stmt;
-           }
-       }
 
       /* We've evaluated the consteval function call.  */
       if (call_p)
@@ -1791,6 +1735,24 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
        }
       break;
 
+    case CONVERT_EXPR:
+      /* convert_to_void used to fold these away to void_node.  Do it now;
+        other code (e.g., trees_out) depends on these being expunged.  We
+        do it here before maybe_save_constexpr_fundef copies function
+        bodies.  */
+      if ((data->flags & (ff_only_non_odr | ff_genericize))
+         && VOID_TYPE_P (TREE_TYPE (stmt))
+         && !TREE_SIDE_EFFECTS (stmt))
+       {
+        /* Since we're discarding it, it's our last chance to check for
+           out-of-consteval expressions.  */
+        check_out_of_consteval_use (stmt);
+        *stmt_p = void_node;
+        *walk_subtrees = 0;
+        return NULL_TREE;
+       }
+      break;
+
     default:
       break;
     }
@@ -2014,6 +1976,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void 
*data)
          *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
          *walk_subtrees = 0;
        }
+      check_out_of_consteval_use (stmt);
       break;
 
     case RETURN_EXPR:
@@ -2192,16 +2155,24 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void 
*data)
          wtd->no_sanitize_p = no_sanitize_p;
        }
       if (flag_reflection)
-       /* Wipe consteval-only vars from BIND_EXPR_VARS and BLOCK_VARS.  */
+       /* Adjust consteval-only vars in BIND_EXPR_VARS so that REFLECT_EXPR
+          doesn't leak into the ME.  */
        for (tree *p = &BIND_EXPR_VARS (stmt); *p; )
          {
-           if (VAR_P (*p) && consteval_only_p (*p))
+           if (VAR_P (*p))
              {
-               if (BIND_EXPR_BLOCK (stmt)
-                   && *p == BLOCK_VARS (BIND_EXPR_BLOCK (stmt)))
-                 BLOCK_VARS (BIND_EXPR_BLOCK (stmt)) = DECL_CHAIN (*p);
-               *p = DECL_CHAIN (*p);
-               continue;
+               /* First, adjust null reflections.  */
+               if (DECL_INITIAL (*p))
+                 rewrite_null_reflection (DECL_INITIAL (*p));
+               /* If the variable is still consteval-only, remove it.  */
+               if (consteval_only_p (*p))
+                 {
+                   if (BIND_EXPR_BLOCK (stmt)
+                       && *p == BLOCK_VARS (BIND_EXPR_BLOCK (stmt)))
+                     BLOCK_VARS (BIND_EXPR_BLOCK (stmt)) = DECL_CHAIN (*p);
+                   *p = DECL_CHAIN (*p);
+                   continue;
+                 }
              }
            p = &DECL_CHAIN (*p);
          }
@@ -2622,6 +2593,12 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void 
*data)
        DECL_NOT_GIMPLE_REG_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)) = 1;
       break;
 
+    case REFLECT_EXPR:
+      /* Only the null reflection may reach the ME.  */
+      check_out_of_consteval_use (stmt);
+      *stmt_p = build_int_cst (meta_info_type_node, 0);
+      break;
+
     default:
       if (IS_TYPE_OR_DECL_P (stmt))
        *walk_subtrees = 0;
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index 8c9930bb2f37..36b9d743afdd 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -646,7 +646,6 @@ cp_common_init_ts (void)
   MARK_TS_TYPE_NON_COMMON (TEMPLATE_TYPE_PARM);
   MARK_TS_TYPE_NON_COMMON (TYPE_PACK_EXPANSION);
   MARK_TS_TYPE_NON_COMMON (PACK_INDEX_TYPE);
-  MARK_TS_TYPE_NON_COMMON (META_TYPE);
   MARK_TS_TYPE_NON_COMMON (SPLICE_SCOPE);
 
   /* Statements.  */
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 894ba61b6dcc..ea1e82419754 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -588,9 +588,6 @@ DEFTREECODE (TU_LOCAL_ENTITY, "tu_local_entity", 
tcc_exceptional, 0)
 /* C++26 reflection expression.  */
 DEFTREECODE (REFLECT_EXPR, "reflect_expr", tcc_expression, 1)
 
-/* Represents the std::meta::info type.  */
-DEFTREECODE (META_TYPE, "meta_type", tcc_type, 0)
-
 /* Represents a dependent splice expression.  If SPLICE_EXPR_EXPRESSION_P
    is set, this tree represents a splice-expression (as opposed to
    a splice-specifier).  */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6a3c41639844..154755fce821 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1924,7 +1924,8 @@ struct GTY(()) tree_requires_expr {
   (((struct tree_requires_expr *) REQUIRES_EXPR_CHECK (NODE))->loc)
 
 /* True iff TYPE is cv decltype(^^int).  */
-#define REFLECTION_TYPE_P(TYPE) (TREE_CODE (TYPE) == META_TYPE)
+#define REFLECTION_TYPE_P(TYPE) \
+  (TYPE_P (TYPE) && TYPE_MAIN_VARIANT (TYPE) == meta_info_type_node)
 
 /* True if NODE is a REFLECT_EXPR.  */
 #define REFLECT_EXPR_P(NODE) (TREE_CODE (NODE) == REFLECT_EXPR)
@@ -9544,9 +9545,10 @@ extern tree process_metafunction (const constexpr_ctx *, 
tree, tree,
 extern tree get_reflection (location_t, tree, reflect_kind = REFLECT_UNDEF);
 extern tree get_null_reflection () ATTRIBUTE_PURE;
 extern bool null_reflection_p (const_tree) ATTRIBUTE_PURE;
+extern void rewrite_null_reflection (tree &);
 extern tree splice (tree);
 extern bool check_out_of_consteval_use (tree, bool = true);
-extern bool consteval_only_p (tree) ATTRIBUTE_PURE;
+extern bool consteval_only_p (tree);
 extern bool compare_reflections (tree, tree) ATTRIBUTE_PURE;
 extern bool valid_splice_type_p (const_tree) ATTRIBUTE_PURE;
 extern bool valid_splice_scope_p (const_tree) ATTRIBUTE_PURE;
@@ -9557,7 +9559,6 @@ extern bool check_splice_expr (location_t, location_t, 
tree, bool, bool, bool,
 extern tree make_splice_scope (tree, bool);
 extern bool dependent_splice_p (const_tree) ATTRIBUTE_PURE;
 extern tree reflection_mangle_prefix (tree, char [3]);
-extern void check_consteval_only_fn (tree);
 extern bool reflection_function_template_p (const_tree) ATTRIBUTE_PURE;
 extern void dump_data_member_spec (pretty_printer *, tree);
 
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index 33d528b3c324..ff54647c5b10 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1234,14 +1234,6 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t complain)
    if (concept_check_p (expr) && !cp_unevaluated_operand)
      expr = evaluate_concept_check (expr);
 
-  /* Detect using expressions of consteval-only types outside manifestly
-     constant-evaluated contexts.  We are going to discard this expression,
-     so we can't wait till cp_fold_immediate_r.  FIXME This is too early;
-     code like "int i = (^^i, 42);" is OK.  We should stop discarding
-     expressions here (PR124249).  */
-  if (stmts_are_full_exprs_p () && check_out_of_consteval_use (expr))
-    return error_mark_node;
-
   if (VOID_TYPE_P (TREE_TYPE (expr)))
     return expr;
 
@@ -1739,10 +1731,8 @@ convert_to_void (tree expr, impl_conv_void implicit, 
tsubst_flags_t complain)
                warn_if_unused_value (e, loc);
            }
        }
-      expr = build1 (CONVERT_EXPR, void_type_node, expr);
+      expr = build1_loc (loc, CONVERT_EXPR, void_type_node, expr);
     }
-  if (! TREE_SIDE_EFFECTS (expr))
-    expr = void_node;
   return expr;
 }
 
diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc
index f5d476a4a991..f844039eb994 100644
--- a/gcc/cp/cxx-pretty-print.cc
+++ b/gcc/cp/cxx-pretty-print.cc
@@ -1442,9 +1442,13 @@ cxx_pretty_printer::simple_type_specifier (tree t)
       pp_cxx_trait (this, t);
       break;
 
-    case META_TYPE:
-      pp_cxx_ws_string (this, "std::meta::info");
-      break;
+    case LANG_TYPE:
+      if (REFLECTION_TYPE_P (t))
+       {
+         pp_cxx_ws_string (this, "std::meta::info");
+         break;
+       }
+      gcc_fallthrough ();
 
     default:
       c_pretty_printer::simple_type_specifier (t);
@@ -1942,7 +1946,6 @@ cxx_pretty_printer::type_id (tree t)
     case NULLPTR_TYPE:
     case TEMPLATE_ID_EXPR:
     case OFFSET_TYPE:
-    case META_TYPE:
       pp_cxx_type_specifier_seq (this, t);
       if (TYPE_PTRMEM_P (t))
        abstract_declarator (t);
@@ -1975,6 +1978,14 @@ cxx_pretty_printer::type_id (tree t)
       }
       break;
 
+    case LANG_TYPE:
+      if (REFLECTION_TYPE_P (t))
+       {
+         pp_cxx_type_specifier_seq (this, t);
+         break;
+       }
+      gcc_fallthrough ();
+
     default:
       c_pretty_printer::type_id (t);
       break;
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index e973b0744a52..067ae20c828e 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1008,6 +1008,10 @@ wrapup_namespace_globals ()
     {
       for (tree decl : *statics)
        {
+         /* Rewrite the REFLECT_EXPR with 0 so that the ME can process it.  */
+         if (flag_reflection && DECL_INITIAL (decl))
+           rewrite_null_reflection (DECL_INITIAL (decl));
+
          if (warn_unused_function
              && TREE_CODE (decl) == FUNCTION_DECL
              && DECL_INITIAL (decl) == 0
@@ -10007,10 +10011,6 @@ cp_finish_decl (tree decl, tree init, bool 
init_const_expr_p,
            }
        }
 
-      /* Detect stuff like 'info r = ^^int;' outside a manifestly
-        constant-evaluated context.  */
-      check_out_of_consteval_use (decl);
-
       /* If this is a local variable that will need a mangled name,
         register it now.  We must do this before processing the
         initializer for the variable, since the initialization might
@@ -10035,10 +10035,10 @@ cp_finish_decl (tree decl, tree init, bool 
init_const_expr_p,
              walk_tree (&init, notice_forced_label_r, NULL, NULL);
              add_local_decl (cfun, decl);
            }
-         if (!consteval_only_p (decl))
-           /* And make sure it's in the symbol table for
-              c_parse_final_cleanups to find.  */
-           varpool_node::get_create (decl);
+         /* And make sure it's in the symbol table for
+            c_parse_final_cleanups to find.  */
+         gcc_checking_assert (!consteval_only_p (decl));
+         varpool_node::get_create (decl);
        }
 
       if (flag_openmp
@@ -12905,12 +12905,6 @@ grokfndecl (tree ctype,
   if (DECL_CONSTRUCTOR_P (decl) && !grok_ctor_properties (ctype, decl))
     return NULL_TREE;
 
-  /* Don't call check_consteval_only_fn for defaulted functions.  Those are
-     immediate-escalating functions but at this point DECL_DEFAULTED_P has
-     not been set.  */
-  if (initialized != SD_DEFAULTED)
-    check_consteval_only_fn (decl);
-
   if (ctype == NULL_TREE || check)
     return decl;
 
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index f3ca6cb7bdba..7fe567f98db1 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2662,9 +2662,7 @@ maybe_make_one_only (tree decl)
   if (! flag_weak)
     return;
 
-  /* These are not to be output.  */
-  if (consteval_only_p (decl))
-    return;
+  gcc_checking_assert (!consteval_only_p (decl));
 
   /* We can't set DECL_COMDAT on functions, or cp_finish_file will think
      we can get away with not emitting them if they aren't used.  We need
@@ -2822,9 +2820,7 @@ var_finalized_p (tree var)
 void
 mark_needed (tree decl)
 {
-  /* These are not to be output.  */
-  if (consteval_only_p (decl))
-    return;
+  gcc_checking_assert (!consteval_only_p (decl));
 
   TREE_USED (decl) = 1;
   if (TREE_CODE (decl) == FUNCTION_DECL)
@@ -5050,14 +5046,6 @@ prune_vars_needing_no_initialization (tree *vars)
          continue;
        }
 
-      /* Reflections are consteval-only types and we don't want them
-        to survive until gimplification.  */
-      if (consteval_only_p (decl))
-       {
-         var = &TREE_CHAIN (t);
-         continue;
-       }
-
       /* This variable is going to need initialization and/or
         finalization, so we add it to the list.  */
       *var = TREE_CHAIN (t);
@@ -6098,6 +6086,10 @@ c_parse_final_cleanups (void)
       /* Static data members are just like namespace-scope globals.  */
       FOR_EACH_VEC_SAFE_ELT (pending_statics, i, decl)
        {
+         /* Rewrite the REFLECT_EXPR with 0 so that the ME can process it.  */
+         if (flag_reflection && DECL_INITIAL (decl))
+           rewrite_null_reflection (DECL_INITIAL (decl));
+
          if (consteval_only_p (decl)
              || var_finalized_p (decl)
              || DECL_REALLY_EXTERN (decl)
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index a5332864bc89..3d5a194b9bc4 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -697,6 +697,11 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
        pp_string (pp, M_("<brace-enclosed initializer list>"));
       else if (t == unknown_type_node)
        pp_string (pp, M_("<unresolved overloaded function type>"));
+      else if (REFLECTION_TYPE_P (t))
+       {
+         pp_cxx_ws_string (pp, "std::meta::info");
+         pp_c_type_qualifier_list (pp, t);
+       }
       else
        {
          pp_cxx_cv_qualifier_seq (pp, t);
@@ -879,11 +884,6 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
       pp_c_type_qualifier_list (pp, t);
       break;
 
-    case META_TYPE:
-      pp_cxx_ws_string (pp, "std::meta::info");
-      pp_c_type_qualifier_list (pp, t);
-      break;
-
     case SPLICE_SCOPE:
       dump_expr (pp, SPLICE_SCOPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);
       break;
@@ -1147,7 +1147,6 @@ dump_type_prefix (cxx_pretty_printer *pp, tree t, int 
flags)
     case FIXED_POINT_TYPE:
     case NULLPTR_TYPE:
     case PACK_INDEX_TYPE:
-    case META_TYPE:
     case SPLICE_SCOPE:
       dump_type (pp, t, flags);
       pp->set_padding (pp_before);
@@ -1282,7 +1281,6 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int 
flags)
     case FIXED_POINT_TYPE:
     case NULLPTR_TYPE:
     case PACK_INDEX_TYPE:
-    case META_TYPE:
     case SPLICE_SCOPE:
       break;
 
@@ -3487,7 +3485,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
                /* For reflection we care about the difference
                   between std::meta::info/std::nullptr_t and
                   decltype(^^int)/decltype(nullptr).  */
-               if (TREE_CODE (h) == META_TYPE && !typedef_variant_p (h))
+               if (REFLECTION_TYPE_P (h) && !typedef_variant_p (h))
                  {
                    pp_cxx_ws_string (pp, "decltype(^^int)");
                    pp_c_type_qualifier_list (pp, h);
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 7c0c0fef55f0..6bdc5fbbeb0b 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -1008,9 +1008,6 @@ perform_member_init (tree member, tree init, 
hash_set<tree> &uninitialized)
   if (init == error_mark_node)
     return;
 
-  if (check_out_of_consteval_use (init))
-    return;
-
   /* Effective C++ rule 12 requires that all data members be
      initialized.  */
   if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE)
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index e90ea00c83f6..739ab2afd60e 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -2739,11 +2739,6 @@ write_type (tree type)
                ++is_builtin_type;
              break;
 
-           case META_TYPE:
-             write_string ("Dm");
-             ++is_builtin_type;
-             break;
-
            case SPLICE_SCOPE:
              write_splice (type);
              break;
@@ -2776,6 +2771,12 @@ write_type (tree type)
              break;
 
            case LANG_TYPE:
+             if (REFLECTION_TYPE_P (type))
+               {
+                 write_string ("Dm");
+                 ++is_builtin_type;
+                 break;
+               }
              /* fall through.  */
 
            default:
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 571e7875ef61..1e9e27a3ec20 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -9890,8 +9890,9 @@ trees_out::type_node (tree type)
        }
       break;
 
-    case META_TYPE:
+    case LANG_TYPE:
       /* No additional data.  */
+      gcc_checking_assert (REFLECTION_TYPE_P (type));
       break;
 
     case SPLICE_SCOPE:
@@ -10745,7 +10746,10 @@ trees_in::tree_node (bool is_use)
            }
            break;
 
-         case META_TYPE:
+         /* LANG_TYPE can be more things, but here we assume it represents
+            std::meta::info.  Unfortunately here it's not possible to check
+            REFLECTION_TYPE_P.  */
+         case LANG_TYPE:
            if (!get_overrun ())
              res = meta_info_type_node;
            break;
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 13cee628faa6..414531100470 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -1570,13 +1570,6 @@ name_lookup::adl_type (tree type)
       adl_type (TYPE_PTRMEM_POINTED_TO_TYPE (type));
       return;
     }
-  else if (REFLECTION_TYPE_P (type))
-    {
-      /* The namespace std::meta is an associated namespace of
-        std::meta::info.  */
-      adl_namespace (std_meta_node);
-      return;
-    }
 
   switch (TREE_CODE (type))
     {
@@ -1611,6 +1604,13 @@ name_lookup::adl_type (tree type)
       return;
 
     case LANG_TYPE:
+      if (REFLECTION_TYPE_P (type))
+       {
+         /* The namespace std::meta is an associated namespace of
+            std::meta::info.  */
+         adl_namespace (std_meta_node);
+         return;
+       }
       gcc_assert (type == unknown_type_node
                  || type == init_list_type_node);
       return;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6191cfbd1682..53e81d8006cd 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -17378,7 +17378,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
     case VECTOR_TYPE:
     case BOOLEAN_TYPE:
     case NULLPTR_TYPE:
-    case META_TYPE:
     case LANG_TYPE:
       return t;
 
@@ -26848,7 +26847,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, 
int strict,
     case VOID_TYPE:
     case OPAQUE_TYPE:
     case NULLPTR_TYPE:
-    case META_TYPE:
+    case LANG_TYPE:
       if (TREE_CODE (arg) != TREE_CODE (parm))
        return unify_type_mismatch (explain_p, parm, arg);
 
@@ -28994,8 +28993,6 @@ instantiate_body (tree pattern, tree args, tree d, bool 
nested_p)
       if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))
        cp_check_omp_declare_reduction (d);
 
-      check_consteval_only_fn (d);
-
       if (int errs = errorcount + sorrycount)
        if (errs > current_tinst_level->errors)
          if (function *f = DECL_STRUCT_FUNCTION (d))
diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 18261d9f10de..1278fc4c489b 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -61,7 +61,7 @@ init_reflection ()
   /* The type std::meta::info is a scalar type for which equality and
      inequality are meaningful, but for which no ordering relation is
      defined.  */
-  meta_info_type_node = make_node (META_TYPE);
+  meta_info_type_node = make_node (LANG_TYPE);
   /* Make it a complete type.  */
   TYPE_SIZE (meta_info_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
   TYPE_SIZE_UNIT (meta_info_type_node) = size_int (GET_MODE_SIZE (ptr_mode));
@@ -291,8 +291,36 @@ get_null_reflection ()
 bool
 null_reflection_p (const_tree t)
 {
-  return (t && TREE_CODE (t) == REFLECT_EXPR
-         && REFLECT_EXPR_HANDLE (t) == unknown_type_node);
+  if (!t)
+    return false;
+
+  if (REFLECT_EXPR_P (t) && REFLECT_EXPR_HANDLE (t) == unknown_type_node)
+    return true;
+
+  /* This is the rewritten form.  */
+  return integer_zerop (t) && REFLECTION_TYPE_P (TREE_TYPE (t));
+}
+
+/* If R represents a null reflection, rewrite it with something the ME
+   can process; that is, something that doesn't use REFLECT_EXPR.  */
+
+void
+rewrite_null_reflection (tree &r)
+{
+  /* A tree walk mostly only so that we recurse through CONSTRUCTORs.  */
+  auto walker = [](tree *tp, int *walk_subtrees, void *) -> tree
+    {
+      if (TYPE_P (*tp))
+       *walk_subtrees = 0;
+      else if (null_reflection_p (*tp))
+       {
+         *tp = build_int_cst (meta_info_type_node, 0);
+         *walk_subtrees = 0;
+       }
+      return NULL_TREE;
+    };
+
+  cp_walk_tree (&r, walker, nullptr, nullptr);
 }
 
 /* Do strip_typedefs on T, but only for types.  */
@@ -8809,153 +8837,116 @@ splice (tree refl)
   return refl;
 }
 
-/* A cache of the known boolean result of consteval_only_p_walker::walk
-   for class types.  */
+static bool consteval_only_p (tree, hash_set<tree> &);
+
+/* True if T is a consteval-only value as per [expr.const.const]/1:
+   A consteval-only value is either
+   -- a reflection value that is not the null reflection value or
+   -- a pointer or pointer-to-member that points to an immediate function
+      or to or past the end of an immediate object.
 
-static GTY((cache)) type_tree_cache_map *consteval_only_class_cache;
+   This function doesn't look for an immediate function; for that, see
+   find_immediate_fndecl.  */
 
-struct consteval_only_p_walker
+static bool
+consteval_only_value_p (tree t, hash_set<tree> &seen)
 {
-  /* The set of class types we've seen.  */
-  hash_set<tree> class_seen;
-  /* The number of class types we're recursively inside.  */
-  int class_depth = 0;
-  /* True if we've optimistically assumed an already-seen
-     consteval-unknown class type is not consteval.  */
-  bool optimistic_p = false;
+  STRIP_NOPS (t);
 
-  tristate walk (tree);
-};
+  if (REFLECT_EXPR_P (t) && !null_reflection_p (t))
+    return true;
+
+  switch (TREE_CODE (t))
+    {
+    case ADDR_EXPR:
+    case POINTER_PLUS_EXPR:
+    case ARRAY_REF:
+    case COMPONENT_REF:
+      return consteval_only_p (TREE_OPERAND (t, 0), seen);
+    default:
+      break;
+    }
+  return false;
+}
 
-/* True if T is a consteval-only type as per [basic.types.general]/12,
-   or is a declaration with such a type, or a TREE_VEC thereof.  */
+/* Return true if T is an immediate object as per [expr.const.const]/2:
+   An object is an immediate object if its complete object has
+   -- a constituent value that is consteval-only or
+   -- a constituent reference that refers to an immediate object or
+   immediate function.
 
-bool
-consteval_only_p (tree t)
+   Also return true for consteval-only values.  This doesn't check for
+   immediate functions.  */
+
+static bool
+consteval_only_p (tree t, hash_set<tree> &seen)
 {
-  if (!flag_reflection)
+  if (!flag_reflection || !t || t == error_mark_node)
     return false;
 
-  if (!TYPE_P (t))
-    t = TREE_TYPE (t);
+  /* Say that the wrapper itself is consteval-only so that
+     check_out_of_consteval_use_r returns the tree carrying the location.  */
+  STRIP_ANY_LOCATION_WRAPPER (t);
 
-  if (!t || t == error_mark_node)
+  /* Walking COMPONENT_REFs can walk back into a CONSTRUCTOR that's still
+     under construction and we'd loop.  */
+  if (seen.add (t))
     return false;
 
   if (TREE_CODE (t) == TREE_VEC)
     {
       for (tree arg : tree_vec_range (t))
-       if (arg && consteval_only_p (arg))
+       if (arg && consteval_only_p (arg, seen))
          return true;
       return false;
     }
 
-  /* For dependent types we can't be sure if this type is consteval-only.  */
-  if (dependent_type_p (t))
-    return false;
+  /* Pull out the initializer.  Don't call fold_non_dependent_expr and
+     similar here because that could prematurely instantiate things.  */
+  if (VAR_P (t))
+    t = DECL_INITIAL (t);
 
-  consteval_only_p_walker walker;
-  return walker.walk (t).is_true ();
-}
-
-/* Recursive workhorse of consteval_only_p.  Returns true if T is definitely
-   consteval-only, false if it's definitely not, and unknown if we saw an
-   incomplete type and therefore don't know.  */
-
-tristate
-consteval_only_p_walker::walk (tree t)
-{
-  if (t == error_mark_node)
-    return false;
-
-  t = TYPE_MAIN_VARIANT (t);
+  if (t && TREE_CODE (t) == TARGET_EXPR)
+    t = TARGET_EXPR_INITIAL (t);
 
-  if (REFLECTION_TYPE_P (t))
-    return true;
-  else if (INDIRECT_TYPE_P (t))
-    return walk (TREE_TYPE (t));
-  else if (TREE_CODE (t) == ARRAY_TYPE)
-    return walk (TREE_TYPE (t));
-  else if (FUNC_OR_METHOD_TYPE_P (t))
-    {
-      tristate r = walk (TREE_TYPE (t));
-      for (tree parm = TYPE_ARG_TYPES (t);
-          parm != NULL_TREE && parm != void_list_node;
-          parm = TREE_CHAIN (parm))
-       {
-         if (r.is_true ())
-           break;
-         r = r || walk (TREE_VALUE (parm));
-       }
-      return r;
-    }
-  else if (RECORD_OR_UNION_TYPE_P (t))
+  if (t && TREE_CODE (t) == CONSTRUCTOR)
     {
-      if (tree *slot = hash_map_safe_get (consteval_only_class_cache, t))
-       return *slot == boolean_true_node;
+      for (constructor_elt &elt : CONSTRUCTOR_ELTS (t))
+       if (consteval_only_p (elt.value, seen))
+         return true;
+      return false;
+    }
 
-      if (!COMPLETE_TYPE_P (t) && LAMBDA_TYPE_P (t))
-       /* Defer until we've definitely gone through prune_lambda_captures.  */
-       return tristate::unknown ();
+  return t && consteval_only_value_p (t, seen);
+}
 
-      if (class_seen.add (t))
-       {
-         /* Optimistically assume this already seen consteval-unknown class is
-            not consteval-only, for sake of mutually recursive classes.  */
-         optimistic_p = true;
-         return false;
-       }
-      ++class_depth;
+/* Wrapper for consteval_only_p that sets up a hash set.  */
 
-      tristate r = COMPLETE_TYPE_P (t) ? false : tristate::unknown ();
-      for (tree member = TYPE_FIELDS (t); member; member = DECL_CHAIN (member))
-       if (TREE_CODE (member) == FIELD_DECL)
-         {
-           r = r || walk (TREE_TYPE (member));
-           if (r.is_true ())
-             break;
-         }
-
-      if (r.is_true ())
-       hash_map_safe_put<hm_ggc> (consteval_only_class_cache,
-                                  t, boolean_true_node);
-      else if (r.is_false ()
-              /* The optimistic assumption above is at odds with caching
-                 'false' results for a nested class type.  */
-              && (class_depth == 1 || !optimistic_p))
-       hash_map_safe_put<hm_ggc> (consteval_only_class_cache,
-                                  t, boolean_false_node);
-
-      --class_depth;
-      return r;
-    }
-  else if (TYPE_PTRMEM_P (t))
-    return (walk (TYPE_PTRMEM_CLASS_TYPE (t))
-           || walk (TYPE_PTRMEM_POINTED_TO_TYPE (t)));
-  else
-    return false;
+bool
+consteval_only_p (tree t)
+{
+  hash_set<tree> seen;
+  return consteval_only_p (t, seen);
 }
 
 /* A walker for check_out_of_consteval_use_r.  It cannot be a lambda, because
    we have to call this recursively.  */
 
 static tree
-check_out_of_consteval_use_r (tree *tp, int *walk_subtrees, void *pset)
+check_out_of_consteval_use_r (tree *tp, int *walk_subtrees, void *pset_)
 {
   tree t = *tp;
+  auto pset = static_cast<hash_set<tree> *>(pset_);
 
   /* No need to look into types or unevaluated operands.  */
   if (TYPE_P (t)
       || (unevaluated_p (TREE_CODE (t)) && !REFLECT_EXPR_P (t))
-      /* Don't walk INIT_EXPRs, because we'd emit bogus errors about
-        member initializers.  */
-      || TREE_CODE (t) == INIT_EXPR
-      /* And don't recurse on DECL_EXPRs.  */
+      /* Don't recurse on DECL_EXPRs.  */
       || TREE_CODE (t) == DECL_EXPR
       /* Neither into USING_STMT.  */
       || TREE_CODE (t) == USING_STMT
       /* The operand of a splice is a constant-expression, thus
-        manifestly constant-evaluated, so consteval-only types are permitted
+        manifestly constant-evaluated, so consteval-only values are permitted
         here.  */
       || TREE_CODE (t) == SPLICE_EXPR
       /* Blocks can appear in the TREE_VEC operand of OpenMP
@@ -8980,19 +8971,33 @@ check_out_of_consteval_use_r (tree *tp, int 
*walk_subtrees, void *pset)
        return NULL_TREE;
       }
 
+  if (TREE_CODE (t) == EXPR_STMT)
+    {
+      if (tree r = cp_walk_tree (&EXPR_STMT_EXPR (t),
+                                check_out_of_consteval_use_r, pset, pset))
+       {
+         /* If we can't give a precise location of the expression,
+            use the location of the whole statement.  */
+         if (cp_expr_location (r) == UNKNOWN_LOCATION)
+           return t;
+         return r;
+       }
+      *walk_subtrees = false;
+      return NULL_TREE;
+    }
+
   if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t))
     {
       tree vexpr = DECL_VALUE_EXPR (t);
       if (tree ret = cp_walk_tree (&vexpr, check_out_of_consteval_use_r, pset,
-                                  (hash_set<tree> *) pset))
+                                  pset))
        return ret;
     }
 
   if (TREE_CODE (t) == BIND_EXPR)
     {
       if (tree r = cp_walk_tree (&BIND_EXPR_BODY (t),
-                                check_out_of_consteval_use_r, pset,
-                                static_cast<hash_set<tree> *>(pset)))
+                                check_out_of_consteval_use_r, pset, pset))
        return r;
       /* Don't walk BIND_EXPR_VARS.  */
       *walk_subtrees = false;
@@ -9004,8 +9009,7 @@ check_out_of_consteval_use_r (tree *tp, int 
*walk_subtrees, void *pset)
       if (IF_STMT_CONSTEVAL_P (t))
        {
          if (tree r = cp_walk_tree (&ELSE_CLAUSE (t),
-                                    check_out_of_consteval_use_r, pset,
-                                    static_cast<hash_set<tree> *>(pset)))
+                                    check_out_of_consteval_use_r, pset, pset))
            return r;
          /* Don't walk the consteval branch.  */
          *walk_subtrees = false;
@@ -9014,12 +9018,10 @@ check_out_of_consteval_use_r (tree *tp, int 
*walk_subtrees, void *pset)
       else if (IF_STMT_CONSTEXPR_P (t))
        {
          if (tree r = cp_walk_tree (&THEN_CLAUSE (t),
-                                    check_out_of_consteval_use_r, pset,
-                                    static_cast<hash_set<tree> *>(pset)))
+                                    check_out_of_consteval_use_r, pset, pset))
            return r;
          if (tree r = cp_walk_tree (&ELSE_CLAUSE (t),
-                                    check_out_of_consteval_use_r, pset,
-                                    static_cast<hash_set<tree> *>(pset)))
+                                    check_out_of_consteval_use_r, pset, pset))
            return r;
          /* Don't walk the condition -- it's a manifestly constant-evaluated
             context.  */
@@ -9039,8 +9041,7 @@ check_out_of_consteval_use_r (tree *tp, int 
*walk_subtrees, void *pset)
       return NULL_TREE;
     }
 
-  /* Now check the type to see if we are dealing with a consteval-only
-     expression.  */
+  /* If we don't find an immediate object, there's nothing to do.  */
   if (!consteval_only_p (t))
     return NULL_TREE;
 
@@ -9067,7 +9068,15 @@ check_out_of_consteval_use_r (tree *tp, int 
*walk_subtrees, void *pset)
 
 /* Detect if a consteval-only expression EXPR or a consteval-only
    variable EXPR not declared constexpr is used outside
-   a manifestly constant-evaluated context.  E.g.:
+   a manifestly constant-evaluated context.
+
+   [expr.const.const]/3: Every immediate object shall be
+   -- the object associated with a constexpr variable or a subobject thereof,
+   -- a template parameter object ([temp.param]) or a subject thereof, or
+   -- an object whose lifetime begins and ends during the evaluation of
+      a core constant expression.
+
+   E.g.:
 
      void f() {
        constexpr auto r = ^^int;  // OK
@@ -9098,20 +9107,9 @@ check_out_of_consteval_use (tree expr, bool 
complain/*=true*/)
   if (tree t = cp_walk_tree (&expr, check_out_of_consteval_use_r, &pset, 
&pset))
     {
       if (complain)
-       {
-         if (VAR_P (t) && !DECL_DECLARED_CONSTEXPR_P (t))
-           {
-             auto_diagnostic_group d;
-             error_at (cp_expr_loc_or_input_loc (t),
-                       "consteval-only variable %qD not declared %<constexpr%> 
"
-                       "used outside a constant-evaluated context", t);
-             inform (DECL_SOURCE_LOCATION (t), "add %<constexpr%>");
-           }
-         else
-           error_at (cp_expr_loc_or_input_loc (t),
-                     "consteval-only expressions are only allowed in "
-                     "a constant-evaluated context");
-       }
+       error_at (cp_expr_loc_or_loc (t, cp_expr_loc_or_input_loc (expr)),
+                 "consteval-only value outside an immediate function "
+                 "context");
       return true;
     }
 
@@ -9123,6 +9121,9 @@ check_out_of_consteval_use (tree expr, bool 
complain/*=true*/)
 bool
 compare_reflections (tree lhs, tree rhs)
 {
+  if (null_reflection_p (lhs) || null_reflection_p (rhs))
+    return null_reflection_p (lhs) == null_reflection_p (rhs);
+
   reflect_kind lkind;
   do
     {
@@ -9244,21 +9245,6 @@ valid_splice_for_member_access_p (const_tree t, bool 
decls_only_p/*=true*/)
          || TREE_CODE (t) == TREE_BINFO);
 }
 
-/* Check a function DECL for CWG 3115: Every function of consteval-only
-   type shall be an immediate function.  */
-
-void
-check_consteval_only_fn (tree decl)
-{
-  if (!DECL_IMMEDIATE_FUNCTION_P (decl)
-      && consteval_only_p (decl)
-      /* But if the function can be escalated, merrily we roll along.  */
-      && !immediate_escalating_function_p (decl))
-    error_at (DECL_SOURCE_LOCATION (decl),
-             "function of consteval-only type must be declared %qs",
-             "consteval");
-}
-
 /* Check if T is a valid result of splice-expression.  ADDRESS_P is true if
    we are taking the address of the splice.  MEMBER_ACCESS_P is true if this
    splice is used in foo.[: bar :] or foo->[: bar :] context.  TEMPLATE_P is
diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index 9845032d28d2..a415b423ef02 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -2131,15 +2131,13 @@ check_final_overrider (tree overrider, tree basefn)
       return 0;
     }
 
-  /* A class with a consteval virtual function that overrides a virtual
-     function that is not consteval shall have consteval-only type (CWG 3117).
-     A consteval virtual function shall not be overridden by a virtual
-     function that is not consteval.  */
+  /* [class.virtual]/18: A non-immediate virtual function shall not be
+     overridden by an immediate virtual function.  An immediate virtual
+     function shall not be overridden by a non-immediate virtual function.  */
   if ((DECL_IMMEDIATE_FUNCTION_P (basefn)
        && !DECL_IMMEDIATE_FUNCTION_P (overrider))
       || (!DECL_IMMEDIATE_FUNCTION_P (basefn)
-         && DECL_IMMEDIATE_FUNCTION_P (overrider)
-         && !consteval_only_p (overrider)))
+         && DECL_IMMEDIATE_FUNCTION_P (overrider)))
     {
       auto_diagnostic_group d;
       if (DECL_IMMEDIATE_FUNCTION_P (overrider))
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index ea34fef38619..978838a050a4 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -15055,12 +15055,6 @@ cp_build_bit_cast (location_t loc, tree type, tree arg,
                         "is not trivially copyable", type);
          return error_mark_node;
        }
-      if (consteval_only_p (type) || consteval_only_p (arg))
-       {
-         error_at (loc, "%<__builtin_bit_cast%> cannot be used with "
-                        "consteval-only types");
-         return error_mark_node;
-       }
     }
 
   if (error_operand_p (arg))
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 406a33bc1605..930694759656 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5175,6 +5175,16 @@ type_has_unique_obj_representations (const_tree t, bool 
explain/*=false*/)
        inform (loc, "%<std::nullptr_t%> has padding bits and no value bits");
       return false;
 
+    case LANG_TYPE:
+      if (REFLECTION_TYPE_P (t))
+       {
+         if (explain)
+           inform (loc, "%<std::meta::info%> has an unspecified object "
+                   "representation");
+         return false;
+       }
+      gcc_fallthrough ();
+
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 712b95ab245c..0b200804fe99 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -6389,7 +6389,7 @@ cp_build_binary_op (const op_location_t &location,
        }
       /* [expr.eq]: "If both operands are of type std::meta::info,
         comparison is defined as follows..."  */
-      else if (code0 == META_TYPE && code1 == META_TYPE)
+      else if (REFLECTION_TYPE_P (type0) && REFLECTION_TYPE_P (type1))
        result_type = type0;
       else
        {
@@ -11901,12 +11901,6 @@ check_return_expr (tree retval, bool *no_warning, bool 
*dangling)
        *dangling = true;
     }
 
-  if (check_out_of_consteval_use (retval))
-    {
-      current_function_return_value = error_mark_node;
-      return error_mark_node;
-    }
-
   /* A naive attempt to reduce the number of -Wdangling-reference false
      positives: if we know that this function can return a variable with
      static storage duration rather than one of its parameters, suppress
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 62f583dcf405..1aea0fde5498 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1136,6 +1136,42 @@ store_init_value (tree decl, tree init, vec<tree, 
va_gc>** cleanups, int flags)
   /* Handle aggregate NSDMI in non-constant initializers, too.  */
   value = replace_placeholders (value, decl);
 
+  /* Detect stuff like 'info r = ^^int;' outside a manifestly
+     constant-evaluated context.  */
+  if (flag_reflection
+      && !processing_template_decl
+      && !DECL_DECLARED_CONSTEXPR_P (decl))
+    {
+      const bool mce_p
+       = (decl_maybe_constant_var_p (decl)
+          || (TREE_STATIC (decl)
+              && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)));
+      bool bad = check_out_of_consteval_use (value, /*complain=*/false);
+      /* A non-constexpr variable at namespace scope with a constant
+        initializer has constant initialization, so we check the folded
+        value not to wrongly reject "int e = (^^int, 42);".  For non-static
+        local variables, there is no such rule, so we check the unfolded
+        initializer.  But we should also reject
+
+          consteval auto fn () { return ^^int; }
+          void g() { auto r = fn (); }
+
+        so we may have to check both.  Note that the first call could
+        have escalated and so we may find ourselves in an immediate
+        context now.  */
+      if (!bad && !mce_p && value != init)
+       bad = check_out_of_consteval_use (init, /*complain=*/false);
+      if (bad)
+       {
+         auto_diagnostic_group d;
+         error_at (DECL_SOURCE_LOCATION (decl),
+                   "%qD is initialized with a consteval-only value but is "
+                   "not declared %<constexpr%>", decl);
+         inform (DECL_SOURCE_LOCATION (decl), "add %<constexpr%>");
+         value = error_mark_node;
+       }
+    }
+
   /* A COMPOUND_LITERAL_P CONSTRUCTOR is the syntactic form; by the time we get
      here it should have been digested into an actual value for the type.  */
   gcc_checking_assert (TREE_CODE (value) != CONSTRUCTOR
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 95dd87242449..a64fa974048d 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -7135,6 +7135,8 @@ count_type_elements (const_tree type, bool for_ctor_p)
     case POINTER_TYPE:
     case OFFSET_TYPE:
     case REFERENCE_TYPE:
+    /* This could represent the C++ std::meta::info type.  */
+    case LANG_TYPE:
     case NULLPTR_TYPE:
     case OPAQUE_TYPE:
     case BITINT_TYPE:
@@ -7146,7 +7148,6 @@ count_type_elements (const_tree type, bool for_ctor_p)
     case VOID_TYPE:
     case METHOD_TYPE:
     case FUNCTION_TYPE:
-    case LANG_TYPE:
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-uneval3.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval3.C
index 7fc4065730b7..fd1abbac433d 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-uneval3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-uneval3.C
@@ -3,7 +3,7 @@
 
 template <class T>
 struct A {
-  void f() requires (this, true) { }
+  void f() requires (this, true) { }   // { dg-error ".this. is not a constant 
expression" }
 };
 
 template struct A<int>;
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-24.C 
b/gcc/testsuite/g++.dg/gcov/gcov-24.C
index d68fda7dbc18..3935d48e0338 100644
--- a/gcc/testsuite/g++.dg/gcov/gcov-24.C
+++ b/gcc/testsuite/g++.dg/gcov/gcov-24.C
@@ -20,8 +20,8 @@ empty_body_for_loop ()
   return i;
 }
 
-/* Making the for (;;) multi line should report count per line.  g++ considers
-   the i++ unexecuted, while gcc counts it.  */
+/* Suppressing the loop should suppress everything within the loop, but not the
+   return.  */
 int
 ignored_for_loop ()
 {
@@ -38,7 +38,7 @@ ignored_for_loop ()
 #pragma GCC suppress_coverage begin
   for (i = 0;                  /* count(#) */
        i < 20;                 /* count(#) */
-       i++)                    /* count(-) */
+       i++)                    /* count(#) */
     {
       noop ();                 /* count(#) */
     }
diff --git a/gcc/testsuite/g++.dg/reflect/bit_cast.C 
b/gcc/testsuite/g++.dg/reflect/bit_cast.C
index bab62717f7ee..d305c54f19a0 100644
--- a/gcc/testsuite/g++.dg/reflect/bit_cast.C
+++ b/gcc/testsuite/g++.dg/reflect/bit_cast.C
@@ -10,10 +10,20 @@ f ()
   auto a = ^^int;
   auto *b = &a;
   void *c = nullptr;
-  (void) std::bit_cast<void *>(b);  // { dg-message "from here" }
-  (void) std::bit_cast<decltype(^^int) *>(c); // { dg-message "from here" }
-  __builtin_bit_cast (void *, b); // { dg-error ".__builtin_bit_cast. cannot 
be used with consteval-only types" }
-  __builtin_bit_cast (decltype(^^int) *, c);  // { dg-error 
".__builtin_bit_cast. cannot be used with consteval-only types" }
+  (void) std::bit_cast<void *>(b);
+  (void) std::bit_cast<decltype(^^int) *>(c);
+  __builtin_bit_cast (void *, b);
+  __builtin_bit_cast (decltype(^^int) *, c);
 }
 
-// { dg-error ".__builtin_bit_cast. cannot be used with consteval-only types" 
"" { target *-*-* } 0 }
+void
+g ()
+{
+  constexpr static auto a = ^^int;
+  constexpr auto *b = &a;
+  void *c = nullptr;
+  (void) std::bit_cast<void *>(b);             // { dg-error "consteval-only 
value outside an immediate function context" }
+  (void) std::bit_cast<decltype(^^int) *>(c);
+  __builtin_bit_cast (void *, b);              // { dg-error "consteval-only 
value outside an immediate function context" }
+  __builtin_bit_cast (decltype(^^int) *, c);
+}
diff --git a/gcc/testsuite/g++.dg/reflect/bit_cast2.C 
b/gcc/testsuite/g++.dg/reflect/bit_cast2.C
new file mode 100644
index 000000000000..b1a3ff49e8f6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/bit_cast2.C
@@ -0,0 +1,16 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+using info = decltype(^^::);
+
+struct S { info i; };
+
+// These are non-constant under https://eel.is/c++draft/bit.cast#2 and
+// https://eel.is/c++draft/expr.const#core-1.2
+constexpr auto x = __builtin_bit_cast (unsigned long, ^^int);   // { dg-error 
".__builtin_bit_cast. is not a constant expression because its type is 
.std::meta::info." }
+constexpr auto y = __builtin_bit_cast (decltype(^^int), 0UL);   // { dg-error 
".__builtin_bit_cast. is not a constant expression because its type is 
.std::meta::info." }
+constexpr auto w = __builtin_bit_cast (S, 0UL);   // { dg-error 
".__builtin_bit_cast. is not a constant expression because .S. contains 
.std::meta::info. type" }
+// TODO: CWG 3217. Run-time treatment of std::meta::info types
+info z = __builtin_bit_cast (decltype(^^int), 0xdeadbeefUL);
diff --git a/gcc/testsuite/g++.dg/reflect/crash12.C 
b/gcc/testsuite/g++.dg/reflect/crash12.C
index a234c95be55e..e289a6891112 100644
--- a/gcc/testsuite/g++.dg/reflect/crash12.C
+++ b/gcc/testsuite/g++.dg/reflect/crash12.C
@@ -3,6 +3,6 @@
 
 #include <meta>
 
-struct X { constexpr operator std::meta::info(); }; // { dg-error "function of 
consteval-only type" }
+struct X { constexpr operator std::meta::info(); };
 // { dg-warning "used but never defined" "" { target *-*-* } .-1 }
 constexpr auto r = std::meta::type_of (X{}); // { dg-error "used before its 
definition" }
diff --git a/gcc/testsuite/g++.dg/reflect/crash18.C 
b/gcc/testsuite/g++.dg/reflect/crash18.C
index 3fe08734f563..51ecd4ad30ee 100644
--- a/gcc/testsuite/g++.dg/reflect/crash18.C
+++ b/gcc/testsuite/g++.dg/reflect/crash18.C
@@ -3,4 +3,4 @@
 
 // We also test this elsewhere but we only crashed when there were no other
 // errors.
-void fn (decltype(^^::)) {} // { dg-error "function of consteval-only type 
must be declared .consteval." }
+void fn (decltype(^^::)) {}
diff --git a/gcc/testsuite/g++.dg/reflect/diag3.C 
b/gcc/testsuite/g++.dg/reflect/diag3.C
index 49233ee354c5..2be45cb962f5 100644
--- a/gcc/testsuite/g++.dg/reflect/diag3.C
+++ b/gcc/testsuite/g++.dg/reflect/diag3.C
@@ -2,31 +2,31 @@
 // { dg-additional-options "-freflection" }
 // Test that we suggest adding "constexpr" (where allowed).
 
-auto foo = ^^int;  // { dg-error "consteval-only variable .foo." }
+auto foo = ^^int;  // { dg-error ".foo. is initialized with a consteval-only 
value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
-constinit auto foo_ = ^^int; // { dg-error "consteval-only variable .foo_." }
+constinit auto foo_ = ^^int; // { dg-error ".foo_. is initialized with a 
consteval-only value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
 constexpr auto foo__ = ^^int;
-thread_local auto tfoo = ^^int;  // { dg-error "consteval-only variable 
.tfoo." }
+thread_local auto tfoo = ^^int;  // { dg-error ".tfoo. is initialized with a 
consteval-only value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
-thread_local constinit auto tfoo_ = ^^int; // { dg-error "consteval-only 
variable .tfoo_." }
+thread_local constinit auto tfoo_ = ^^int; // { dg-error ".tfoo_. is 
initialized with a consteval-only value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
 thread_local constexpr auto tfoo__ = ^^int;
 
 void
 f ()
 {
-  auto ref = ^^int;  // { dg-error "consteval-only variable .ref." }
+  auto ref = ^^int;  // { dg-error ".ref. is initialized with a consteval-only 
value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
   constexpr auto ref_ = ^^int;
-  static auto sref = ^^int;  // { dg-error "consteval-only variable .sref." }
+  static auto sref = ^^int;  // { dg-error ".sref. is initialized with a 
consteval-only value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
-  static auto constinit sref_ = ^^int; // { dg-error "consteval-only variable 
.sref_." }
+  static auto constinit sref_ = ^^int; // { dg-error ".sref_. is initialized 
with a consteval-only value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
   static auto constexpr sref__ = ^^int;
-  thread_local auto tref = ^^int; // { dg-error "consteval-only variable 
.tref." }
+  thread_local auto tref = ^^int; // { dg-error ".tref. is initialized with a 
consteval-only value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
-  thread_local constinit auto tref_ = ^^int; // { dg-error "consteval-only 
variable .tref_." }
+  thread_local constinit auto tref_ = ^^int; // { dg-error ".tref_. is 
initialized with a consteval-only value" }
 // { dg-message "add .constexpr." "" { target *-*-* } .-1 }
   thread_local constexpr auto tref__ = ^^int;
 }
diff --git a/gcc/testsuite/g++.dg/reflect/expr11.C 
b/gcc/testsuite/g++.dg/reflect/expr11.C
index 44d66947d9d6..61f934f8bab3 100644
--- a/gcc/testsuite/g++.dg/reflect/expr11.C
+++ b/gcc/testsuite/g++.dg/reflect/expr11.C
@@ -11,18 +11,18 @@ f ()
   constexpr auto q = ^^float;
   if constexpr (foo (^^::) == ^^::)
     {
-      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+      auto r = ^^int; // { dg-error "consteval-only value" }
       constexpr auto cr = ^^int;
     }
-  if constexpr (auto r = ^^int;  // { dg-error "consteval-only variable .r." }
+  if constexpr (auto r = ^^int;  // { dg-error "consteval-only value" }
                r == ^^int);     // { dg-error "the value of .r. is not usable" 
}
   if constexpr (constexpr auto r = ^^int; r == ^^int);
   if constexpr (q != ^^char);
   if constexpr (^^int != ^^char);
-  if (q != ^^char);  // { dg-error "consteval-only expressions" }
-  if (^^char == ^^char);  // { dg-error "consteval-only expressions" }
-  while (^^char == ^^char);  // { dg-error "consteval-only expressions" }
-  do {} while (^^char == ^^char);  // { dg-error "consteval-only expressions" }
+  if (q != ^^char);  // { dg-error "consteval-only value" }
+  if (^^char == ^^char);  // { dg-error "consteval-only value" }
+  while (^^char == ^^char);  // { dg-error "consteval-only value" }
+  do {} while (^^char == ^^char);  // { dg-error "consteval-only value" }
   consteval {
     if (q != ^^char);
     if (^^char == ^^char);
@@ -32,18 +32,18 @@ f ()
 
   if constexpr (true)
     {
-      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+      auto r = ^^int; // { dg-error "consteval-only value" }
     }
   else
     {
-      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+      auto r = ^^int; // { dg-error "consteval-only value" }
     }
   if constexpr (false)
     {
-      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+      auto r = ^^int; // { dg-error "consteval-only value" }
     }
   else
     {
-      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+      auto r = ^^int; // { dg-error "consteval-only value" }
     }
 }
diff --git a/gcc/testsuite/g++.dg/reflect/expr12.C 
b/gcc/testsuite/g++.dg/reflect/expr12.C
index 34aed536429c..6120793a06be 100644
--- a/gcc/testsuite/g++.dg/reflect/expr12.C
+++ b/gcc/testsuite/g++.dg/reflect/expr12.C
@@ -19,30 +19,30 @@ f ()
 
   if not consteval
     {
-      ^^void;  // { dg-error "consteval-only expressions" }
+      ^^void;  // { dg-error "consteval-only value" }
     }
   if not consteval
     {
-      q;  // { dg-error "consteval-only expressions" }
+      q;  // { dg-error "consteval-only value" }
     }
   if not consteval
     {
-      auto r = ^^int;  // { dg-error "consteval-only variable" }
+      auto r = ^^int;  // { dg-error "consteval-only value" }
     }
   if not consteval
     {
-      if (q != ^^char);  // { dg-error "consteval-only expressions" }
+      if (q != ^^char);  // { dg-error "consteval-only value" }
     }
   if not consteval
     {
-      if (^^char == ^^char);  // { dg-error "consteval-only expressions" }
+      if (^^char == ^^char);  // { dg-error "consteval-only value" }
     }
   if not consteval
     {
-      while (^^char != ^^char);  // { dg-error "consteval-only expressions" }
+      while (^^char != ^^char);  // { dg-error "consteval-only value" }
     }
   if not consteval
     {
-      do {} while (^^char != ^^char);  // { dg-error "consteval-only 
expressions" }
+      do {} while (^^char != ^^char);  // { dg-error "consteval-only value" }
     }
 }
diff --git a/gcc/testsuite/g++.dg/reflect/expr19.C 
b/gcc/testsuite/g++.dg/reflect/expr19.C
new file mode 100644
index 000000000000..9beddcefd756
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/expr19.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+constexpr auto r = ^^int;
+
+void f () { (void) r; }                      // { dg-error "consteval-only" }
+void g (bool c) { if (c) (void) r; }  // { dg-error "consteval-only" }
+auto h () { return r; }                      // { dg-error "consteval-only" }
diff --git a/gcc/testsuite/g++.dg/reflect/init10.C 
b/gcc/testsuite/g++.dg/reflect/init10.C
index df81b890fae9..02bdf61d0d51 100644
--- a/gcc/testsuite/g++.dg/reflect/init10.C
+++ b/gcc/testsuite/g++.dg/reflect/init10.C
@@ -9,8 +9,8 @@ struct A {
   consteval A() : i{^^void} {}
 };
 
-A a1;  // { dg-error "consteval-only variable .a1." }
-constinit A a2;  // { dg-error "consteval-only variable .a2." }
+A a1;  // { dg-error "consteval-only value" }
+constinit A a2;  // { dg-error "consteval-only value" }
 constexpr A a3;
 
 struct B {
@@ -19,6 +19,6 @@ struct B {
  consteval B() : i{}, j{i} {}
 };
 
-B b1;  // { dg-error "consteval-only variable .b1." }
-constinit B b2;  // { dg-error "consteval-only variable .b2." }
+B b1;
+constinit B b2;
 constexpr B b3;
diff --git a/gcc/testsuite/g++.dg/reflect/init11.C 
b/gcc/testsuite/g++.dg/reflect/init11.C
index 7173023e6023..05e2d0cad733 100644
--- a/gcc/testsuite/g++.dg/reflect/init11.C
+++ b/gcc/testsuite/g++.dg/reflect/init11.C
@@ -1,6 +1,5 @@
 // { dg-do compile { target c++26 } }
 // { dg-additional-options "-freflection" }
-// Test invalid reflections in member init lists.
 
 using info = decltype(^^void);
 
@@ -16,10 +15,10 @@ struct B {
 
 struct C {
   info i;
-  constexpr C() : i{} {}  // { dg-error "function of consteval-only type must 
be declared .consteval." }
+  constexpr C() : i{} {}
 };
 
 struct D {
   info i;
-  D() : i{} {}  // { dg-error "function of consteval-only type must be 
declared .consteval." }
+  D() : i{} {}
 };
diff --git a/gcc/testsuite/g++.dg/reflect/init12.C 
b/gcc/testsuite/g++.dg/reflect/init12.C
index 8ec456d1cbaf..3d1ca6a46cbf 100644
--- a/gcc/testsuite/g++.dg/reflect/init12.C
+++ b/gcc/testsuite/g++.dg/reflect/init12.C
@@ -24,6 +24,6 @@ void
 g ()
 {
   constexpr static auto r = ^^int;
-  constexpr auto x = foo<info>(&r); // { dg-error "pointer into an object of 
consteval-only type" }
+  constexpr auto x = foo<info>(&r);
   constexpr auto y = bar<info>(nullptr);
 }
diff --git a/gcc/testsuite/g++.dg/reflect/init16.C 
b/gcc/testsuite/g++.dg/reflect/init16.C
index 621b1c57d3b9..d411ef7450db 100644
--- a/gcc/testsuite/g++.dg/reflect/init16.C
+++ b/gcc/testsuite/g++.dg/reflect/init16.C
@@ -41,7 +41,7 @@ void fox() {
         do_something_runtime<A>();
         int C = something_of(A);
         constexpr int E = something_of(A);
-        identity(A); // { dg-error "consteval-only expressions" }
-        identity(B); // { dg-error "consteval-only expressions" }
+        identity(A); // { dg-error "consteval-only value" }
+        identity(B); // { dg-error "consteval-only value" }
     }
 }
diff --git a/gcc/testsuite/g++.dg/reflect/init19.C 
b/gcc/testsuite/g++.dg/reflect/init19.C
index bfebe4cf2d72..bd0d10fa9d27 100644
--- a/gcc/testsuite/g++.dg/reflect/init19.C
+++ b/gcc/testsuite/g++.dg/reflect/init19.C
@@ -8,5 +8,5 @@ struct N { int i; };
 template<typename T>
 struct X : T { };
 
-auto a = X<C>{}; // { dg-error "outside a constant-evaluated context" }
+auto a = X<C>{};
 auto b = X<N>{};
diff --git a/gcc/testsuite/g++.dg/reflect/init4.C 
b/gcc/testsuite/g++.dg/reflect/init4.C
index 6d9a39b40e0c..f337def032cb 100644
--- a/gcc/testsuite/g++.dg/reflect/init4.C
+++ b/gcc/testsuite/g++.dg/reflect/init4.C
@@ -49,7 +49,7 @@ constexpr G g;
 struct H {
   info (*fp)();
 };
-constexpr H h{foo}; // { dg-error "address of immediate function" }
+constexpr H h{foo};    // { dg-bogus "returns address" "" { xfail *-*-* } }
 
 union U {
   int n;
diff --git a/gcc/testsuite/g++.dg/reflect/init5.C 
b/gcc/testsuite/g++.dg/reflect/init5.C
index dd9f07bf4d62..abefac118667 100644
--- a/gcc/testsuite/g++.dg/reflect/init5.C
+++ b/gcc/testsuite/g++.dg/reflect/init5.C
@@ -12,10 +12,10 @@ consteval const Base &fn1() {
   static constexpr Derived d;
   return d;
 }
-constexpr auto &ref = fn1(); // { dg-error "reference into an object of 
consteval-only type" }
+constexpr auto &ref = fn1();
 
 consteval void *fn2() {
   static constexpr auto v = ^^int;
   return (void *)&v;
 }
-constexpr const void *ptr = fn2(); // { dg-error "pointer into an object of 
consteval-only type" }
+constexpr const void *ptr = fn2();
diff --git a/gcc/testsuite/g++.dg/reflect/init6.C 
b/gcc/testsuite/g++.dg/reflect/init6.C
index 371d8cee314d..36f598c1c00a 100644
--- a/gcc/testsuite/g++.dg/reflect/init6.C
+++ b/gcc/testsuite/g++.dg/reflect/init6.C
@@ -11,12 +11,12 @@ struct N {
   info i = ^^void;
 };
 
-S s1;  // { dg-error "consteval-only variable" }
-constinit S s2{};  // { dg-error "consteval-only variable" }
+S s1;
+constinit S s2{};
 constexpr S s3{^^int};
 
-N n1;  // { dg-error "consteval-only variable" }
-constinit N n2;  // { dg-error "consteval-only variable" }
+N n1;  // { dg-error "consteval-only value" }
+constinit N n2;  // { dg-error "consteval-only value" }
 constexpr N n3;
 
 template<typename T>
@@ -24,8 +24,8 @@ struct X {
   T t;
 };
 
-X<info> x1;  // { dg-error "consteval-only variable" }
-constinit X<info> x2{};  // { dg-error "consteval-only variable" }
+X<info> x1;
+constinit X<info> x2{};
 constexpr X<info> x3{^^int};
 
 void
diff --git a/gcc/testsuite/g++.dg/reflect/init7.C 
b/gcc/testsuite/g++.dg/reflect/init7.C
index c530776d74ba..c9155e2d4348 100644
--- a/gcc/testsuite/g++.dg/reflect/init7.C
+++ b/gcc/testsuite/g++.dg/reflect/init7.C
@@ -5,25 +5,25 @@
 
 using info = decltype(^^int);
 
-info r1 = ^^int;  // { dg-error "consteval-only variable .r1. not declared 
.constexpr. used outside a constant-evaluated context" }
-const info r2 = ^^int;  // { dg-error "consteval-only variable .r2. not 
declared .constexpr. used outside a constant-evaluated context" }
+info r1 = ^^int;  // { dg-error ".r1. is initialized with a consteval-only 
value but is not declared .constexpr." }
+const info r2 = ^^int;  // { dg-error ".r2. is initialized with a 
consteval-only value but is not declared .constexpr." }
 
 constexpr info r3 = ^^int;
-constinit info r4 = ^^int;  // { dg-error "consteval-only variable .r4. not 
declared .constexpr. used outside a constant-evaluated context" }
-const info *const p1 = &r3;  // { dg-error "consteval-only variable .p1. not 
declared .constexpr. used outside a constant-evaluated context" }
-info *p2;  // { dg-error "consteval-only variable .p2. not declared 
.constexpr. used outside a constant-evaluated context" }
-const info &q = r3;  // { dg-error "consteval-only variable .q. not declared 
.constexpr. used outside a constant-evaluated context" }
+constinit info r4 = ^^int;  // { dg-error ".r4. is initialized with a 
consteval-only value but is not declared .constexpr." }
+const info *const p1 = &r3;  // { dg-error ".p1. is initialized with a 
consteval-only value but is not declared .constexpr." }
+info *p2;
+const info &q = r3;  // { dg-error ".q. is initialized with a consteval-only 
value but is not declared .constexpr." }
 
 void
 g ()
 {
-  info l1 = ^^int;  // { dg-error "consteval-only variable .l1. not declared 
.constexpr. used outside a constant-evaluated context" }
-  const info l2 = ^^int;  // { dg-error "consteval-only variable .l2. not 
declared .constexpr. used outside a constant-evaluated context" }
+  info l1 = ^^int;  // { dg-error ".l1. is initialized with a consteval-only 
value but is not declared .constexpr." }
+  const info l2 = ^^int;  // { dg-error ".l2. is initialized with a 
consteval-only value but is not declared .constexpr." }
   constexpr info l3 = ^^int;
-  static info l4 = ^^int;  // { dg-error "consteval-only variable .l4. not 
declared .constexpr. used outside a constant-evaluated context" }
-  static const info l5 = ^^int;  // { dg-error "consteval-only variable .l5. 
not declared .constexpr. used outside a constant-evaluated context" }
+  static info l4 = ^^int;  // { dg-error ".l4. is initialized with a 
consteval-only value but is not declared .constexpr." }
+  static const info l5 = ^^int;  // { dg-error ".l5. is initialized with a 
consteval-only value but is not declared .constexpr." }
   static constexpr info l6 = ^^int;
-  static constinit info l7 = ^^int;  // { dg-error "consteval-only variable 
.l7. not declared .constexpr. used outside a constant-evaluated context" }
+  static constinit info l7 = ^^int;  // { dg-error ".l7. is initialized with a 
consteval-only value but is not declared .constexpr." }
 }
 
 consteval void
diff --git a/gcc/testsuite/g++.dg/reflect/init9.C 
b/gcc/testsuite/g++.dg/reflect/init9.C
index c088a2d9a7c8..a8005e04344b 100644
--- a/gcc/testsuite/g++.dg/reflect/init9.C
+++ b/gcc/testsuite/g++.dg/reflect/init9.C
@@ -4,9 +4,9 @@
 
 using info = decltype(^^int);
 
-info foo (); // { dg-error "function of consteval-only type must be declared 
.consteval." }
-constexpr info bar (); // { dg-error "function of consteval-only type must be 
declared .consteval." }
-void baz (info); // { dg-error "function of consteval-only type must be 
declared .consteval." }
+info foo ();
+constexpr info bar ();
+void baz (info);
 
 consteval info
 ok1 ()
@@ -28,26 +28,26 @@ ok3 (info i)
 }
 
 constexpr info
-bad1 () // { dg-error "function of consteval-only type must be declared 
.consteval." }
+bad1 ()
 {
-  return ^^int;  // { dg-error "consteval-only expressions" }
+  return ^^int;  // { dg-error "consteval-only value" }
 }
 
 info
-bad2 () // { dg-error "function of consteval-only type must be declared 
.consteval." }
+bad2 ()
 {
-  return ^^int;  // { dg-error "consteval-only expressions" }
+  return ^^int;  // { dg-error "consteval-only value" }
 }
 
 constexpr auto
-bad3 (info i) // { dg-error "function of consteval-only type must be declared 
.consteval." }
+bad3 (info i)
 {
-  return i;  // { dg-error "consteval-only expressions" }
+  return i;
 }
 
 template<info R>
 info
-bad4 () // { dg-error "function of consteval-only type must be declared 
.consteval." }
+bad4 ()
 {
-  return R;  // { dg-error "consteval-only expressions" }
+  return R;
 }
diff --git a/gcc/testsuite/g++.dg/reflect/null7.C 
b/gcc/testsuite/g++.dg/reflect/null7.C
new file mode 100644
index 000000000000..96bdc999c531
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/null7.C
@@ -0,0 +1,32 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+using info = decltype(^^::);
+
+info g = info ();
+info g2;
+
+struct S { info a, b; };
+constexpr S s = { ^^::S };
+static_assert (s.b == info ());
+
+constexpr S s2[2] = { { ^^::S, ^^::S } };
+static_assert (s2[1].a == info ());
+
+S gs = {};
+info garr[3] = { };
+
+constexpr info arr[3] = { ^^::S };
+static_assert (arr[1] == arr[2]);
+static_assert (arr[2] == info ());
+
+struct T { info r; T () = default; };
+constexpr T t {};
+static_assert (t.r == info ());
+
+bool h (S s) { return s.b == info (); }
+
+constexpr info r = info ();
+static_assert (r == info ());
+
+info *k () { static info lg = info (); return &lg; }
diff --git a/gcc/testsuite/g++.dg/reflect/override1.C 
b/gcc/testsuite/g++.dg/reflect/override1.C
index d3124f55152a..540287d6f8a4 100644
--- a/gcc/testsuite/g++.dg/reflect/override1.C
+++ b/gcc/testsuite/g++.dg/reflect/override1.C
@@ -9,12 +9,12 @@ struct B {
 };
 
 struct D1 : B {
-  consteval virtual void foo() override { } // { dg-error "overriding" }
+  consteval virtual void foo() override { } // { dg-error "overriding 
non-.consteval. function" }
 };
 
 struct D2 : B {
   info i;
-  consteval virtual void foo() override { }
+  consteval virtual void foo() override { } // { dg-error "overriding 
non-.consteval. function" }
 };
 
 struct D3 : B {
@@ -30,10 +30,10 @@ struct D4 : B2 {
 };
 
 struct D5 : B2 {
-  virtual void foo() override { } // { dg-error "overriding" }
+  virtual void foo() override { } // { dg-error "overriding .consteval. 
function" }
 };
 
 struct D6 : B2 {
   info i;
-  virtual void foo() override { } // { dg-error "consteval-only 
type|overriding" }
+  virtual void foo() override { } // { dg-error "overriding .consteval. 
function" }
 };
diff --git a/gcc/testsuite/g++.dg/reflect/p2996-15.C 
b/gcc/testsuite/g++.dg/reflect/p2996-15.C
index 3ced17647aeb..867db78163d8 100644
--- a/gcc/testsuite/g++.dg/reflect/p2996-15.C
+++ b/gcc/testsuite/g++.dg/reflect/p2996-15.C
@@ -11,6 +11,6 @@ consteval const Base& fn(const Derived& derived) { return 
derived; }
 
 constexpr Derived obj{.r=^^::}; // OK
 constexpr const Derived& d = obj; // OK
-constexpr const Base& b1 = fn(obj); // { dg-error "reference into an object of 
consteval-only" }
-constexpr const Base& b2 = obj;          // { dg-error "reference into an 
object of consteval-only" }
+constexpr const Base& b1 = fn(obj);
+constexpr const Base& b2 = obj;
 constexpr Base b3 = obj;
diff --git a/gcc/testsuite/g++.dg/reflect/parm3.C 
b/gcc/testsuite/g++.dg/reflect/parm3.C
index 1ff9357dc3df..4128166ac5ee 100644
--- a/gcc/testsuite/g++.dg/reflect/parm3.C
+++ b/gcc/testsuite/g++.dg/reflect/parm3.C
@@ -5,23 +5,23 @@
 using info = decltype(^^int);
 
 consteval void foo (info) { }
-constexpr void bar (info) { } // { dg-error "function of consteval-only type 
must be declared .consteval." }
-void baz (info) { }  // { dg-error "function of consteval-only type must be 
declared .consteval." }
+constexpr void bar (info) { }
+void baz (info) { }
 
 void
 f ()
 {
   foo (^^void);
-  bar (^^void);  // { dg-error "consteval-only expressions" }
-  baz (^^void);  // { dg-error "consteval-only expressions" }
+  bar (^^void);  // { dg-error "consteval-only value" }
+  baz (^^void);  // { dg-error "consteval-only value" }
 }
 
 constexpr void
 g ()
 {
   foo (^^void);
-  bar (^^void);  // { dg-error "consteval-only expressions" }
-  baz (^^void);  // { dg-error "consteval-only expressions" }
+  bar (^^void);  // { dg-error "consteval-only value" }
+  baz (^^void);  // { dg-error "consteval-only value" }
 }
 
 consteval void
diff --git a/gcc/testsuite/g++.dg/reflect/parm4.C 
b/gcc/testsuite/g++.dg/reflect/parm4.C
index 8867e6adbb68..bb733f172330 100644
--- a/gcc/testsuite/g++.dg/reflect/parm4.C
+++ b/gcc/testsuite/g++.dg/reflect/parm4.C
@@ -5,28 +5,28 @@
 using info = decltype(^^int);
 
 struct S {
-  int mfn0 (info) { return 0; }  // { dg-error "function of consteval-only 
type must be declared .consteval." }
-  constexpr int mfn1 (info) { return 1; }  // { dg-error "function of 
consteval-only type must be declared .consteval." }
+  int mfn0 (info) { return 0; }
+  constexpr int mfn1 (info) { return 1; }
   consteval int mfn2 (info) { return 2; }
-  int mfn3 (int, info) { return 0; }  // { dg-error "function of 
consteval-only type must be declared .consteval." }
-  info mfn4 () { return ^^int; }  // { dg-error "consteval-only 
expressions|function of consteval-only type must be declared .consteval." }
+  int mfn3 (int, info) { return 0; }
+  info mfn4 () { return ^^int; }    // { dg-error "consteval-only value" }
 };
 
 void
 g (S s)
 {
-  int i0 = s.mfn0 (^^int);  // { dg-error "consteval-only expressions" "" { 
target { ! implicit_constexpr } } }
+  int i0 = s.mfn0 (^^int);  // { dg-error "consteval-only value" }
   constexpr int i1 = s.mfn1 (^^int);
   constexpr int i2 = s.mfn2 (^^int);
-  int i3 = s.mfn3 (42, ^^int);  // { dg-error "consteval-only expressions" "" 
{ target { ! implicit_constexpr } } }
-  info i4 = s.mfn4 ();  // { dg-error "consteval-only variable" }
+  int i3 = s.mfn3 (42, ^^int);  // { dg-error "consteval-only value" }
+  info i4 = s.mfn4 ();
 }
 
 template<typename T>
-int fn (T) { return 4; } // { dg-error "function of consteval-only type must 
be declared .consteval." }
-const int a = fn (^^int); // { dg-error "consteval-only expressions" }
-int b = fn (^^int); // { dg-error "consteval-only expressions" }
+int fn (T) { return 4; }
+const int a = fn (^^int); // { dg-error "consteval-only value" }
+int b = fn (^^int); // { dg-error "consteval-only value" }
 
 template<typename T>
 T fn2 () { return ^^void; } // { dg-error "consteval-only" }
-const info i = fn2<info>(); // { dg-error "consteval-only variable" }
+const info i = fn2<info>();
diff --git a/gcc/testsuite/g++.dg/reflect/pr124012.C 
b/gcc/testsuite/g++.dg/reflect/pr124012.C
index 84783d1a8054..55df158808d7 100644
--- a/gcc/testsuite/g++.dg/reflect/pr124012.C
+++ b/gcc/testsuite/g++.dg/reflect/pr124012.C
@@ -10,28 +10,28 @@ void
 bar ()
 {
   constexpr auto [a, b] = A {};
-  foo (a);                     // { dg-error "consteval-only expressions are 
only allowed in a constant-evaluated context" }
+  foo (a);
 }
 
 void
 baz ()
 {
   constexpr auto a = A {};
-  foo (a.a);                   // { dg-error "consteval-only expressions are 
only allowed in a constant-evaluated context" }
+  foo (a.a);
 }
 
 void
 qux ()
 {
   constexpr auto a = A {};
-  corge (&a.a);                        // { dg-error "consteval-only 
expressions are only allowed in a constant-evaluated context" }
+  corge (&a.a);
 }
 
 void
 garply ()
 {
   constexpr auto [a, b] = A {};
-  corge (&a);                  // { dg-error "consteval-only expressions are 
only allowed in a constant-evaluated context" }
+  corge (&a);
 }
 
 void
diff --git a/gcc/testsuite/g++.dg/reflect/type12.C 
b/gcc/testsuite/g++.dg/reflect/type12.C
index c066f27fb699..31717841705d 100644
--- a/gcc/testsuite/g++.dg/reflect/type12.C
+++ b/gcc/testsuite/g++.dg/reflect/type12.C
@@ -17,7 +17,7 @@ struct CE { decltype(^^::) i; };
 struct A {
   static const Array<CE, 10> mData;
 };
-const Array<CE, 10> A::mData{}; // { dg-error "outside a constant-evaluated 
context" }
+const Array<CE, 10> A::mData{};
 
 struct B {
   static constexpr Array<CE, 11> mData{};
diff --git a/gcc/testsuite/g++.dg/reflect/type2.C 
b/gcc/testsuite/g++.dg/reflect/type2.C
index 7d1f16b981dd..2ca31d1a6483 100644
--- a/gcc/testsuite/g++.dg/reflect/type2.C
+++ b/gcc/testsuite/g++.dg/reflect/type2.C
@@ -7,13 +7,13 @@ struct A;
 void
 f1 ()
 {
-  const auto r = ^^double; // { dg-error "consteval-only variable" }
+  const auto r = ^^double; // { dg-error "consteval-only value" }
   constexpr auto r2 = ^^int;
-  r2; // { dg-error "consteval-only expressions" }
-  ^^void; // { dg-error "consteval-only expressions" }
-  ^^int == ^^int; // { dg-error "consteval-only expressions" }
-  (void) ^^float; // { dg-error "consteval-only expressions" }
-  auto rr = r; // { dg-error "consteval-only variable" }
+  r2; // { dg-error "consteval-only value" }
+  ^^void; // { dg-error "consteval-only value" }
+  ^^int == ^^int; // { dg-error "consteval-only value" }
+  (void) ^^float; // { dg-error "consteval-only value" }
+  auto rr = r2; // { dg-error "consteval-only value" }
 
   constexpr auto x = &(^^int); // { dg-error "lvalue required" }
 
@@ -28,7 +28,7 @@ f1 ()
 constexpr void
 f2 ()
 {
-  auto r = ^^int; // { dg-error "consteval-only variable" }
+  auto r = ^^int; // { dg-error "consteval-only value" }
 }
 
 void
diff --git a/gcc/testsuite/g++.dg/reflect/type_trait19.C 
b/gcc/testsuite/g++.dg/reflect/type_trait19.C
new file mode 100644
index 000000000000..3a09edec7ff8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/type_trait19.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+// Test reflection type traits [meta.reflection.traits], type properties.
+
+#include <meta>
+using namespace std::meta;
+
+using U = std::meta::info;
+using A = U[5];
+struct S { std::meta::info i; };
+
+static_assert (!has_unique_object_representations (^^std::meta::info));
+static_assert (!has_unique_object_representations (^^U));
+static_assert (!has_unique_object_representations (^^S));
+static_assert (!has_unique_object_representations (^^A));
diff --git a/gcc/testsuite/g++.dg/reflect/typeinfo1.C 
b/gcc/testsuite/g++.dg/reflect/typeinfo1.C
new file mode 100644
index 000000000000..baf3025a1731
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/typeinfo1.C
@@ -0,0 +1,7 @@
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <typeinfo>
+
+const std::type_info &ti = typeid(decltype(^^int));
+int main () {}
diff --git a/gcc/testsuite/g++.dg/reflect/value1.C 
b/gcc/testsuite/g++.dg/reflect/value1.C
new file mode 100644
index 000000000000..1d6d7d59098a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/value1.C
@@ -0,0 +1,543 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection -g" }
+
+using info = decltype(^^::);
+using size_t = decltype (sizeof 0);
+void *operator new (size_t, void *);
+
+consteval int imm_fn() { return 42; }
+constexpr int not_imm_fn() { return 42; }
+int fn();
+auto id (info i) { return i; }
+
+struct S { info r; };
+struct DS : S { int i; };
+constexpr DS cds{ { ^^int }, 0 };
+DS dsn{ { info{} }, 0 };
+DS ds{ { ^^int }, 0 }; // { dg-error "initialized with a consteval-only value" 
}
+auto basep1 = (S *) &cds; // { dg-error "initialized with a consteval-only 
value" }
+constexpr auto basep2 = (S *) &cds;
+
+struct O { consteval int f() const { return 1; } };
+auto pm1 = &O::f;            // { dg-error "address of an immediate function" }
+constexpr auto pm2 = &O::f;   // { dg-bogus "returns address" "" { xfail *-*-* 
} }
+
+struct C {
+  info r;
+  constexpr C(info x) : r(x) {}
+};
+constexpr C c1(^^int);
+C c2(info{});
+C c3(^^int);           // { dg-error "initialized with a consteval-only value" 
}
+
+struct CB : C {
+  constexpr CB(info x) : C(x) {}
+};
+constexpr CB cb1(^^int);
+CB cb2(info{});
+CB cb3(^^int);         // { dg-error "initialized with a consteval-only value" 
}
+
+struct Deleg {
+  info r;
+  constexpr Deleg() : Deleg(info{}) {}
+  constexpr Deleg(info x) : r(x) {}
+};
+constexpr Deleg cdlg{};
+Deleg dlg{};
+
+struct N {
+  info i = ^^int;
+};
+
+struct N2 {
+  info i = ^^int;      // { dg-error "consteval-only value" }
+  constexpr N2() {}     // not immediate-escalating
+  constexpr N2(info x) : i(x) {}
+};
+constexpr N2 cn2a;
+
+struct N3 {
+  info i = ^^int;
+  consteval N3() {}
+  constexpr N3(info x) : i(x) {}
+};
+constexpr N3 cn3a;
+
+struct N4 {
+  info i = ^^int;
+  constexpr N4() = default;
+  constexpr N4(info x) : i(x) {}
+};
+constexpr N4 cn4a;
+N4 n4a;            // { dg-error "initialized with a consteval-only value" }
+
+struct N5 {
+  static constexpr info si = ^^int;
+  static info si2;
+};
+info N5::si2 = ^^int;  // { dg-error "initialized with a consteval-only value" 
}
+
+struct L {
+  static constexpr info si = info{};
+  static info si2;
+};
+info L::si2 = info{};
+
+template<typename T, typename U>
+struct V {
+  T t;
+  U u;
+};
+auto v1 = V{info{}, 42};
+constexpr auto v2 = V{^^int, 42};
+auto v3 = V{^^int, 42};          // { dg-error "initialized with a 
consteval-only value" }
+
+struct Wrapper { const info &r; };
+Wrapper w1{ ^^int };       // { dg-error "initialized with a consteval-only 
value" }
+constexpr Wrapper w2{ ^^int };
+
+info a;
+info *pa;
+info **ppa;
+S b;
+S b2{};
+
+template<typename> struct E;
+void foo (E<int> *);
+
+auto normal() -> void {
+  info c;
+  S d;
+}
+
+constexpr auto r = ^^int;
+auto e1 = ^^int; // { dg-error "initialized with a consteval-only value" }
+auto en = info{};
+
+const info &ref1 = r;      // { dg-error "initialized with a consteval-only 
value" }
+constexpr const info &ref2 = r;
+
+constexpr info arr[] = { ^^int, ^^char };
+constexpr info e5 = arr[0];
+info e6 = arr[0];    // { dg-error "initialized with a consteval-only value" }
+auto epast1 = arr + 2; // { dg-error "initialized with a consteval-only value" 
}
+constexpr auto epast2 = arr + 2;
+info narr[] = { info{}, info{} };
+info narr2[3];
+info narr3[3]{};
+
+// See PR124249.  This is OK because the initializer is constant:
+// namespace scope, (r, 42) is a constant expression -> i2 has constant
+// initialization -> the initializer is manifestly constant-evaluated
+// -> r is in an immediate function context -> we accept.
+int i1 = (^^int, 42);
+int i2 = (r, 42);
+int i3 = (info{}, 42);
+// No constant initialization, so not MCE.
+int i4 = (r, fn());    // { dg-error "initialized with a consteval-only value" 
}
+
+const int &gref = (r, 42);
+
+constexpr N cng{};
+N ng;  // { dg-error "initialized with a consteval-only value" }
+static N nsg;  // { dg-error "initialized with a consteval-only value" }
+
+constexpr const info *p = &r;
+const info *q = &r;   // { dg-error "initialized with a consteval-only value" }
+
+struct Ptr {
+  const info *p;
+};
+auto ptr1 = Ptr{ .p = nullptr };
+constexpr auto ptr2 = Ptr{ .p = &r };
+auto ptr3 = Ptr{ .p = &r };    // { dg-error "initialized with a 
consteval-only value" }
+
+struct Pair { info r; int i; };
+constexpr Pair p1 = { ^^int, 0 };
+Pair p2 = { info{}, 0 };
+Pair p3 = { ^^int, 0 };          // { dg-error "initialized with a 
consteval-only value" }
+auto [sb1, sb2] = Pair{^^int, 0}; // { dg-error "initialized with a 
consteval-only value" }
+constexpr auto [sb3, sb4] = Pair{^^int, 0};
+auto [sb5, sb6] = Pair{info{}, 0};
+
+struct Nested { Pair inner; int c; };
+auto ne = Nested{{^^int, 0}, 1};  // { dg-error "initialized with a 
consteval-only value" }
+constexpr auto cne = Nested{{^^int, 0}, 1};
+auto ne2 = Nested{{info{}, 0}, 1};
+constexpr auto cne2 = Nested{{info{}, 0}, 1};
+
+consteval auto getr () { return ^^int; }
+consteval auto getnr () { return info{}; }
+constexpr auto r1 = getr ();
+auto r2 = getnr ();
+// r3 is an object with a constituent consteval-only value
+// but is not associated with a constexpr variable.
+auto r3 = getr ();       // { dg-error "initialized with a consteval-only 
value" }
+
+union U { info r; int i; };
+// Only the active member counts here.
+constexpr U u1 = { .i = 0 };
+constexpr U u2 = { .r = ^^int };
+auto u3 = U{ .i = 0 };
+auto u4 = U{ .r = ^^int };     // { dg-error "initialized with a 
consteval-only value" }
+auto u5 = U{ .r = info{} };
+
+template<bool B>
+void
+tfn ()
+{
+  info rn = B ? info{} : ^^int;          // { dg-error "initialized with a 
consteval-only value" }
+  info ri = B ? ^^int : info{};          // { dg-error "initialized with a 
consteval-only value" }
+}
+
+template<bool B>
+constexpr void
+ctfn ()
+{
+  info rn = B ? info{} : ^^int;
+  info ri = B ? ^^int : info{};
+}
+
+template<bool B>
+void
+uninst ()
+{
+  info rn = B ? info{} : ^^int;
+  info ri = B ? ^^int : info{};
+}
+
+template<typename>
+constexpr void
+esc ()
+{
+  N n;
+}
+
+void
+dflt (info x = ^^int) // { dg-error "consteval-only value outside an immediate 
function context" }
+{
+}
+
+void
+dflt_null (info x = info{})
+{
+}
+
+consteval void
+dflt_ok (info x = ^^int)
+{
+}
+
+template<auto V> struct TC { };
+auto e7 = TC<^^int>();
+auto e7n = TC<info{}>();
+
+template<Pair> struct D { };
+auto e8 = D<Pair{^^int, 42}>();
+auto e8n = D<Pair{info{}, 42}>();
+
+void
+g (bool b)
+{
+  info null;
+  null = info();
+
+  constexpr auto lr = ^^int;
+  auto e2 = ^^int;       // { dg-error "initialized with a consteval-only 
value" }
+  auto en = info{};
+  static constexpr info sg = ^^int;
+  static info sg2 = ^^int;  // { dg-error "initialized with a consteval-only 
value" }
+  const info &lref1 = r;    // { dg-error "initialized with a consteval-only 
value" }
+  constexpr const info &lref2 = r;
+
+  // Don't accept these: the "has constant initialization" rule applies to
+  // variables at namespace scope only.
+  int e3 = (^^int, 42);            // { dg-error "initialized with a 
consteval-only value" }
+  int e4 = (r, 42);        // { dg-error "initialized with a consteval-only 
value" }
+  int e5 = (r, fn());      // { dg-error "initialized with a consteval-only 
value" }
+  // But these are static.
+  static int e6 = (^^int, 42);
+  static int e7 = (r, 42);
+  static int e8 = (r, fn());       // { dg-error "initialized with a 
consteval-only value" }
+
+  // grok_reference_init turns the init into
+  // (const int &) &D.2686 and so store_init_value won't see
+  // any consteval-only value.
+  const int &ref = (r, 42);      // { dg-error "initialized with a 
consteval-only value" "" { xfail *-*-* } }
+
+  info rn = b ? info{} : ^^int;          // { dg-error "initialized with a 
consteval-only value" }
+  info ri = b ? ^^int : info{};          // { dg-error "initialized with a 
consteval-only value" }
+
+  constexpr info larr[] = { ^^int, ^^char };
+  constexpr info le5 = arr[0];
+  info le6 = arr[0];    // { dg-error "initialized with a consteval-only 
value" }
+  info lnarr[] = { info{}, info{} };
+
+  constexpr const info *lp = &r;
+  const info *lq = &r;   // { dg-error "initialized with a consteval-only 
value" }
+
+  constexpr C lc1(^^int);
+  C lc2(info{});
+  C lc3(^^int);                // { dg-error "initialized with a 
consteval-only value" }
+
+  constexpr CB lcb1(^^int);
+  CB lcb2(info{});
+  CB lcb3(^^int);              // { dg-error "initialized with a 
consteval-only value" }
+
+  Wrapper lw1{ ^^int };            // { dg-error "initialized with a 
consteval-only value" }
+  // w2 at block scope has this initializer:
+  // {.r=(<<< Unknown tree: lang_type >>> &) &_ZGRL2w2_}
+  // which is reduced_constant_expression_p but here we have
+  // {.r=(<<< Unknown tree: lang_type >>> &) &D.2718}
+  // which is not reduced_constant_expression_p.  The error
+  // also happens without reflection:
+  // struct W { const int &r; }
+  // void h () { constexpr W lw{42}; }
+  constexpr Wrapper lw2{ ^^int }; // { dg-error "not a constant expression" }
+
+  constexpr N lcng{};
+  N lng;       // { dg-error "initialized with a consteval-only value" }
+
+  constexpr Pair p4 = { ^^int, 0 };
+  Pair p5 = { info{}, 0 };
+  Pair p6 = { ^^int, 0 };        // { dg-error "initialized with a 
consteval-only value" }
+  auto [lsb1, lsb2] = Pair{^^int, 0}; // { dg-error "initialized with a 
consteval-only value" }
+  constexpr auto [lsb3, lsb4] = Pair{^^int, 0};
+  auto [lsb5, lsb6] = Pair{info{}, 0};
+
+  auto lptr1 = Ptr{ .p = nullptr };
+  constexpr auto lptr2 = Ptr{ .p = &r };
+  auto lptr3 = Ptr{ .p = &r };    // { dg-error "initialized with a 
consteval-only value" }
+
+  auto lne = Nested{{^^int, 0}, 1};  // { dg-error "initialized with a 
consteval-only value" }
+  constexpr auto lcne = Nested{{^^int, 0}, 1};
+  auto lne2 = Nested{{info{}, 0}, 1};
+  constexpr auto lcne2 = Nested{{info{}, 0}, 1};
+
+  constexpr DS lcds{ { ^^int }, 0 };
+  DS ldsn{ { info{} }, 0 };
+  DS lds{ { ^^int }, 0 };      // { dg-error "initialized with a 
consteval-only value" }
+  auto lbasep1 = (S *) &cds; // { dg-error "initialized with a consteval-only 
value" }
+  constexpr auto lbasep2 = (S *) &cds;
+
+  constexpr U lu1 = { .i = 0 };
+  constexpr U lu2 = { .r = ^^int };
+  auto lu3 = U{ .i = 0 };
+  auto lu4 = U{ .r = ^^int };  // { dg-error "initialized with a 
consteval-only value" }
+  auto lu5 = U{ .r = info{} };
+
+  constexpr auto lr1 = getr ();
+  auto lr2 = getnr ();
+  auto lr3 = getr ();    // { dg-error "initialized with a consteval-only 
value" }
+
+  // We think that [expr.const.imm]/2 gives us the rationale for
+  // rejecting this code, even though r isn't ODR-used here.
+  ^^int;  // { dg-error "consteval-only value outside an immediate function 
context" }
+  r;     // { dg-error "consteval-only value outside an immediate function 
context" }
+  (^^int, true);  // { dg-error "consteval-only value outside an immediate 
function context" }
+  (r, true);     // { dg-error "consteval-only value outside an immediate 
function context" }
+  lr;    // { dg-error "consteval-only value outside an immediate function 
context" }
+
+  a = info();
+  a = ^^int; // { dg-error "consteval-only value outside an immediate function 
context" }
+  a = r; // { dg-error "consteval-only value outside an immediate function 
context" }
+
+  a == a;
+  a == ^^int; // { dg-error "consteval-only value outside an immediate 
function context" }
+  ^^int != info{};  // { dg-error "consteval-only value outside an immediate 
function context" }
+  ^^int == ^^int;   // { dg-error "consteval-only value outside an immediate 
function context" }
+  constexpr bool b1 = ^^int != info{};
+  constexpr bool b2 = ^^int == ^^int;
+
+  a == r; // { dg-error "consteval-only value outside an immediate function 
context" }
+
+  constexpr N cln;
+  N ln;        // { dg-error "initialized with a consteval-only value" }
+
+  new (&a) info();
+  new (&a) info(^^int); // { dg-error "consteval-only value outside an 
immediate function context" }
+  new info(info{});
+  new info(^^int);     // { dg-error "consteval-only value outside an 
immediate function context" }
+
+  S{};
+  S{.r={}};
+  S{.r=^^int}; // { dg-error "consteval-only value outside an immediate 
function context" }
+
+  auto lam = [] { info l = ^^int; };
+  lam ();
+
+  auto lam2 = [] { return ^^int; };
+  auto e9 = lam2 ();   // { dg-error "initialized with a consteval-only value" 
}
+  constexpr auto e10 = lam2 ();
+  constexpr auto lam3 = [i = ^^int]{ return i; };
+  auto lam4 = [i = ^^int]{ return i; };        // { dg-error "initialized with 
a consteval-only value" }
+  auto lam5 = [lr]{ return lr; };      // { dg-error "initialized with a 
consteval-only value" }
+  constexpr auto lam6 = [lr]{ return lr; };
+
+  if consteval {
+    auto ifc = ^^int;
+  }
+
+  auto x1 = imm_fn ();
+  auto x2 = []() consteval { return ^^int; }();  // { dg-error "initialized 
with a consteval-only value" }
+
+  id (null);
+  id (^^int);  // { dg-error "consteval-only value outside an immediate 
function context" }
+  dflt ();
+  dflt_null ();
+  dflt_ok ();
+  tfn<true>();
+  ctfn<true>();
+  esc<int>();
+}
+
+consteval void
+ceg (bool b)
+{
+  info null;
+  null = info();
+
+  constexpr auto lr = ^^int;
+  auto e2 = ^^int;
+  static constexpr info sg = ^^int;
+  static info sg2 = ^^int;
+  const info &lref1 = r;
+  constexpr const info &lref2 = r;
+
+  int e3 = (^^int, 42);
+  int e4 = (r, 42);
+  int e5 = (r, fn());
+  static int e6 = (^^int, 42);
+  static int e7 = (r, 42);
+  static int e8 = (r, fn());
+
+  const int &ref = (r, 42);
+
+  info rn = b ? info{} : ^^int;
+  info ri = b ? ^^int : info{};
+
+  constexpr info larr[] = { ^^int, ^^char };
+  constexpr info le5 = arr[0];
+  info le6 = arr[0];
+  info lnarr[] = { info{}, info{} };
+
+  constexpr const info *lp = &r;
+  const info *lq = &r;
+
+  constexpr C lc1(^^int);
+  C lc2(info{});
+  C lc3(^^int);
+
+  constexpr CB lcb1(^^int);
+  CB lcb2(info{});
+  CB lcb3(^^int);
+
+  Wrapper lw1{ ^^int };
+
+  constexpr N lcng{};
+  N lng;
+
+  constexpr Pair p4 = { ^^int, 0 };
+  Pair p5 = { info{}, 0 };
+  Pair p6 = { ^^int, 0 };
+  auto [lsb1, lsb2] = Pair{^^int, 0};
+  constexpr auto [lsb3, lsb4] = Pair{^^int, 0};
+  auto [lsb5, lsb6] = Pair{info{}, 0};
+
+  auto lptr1 = Ptr{ .p = nullptr };
+  constexpr auto lptr2 = Ptr{ .p = &r };
+  auto lptr3 = Ptr{ .p = &r };
+
+  auto lne = Nested{{^^int, 0}, 1};
+  constexpr auto lcne = Nested{{^^int, 0}, 1};
+  auto lne2 = Nested{{info{}, 0}, 1};
+  constexpr auto lcne2 = Nested{{info{}, 0}, 1};
+
+  constexpr DS lcds{ { ^^int }, 0 };
+  DS ldsn{ { info{} }, 0 };
+  DS lds{ { ^^int }, 0 };
+  auto lbasep1 = (S *) &cds;
+  constexpr auto lbasep2 = (S *) &cds;
+
+  constexpr U lu1 = { .i = 0 };
+  constexpr U lu2 = { .r = ^^int };
+  auto lu3 = U{ .i = 0 };
+  auto lu4 = U{ .r = ^^int };
+  auto lu5 = U{ .r = info{} };
+
+  constexpr auto lr1 = getr ();
+  auto lr2 = getnr ();
+  auto lr3 = getr ();
+
+  ^^int;
+  r;
+  lr;
+  (^^int, true);
+  (r, true);
+
+  a = info();
+  a = ^^int;
+  a = r;
+
+  a == a;
+  a == ^^int;
+  ^^int != info{};
+  ^^int == ^^int;
+  constexpr bool b1 = ^^int != info{};
+  constexpr bool b2 = ^^int == ^^int;
+
+  a == r;
+
+  constexpr N cln;
+  N ln;
+
+  new (&a) info();
+  new (&a) info(^^int);
+  new info(info{});
+  new info(^^int);
+
+  S{};
+  S{.r={}};
+  S{.r=^^int};
+
+  auto lam = [] { info l = ^^int; };
+  lam ();
+
+  auto lam2 = [] { return ^^int; };
+  auto e9 = lam2 ();
+  constexpr auto e10 = lam2 ();
+  constexpr auto lam3 = [i = ^^int]{ return i; };
+  auto lam4 = [i = ^^int]{ return i; };
+  auto lam5 = [lr]{ return lr; };
+  constexpr auto lam6 = [lr]{ return lr; };
+
+  if consteval {
+    auto ifc = ^^int;
+  }
+
+  auto x1 = imm_fn ();
+  auto x2 = []() consteval { return ^^int; }();
+
+  id (null);
+  id (^^int);
+}
+
+constexpr void
+cg (bool b)
+{
+  int e3 = (^^int, 42);            // { dg-error "initialized with a 
consteval-only value" }
+  int e4 = (r, 42);        // { dg-error "initialized with a consteval-only 
value" }
+  int e5 = (r, fn());      // { dg-error "initialized with a consteval-only 
value" }
+  static int e6 = (^^int, 42);
+  static int e7 = (r, 42);
+  static int e8 = (r, fn());       // { dg-error "initialized with a 
consteval-only value" }
+
+  info rn = b ? info{} : ^^int;        // { dg-error "initialized with a 
consteval-only value" }
+  info ri = b ? ^^int : info{};        // { dg-error "initialized with a 
consteval-only value" }
+
+  constexpr auto lr1 = getr ();
+  auto lr2 = getnr ();
+  auto lr3 = getr ();    // { dg-error "consteval-only value" }
+}
diff --git a/gcc/testsuite/g++.dg/reflect/value2.C 
b/gcc/testsuite/g++.dg/reflect/value2.C
new file mode 100644
index 000000000000..1c73055acf76
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/value2.C
@@ -0,0 +1,32 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+using info = decltype(^^::);
+
+// [expr.const.const]
+
+consteval int plus1(int x) { return x + 1; }
+template <auto V> struct C { };
+
+auto a = plus1; // { dg-error "taking address of an immediate function" }
+constexpr auto b = plus1; // // { dg-bogus "returns address" "" { xfail *-*-* 
} } OK
+auto c = C<plus1>(); // OK
+
+auto d = ^^int; // { dg-error "initialized with a consteval-only value" }
+auto e = C<^^char>(); // OK
+
+// [expr.const.imm]
+
+consteval info refl() { return ^^int; }
+template <auto F>
+constexpr void ex() {
+  auto x = F();
+}
+auto p = &ex<refl>; // { dg-error "taking address of an immediate function" }
+
+consteval int id(int x) { return x; }
+template <auto F>
+constexpr auto apply_to(int i) { return F(i); }
+auto q = &apply_to<id>; // { dg-error "taking address of an immediate 
function" }
diff --git a/gcc/testsuite/g++.dg/reflect/value3.C 
b/gcc/testsuite/g++.dg/reflect/value3.C
new file mode 100644
index 000000000000..07589afa9726
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/value3.C
@@ -0,0 +1,63 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection -g" }
+
+using info = decltype(^^::);
+
+struct A { info i; };
+struct B : A { };
+struct C { A a; };
+struct D { info i1, i2, i3; };
+struct E { C c; info i; };
+struct F { A a[10]; };
+struct G { info i = info{}; };
+
+A a1 = { info{} };
+A a2{ info{} };
+B b1 = { info{} };
+B b2{ info{} };
+C c1 = { { info{} } };
+C c2{ { info{} } };
+D d1 = { info{}, info{}, info{} };
+D d2{ info{}, info{}, info{} };
+E e1 = { { { info{} } }, info{} };
+E e2{ { { info{} } }, info{} };
+F f1 = { { { info{} }, { info{} } } };
+F f2{ { { info{} }, { info{} } } };
+G g1{};
+G g2;
+
+void
+fn ()
+{
+  A la1 = { info{} };
+  A la2{ info{} };
+  B lb1 = { info{} };
+  B lb2{ info{} };
+  C lc1 = { { info{} } };
+  C lc2{ { info{} } };
+  D ld1 = { info{}, info{}, info{} };
+  D ld2{ info{}, info{}, info{} };
+  E le1 = { { { info{} } }, info{} };
+  E le2{ { { info{} } }, info{} };
+  F lf1 = { { { info{} }, { info{} } } };
+  F lf2{ { { info{} }, { info{} } } };
+  G lg1{};
+  G lg2;
+
+  static A sa1 = { info{} };
+  static A sa2{ info{} };
+  static B sb1 = { info{} };
+  static B sb2{ info{} };
+  static C sc1 = { { info{} } };
+  static C sc2{ { info{} } };
+  static D sd1 = { info{}, info{}, info{} };
+  static D sd2{ info{}, info{}, info{} };
+  static E se1 = { { { info{} } }, info{} };
+  static E se2{ { { info{} } }, info{} };
+  static F sf1 = { { { info{} }, { info{} } } };
+  static F sf2{ { { info{} }, { info{} } } };
+  static G sg1{};
+  static G sg2;
+}
diff --git a/gcc/testsuite/g++.dg/reflect/value4.C 
b/gcc/testsuite/g++.dg/reflect/value4.C
new file mode 100644
index 000000000000..26ba9a9d3710
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/value4.C
@@ -0,0 +1,24 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+using info = decltype(^^::);
+
+struct V { int a, b, c; };
+constexpr info varr[] = { ^^V::a, ^^V::b, ^^V::c };
+constexpr const info *p = varr;
+static_assert (p[0] == ^^V::a);
+static_assert (p[1] == ^^V::b);
+static_assert (p[2] == ^^V::c);
+static_assert (varr[0] == ^^V::a);
+
+constexpr info arr[] = { ^^int, ^^double };
+auto q = &arr[0]; // { dg-error ".q. is initialized with a consteval-only 
value but is not declared .constexpr." }
+
+void
+fn ()
+{
+  auto r = arr; // { dg-error ".r. is initialized with a consteval-only value 
but is not declared .constexpr." }
+  (void) r;
+}
diff --git a/gcc/testsuite/g++.dg/reflect/value5.C 
b/gcc/testsuite/g++.dg/reflect/value5.C
new file mode 100644
index 000000000000..9dec04e7247d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/value5.C
@@ -0,0 +1,40 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+using info = decltype(^^::);
+
+struct S
+{
+  info i;
+  int n;
+};
+
+constexpr info arr[] = { ^^int, ^^double, ^^char };
+constexpr S s = { ^^int, 42 };
+constexpr S sarr[2] = { { ^^int, 1 }, { ^^double, 2 } };
+constexpr const info *p = arr;
+
+// These check check_out_of_consteval_use which uses a tree walk
+// on its expr.  value6.C checks consteval_only_p not used in
+// a tree walk.
+const void *vp = &p;             // { dg-error "initialized with a 
consteval-only value" }
+
+const auto p1 = &arr[0];         // { dg-error "initialized with a 
consteval-only value" }
+const auto p2 = arr;     // { dg-error "initialized with a consteval-only 
value" }
+const auto p3 = arr + 1;         // { dg-error "initialized with a 
consteval-only value" }
+const auto p4 = arr + 3;         // { dg-error "initialized with a 
consteval-only value" }
+const auto p5 = &s;              // { dg-error "initialized with a 
consteval-only value" }
+const auto p6 = &s.i;    // { dg-error "initialized with a consteval-only 
value" }
+const auto p7 = &sarr[1];        // { dg-error "initialized with a 
consteval-only value" }
+const auto p8 = &sarr[1].i;      // { dg-error "initialized with a 
consteval-only value" }
+
+struct Holder { const info *p; int n; };
+auto h = Holder{ &arr[0], 1 };   // { dg-error "initialized with a 
consteval-only value" }
+
+constexpr bool cond = true;
+const auto p_cond = cond ? &arr[0] : &arr[1];    // { dg-error "initialized 
with a consteval-only value" }
+
+// Not an error.
+auto pdm = &S::i;
diff --git a/gcc/testsuite/g++.dg/reflect/value6.C 
b/gcc/testsuite/g++.dg/reflect/value6.C
new file mode 100644
index 000000000000..4bff1b81179e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/value6.C
@@ -0,0 +1,41 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+using info = decltype(^^::);
+
+struct S
+{
+  info i;
+  int n;
+};
+
+constexpr info arr[] = { ^^int, ^^double, ^^char };
+constexpr S s = { ^^int, 42 };
+constexpr S sarr[2] = { { ^^int, 1 }, { ^^double, 2 } };
+constexpr const info *p = arr;
+
+constexpr const void *vp = &p;
+
+// This tests that consteval_only_value_p properly detects
+// consteval-only values when they are in ADDR_EXPR, POINTER_PLUS_EXPR,
+// ARRAY_REF, and similar.  A failure would result in a link error.
+constexpr const auto p1 = &arr[0];
+constexpr const auto p2 = arr;
+constexpr const auto p3 = arr + 1;
+constexpr const auto p4 = arr + 3;
+constexpr const auto p5 = &s;
+constexpr const auto p6 = &s.i;
+constexpr const auto p7 = &sarr[1];
+constexpr const auto p8 = &sarr[1].i;
+
+constexpr bool cond = true;
+constexpr auto p_cond = cond ? &arr[0] : &arr[1];
+
+struct Holder { const info *p; int n; };
+constexpr Holder h = { &arr[0], 1 };
+
+constexpr auto cpdm = &S::i;
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/reflect/value7.C 
b/gcc/testsuite/g++.dg/reflect/value7.C
new file mode 100644
index 000000000000..8b5e2434eae9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/value7.C
@@ -0,0 +1,52 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-freflection" }
+// Like value6.C, but with function-local static.
+
+using info = decltype(^^::);
+
+struct S
+{
+  info i;
+  int n;
+};
+struct Holder { const info *p; int n; };
+
+void
+g ()
+{
+  constexpr static info arr[] = { ^^int, ^^double, ^^char };
+  constexpr static S s = { ^^int, 42 };
+  constexpr static S sarr[2] = { { ^^int, 1 }, { ^^double, 2 } };
+  constexpr static const info *p = arr;
+
+  constexpr const void *vp = &p;
+  constexpr const auto p1 = &arr[0];
+  constexpr const auto p2 = arr;
+  constexpr const auto p3 = arr + 1;
+  constexpr const auto p4 = arr + 3;
+  constexpr const auto p5 = &s;
+  constexpr const auto p6 = &s.i;
+  constexpr const auto p7 = &sarr[1];
+  constexpr const auto p8 = &sarr[1].i;
+  constexpr bool cond = true;
+  constexpr auto p_cond = cond ? &arr[0] : &arr[1];
+  constexpr Holder h = { &arr[0], 1 };
+  constexpr auto cpdm = &S::i;
+
+  constexpr static const void *svp = &p;
+  constexpr static const auto sp1 = &arr[0];
+  constexpr static const auto sp2 = arr;
+  constexpr static const auto sp3 = arr + 1;
+  constexpr static const auto sp4 = arr + 3;
+  constexpr static const auto sp5 = &s;
+  constexpr static const auto sp6 = &s.i;
+  constexpr static const auto sp7 = &sarr[1];
+  constexpr static const auto sp8 = &sarr[1].i;
+  constexpr static auto sp_cond = cond ? &arr[0] : &arr[1];
+  constexpr static Holder sh = { &arr[0], 1 };
+  constexpr static auto scpdm = &S::i;
+}
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/reflect/value8.C 
b/gcc/testsuite/g++.dg/reflect/value8.C
new file mode 100644
index 000000000000..fe895c190ff7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/value8.C
@@ -0,0 +1,64 @@
+// PR c++/125820
+// P4101R1, Consteval-only Values for C++26
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+using info = decltype(^^int);
+
+void
+uneval ()
+{
+  auto a = sizeof(^^int);
+  auto b = alignof (decltype (^^int));
+  auto c = noexcept (^^int == ^^void);
+  auto d = sizeof (info);
+  auto e = requires { ^^int; };
+  __extension__ using U = decltype (({ ^^int; }));
+}
+
+void
+discarded ()
+{
+  (void) ^^int;                                        // { dg-error 
"consteval-only" }
+  static_cast<void> (^^int);                   // { dg-error "consteval-only" }
+  ^^int;                                       // { dg-error "consteval-only" }
+  ^^int, 42;                                   // { dg-error "consteval-only" }
+  auto b1 = (^^int, 42);                       // { dg-error "consteval-only" }
+  auto b2 = (42, ^^int);                       // { dg-error "consteval-only" }
+  __extension__ auto b3 = ({ (^^int, 42); });  // { dg-error "consteval-only" }
+  __extension__ auto b4 = ({ (42, ^^int); });  // { dg-error "consteval-only" }
+  auto b5 = (^^int == ^^void, 42);             // { dg-error "consteval-only" }
+}
+
+void
+stmt_exprs (bool cond)
+{
+  __extension__ auto c1 = ({ ^^int; 42; });                    // { dg-error 
"consteval-only" }
+  __extension__ auto c2 = ({ 42; ^^int; });                    // { dg-error 
"consteval-only" }
+  __extension__ auto c3 = ({ ({ ^^int; }); });                 // { dg-error 
"consteval-only" }
+  __extension__ auto c4 = ({ ({ ^^int; }); 42; });             // { dg-error 
"consteval-only" }
+  __extension__ auto c5 = ({ if (cond) ; ^^int; });            // { dg-error 
"consteval-only" }
+  __extension__ auto c6 = ({ if (cond) (void) ^^int; 42; });   // { dg-error 
"consteval-only" }
+  __extension__ auto c7 = ({ while (0) { ^^int; } 42; });      // { dg-error 
"consteval-only" }
+  __extension__ auto c8 = ({ for (int i = 0; i < 2; ++i) { ^^int; } 42; });    
// { dg-error "consteval-only" }
+  __extension__ auto c9 = ({ switch (cond) { case 0: ^^int; } 42; });          
// { dg-error "consteval-only" }
+  __extension__ auto c10 = ({ info x = ^^int; 42; });          // { dg-error 
"consteval-only" }
+  __extension__ auto c11 = ({ constexpr info x = ^^int; 42; });
+  __extension__ auto c12 = ({ constexpr info x = ^^int; x == ^^void; });       
// { dg-error "consteval-only" }
+  __extension__ auto c13 = ({ constexpr info x = ^^int; x; }); // { dg-error 
"consteval-only" }
+  __extension__ auto c14 = ({ cond ? ^^int : ^^void; });       // { dg-error 
"consteval-only" }
+  __extension__ auto c15 = ({ true ? ^^int : ^^void; });       // { dg-error 
"consteval-only" }
+  __extension__ auto c16 = ({ int i = 0; i; });
+  __extension__ auto c17 = ({ ^^int; });                       // { dg-error 
"consteval-only" }
+  __extension__ constexpr auto c18 = ({ ^^int; });
+  __extension__ constexpr bool c19 = ({ ^^int == ^^void; });
+  __extension__ auto c20 = ({ [] { return ^^int == ^^void; } (); });
+  __extension__ auto c21 = ({ struct S { info r; }; S{}.r; });
+  __extension__ auto c22 = ({ using U = info; U{}; });
+  __extension__ auto c23 = ({ using U = decltype(^^int); U{}; });
+  __extension__ auto c24 = ({ using U = decltype(^^int); U u = ^^int; u; });   
// { dg-error "consteval-only" }
+  __extension__ auto c25 = ({ if constexpr (false) ^^int; 42; });
+  __extension__ auto c26 = ({ if constexpr (true) ^^int; 42; });               
// { dg-error "consteval-only" }
+  __extension__ auto c27 = ({ if consteval { 42; } else { ^^int; } 42; });     
// { dg-error "consteval-only" }
+  __extension__ auto c28 = ({ if ! consteval { 42; } else { ^^int; } 42; });
+}
diff --git a/gcc/testsuite/g++.dg/reflect/vector2.C 
b/gcc/testsuite/g++.dg/reflect/vector2.C
new file mode 100644
index 000000000000..31e8e24aa653
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/vector2.C
@@ -0,0 +1,26 @@
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-freflection" }
+// No use of Reflection in this test, but it crashed with Reflection
+// enabled.
+
+#include <vector>
+#include <ranges>
+
+using VVI = std::vector<std::vector<int>>;
+using JV = decltype (std::views::join (std::declval<VVI> ()));
+
+static_assert (std::ranges::input_range<JV>);
+static_assert (std::ranges::forward_range<JV>);
+
+int
+main ()
+{
+  VVI vv { { 1, 2 }, { 3, 4, 5 } };
+  int n = 0;
+  for (auto &elt : vv | std::views::join)
+    {
+      (void) elt;
+      ++n;
+    }
+  return n == 5 ? 0 : 1;
+}
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 69a7c7e6d34d..db3713c2f1b8 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -1860,6 +1860,8 @@ wide_int_to_tree_1 (tree type, const wide_int_ref &pcst)
 
       switch (code)
        {
+       /* This could represent the C++ std::meta::info type.  */
+       case LANG_TYPE:
        case NULLPTR_TYPE:
          gcc_assert (hwi == 0);
          /* Fallthru.  */
@@ -2035,6 +2037,8 @@ cache_integer_cst (tree t, bool might_duplicate 
ATTRIBUTE_UNUSED)
      wide_int_to_type_1.  */
   switch (TREE_CODE (type))
     {
+    /* This could represent the C++ std::meta::info type.  */
+    case LANG_TYPE:
     case NULLPTR_TYPE:
       gcc_checking_assert (integer_zerop (t));
       /* Fallthru.  */
diff --git a/libstdc++-v3/include/std/meta b/libstdc++-v3/include/std/meta
index bc04dddcb649..3b49a17ad223 100644
--- a/libstdc++-v3/include/std/meta
+++ b/libstdc++-v3/include/std/meta
@@ -113,7 +113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       consteval exception& operator=(const exception&) = default;
       consteval exception& operator=(exception&&) = default;
 
-      consteval const char*
+      constexpr const char*
       what() const noexcept override
       {
        // If u8string is not empty and string is empty, conversion

Reply via email to