get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.0/patches/2175266/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2175266,
    "url": "http://patchwork.ozlabs.org/api/1.0/patches/2175266/?format=api",
    "project": {
        "id": 17,
        "url": "http://patchwork.ozlabs.org/api/1.0/projects/17/?format=api",
        "name": "GNU Compiler Collection",
        "link_name": "gcc",
        "list_id": "gcc-patches.gcc.gnu.org",
        "list_email": "gcc-patches@gcc.gnu.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null
    },
    "msgid": "<aULeb0hfGZPbJj19@redhat.com>",
    "date": "2025-12-17T16:46:39",
    "name": "[3/9,v2] c++: C++26 Reflection [PR120775]",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "67e78771330daa2c4d9e51c67bf81b8146366844",
    "submitter": {
        "id": 14370,
        "url": "http://patchwork.ozlabs.org/api/1.0/people/14370/?format=api",
        "name": "Marek Polacek",
        "email": "polacek@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/aULeb0hfGZPbJj19@redhat.com/mbox/",
    "series": [
        {
            "id": 485726,
            "url": "http://patchwork.ozlabs.org/api/1.0/series/485726/?format=api",
            "date": "2025-12-17T16:42:41",
            "name": "c++: C++26 Reflection [PR120775]",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/485726/mbox/"
        }
    ],
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2175266/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=Jir/ZA4W;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=Jir/ZA4W",
            "sourceware.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com",
            "sourceware.org; spf=pass smtp.mailfrom=redhat.com",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=170.10.133.124"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org [38.145.34.32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dWfqz46Tjz1xty\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 18 Dec 2025 03:48:15 +1100 (AEDT)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 5101C4BA23E7\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 17 Dec 2025 16:48:13 +0000 (GMT)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by sourceware.org (Postfix) with ESMTP id A162E4BA2E1E\n for <gcc-patches@gcc.gnu.org>; Wed, 17 Dec 2025 16:46:51 +0000 (GMT)",
            "from mail-qv1-f69.google.com (mail-qv1-f69.google.com\n [209.85.219.69]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-570-V8Wgx4QrMneDw-C3cnyuLQ-1; Wed, 17 Dec 2025 11:46:49 -0500",
            "by mail-qv1-f69.google.com with SMTP id\n 6a1803df08f44-88a3822c06bso88424876d6.2\n for <gcc-patches@gcc.gnu.org>; Wed, 17 Dec 2025 08:46:48 -0800 (PST)",
            "from redhat.com ([2603:7000:9500:10::1db4])\n by smtp.gmail.com with ESMTPSA id\n 6a1803df08f44-8899ea3621bsm98502556d6.36.2025.12.17.08.46.40\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 17 Dec 2025 08:46:40 -0800 (PST)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org 5101C4BA23E7",
            "OpenDKIM Filter v2.11.0 sourceware.org A162E4BA2E1E"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org A162E4BA2E1E",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org A162E4BA2E1E",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1765990011; cv=none;\n b=xBUWcNFxUdGqx6BLI2euUYMFXYXYCcDHh3iZIOp0VZRnZT4wVyehKubjlIYSTyeIHlPMeZWHKTzSyTmX7ZrbVDx+q6cVGhOotWSEHXmQuMJVljndd+855y9neYMBjJ/SWUGe6e0SpXeyiGdrmzsHJhSCKlAsQGctC0qKQrkHQ4g=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1765990011; c=relaxed/simple;\n bh=WChuXVwYqSAVPALUIyItmCDBZDDIrAf4262wUBK3rTQ=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=EDj0uxMaSJlap+FaqrEpGvvmBFDznr8ytFw3HLOxOantglyA5LsxjiwYUqgcBWPRZb19vFKp9boWp6MS6+jQTG90JFxSFyTLFtUKEdyTkrXJfOBsX8egRdIVKd6Z3KAuXO5GVoJ4b1u5LNBnnbMeCgIt9LcmJbJzCuNAE4bAjz8=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1765990011;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:content-type:content-type:\n in-reply-to:in-reply-to:references:references;\n bh=2ctuuHUTvF4jnthJmtWJ9n7iT7jRq8v0WLKAM+LAXes=;\n b=Jir/ZA4WY0GIatQEsDANPO4Gm+zyfhxEpxKtxjffIItNkWv89y7HAVMcwJ8UKPF990m7+y\n koVBbQ3nojp3YM6EURhGoc0FWnjgVlKTRVrIV0ve0SaFnGCxEyHDsJUjmJy9eCvsaHgtZ1\n 3MziHMspmFVktRG/iaCr2vkdV+T8LDs=",
        "X-MC-Unique": "V8Wgx4QrMneDw-C3cnyuLQ-1",
        "X-Mimecast-MFC-AGG-ID": "V8Wgx4QrMneDw-C3cnyuLQ_1765990008",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1765990007; x=1766594807;\n h=user-agent:in-reply-to:content-disposition:mime-version:references\n :message-id:subject:to:from:date:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=2ctuuHUTvF4jnthJmtWJ9n7iT7jRq8v0WLKAM+LAXes=;\n b=k0f4cYedZKI2KAae9tn+0bLoVrMI5Hiiqt9EawV5QDFIEuIE+d9hU9Q62xVToYZ13w\n UVTYFMuaaPPEiJT0wyFDsuVOuqvI9m/BPWDoKiZhEAnvJfckQ3iXUMYzT3WZNnHIPNra\n Hf06J0wXvKLvQw3K8u5/u/qEijFiD+GrzUO27hsTg8ZlB2Lu/7modx9m5rVlb1jv3VHl\n MjiOskZ+Pvr+vMeZ8yrrx0Qr1CtEoxKITCT9Kz0hxNIH1pOe2tRySPHK1QEevKTfvGaa\n TUCZwgSh8KRuti6n+Lh+HxB1oTB2d9617IInvVCChNlMlk4LQ+Vf4mhvZYWwZDLXAPcs\n 3qmw==",
        "X-Gm-Message-State": "AOJu0Yx0SP/WlqgBZJzJkTMAM+5PiEuZsqM4Gia+Hqt9f2rGwV0wafzH\n uZQ1d7SD70X/frHwb9nVlrryZCDRXW6W06xzEpiRhSR/+Mol1Kf4SMqap/yVLiENuiOd/5+L+IW\n Di5J8GIQ4DgXIJVdi75bHvur1IfzTro+e1a8PX2I4kVS4mWJroKoc6WK9KzcpzSUE3ys0OhvhuO\n EYjMat2IO/wq/Utp+qG8SAYK93HD+w8UzkCjBxImnz/A==",
        "X-Gm-Gg": "AY/fxX5yYkp67jEnE8EJbVQ181uKJrtbRG/qs563Enc3fElx+QdV2mIQ2mFzbfPGugl\n MuMnNw9ulAnpWVO6TqK8NmwApXZKL5gFjSm+fu/FUKqBECbRsCDmEtOSQIe4MizvosB4zvUe/SJ\n GuZE/bRbJCGI83AHcKYpqyKjlG+BXr7/QojokOk/tCZQdQffNQqfEWXfJ4r0+v+mK7Hlk1boSiA\n YwgDRpziBnzpDvbpx7FLXhPrxzTbAeI+J4rANao9UTB9hq2cE0nTyGKFhAcXpd07Lf6zTbFLGy9\n sMgzhbEuJhPy0dHYHn+L8K9tlgqtAUbsgRrhMpIOYG2oxggIAzk0IDyP3SsYAJBbaA==",
        "X-Received": [
            "by 2002:a05:6214:766:b0:882:437d:282d with SMTP id\n 6a1803df08f44-8887e0454c6mr272075796d6.30.1765990004552;\n Wed, 17 Dec 2025 08:46:44 -0800 (PST)",
            "by 2002:a05:6214:766:b0:882:437d:282d with SMTP id\n 6a1803df08f44-8887e0454c6mr272074096d6.30.1765990002330;\n Wed, 17 Dec 2025 08:46:42 -0800 (PST)"
        ],
        "X-Google-Smtp-Source": "\n AGHT+IEKXYa0I+VHPIftTDVA5F+ZufgxL/FGLRPf5sx2uQrKtWWhkaRxgeU+LszMVkzJzJdRqHHM3A==",
        "Date": "Wed, 17 Dec 2025 11:46:39 -0500",
        "From": "Marek Polacek <polacek@redhat.com>",
        "To": "GCC Patches <gcc-patches@gcc.gnu.org>, Jason Merrill <jason@redhat.com>,\n Jakub Jelinek <jakub@redhat.com>, Jonathan Wakely <jwakely@redhat.com>",
        "Subject": "[PATCH 3/9 v2] c++: C++26 Reflection [PR120775]",
        "Message-ID": "<aULeb0hfGZPbJj19@redhat.com>",
        "References": "<aULdgYtbcyGQIxK1@redhat.com>",
        "MIME-Version": "1.0",
        "In-Reply-To": "<aULdgYtbcyGQIxK1@redhat.com>",
        "User-Agent": "Mutt/2.2.14 (2025-02-20)",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "Y_z-ufjxTpg8zI5K7Mhw_tjdgyxUfFhKPJ8sp3TlGgM_1765990008",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Type": "text/plain; charset=us-ascii",
        "Content-Disposition": "inline",
        "X-BeenThere": "gcc-patches@gcc.gnu.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>",
        "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>",
        "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>",
        "List-Post": "<mailto:gcc-patches@gcc.gnu.org>",
        "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>",
        "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>",
        "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"
    },
    "content": "This contains reflect.cc.\n\n-- >8 --",
    "diff": "diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc\nnew file mode 100644\nindex 00000000000..3c7add41543\n--- /dev/null\n+++ b/gcc/cp/reflect.cc\n@@ -0,0 +1,8786 @@\n+/* C++ reflection code.\n+   Copyright (C) 2025 Free Software Foundation, Inc.\n+   Written by Marek Polacek <polacek@redhat.com> and\n+   Jakub Jelinek <jakub@redhat.com>.\n+\n+This file is part of GCC.\n+\n+GCC is free software; you can redistribute it and/or modify\n+it under the terms of the GNU General Public License as published by\n+the Free Software Foundation; either version 3, or (at your option)\n+any later version.\n+\n+GCC is distributed in the hope that it will be useful,\n+but WITHOUT ANY WARRANTY; without even the implied warranty of\n+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+GNU General Public License for more details.\n+\n+You should have received a copy of the GNU General Public License\n+along with GCC; see the file COPYING3.  If not see\n+<http://www.gnu.org/licenses/>.  */\n+\n+#include \"config.h\"\n+#include \"system.h\"\n+#include \"coretypes.h\"\n+#include \"target.h\"\n+#include \"tm.h\"\n+#include \"cp-tree.h\"\n+#include \"stringpool.h\" // for get_identifier\n+#include \"intl.h\"\n+#include \"attribs.h\"\n+#include \"c-family/c-pragma.h\" // for parse_in\n+#include \"gimplify.h\" // for unshare_expr\n+\n+static tree eval_is_function_type (tree);\n+static tree eval_is_object_type (location_t, tree);\n+static tree eval_reflect_constant (location_t, const constexpr_ctx *, tree,\n+\t\t\t\t   tree, bool *, tree *, tree);\n+static tree eval_is_array_type (location_t, tree);\n+static tree eval_reflect_constant_array (location_t, const constexpr_ctx *,\n+\t\t\t\t\t tree, bool *, bool *, tree *, tree);\n+static tree eval_reflect_function (location_t, const constexpr_ctx *, tree,\n+\t\t\t\t   tree, bool *, tree *, tree);\n+struct constexpr_ctx;\n+\n+static GTY(()) tree vector_identifier;\n+\n+/* Initialize state for reflection; e.g., initialize meta_info_type_node.  */\n+\n+void\n+init_reflection ()\n+{\n+  /* The type std::meta::info is a scalar type for which equality and\n+     inequality are meaningful, but for which no ordering relation is\n+     defined.  */\n+  meta_info_type_node = make_node (META_TYPE);\n+  /* Make it a complete type.  */\n+  TYPE_SIZE (meta_info_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));\n+  TYPE_SIZE_UNIT (meta_info_type_node) = size_int (GET_MODE_SIZE (ptr_mode));\n+  /* Name it.  */\n+  record_builtin_type (RID_MAX, \"decltype(^^int)\", meta_info_type_node);\n+\n+  vector_identifier = get_identifier (\"vector\");\n+\n+  TREE_TYPE (std_meta_node) = void_type_node;\n+}\n+\n+/* Create a REFLECT_EXPR expression of kind KIND around T.  */\n+\n+static tree\n+get_reflection_raw (location_t loc, tree t, reflect_kind kind = REFLECT_UNDEF)\n+{\n+  t = build1_loc (loc, REFLECT_EXPR, meta_info_type_node, t);\n+  SET_REFLECT_EXPR_KIND (t, kind);\n+  TREE_CONSTANT (t) = true;\n+  TREE_READONLY (t) = true;\n+  TREE_SIDE_EFFECTS (t) = false;\n+  return t;\n+}\n+\n+/* Return the reflection for T.\n+\n+    [basic.fundamental]: A value of type std::meta::info is called a reflection.\n+    There exists a unique null reflection; every other reflection is\n+    a representation of\n+\n+    -- a value of scalar type,\n+    -- an object with static storage duration,\n+    -- a variable,\n+    -- a structured binding,\n+    -- a function,\n+    -- a function parameter,\n+    -- an enumerator,\n+    -- an annotation,\n+    -- a type alias,\n+    -- a type,\n+    -- a class member,\n+    -- an unnamed bit-field,\n+    -- a class template,\n+    -- a function template,\n+    -- a variable template,\n+    -- an alias template,\n+    -- a concept,\n+    -- a namespace alias,\n+    -- a namespace,\n+    -- a direct base class relationship, or\n+    -- a data member description.\n+\n+   KIND is used to distinguish between categories that are represented\n+   by the same handle.  */\n+\n+tree\n+get_reflection (location_t loc, tree t, reflect_kind kind/*=REFLECT_UNDEF*/)\n+{\n+  STRIP_ANY_LOCATION_WRAPPER (t);\n+\n+  /* [expr.reflect] If the type-id designates a placeholder type, R is\n+     ill-formed.  */\n+  if (is_auto (t))\n+    {\n+      error_at (loc, \"%<^^%> cannot be applied to a placeholder type\");\n+      return error_mark_node;\n+    }\n+  /* Constant template parameters and pack-index-expressions cannot\n+     appear as operands of the reflection operator.  */\n+  else if (PACK_INDEX_P (t))\n+    {\n+      error_at (loc, \"%<^^%> cannot be applied to a pack index\");\n+      return error_mark_node;\n+    }\n+  else if (TREE_CODE (t) == CONST_DECL && DECL_TEMPLATE_PARM_P (t))\n+    {\n+      error_at (loc, \"%<^^%> cannot be applied to a non-type template \"\n+\t\t\"parameter %qD\", t);\n+      return error_mark_node;\n+    }\n+  /* If the id-expression denotes a local parameter introduced by\n+     a requires-expression, R is ill-formed.  */\n+  else if (TREE_CODE (t) == PARM_DECL && CONSTRAINT_VAR_P (t))\n+    {\n+      error_at (loc, \"%<^^%> cannot be applied to a local parameter of \"\n+\t\t\"a requires-expression %qD\", t);\n+      return error_mark_node;\n+    }\n+  /* If the id-expression denotes a local entity E for which there is\n+     a lambda scope that intervenes between R and the point at which E\n+     was introduced, R is ill-formed.  */\n+  else if (outer_automatic_var_p (t)\n+\t   /* Since outer_automatic_var_p is also true when we are in\n+\t      a local class member function, additionally check that\n+\t      we are in a lambda.  */\n+\t   && ((current_function_decl\n+\t\t&& LAMBDA_FUNCTION_P (current_function_decl))\n+\t       || parsing_lambda_declarator ()))\n+    {\n+      auto_diagnostic_group d;\n+      error_at (loc, \"%<^^%> cannot be applied a local entity for which \"\n+\t\t\"there is an intervening lambda expression\");\n+      inform (DECL_SOURCE_LOCATION (t), \"%qD declared here\", t);\n+      return error_mark_node;\n+    }\n+  /* If the id-expression denotes a variable declared by an init-capture,\n+     R is ill-formed.  */\n+  else if (is_capture_proxy (t) && !is_normal_capture_proxy (t))\n+    {\n+      error_at (loc, \"%<^^%> cannot be applied to a local entity declared \"\n+\t\t\"by init-capture\");\n+      return error_mark_node;\n+    }\n+  /* If lookup finds a declaration that replaced a using-declarator during\n+     a single search, R is ill-formed.  */\n+  else if (TREE_CODE (t) == USING_DECL\n+\t   || (TREE_CODE (t) == OVERLOAD && OVL_USING_P (t)))\n+    {\n+      error_at (loc, \"%<^^%> cannot be applied to a using-declarator\");\n+      return error_mark_node;\n+    }\n+  /* A concept is fine, but not Concept<arg>.  */\n+  else if (concept_check_p (t))\n+    {\n+      error_at (loc, \"%<^^%> cannot be applied to a concept check\");\n+      return error_mark_node;\n+    }\n+\n+  /* Otherwise, if the template-name names a function template F,\n+     then the template-name interpreted as an id-expression shall\n+     denote an overload set containing only F.  R represents F.\n+\n+     When we have:\n+       template<typename T>\n+       void foo (T) {}\n+       constexpr auto a = ^^foo;\n+     we will get an OVERLOAD containing only one function.  */\n+  tree r = MAYBE_BASELINK_FUNCTIONS (t);\n+  if (OVL_P (r))\n+    {\n+      if (!OVL_SINGLE_P (r))\n+\t{\n+\t  error_at (loc, \"cannot take the reflection of an overload set\");\n+\t  return error_mark_node;\n+\t}\n+    }\n+  /* [expr.reflect] If the id-expression denotes an overload set S,\n+     overload resolution for the expression &S with no target shall\n+     select a unique function; R represents that function.  */\n+  else if (!processing_template_decl && t != unknown_type_node)\n+    {\n+      /* We can't resolve all TEMPLATE_ID_EXPRs here (due to\n+\t _postfix_dot_deref_expression) but we can weed out the bad ones.  */\n+      r = resolve_nondeduced_context_or_error (t, tf_warning_or_error);\n+      if (r == error_mark_node)\n+\tt = r;\n+    }\n+\n+  /* For injected-class-name, use the main variant so that comparing\n+     reflections works (cf. compare3.C).  */\n+  if (RECORD_OR_UNION_TYPE_P (t)\n+      && TYPE_NAME (t)\n+      && DECL_SELF_REFERENCE_P (TYPE_NAME (t)))\n+    t = TYPE_MAIN_VARIANT (t);\n+\n+  /* It's annoying to deal with BIT_NOT_EXPR in a reflection later, so\n+     look up the FUNCTION_DECL here.  */\n+  if (TREE_CODE (t) == BIT_NOT_EXPR\n+      && CLASS_TYPE_P (TREE_OPERAND (t, 0))\n+      && COMPLETE_TYPE_P (TREE_OPERAND (t, 0)))\n+    {\n+      r = TREE_OPERAND (t, 0);\n+      if (CLASSTYPE_LAZY_DESTRUCTOR (r))\n+\tlazily_declare_fn (sfk_destructor, r);\n+      if (tree dtor = CLASSTYPE_DESTRUCTOR (r))\n+\tt = dtor;\n+    }\n+\n+  if (t == error_mark_node)\n+    return error_mark_node;\n+\n+  return get_reflection_raw (loc, t, kind);\n+}\n+\n+/* Null reflection shared tree.  */\n+\n+static GTY(()) tree null_reflection;\n+\n+/* Return a null reflection value.  */\n+\n+tree\n+get_null_reflection ()\n+{\n+  if (!null_reflection)\n+    null_reflection = get_reflection_raw (UNKNOWN_LOCATION, unknown_type_node);\n+  return null_reflection;\n+}\n+\n+/* Do strip_typedefs on T, but only for types.  */\n+\n+static tree\n+maybe_strip_typedefs (tree t)\n+{\n+  if (TYPE_P (t))\n+    return strip_typedefs (t);\n+  return t;\n+}\n+\n+/* If PARM_DECL comes from an earlier reflection of a function parameter\n+   and function definition is seen after that, DECL_ARGUMENTS is\n+   overwritten and so the old PARM_DECL is no longer present in the\n+   DECL_ARGUMENTS (DECL_CONTEXT (parm)) chain.  Return corresponding\n+   PARM_DECL which is in the chain.  */\n+\n+static tree\n+maybe_update_function_parm (tree parm)\n+{\n+  if (!OLD_PARM_DECL_P (parm))\n+    return parm;\n+  tree fn = DECL_CONTEXT (parm);\n+  int oldlen = list_length (parm);\n+  int newlen = list_length (DECL_ARGUMENTS (fn));\n+  gcc_assert (newlen >= oldlen);\n+  tree ret = DECL_ARGUMENTS (fn);\n+  int n = newlen - oldlen;\n+  while (n)\n+    {\n+      ret = DECL_CHAIN (ret);\n+      --n;\n+    }\n+  return ret;\n+}\n+\n+/* Return true if DECL comes from std::meta.  */\n+\n+static bool\n+decl_in_std_meta_p (tree decl)\n+{\n+  return decl_namespace_context (decl) == std_meta_node;\n+}\n+\n+/* Returns true if FNDECL, a FUNCTION_DECL, is a call to a metafunction\n+   declared in namespace std::meta.  */\n+\n+bool\n+metafunction_p (tree fndecl)\n+{\n+  if (!flag_reflection)\n+    return false;\n+\n+  /* Metafunctions are expected to be marked consteval.  */\n+  if (!DECL_IMMEDIATE_FUNCTION_P (fndecl))\n+    return false;\n+\n+  if (special_function_p (fndecl))\n+    return false;\n+\n+  if (!decl_in_std_meta_p (fndecl))\n+    return false;\n+\n+  /* They should be user provided and not defined.  */\n+  if (!user_provided_p (fndecl)\n+      || (DECL_NAMESPACE_SCOPE_P (fndecl) && DECL_DELETED_FN (fndecl)))\n+    return false;\n+  if (DECL_INITIAL (fndecl))\n+    return false;\n+\n+  return true;\n+}\n+\n+/* Extract the N-th reflection argument from a metafunction call CALL.  */\n+\n+static tree\n+get_info (const constexpr_ctx *ctx, tree call, int n, bool *non_constant_p,\n+\t  bool *overflow_p, tree *jump_target)\n+{\n+  gcc_checking_assert (call_expr_nargs (call) > n);\n+  tree info = get_nth_callarg (call, n);\n+  gcc_checking_assert (REFLECTION_TYPE_P (TREE_TYPE (info)));\n+  info = cxx_eval_constant_expression (ctx, info, vc_prvalue,\n+\t\t\t\t       non_constant_p, overflow_p,\n+\t\t\t\t       jump_target);\n+  if (*jump_target)\n+    return NULL_TREE;\n+  if (!REFLECT_EXPR_P (info))\n+    {\n+      *non_constant_p = true;\n+      return NULL_TREE;\n+    }\n+  return info;\n+}\n+\n+/* Try to get the underlying FUNCTION_DECL from reflection if any,\n+   otherwise return R.  */\n+\n+static tree\n+maybe_get_reflection_fndecl (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  r = OVL_FIRST (r);\n+  return r;\n+}\n+\n+/* Helper function for get_range_elts, called through cp_walk_tree.  */\n+\n+static tree\n+replace_parm_r (tree *tp, int *walk_subtrees, void *data)\n+{\n+  tree *p = (tree *) data;\n+  if (*tp == p[0])\n+    *tp = p[1];\n+  else if (TYPE_P (*tp))\n+    *walk_subtrees = 0;\n+  return NULL_TREE;\n+}\n+\n+static tree throw_exception (location_t, const constexpr_ctx *, const char *,\n+\t\t\t     tree, bool *, tree *);\n+\n+/* Kinds for get_range_elts.  */\n+\n+enum get_range_elts_kind {\n+  GET_INFO_VEC,\n+  REFLECT_CONSTANT_STRING,\n+  REFLECT_CONSTANT_ARRAY\n+};\n+\n+/* Extract the N-th input_range argument from a metafunction call CALL\n+   and return it as TREE_VEC or STRING_CST or CONSTRUCTOR.  Helper function\n+   for get_info_vec, eval_reflect_constant_string and\n+   eval_reflect_constant_array.  For GET_INFO_VEC kind, <meta> ensures\n+   the argument is reference to reflection_range concept and so both\n+   range_value_t is info and range_refernce_t is cv info or cv info & or\n+   cv info &&.  */\n+\n+static tree\n+get_range_elts (location_t loc, const constexpr_ctx *ctx, tree call, int n,\n+\t\tbool *non_constant_p, bool *overflow_p, tree *jump_target,\n+\t\tget_range_elts_kind kind, tree fun)\n+{\n+  gcc_checking_assert (call_expr_nargs (call) > n);\n+  tree arg = get_nth_callarg (call, n);\n+  tree parm = DECL_ARGUMENTS (cp_get_callee_fndecl_nofold (call));\n+  for (int i = 0; i < n; ++i)\n+    parm = DECL_CHAIN (parm);\n+  tree type = TREE_TYPE (arg);\n+  gcc_checking_assert (TYPE_REF_P (type));\n+  arg = cxx_eval_constant_expression (ctx, arg, vc_prvalue, non_constant_p,\n+\t\t\t\t      overflow_p, jump_target);\n+fail_ret:\n+  if (*jump_target || *non_constant_p)\n+    return NULL_TREE;\n+  tree map[2] = { parm, arg };\n+  /* To speed things up, check\n+     if constexpr (std::ranges::contiguous_range <_R>).  */\n+  tree ranges_ns = lookup_qualified_name (std_node, \"ranges\");\n+  if (TREE_CODE (ranges_ns) != NAMESPACE_DECL)\n+    {\n+      error_at (loc, \"%<std::ranges%> is not a namespace\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  tree contiguous_range\n+    = lookup_qualified_name (ranges_ns, \"contiguous_range\");\n+  if (TREE_CODE (contiguous_range) != TEMPLATE_DECL\n+      || !concept_definition_p (contiguous_range))\n+    contiguous_range = NULL_TREE;\n+  else\n+    {\n+      tree args = make_tree_vec (1);\n+      TREE_VEC_ELT (args, 0) = TREE_TYPE (type);\n+      contiguous_range = build2_loc (loc, TEMPLATE_ID_EXPR, boolean_type_node,\n+\t\t\t\t     contiguous_range, args);\n+      if (!integer_nonzerop (maybe_constant_value (contiguous_range)))\n+\tcontiguous_range = NULL_TREE;\n+    }\n+  tree valuet = meta_info_type_node;\n+  tree ret = NULL_TREE;\n+  if (kind != GET_INFO_VEC)\n+    {\n+      tree args = make_tree_vec (1);\n+      TREE_VEC_ELT (args, 0) = TREE_TYPE (type);\n+      tree inst = lookup_template_class (get_identifier (\"range_value_t\"),\n+\t\t\t\t\t args, /*in_decl*/NULL_TREE,\n+\t\t\t\t\t /*context*/ranges_ns,\n+\t\t\t\t\t tf_warning_or_error);\n+      inst = complete_type (inst);\n+      if (inst == error_mark_node)\n+\t{\n+\t  *non_constant_p = true;\n+\t  return call;\n+\t}\n+      valuet = TYPE_MAIN_VARIANT (inst);\n+      if (kind == REFLECT_CONSTANT_STRING\n+\t  && valuet != char_type_node\n+\t  && valuet != wchar_type_node\n+\t  && valuet != char8_type_node\n+\t  && valuet != char16_type_node\n+\t  && valuet != char32_type_node)\n+\t{\n+\t  if (!cxx_constexpr_quiet_p (ctx))\n+\t    error_at (loc, \"%<reflect_constant_string%> called with %qT \"\n+\t\t\t   \"%<std::ranges::range_value_t%> rather than \"\n+\t\t\t   \"%<char%>, %<wchar_t%>, %<char8_t%>, %<char16_t%> \"\n+\t\t\t   \"or %<char32_t%>\", valuet);\n+\t  *non_constant_p = true;\n+\t  return call;\n+\t}\n+      /* Check for the reflect_object_string special-case, where r\n+\t refers to a string literal.  In that case CharT() should not\n+\t be appended.  */\n+      if (kind == REFLECT_CONSTANT_STRING\n+\t  && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE\n+\t  && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) == valuet\n+\t  && TYPE_DOMAIN (TREE_TYPE (type)))\n+\t{\n+\t  tree a = arg;\n+\t  tree maxv = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (type)));\n+\t  STRIP_NOPS (a);\n+\t  tree at;\n+\t  if (TREE_CODE (a) == ADDR_EXPR\n+\t      && TREE_CODE (TREE_OPERAND (a, 0)) == STRING_CST\n+\t      && tree_fits_uhwi_p (maxv)\n+\t      && ((unsigned) TREE_STRING_LENGTH (TREE_OPERAND (a, 0))\n+\t\t  == ((tree_to_uhwi (maxv) + 1)\n+\t\t       * tree_to_uhwi (TYPE_SIZE_UNIT (valuet))))\n+\t      && (at = TREE_TYPE (TREE_OPERAND (a, 0)))\n+\t      && TREE_CODE (at) == ARRAY_TYPE\n+\t      && TYPE_MAIN_VARIANT (TREE_TYPE (at)) == valuet\n+\t      && TYPE_DOMAIN (at)\n+\t      && tree_int_cst_equal (maxv, TYPE_MAX_VALUE (TYPE_DOMAIN (at))))\n+\t    return TREE_OPERAND (a, 0);\n+\t}\n+      if (kind == REFLECT_CONSTANT_ARRAY)\n+\t{\n+\t  if (!structural_type_p (valuet))\n+\t    {\n+\t      if (!cxx_constexpr_quiet_p (ctx))\n+\t\t{\n+\t\t  auto_diagnostic_group d;\n+\t\t  error_at (loc, \"%<reflect_constant_array%> argument with \"\n+\t\t\t\t \"%qT %<std::ranges::range_value_t%> which \"\n+\t\t\t\t \"is not a structural type\", valuet);\n+\t\t  structural_type_p (valuet, true);\n+\t\t}\n+\t      *non_constant_p = true;\n+\t      return call;\n+\t    }\n+\t  tree cvaluet\n+\t    = cp_build_qualified_type (valuet, cp_type_quals (valuet)\n+\t\t\t\t\t       | TYPE_QUAL_CONST);\n+\t  TREE_VEC_ELT (args, 0)\n+\t    = cp_build_reference_type (cvaluet, /*rval=*/false);\n+\t  if (!is_xible (INIT_EXPR, valuet, args))\n+\t    {\n+\t      if (!cxx_constexpr_quiet_p (ctx))\n+\t\terror_at (loc, \"%<reflect_constant_array%> argument with %qT \"\n+\t\t\t       \"%<std::ranges::range_value_t%> which is not \"\n+\t\t\t       \"copy constructible\", valuet);\n+\t      *non_constant_p = true;\n+\t      return call;\n+\t    }\n+\t  TREE_VEC_ELT (args, 0) = TREE_TYPE (type);\n+\t  inst = lookup_template_class (get_identifier (\"range_reference_t\"),\n+\t\t\t\t\targs, /*in_decl*/NULL_TREE,\n+\t\t\t\t\t/*context*/ranges_ns,\n+\t\t\t\t\ttf_warning_or_error);\n+\t  inst = complete_type (inst);\n+\t  if (inst == error_mark_node)\n+\t    {\n+\t      *non_constant_p = true;\n+\t      return call;\n+\t    }\n+\t  tree referencet = TYPE_MAIN_VARIANT (inst);\n+\t  TREE_VEC_ELT (args, 0) = referencet;\n+\t  if (!is_xible (INIT_EXPR, valuet, args))\n+\t    {\n+\t      if (!cxx_constexpr_quiet_p (ctx))\n+\t\terror_at (loc, \"%<reflect_constant_array%> argument with %qT \"\n+\t\t\t       \"%<std::ranges::range_value_t%> which is not \"\n+\t\t\t       \"constructible from %qT \"\n+\t\t\t       \"%<std::ranges::range_reference_t%>\",\n+\t\t\tvaluet, referencet);\n+\t      *non_constant_p = true;\n+\t      return call;\n+\t    }\n+\t}\n+    }\n+  auto_vec<tree, 32> retvec;\n+  tree p = convert_from_reference (parm);\n+  auto obj_call = [=, &map] (tree obj, tsubst_flags_t complain) {\n+    releasing_vec args;\n+    vec_safe_push (args, p);\n+    tree call = finish_call_expr (obj, &args, true, false, complain);\n+    if (call == error_mark_node)\n+      return call;\n+    cp_walk_tree (&call, replace_parm_r, map, NULL);\n+    if (complain != tf_none)\n+      return call;\n+    call = cxx_eval_constant_expression (ctx, call, vc_prvalue, non_constant_p,\n+\t\t\t\t\t overflow_p, jump_target);\n+    if (*jump_target || *non_constant_p)\n+      return NULL_TREE;\n+    return call;\n+  };\n+  auto ret_retvec = [=, &retvec] () {\n+    unsigned HOST_WIDE_INT sz = retvec.length ();\n+    for (size_t i = 0; i < sz; ++i)\n+      {\n+\tif (INTEGRAL_TYPE_P (valuet))\n+\t  {\n+\t    if (TREE_CODE (retvec[i]) != INTEGER_CST)\n+\t      return throw_exception (loc, ctx,\n+\t\t\t\t      \"array element not a constant integer\",\n+\t\t\t\t      fun, non_constant_p, jump_target);\n+\t  }\n+\telse\n+\t  {\n+\t    gcc_assert (kind == REFLECT_CONSTANT_ARRAY);\n+\t    tree expr = convert_reflect_constant_arg (valuet, retvec[i]);\n+\t    if (expr == error_mark_node)\n+\t      return throw_exception (loc, ctx, \"reflect_constant failed\",\n+\t\t\t\t      fun, non_constant_p, jump_target);\n+\t    if (VAR_P (expr))\n+\t      expr = unshare_expr (DECL_INITIAL (expr));\n+\t    retvec[i] = expr;\n+\t  }\n+      }\n+    if (kind == REFLECT_CONSTANT_ARRAY && sz == 0)\n+      {\n+\t/* Return std::array <valuet, 0> {}.  */\n+\ttree args = make_tree_vec (2);\n+\tTREE_VEC_ELT (args, 0) = valuet;\n+\tTREE_VEC_ELT (args, 1) = size_zero_node;\n+\ttree inst = lookup_template_class (get_identifier (\"array\"), args,\n+\t\t\t\t\t   /*in_decl*/NULL_TREE,\n+\t\t\t\t\t   /*context*/std_node,\n+\t\t\t\t\t   tf_warning_or_error);\n+\ttree type = complete_type (inst);\n+\tif (type == error_mark_node)\n+\t  {\n+\t    *non_constant_p = true;\n+\t    return call;\n+\t  }\n+\ttree ctor = build_constructor (init_list_type_node, nullptr);\n+\tCONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;\n+\tTREE_CONSTANT (ctor) = true;\n+\tTREE_STATIC (ctor) = true;\n+\ttree r = finish_compound_literal (type, ctor, tf_warning_or_error,\n+\t\t\t\t\t  fcl_functional);\n+\tif (TREE_CODE (r) == TARGET_EXPR)\n+\t  r = TARGET_EXPR_INITIAL (r);\n+\treturn r;\n+      }\n+    unsigned esz = tree_to_uhwi (TYPE_SIZE_UNIT (valuet));\n+    unsigned last = kind == REFLECT_CONSTANT_STRING ? esz : 0;\n+    tree index = build_index_type (size_int (last ? sz : sz - 1));\n+    tree at = build_array_type (valuet, index);\n+    at = cp_build_qualified_type (at, TYPE_QUAL_CONST);\n+    if (kind == REFLECT_CONSTANT_STRING\n+\t|| ((valuet == char_type_node\n+\t     || valuet == wchar_type_node\n+\t     || valuet == char8_type_node\n+\t     || valuet == char16_type_node\n+\t     || valuet == char32_type_node)\n+\t    && integer_zerop (retvec.last ())))\n+      {\n+\tunsigned HOST_WIDE_INT szt = sz * esz;\n+\tchar *p;\n+\tif (szt < 4096)\n+\t  p = XALLOCAVEC (char, szt + last);\n+\telse\n+\t  p = XNEWVEC (char, szt + last);\n+\tfor (size_t i = 0; i < sz; ++i)\n+\t  native_encode_expr (retvec[i], (unsigned char *) p + i * esz,\n+\t\t\t      esz, 0);\n+\tif (last)\n+\t  memset (p + szt, '\\0', last);\n+\ttree ret = build_string (szt + last, p);\n+\tTREE_TYPE (ret) = at;\n+\tTREE_CONSTANT (ret) = 1;\n+\tTREE_READONLY (ret) = 1;\n+\tTREE_STATIC (ret) = 1;\n+\tif (szt >= 4096)\n+\t  XDELETEVEC (p);\n+\treturn ret;\n+      }\n+    vec<constructor_elt, va_gc> *elts = nullptr;\n+    for (unsigned i = 0; i < sz; ++i)\n+      CONSTRUCTOR_APPEND_ELT (elts, bitsize_int (i), retvec[i]);\n+    return build_constructor (at, elts);\n+  };\n+  /* If true, call std::ranges::data (p) and std::ranges::size (p)\n+     and if that works out and what the former returns can be handled,\n+     grab the elements from the initializer of the decl pointed by the\n+     first expression.  p has to be convert_from_reference (PARM_DECL)\n+     rather than its value, otherwise it is not considered lvalue.  */\n+  if (contiguous_range)\n+    {\n+      tree data = lookup_qualified_name (ranges_ns, \"data\");\n+      tree size = lookup_qualified_name (ranges_ns, \"size\");\n+      if (TREE_CODE (data) != VAR_DECL || TREE_CODE (size) != VAR_DECL)\n+\tgoto non_contiguous;\n+      data = obj_call (data, tf_none);\n+      if (error_operand_p (data))\n+\tgoto non_contiguous;\n+      if (data == NULL_TREE)\n+\tgoto fail_ret;\n+      size = obj_call (size, tf_none);\n+      if (error_operand_p (size))\n+\tgoto non_contiguous;\n+      if (size == NULL_TREE)\n+\tgoto fail_ret;\n+      if (!tree_fits_uhwi_p (size) || tree_to_uhwi (size) > INT_MAX)\n+\tgoto non_contiguous;\n+      if (integer_zerop (size))\n+\t{\n+\t  if (kind == GET_INFO_VEC)\n+\t    return make_tree_vec (0);\n+\t  return ret_retvec ();\n+\t}\n+      STRIP_NOPS (data);\n+      unsigned HOST_WIDE_INT minidx = 0, pplus = 0;\n+      if (TREE_CODE (data) == POINTER_PLUS_EXPR\n+\t  && tree_fits_uhwi_p (TREE_OPERAND (data, 1))\n+\t  && !wi::neg_p (wi::to_wide (TREE_OPERAND (data, 1))))\n+\t{\n+\t  pplus = tree_to_uhwi (TREE_OPERAND (data, 1));\n+\t  data = TREE_OPERAND (data, 0);\n+\t  STRIP_NOPS (data);\n+\t}\n+      if (TREE_CODE (data) != ADDR_EXPR)\n+\tgoto non_contiguous;\n+      data = TREE_OPERAND (data, 0);\n+      if (TREE_CODE (data) == ARRAY_REF\n+\t  && tree_fits_uhwi_p (TREE_OPERAND (data, 1)))\n+\t{\n+\t  minidx = tree_to_uhwi (TREE_OPERAND (data, 1));\n+\t  data = TREE_OPERAND (data, 0);\n+\t}\n+      data = cxx_eval_constant_expression (ctx, data, vc_prvalue,\n+\t\t\t\t\t   non_constant_p, overflow_p,\n+\t\t\t\t\t   jump_target);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      if (TREE_CODE (TREE_TYPE (data)) != ARRAY_TYPE\n+\t  || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (data))) != valuet)\n+\tgoto non_contiguous;\n+      if (pplus\n+\t  && (pplus % tree_to_uhwi (TYPE_SIZE_UNIT (valuet))) != 0)\n+\tgoto non_contiguous;\n+      minidx += pplus / tree_to_uhwi (TYPE_SIZE_UNIT (valuet));\n+      if (kind != GET_INFO_VEC && TREE_CODE (data) == STRING_CST)\n+\t{\n+\t  unsigned esz = tree_to_uhwi (TYPE_SIZE_UNIT (valuet));\n+\t  unsigned HOST_WIDE_INT sz = tree_to_uhwi (size) * esz;\n+\t  if (minidx > INT_MAX\n+\t      || (unsigned) TREE_STRING_LENGTH (data) < sz + minidx * esz)\n+\t    goto non_contiguous;\n+\t  if (kind == REFLECT_CONSTANT_ARRAY && sz == 0)\n+\t    return ret_retvec ();\n+\t  tree index\n+\t    = build_index_type (size_int ((kind == REFLECT_CONSTANT_ARRAY\n+\t\t\t\t\t   ? -1 : 0) + tree_to_uhwi (size)));\n+\t  tree at = build_array_type (valuet, index);\n+\t  at = cp_build_qualified_type (at, TYPE_QUAL_CONST);\n+\t  const unsigned char *q\n+\t    = (const unsigned char *) TREE_STRING_POINTER (data);\n+\t  q += minidx * esz;\n+\t  if (kind == REFLECT_CONSTANT_ARRAY)\n+\t    {\n+\t      unsigned HOST_WIDE_INT i;\n+\t      for (i = 0; i < esz; ++i)\n+\t\tif (q[sz - esz + i])\n+\t\t  break;\n+\t      if (i != esz)\n+\t\t{\n+\t\t  /* Not a NUL terminated string.  Build a CONSTRUCTOR\n+\t\t     instead.  */\n+\t\t  for (i = 0; i < sz; i += esz)\n+\t\t    {\n+\t\t      tree t = native_interpret_expr (valuet, q + i, sz);\n+\t\t      retvec.safe_push (t);\n+\t\t    }\n+\t\t  return ret_retvec ();\n+\t\t}\n+\t    }\n+\t  char *p;\n+\t  if (sz < 4096)\n+\t    p = XALLOCAVEC (char, sz + esz);\n+\t  else\n+\t    p = XNEWVEC (char, sz + esz);\n+\t  memcpy (p, q, sz);\n+\t  memset (p + sz, '\\0', esz);\n+\t  ret = build_string (sz + (kind == REFLECT_CONSTANT_ARRAY\n+\t\t\t\t    ? 0 : esz), p);\n+\t  TREE_TYPE (ret) = at;\n+\t  TREE_CONSTANT (ret) = 1;\n+\t  TREE_READONLY (ret) = 1;\n+\t  TREE_STATIC (ret) = 1;\n+\t  if (sz >= 4096)\n+\t    XDELETEVEC (p);\n+\t  return ret;\n+\t}\n+      if (TREE_CODE (data) != CONSTRUCTOR)\n+\tgoto non_contiguous;\n+      unsigned sz = tree_to_uhwi (size), i;\n+      unsigned HOST_WIDE_INT j = 0;\n+      tree *r, null = NULL_TREE;\n+      if (kind == GET_INFO_VEC)\n+\t{\n+\t  ret = make_tree_vec (sz);\n+\t  r = TREE_VEC_BEGIN (ret);\n+\t  null = get_null_reflection ();\n+\t}\n+      else\n+\t{\n+\t  retvec.safe_grow (sz, true);\n+\t  r = retvec.address ();\n+\t}\n+      for (i = 0; i < sz; ++i)\n+\tr[i] = null;\n+      tree field, value;\n+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (data), i, field, value)\n+\tif (field == NULL_TREE)\n+\t  {\n+\t    if (j >= minidx && j - minidx < sz)\n+\t      r[j - minidx] = value;\n+\t    ++j;\n+\t  }\n+\telse if (TREE_CODE (field) == RANGE_EXPR)\n+\t  {\n+\t    tree lo = TREE_OPERAND (field, 0);\n+\t    tree hi = TREE_OPERAND (field, 1);\n+\t    if (!tree_fits_uhwi_p (lo) || !tree_fits_uhwi_p (hi))\n+\t      goto non_contiguous;\n+\t    unsigned HOST_WIDE_INT m = tree_to_uhwi (hi);\n+\t    for (j = tree_to_uhwi (lo); j <= m; ++j)\n+\t      if (j >= minidx && j - minidx < sz)\n+\t\tr[j - minidx] = value;\n+\t  }\n+\telse if (tree_fits_uhwi_p (field))\n+\t  {\n+\t    j = tree_to_uhwi (field);\n+\t    if (j >= minidx && j - minidx < sz)\n+\t      r[j - minidx] = value;\n+\t    ++j;\n+\t  }\n+\telse\n+\t  goto non_contiguous;\n+      if (kind == GET_INFO_VEC)\n+\treturn ret;\n+      for (i = 0; i < sz; ++i)\n+\tif (r[i] == NULL_TREE || !tree_fits_shwi_p (r[i]))\n+\t  goto non_contiguous;\n+      return ret_retvec ();\n+    }\n+ non_contiguous:\n+  /* Otherwise, do it the slower way.  Initialize two temporaries,\n+     one to std::ranges::base (p) and another to std::ranges::end (p)\n+     and use a loop.  */\n+  tree begin = lookup_qualified_name (ranges_ns, \"begin\");\n+  tree end = lookup_qualified_name (ranges_ns, \"end\");\n+  if (TREE_CODE (begin) != VAR_DECL || TREE_CODE (end) != VAR_DECL)\n+    {\n+      error_at (loc, \"missing %<std::ranges::begin%> or %<std::ranges::end%>\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  begin = obj_call (begin, tf_warning_or_error);\n+  if (error_operand_p (begin))\n+    {\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  end = obj_call (end, tf_warning_or_error);\n+  if (error_operand_p (end))\n+    {\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  if (!CLASS_TYPE_P (TREE_TYPE (begin)) && !POINTER_TYPE_P (TREE_TYPE (begin)))\n+    {\n+      error_at (loc, \"incorrect type %qT of %<std::ranges::begin(arg)%>\",\n+\t\tTREE_TYPE (begin));\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  if (VOID_TYPE_P (TREE_TYPE (end)))\n+    {\n+      error_at (loc, \"incorrect type %qT of %<std::ranges::end(arg)%>\",\n+\t\tTREE_TYPE (end));\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  begin = get_target_expr (begin);\n+  end = get_target_expr (end);\n+  begin = cxx_eval_constant_expression (ctx, begin, vc_glvalue, non_constant_p,\n+\t\t\t\t\toverflow_p, jump_target);\n+  if (*jump_target || *non_constant_p)\n+    goto fail_ret;\n+  end = cxx_eval_constant_expression (ctx, end, vc_glvalue, non_constant_p,\n+\t\t\t\t      overflow_p, jump_target);\n+  if (*jump_target || *non_constant_p)\n+    goto fail_ret;\n+  tree cmp = build_new_op (loc, NE_EXPR, LOOKUP_NORMAL, begin, end,\n+\t\t\t   tf_warning_or_error);\n+  tree deref = build_new_op (loc, INDIRECT_REF, LOOKUP_NORMAL, begin,\n+\t\t\t     NULL_TREE, tf_warning_or_error);\n+  tree inc = build_new_op (loc, PREINCREMENT_EXPR, LOOKUP_NORMAL, begin,\n+\t\t\t   NULL_TREE, tf_warning_or_error);\n+  cmp = condition_conversion (cmp);\n+  if (error_operand_p (cmp)\n+      || error_operand_p (deref)\n+      || error_operand_p (inc))\n+    {\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  // TODO: For REFLECT_CONSTANT_* handle proxy iterators.\n+  if (TYPE_MAIN_VARIANT (TREE_TYPE (deref)) != valuet)\n+    {\n+      if (!cxx_constexpr_quiet_p (ctx))\n+\terror_at (loc, \"unexpected type %qT of iterator dereference\",\n+\t\t  TREE_TYPE (deref));\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  retvec.truncate (0);\n+  /* while (begin != end) { push (*begin); ++begin; }  */\n+  do\n+    {\n+      tree t = cxx_eval_constant_expression (ctx, cmp, vc_prvalue,\n+\t\t\t\t\t     non_constant_p, overflow_p,\n+\t\t\t\t\t     jump_target);\n+      if (*jump_target || *non_constant_p)\n+\tgoto fail_ret;\n+      if (integer_zerop (t))\n+\tbreak;\n+      t = cxx_eval_constant_expression (ctx, deref, vc_prvalue, non_constant_p,\n+\t\t\t\t\toverflow_p, jump_target);\n+      if (*jump_target || *non_constant_p)\n+\tgoto fail_ret;\n+      retvec.safe_push (t);\n+      cxx_eval_constant_expression (ctx, inc, vc_discard, non_constant_p,\n+\t\t\t\t    overflow_p, jump_target);\n+      if (*jump_target || *non_constant_p)\n+\tgoto fail_ret;\n+    }\n+  while (true);\n+  if (kind != GET_INFO_VEC)\n+    return ret_retvec ();\n+  ret = make_tree_vec (retvec.length ());\n+  tree v;\n+  unsigned int i;\n+  FOR_EACH_VEC_ELT (retvec, i, v)\n+    TREE_VEC_ELT (ret, i) = v;\n+  return ret;\n+}\n+\n+/* Extract the N-th reflection_range argument from a metafunction call CALL\n+   and return it as TREE_VEC.  */\n+\n+static tree\n+get_info_vec (location_t loc, const constexpr_ctx *ctx, tree call, int n,\n+\t      bool *non_constant_p, bool *overflow_p, tree *jump_target,\n+\t      tree fun)\n+{\n+  return get_range_elts (loc, ctx, call, n, non_constant_p, overflow_p,\n+\t\t\t jump_target, GET_INFO_VEC, fun);\n+}\n+\n+/* Return std::vector<info>.  */\n+\n+static tree\n+get_vector_info ()\n+{\n+  tree args = make_tree_vec (1);\n+  TREE_VEC_ELT (args, 0) = meta_info_type_node;\n+  tree inst = lookup_template_class (vector_identifier, args,\n+\t\t\t\t     /*in_decl*/NULL_TREE,\n+\t\t\t\t     /*context*/std_node, tf_none);\n+  inst = complete_type (inst);\n+  if (inst == error_mark_node || !COMPLETE_TYPE_P (inst))\n+    {\n+      error (\"couldn%'t look up %qs\", \"std::vector\");\n+      return NULL_TREE;\n+    }\n+\n+  return inst;\n+}\n+\n+/* Create std::meta::exception{ what, from }.  WHAT is the string for what(),\n+   and FROM is the info for from().  */\n+\n+static tree\n+get_meta_exception_object (location_t loc, const char *what, tree from,\n+\t\t\t   bool *non_constant_p)\n+{\n+  /* Don't throw in a template.  */\n+  // TODO For -fno-exceptions, report an error.\n+  if (processing_template_decl)\n+    {\n+      *non_constant_p = true;\n+      return NULL_TREE;\n+    }\n+\n+  tree type = lookup_qualified_name (std_meta_node, \"exception\",\n+\t\t\t\t     LOOK_want::TYPE, /*complain*/true);\n+  if (TREE_CODE (type) != TYPE_DECL || !CLASS_TYPE_P (TREE_TYPE (type)))\n+    {\n+      error_at (loc, \"couldn%'t throw %qs\", \"std::meta::exception\");\n+      return NULL_TREE;\n+    }\n+  type = TREE_TYPE (type);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  what = _(what);\n+  /* Translate what from SOURCE_CHARSET to exec charset.  */\n+  cpp_string istr, ostr;\n+  istr.len = strlen (what) + 1;\n+  istr.text = (const unsigned char *) what;\n+  if (!cpp_translate_string (parse_in, &istr, &ostr, CPP_STRING, false))\n+    {\n+      what = \"\";\n+      ostr.text = NULL;\n+    }\n+  else\n+    what = (const char *) ostr.text;\n+  if (TREE_CODE (from) == FUNCTION_DECL && DECL_TEMPLATE_INFO (from))\n+    from = DECL_TI_TEMPLATE (from);\n+  tree string_lit = build_string (strlen (what) + 1, what);\n+  free (const_cast <unsigned char *> (ostr.text));\n+  TREE_TYPE (string_lit) = char_array_type_node;\n+  string_lit = fix_string_type (string_lit);\n+  CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, string_lit);\n+  CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, get_reflection_raw (loc, from));\n+  tree ctor = build_constructor (init_list_type_node, elts);\n+  CONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;\n+  TREE_CONSTANT (ctor) = true;\n+  TREE_STATIC (ctor) = true;\n+  return finish_compound_literal (type, ctor, tf_warning_or_error,\n+\t\t\t\t  fcl_functional);\n+}\n+\n+/* Perform 'throw std::meta::exception{...}'.  MSGID is the string for what(),\n+   FROM is the reflection for from().  */\n+\n+static tree\n+throw_exception (location_t loc, const constexpr_ctx *ctx, const char *msgid,\n+\t\t tree from, bool *non_constant_p, tree *jump_target)\n+{\n+  if (tree obj = get_meta_exception_object (loc, msgid, from, non_constant_p))\n+    *jump_target = cxa_allocate_and_throw_exception (loc, ctx, obj);\n+  return NULL_TREE;\n+}\n+\n+/* Wrapper around throw_exception to complain that the reflection does not\n+   represent a type.  */\n+\n+static tree\n+throw_exception_nontype (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t tree from, bool *non_constant_p, tree *jump_target)\n+{\n+  return throw_exception (loc, ctx,\n+\t\t\t  \"reflection does not represent a type\",\n+\t\t\t  from, non_constant_p, jump_target);\n+}\n+\n+/* Wrapper around throw_exception to complain that the reflection does not\n+   represent something that satisfies has_template_arguments.  */\n+\n+static tree\n+throw_exception_notargs (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t tree from, bool *non_constant_p, tree *jump_target)\n+{\n+  return throw_exception (loc, ctx,\n+\t\t\t  \"reflection does not have template arguments\",\n+\t\t\t  from, non_constant_p, jump_target);\n+}\n+\n+/* Wrapper around throw_exception to complain that the reflection does not\n+   represent a function or a function type.  */\n+\n+static tree\n+throw_exception_nofn (location_t loc, const constexpr_ctx *ctx,\n+\t\t      tree from, bool *non_constant_p, tree *jump_target)\n+{\n+  return throw_exception (loc, ctx, \"reflection does not represent a \"\n+\t\t\t\t    \"function or function type\",\n+\t\t\t  from, non_constant_p, jump_target);\n+}\n+\n+/* The values of std::meta::operators enumerators corresponding to\n+   the ovl_op_code and IDENTIFIER_ASSIGN_OP_P pair.  */\n+\n+static unsigned char meta_operators[2][OVL_OP_MAX];\n+\n+/* Init the meta_operators table if not yet initialized.  */\n+\n+static void\n+maybe_init_meta_operators (location_t loc)\n+{\n+  if (meta_operators[0][OVL_OP_ERROR_MARK])\n+    return;\n+  meta_operators[0][OVL_OP_ERROR_MARK] = 1;\n+  tree operators = lookup_qualified_name (std_meta_node, \"operators\");\n+  if (TREE_CODE (operators) != TYPE_DECL\n+      || TREE_CODE (TREE_TYPE (operators)) != ENUMERAL_TYPE)\n+    {\n+    fail:\n+      error_at (loc, \"unexpected %<std::meta::operators%>\");\n+      return;\n+    }\n+  char buf[sizeof \"op_greater_greater_equals\"];\n+  memcpy (buf, \"op_\", 3);\n+  for (int i = 0; i < 2; ++i)\n+    for (int j = OVL_OP_ERROR_MARK + 1; j < OVL_OP_MAX; ++j)\n+      if (ovl_op_info[i][j].meta_name)\n+\t{\n+\t  strcpy (buf + 3, ovl_op_info[i][j].meta_name);\n+\t  tree id = get_identifier (buf);\n+\t  tree t = lookup_enumerator (TREE_TYPE (operators), id);\n+\t  if (t == NULL_TREE || TREE_CODE (t) != CONST_DECL)\n+\t    goto fail;\n+\t  tree v = DECL_INITIAL (t);\n+\t  if (!tree_fits_uhwi_p (v) || tree_to_uhwi (v) > UCHAR_MAX)\n+\t    goto fail;\n+\t  meta_operators[i][j] = tree_to_uhwi (v);\n+\t}\n+}\n+\n+/* Process std::meta::is_variable.\n+   Returns: true if r represents a variable.  Otherwise, false.  */\n+\n+static tree\n+eval_is_variable (const_tree r, reflect_kind kind)\n+{\n+  /* ^^param is a variable but parameters_of(parent_of(^^param))[0] is not.  */\n+  if ((TREE_CODE (r) == PARM_DECL && kind != REFLECT_PARM)\n+      || (VAR_P (r)\n+\t  && kind == REFLECT_UNDEF\n+\t  /* The definition of a variable excludes non-static data members.  */\n+\t  && !DECL_ANON_UNION_VAR_P (r)\n+\t  /* A structured binding is not a variable.  */\n+\t  && !(DECL_DECOMPOSITION_P (r) && !DECL_DECOMP_IS_BASE (r)))\n+      || (VAR_P (r)\n+\t  /* Underlying variable of tuple using structured binding is a\n+\t     variable.  */\n+\t  && kind == REFLECT_VAR\n+\t  && DECL_DECOMPOSITION_P (r)\n+\t  && !DECL_DECOMP_IS_BASE (r)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_type.\n+   Returns: true if r represents an entity whose underlying entity is\n+   a type.  Otherwise, false.  */\n+\n+static tree\n+eval_is_type (const_tree r)\n+{\n+  /* Null reflection isn't a type.  */\n+  if (TYPE_P (r) && r != unknown_type_node)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_type_alias.\n+   Returns: true if r represents a type alias.  Otherwise, false.  */\n+\n+static tree\n+eval_is_type_alias (const_tree r)\n+{\n+  if (TYPE_P (r) && typedef_variant_p (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_namespace.\n+   Returns: true if r represents an entity whose underlying entity is\n+   a namespace.  Otherwise, false.  */\n+\n+static tree\n+eval_is_namespace (const_tree r)\n+{\n+  if (TREE_CODE (r) == NAMESPACE_DECL)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_namespace_alias.\n+   Returns: true if r represents a namespace alias.  Otherwise, false.  */\n+\n+static tree\n+eval_is_namespace_alias (const_tree r)\n+{\n+  if (TREE_CODE (r) == NAMESPACE_DECL && DECL_NAMESPACE_ALIAS (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_function.\n+   Returns: true if r represents a function.  Otherwise, false.  */\n+\n+static tree\n+eval_is_function (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+\n+  if (TREE_CODE (r) == FUNCTION_DECL)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_function_template.\n+   Returns: true if r represents a function template.  Otherwise, false.  */\n+\n+static tree\n+eval_is_function_template (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+\n+  if (DECL_FUNCTION_TEMPLATE_P (r))\n+    return boolean_true_node;\n+\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_variable_template.\n+   Returns: true if r represents a variable template.  Otherwise, false.  */\n+\n+static tree\n+eval_is_variable_template (tree r)\n+{\n+  if (variable_template_p (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_class_template.\n+   Returns: true if r represents a class template.  Otherwise, false.  */\n+\n+static tree\n+eval_is_class_template (const_tree r)\n+{\n+  if (DECL_CLASS_TEMPLATE_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_alias_template.\n+   Returns: true if r represents an alias template.  Otherwise, false.  */\n+\n+static tree\n+eval_is_alias_template (const_tree r)\n+{\n+  if (DECL_ALIAS_TEMPLATE_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_concept.\n+   Returns: true if r represents a concept.  Otherwise, false.  */\n+\n+static tree\n+eval_is_concept (const_tree r)\n+{\n+  if (concept_definition_p (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_object.\n+   Returns: true if r represents an object.  Otherwise, false.  */\n+\n+static tree\n+eval_is_object (reflect_kind kind)\n+{\n+  if (kind == REFLECT_OBJECT)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_value.\n+   Returns: true if r represents a value.  Otherwise, false.  */\n+\n+static tree\n+eval_is_value (reflect_kind kind)\n+{\n+  if (kind == REFLECT_VALUE)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Like get_info_vec, but throw exception if any of the elements aren't\n+   eval_is_type reflections and change their content to the corresponding\n+   REFLECT_EXPR_HANDLE.  */\n+\n+static tree\n+get_type_info_vec (location_t loc, const constexpr_ctx *ctx, tree call, int n,\n+\t\t   bool *non_constant_p, bool *overflow_p, tree *jump_target,\n+\t\t   tree fun)\n+{\n+  tree vec = get_info_vec (loc, ctx, call, n, non_constant_p, overflow_p,\n+\t\t\t   jump_target, fun);\n+  if (*jump_target || *non_constant_p)\n+    return NULL_TREE;\n+  for (int i = 0; i < TREE_VEC_LENGTH (vec); i++)\n+    {\n+      tree type = REFLECT_EXPR_HANDLE (TREE_VEC_ELT (vec, i));\n+      if (eval_is_type (type) != boolean_true_node)\n+\treturn throw_exception_nontype (loc, ctx, fun, non_constant_p,\n+\t\t\t\t\tjump_target);\n+      TREE_VEC_ELT (vec, i) = type;\n+    }\n+  return vec;\n+}\n+\n+/* Process std::meta::is_structured_binding.\n+   Returns: true if r represents a structured binding.  Otherwise, false.  */\n+\n+static tree\n+eval_is_structured_binding (const_tree r, reflect_kind kind)\n+{\n+  if (DECL_DECOMPOSITION_P (r)\n+      && !DECL_DECOMP_IS_BASE (r)\n+      && kind != REFLECT_VAR)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_class_member.\n+   Returns: true if r represents a class member.  Otherwise, false.  */\n+\n+static tree\n+eval_is_class_member (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == CONST_DECL)\n+    {\n+      /* [class.mem.general]/5 - The enumerators of an unscoped enumeration\n+\t defined in the class are members of the class.  */\n+      if (UNSCOPED_ENUM_P (DECL_CONTEXT (r)))\n+\tr = DECL_CONTEXT (r);\n+      else\n+\treturn boolean_false_node;\n+    }\n+  else if (TYPE_P (r) && typedef_variant_p (r))\n+    r = TYPE_NAME (r);\n+  else if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))\n+    return boolean_true_node;\n+  if (DECL_P (r) && DECL_CLASS_SCOPE_P (r))\n+    return boolean_true_node;\n+  else if (TYPE_P (r) && TYPE_CLASS_SCOPE_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Helper function for eval_is_{public, protected, private}.  */\n+\n+static tree\n+eval_is_expected_access (tree r, reflect_kind kind, tree expected_access)\n+{\n+  if (eval_is_class_member (r) == boolean_true_node)\n+    {\n+      r = maybe_get_reflection_fndecl (r);\n+\n+      if (TYPE_P (r))\n+\t{\n+\t  if (TYPE_NAME (r) == NULL_TREE || !DECL_P (TYPE_NAME (r)))\n+\t    return boolean_false_node;\n+\t  r = TYPE_NAME (r);\n+\t}\n+\n+      bool matches = false;\n+      if (expected_access == access_private_node)\n+\tmatches = TREE_PRIVATE (r);\n+      else if (expected_access == access_protected_node)\n+\tmatches = TREE_PROTECTED (r);\n+      else if (expected_access == access_public_node)\n+\tmatches = !(TREE_PRIVATE (r) || TREE_PROTECTED (r));\n+      else\n+\tgcc_unreachable ();\n+\n+      if (matches)\n+\treturn boolean_true_node;\n+      else\n+\treturn boolean_false_node;\n+    }\n+\n+  if (kind == REFLECT_BASE)\n+    {\n+      gcc_assert (TREE_CODE (r) == TREE_BINFO);\n+      tree c = r;\n+      /* Looping needed for multiple virtual inheritance.  */\n+      while (BINFO_INHERITANCE_CHAIN (c))\n+\tc = BINFO_INHERITANCE_CHAIN (c);\n+\n+      tree base_binfo;\n+      for (unsigned ix = 0; BINFO_BASE_ITERATE (c, ix, base_binfo); ix++)\n+\tif (base_binfo == r)\n+\t  {\n+\t    tree access = BINFO_BASE_ACCESS (c, ix);\n+\t    if (access == expected_access)\n+\t      return boolean_true_node;\n+\t    else\n+\t      return boolean_false_node;\n+\t  }\n+      gcc_unreachable ();\n+    }\n+\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_public.\n+   Returns: true if r represents either:\n+   - a class member or unnamed bit-field that is public or\n+   - a direct base class relationship (D, B) for which\n+   B is a public base class of D.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_public (tree r, reflect_kind kind)\n+{\n+  return eval_is_expected_access (r, kind, access_public_node);\n+}\n+\n+/* Process std::meta::is_protected.\n+   Returns: true if r represents either:\n+   - a class member or unnamed bit-field that is protected, or\n+   - a direct base class relationship (D, B) for which\n+   B is a protected base class of D.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_protected (tree r, reflect_kind kind)\n+{\n+  return eval_is_expected_access (r, kind, access_protected_node);\n+}\n+\n+/* Process std::meta::is_private\n+   Returns: true if r represents either:\n+   - a class member or unnamed bit-field that is private, or\n+   - a direct base class relationship (D, B) for which\n+   B is a private base class of D.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_private (tree r, reflect_kind kind)\n+{\n+  return eval_is_expected_access (r, kind, access_private_node);\n+}\n+\n+/* Process std::meta::is_virtual.\n+   Returns: true if r represents either a virtual member function or a direct\n+   base class relationship (D,B) for which B is a virtual base class of D.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_virtual (tree r, reflect_kind kind)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_VIRTUAL_P (r))\n+    return boolean_true_node;\n+\n+  if (kind == REFLECT_BASE && BINFO_VIRTUAL_P (r))\n+    return boolean_true_node;\n+\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_pure_virtual.\n+   Returns: true if r represents a member function that is pure virtual.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_pure_virtual (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_PURE_VIRTUAL_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Helper function for eval_is_override, return true if FNDECL in TYPE\n+   overrides another function.  */\n+\n+static bool\n+is_override (tree type, tree fndecl)\n+{\n+  tree binfo = TYPE_BINFO (type), base_binfo;\n+\n+  for (unsigned ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)\n+    {\n+      tree basetype = BINFO_TYPE (base_binfo);\n+      if (TYPE_POLYMORPHIC_P (basetype))\n+\t{\n+\t  if (look_for_overrides_here (basetype, fndecl))\n+\t    return true;\n+\t  if (is_override (basetype, fndecl))\n+\t    return true;\n+\t}\n+    }\n+  return false;\n+}\n+\n+/* Process std::meta::is_override.\n+   Returns: true if r represents a member function that overrides another\n+   member function.  Otherwise, false.  */\n+\n+static tree\n+eval_is_override (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL\n+      && DECL_CLASS_SCOPE_P (r)\n+      && !DECL_CONSTRUCTOR_P (r)\n+      && (IDENTIFIER_VIRTUAL_P (DECL_NAME (r))\n+\t  || DECL_CONV_FN_P (r))\n+      && !DECL_STATIC_FUNCTION_P (r)\n+      && is_override (DECL_CONTEXT (r), r))\n+    return boolean_true_node;\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_namespace_member.\n+   Returns: true if r represents a namespace member.  Otherwise, false.  */\n+\n+static tree\n+eval_is_namespace_member (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == CONST_DECL)\n+    {\n+      if (UNSCOPED_ENUM_P (DECL_CONTEXT (r)))\n+\tr = DECL_CONTEXT (r);\n+      else\n+\treturn boolean_false_node;\n+    }\n+  else if (TYPE_P (r) && typedef_variant_p (r))\n+    r = TYPE_NAME (r);\n+  else if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))\n+    return boolean_false_node;\n+  if (r == global_namespace || r == unknown_type_node)\n+    return boolean_false_node;\n+  if (DECL_P (r) && DECL_NAMESPACE_SCOPE_P (r))\n+    return boolean_true_node;\n+  else if (TYPE_P (r) && TYPE_NAMESPACE_SCOPE_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_nonstatic_data_member.\n+   Returns: true if r represents a non-static data member.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_nonstatic_data_member (const_tree r)\n+{\n+  if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))\n+    return boolean_true_node;\n+  if (TREE_CODE (r) == FIELD_DECL && !DECL_UNNAMED_BIT_FIELD (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_static_member.\n+   Returns: true if r represents a static member.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_static_member (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  r = STRIP_TEMPLATE (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (r))\n+    return boolean_true_node;\n+  else if (VAR_P (r) && DECL_CLASS_SCOPE_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_base.\n+   Returns: true if r represents a direct base class relationship.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_base (tree r, reflect_kind kind)\n+{\n+  if (kind == REFLECT_BASE)\n+    {\n+      gcc_assert (TREE_CODE (r) == TREE_BINFO);\n+      return boolean_true_node;\n+    }\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_default_member_initializer.\n+   Returns: true if r represents a non-static data member that has a default\n+   member initializer.  Otherwise, false.  */\n+\n+static tree\n+eval_has_default_member_initializer (const_tree r)\n+{\n+  if (TREE_CODE (r) == FIELD_DECL\n+      && !DECL_UNNAMED_BIT_FIELD (r)\n+      && DECL_INITIAL (r) != NULL_TREE)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_static_storage_duration.\n+   Returns: true if r represents an object or variable that has static\n+   storage duration.  Otherwise, false.  */\n+\n+static tree\n+eval_has_static_storage_duration (const_tree r, reflect_kind kind)\n+{\n+  if (eval_is_variable (r, kind) == boolean_true_node\n+      && decl_storage_duration (CONST_CAST_TREE (r)) == dk_static)\n+    return boolean_true_node;\n+  /* This includes DECL_NTTP_OBJECT_P objects.  */\n+  else if (eval_is_object (kind) == boolean_true_node)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_thread_storage_duration.\n+   Returns: true if r represents an object or variable that has thread\n+   storage duration.  Otherwise, false.  */\n+\n+static tree\n+eval_has_thread_storage_duration (const_tree r, reflect_kind kind)\n+{\n+  if (eval_is_variable (r, kind) == boolean_true_node\n+      && decl_storage_duration (CONST_CAST_TREE (r)) == dk_thread)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_automatic_storage_duration.\n+   Returns: true if r represents an object or variable that has automatic\n+   storage duration.  Otherwise, false.  */\n+\n+static tree\n+eval_has_automatic_storage_duration (const_tree r, reflect_kind kind)\n+{\n+  if (eval_is_variable (r, kind) == boolean_true_node\n+      && decl_storage_duration (CONST_CAST_TREE (r)) == dk_auto)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_mutable_member.\n+   Returns: true if r represents a mutable non-static data member.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_mutable_member (tree r)\n+{\n+  if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))\n+    {\n+      tree v = DECL_VALUE_EXPR (r);\n+      if (v != error_mark_node && TREE_CODE (v) == COMPONENT_REF)\n+\tr = TREE_OPERAND (v, 1);\n+    }\n+  if (TREE_CODE (r) == FIELD_DECL\n+      && !DECL_UNNAMED_BIT_FIELD (r)\n+      && DECL_MUTABLE_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_template.\n+   Returns: true if r represents a function template, class template, variable\n+   template, alias template, or concept.  Otherwise, false.  */\n+\n+static tree\n+eval_is_template (tree r)\n+{\n+  if (eval_is_function_template (r) == boolean_true_node\n+      || eval_is_class_template (r) == boolean_true_node\n+      || eval_is_variable_template (r) == boolean_true_node\n+      || eval_is_alias_template (r) == boolean_true_node\n+      || eval_is_concept (r) == boolean_true_node)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_function_parameter.\n+   Returns: true if r represents a function parameter.  Otherwise, false.  */\n+\n+static tree\n+eval_is_function_parameter (const_tree r, reflect_kind kind)\n+{\n+  if (kind == REFLECT_PARM)\n+    {\n+      gcc_checking_assert (TREE_CODE (r) == PARM_DECL);\n+      return boolean_true_node;\n+    }\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_data_member_spec.\n+   Returns: true if r represents a data member description.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_data_member_spec (const_tree r, reflect_kind kind)\n+{\n+  if (kind == REFLECT_DATA_MEMBER_SPEC)\n+    {\n+      gcc_checking_assert (TREE_CODE (r) == TREE_VEC);\n+      return boolean_true_node;\n+    }\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_explicit_object_parameter.\n+   Returns: true if r represents a function parameter that is an explicit\n+   object parameter.  Otherwise, false.  */\n+\n+static tree\n+eval_is_explicit_object_parameter (const_tree r, reflect_kind kind)\n+{\n+  if (eval_is_function_parameter (r, kind) == boolean_true_node\n+      && r == DECL_ARGUMENTS (DECL_CONTEXT (r))\n+      && DECL_XOBJ_MEMBER_FUNCTION_P (DECL_CONTEXT (r)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_default_argument.\n+   Returns: If r represents a parameter P of a function F, then:\n+   -- If F is a specialization of a templated function T, then true if there\n+      exists a declaration D of T that precedes some point in the evaluation\n+      context and D specifies a default argument for the parameter of T\n+      corresponding to P.  Otherwise, false.\n+   -- Otherwise, if there exists a declaration D of F that precedes some\n+      point in the evaluation context and D specifies a default argument\n+      for P, then true.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_has_default_argument (tree r, reflect_kind kind)\n+{\n+  if (eval_is_function_parameter (r, kind) == boolean_false_node)\n+    return boolean_false_node;\n+  r = maybe_update_function_parm (r);\n+  tree fn = DECL_CONTEXT (r);\n+  tree args = FUNCTION_FIRST_USER_PARM (fn);\n+  tree types = FUNCTION_FIRST_USER_PARMTYPE (fn);\n+  while (r != args)\n+    {\n+      args = DECL_CHAIN (args);\n+      types = TREE_CHAIN (types);\n+    }\n+  if (TREE_PURPOSE (types))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_ellipsis_parameter.\n+   Returns: true if r represents a function or function type that has an\n+   ellipsis in its parameter-type-list.  Otherwise, false.  */\n+\n+static tree\n+eval_has_ellipsis_parameter (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL)\n+    r = TREE_TYPE (r);\n+  if (FUNC_OR_METHOD_TYPE_P (r) && stdarg_p (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_deleted.\n+   Returns: true if r represents a function that is deleted.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_deleted (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_MAYBE_DELETED (r))\n+    {\n+      ++function_depth;\n+      maybe_synthesize_method (r);\n+      --function_depth;\n+    }\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_DELETED_FN (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_defaulted.\n+   Returns: true if r represents a function that is defaulted.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_defaulted (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_DEFAULTED_FN (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_user_provided.\n+   Returns: true if r represents a function that is user-provided.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_user_provided (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL\n+      && user_provided_p (r)\n+      // TODO: user_provided_p is false for non-members defaulted on\n+      // first declaration.\n+      && (!DECL_NAMESPACE_SCOPE_P (r) || !DECL_DELETED_FN (r)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_user_declared.\n+   Returns: true if r represents a function that is user-declared.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_user_declared (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && !DECL_ARTIFICIAL (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_explicit.\n+   Returns: true if r represents\n+   a member function that is declared explicit.\n+   Otherwise, false.\n+   If r represents a member function template\n+   that is declared explicit, is_explicit(r)\n+   is still false because in general such queries\n+   for templates cannot be answered.  */\n+\n+static tree\n+eval_is_explicit (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_NONCONVERTING_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_bit_field.\n+   Returns: true if r represents a bit-field, or if r represents a data member\n+   description (T,N,A,W,NUA) for which W is not _|_.  Otherwise, false.  */\n+\n+static tree\n+eval_is_bit_field (const_tree r, reflect_kind kind)\n+{\n+  if (TREE_CODE (r) == FIELD_DECL && DECL_C_BIT_FIELD (r))\n+    return boolean_true_node;\n+  else if (kind == REFLECT_DATA_MEMBER_SPEC && TREE_VEC_ELT (r, 3))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_enumerator.\n+   Returns: true if r represents an enumerator.  Otherwise, false.  */\n+\n+static tree\n+eval_is_enumerator (const_tree r)\n+{\n+  /* This doesn't check !DECL_TEMPLATE_PARM_P because such CONST_DECLs\n+     would already have been rejected.  */\n+  if (TREE_CODE (r) == CONST_DECL)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_internal_linkage.\n+   Returns: true if r represents a variable, function, type, template, or\n+   namespace whose name has internal linkage.  Otherwise, false.  */\n+\n+static tree\n+eval_has_internal_linkage (tree r, reflect_kind kind)\n+{\n+  if (eval_is_variable (r, kind) == boolean_false_node\n+      && eval_is_function (r) == boolean_false_node\n+      && eval_is_type (r) == boolean_false_node\n+      && eval_is_template (r) == boolean_false_node\n+      && eval_is_namespace (r) == boolean_false_node)\n+    return boolean_false_node;\n+  r = maybe_get_reflection_fndecl (r);\n+  r = STRIP_TEMPLATE (r);\n+  if (TYPE_P (r))\n+    {\n+      if (TYPE_NAME (r) == NULL_TREE\n+\t  || !DECL_P (TYPE_NAME (r))\n+\t  || (!DECL_IMPLICIT_TYPEDEF_P (TYPE_NAME (r))\n+\t      && TYPE_NAME (r) == TYPE_NAME (TYPE_MAIN_VARIANT (r))\n+\t      && !TYPE_MAIN_DECL (r)))\n+\treturn boolean_false_node;\n+      r = TYPE_NAME (r);\n+    }\n+  if (decl_linkage (r) == lk_internal)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_module_linkage.\n+   Returns: true if r represents a variable, function, type, template, or\n+   namespace whose name has module linkage.  Otherwise, false.  */\n+\n+static tree\n+eval_has_module_linkage (tree r, reflect_kind kind)\n+{\n+  if (eval_is_variable (r, kind) == boolean_false_node\n+      && eval_is_function (r) == boolean_false_node\n+      && eval_is_type (r) == boolean_false_node\n+      && eval_is_template (r) == boolean_false_node\n+      && eval_is_namespace (r) == boolean_false_node)\n+    return boolean_false_node;\n+  r = maybe_get_reflection_fndecl (r);\n+  r = STRIP_TEMPLATE (r);\n+  if (TYPE_P (r))\n+    {\n+      if (TYPE_NAME (r) == NULL_TREE\n+\t  || !DECL_P (TYPE_NAME (r))\n+\t  || (!DECL_IMPLICIT_TYPEDEF_P (TYPE_NAME (r))\n+\t      && TYPE_NAME (r) == TYPE_NAME (TYPE_MAIN_VARIANT (r))\n+\t      && !TYPE_MAIN_DECL (r)))\n+\treturn boolean_false_node;\n+      r = TYPE_NAME (r);\n+    }\n+  if (decl_linkage (r) == lk_external\n+      && DECL_LANG_SPECIFIC (r)\n+      && DECL_MODULE_ATTACH_P (r)\n+      && !DECL_MODULE_EXPORT_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_external_linkage.\n+   Returns: true if r represents a variable, function, type, template, or\n+   namespace whose name has external linkage.  Otherwise, false.  */\n+\n+static tree\n+eval_has_external_linkage (tree r, reflect_kind kind)\n+{\n+  if (eval_is_variable (r, kind) == boolean_false_node\n+      && eval_is_function (r) == boolean_false_node\n+      && eval_is_type (r) == boolean_false_node\n+      && eval_is_template (r) == boolean_false_node\n+      && eval_is_namespace (r) == boolean_false_node)\n+    return boolean_false_node;\n+  r = maybe_get_reflection_fndecl (r);\n+  r = STRIP_TEMPLATE (r);\n+  if (TYPE_P (r))\n+    {\n+      if (TYPE_NAME (r) == NULL_TREE\n+\t  || !DECL_P (TYPE_NAME (r))\n+\t  || (!DECL_IMPLICIT_TYPEDEF_P (TYPE_NAME (r))\n+\t      && TYPE_NAME (r) == TYPE_NAME (TYPE_MAIN_VARIANT (r))\n+\t      && !TYPE_MAIN_DECL (r)))\n+\treturn boolean_false_node;\n+      r = TYPE_NAME (r);\n+    }\n+  if (decl_linkage (r) == lk_external\n+      && !(DECL_LANG_SPECIFIC (r)\n+\t   && DECL_MODULE_ATTACH_P (r)\n+\t   && !DECL_MODULE_EXPORT_P (r)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_c_language_linkage\n+   Returns: true if r represents a variable, function, or function type with\n+   C language linkage. Otherwise, false.  */\n+\n+static tree\n+eval_has_c_language_linkage (tree r, reflect_kind kind)\n+{\n+  if (eval_is_variable (r, kind) == boolean_false_node\n+      && eval_is_function (r) == boolean_false_node\n+      && eval_is_function_type (r) == boolean_false_node)\n+    return boolean_false_node;\n+  r = maybe_get_reflection_fndecl (r);\n+  r = STRIP_TEMPLATE (r);\n+  if (TYPE_P (r))\n+    {\n+      if (TYPE_NAME (r) == NULL_TREE\n+\t  || !DECL_P (TYPE_NAME (r))\n+\t  || (!DECL_IMPLICIT_TYPEDEF_P (TYPE_NAME (r))\n+\t      && TYPE_NAME (r) == TYPE_NAME (TYPE_MAIN_VARIANT (r))\n+\t      && !TYPE_MAIN_DECL (r)))\n+\treturn boolean_false_node;\n+      r = TYPE_NAME (r);\n+    }\n+  if (decl_linkage (r) == lk_external && DECL_LANGUAGE (r) == lang_c)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_linkage.\n+   Returns: true if r represents a variable, function, type, template, or\n+   namespace whose name has any linkage.  Otherwise, false.  */\n+\n+static tree\n+eval_has_linkage (tree r, reflect_kind kind)\n+{\n+  if (eval_is_variable (r, kind) == boolean_false_node\n+      && eval_is_function (r) == boolean_false_node\n+      && eval_is_type (r) == boolean_false_node\n+      && eval_is_template (r) == boolean_false_node\n+      && eval_is_namespace (r) == boolean_false_node)\n+    return boolean_false_node;\n+  r = maybe_get_reflection_fndecl (r);\n+  r = STRIP_TEMPLATE (r);\n+  if (TYPE_P (r))\n+    {\n+      if (TYPE_NAME (r) == NULL_TREE\n+\t  || !DECL_P (TYPE_NAME (r))\n+\t  || (!DECL_IMPLICIT_TYPEDEF_P (TYPE_NAME (r))\n+\t      && TYPE_NAME (r) == TYPE_NAME (TYPE_MAIN_VARIANT (r))\n+\t      && !TYPE_MAIN_DECL (r)))\n+\treturn boolean_false_node;\n+      r = TYPE_NAME (r);\n+    }\n+  if (decl_linkage (r) != lk_none)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_complete_type.\n+   Returns: true if is_type(r) is true and there is some point in the\n+   evaluation context from which the type represented by dealias(r) is\n+   not an incomplete type.  Otherwise, false.  */\n+\n+static tree\n+eval_is_complete_type (const_tree r)\n+{\n+  if (eval_is_type (r) == boolean_true_node)\n+    {\n+      r = strip_typedefs (const_cast<tree> (r));\n+      complete_type (const_cast<tree> (r));\n+      if (COMPLETE_TYPE_P (r))\n+\treturn boolean_true_node;\n+    }\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_enumerable_type.\n+   A type T is enumerable from a point P if either\n+   -- T is a class type complete at point P or\n+   -- T is an enumeration type defined by a declaration D such that D is\n+      reachable from P but P does not occur within an enum-specifier of D.\n+  Returns: true if dealias(r) represents a type that is enumerable from some\n+  point in the evaluation context.  Otherwise, false.  */\n+\n+static tree\n+eval_is_enumerable_type (const_tree r)\n+{\n+  if (CLASS_TYPE_P (r))\n+    {\n+      complete_type (const_cast<tree> (r));\n+      if (COMPLETE_TYPE_P (r))\n+\treturn boolean_true_node;\n+     }\n+  else if (TREE_CODE (r) == ENUMERAL_TYPE)\n+    {\n+      r = TYPE_MAIN_VARIANT (r);\n+      if (!ENUM_IS_OPAQUE (r) && !ENUM_BEING_DEFINED_P (r))\n+\treturn boolean_true_node;\n+    }\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_annotation.\n+   Returns: true if r represents an annotation.  Otherwise, false.  */\n+\n+static tree\n+eval_is_annotation (const_tree r, reflect_kind kind)\n+{\n+  if (kind == REFLECT_ANNOTATION)\n+    {\n+      gcc_assert (TREE_CODE (r) == TREE_LIST);\n+      return boolean_true_node;\n+    }\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_conversion_function.\n+   Returns: true if r represents a function that is a conversion function.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_conversion_function (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_CONV_FN_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_operator_function.\n+   Returns: true if r represents a function that is an operator function.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_operator_function (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+\n+  if (TREE_CODE (r) == FUNCTION_DECL)\n+    {\n+      r = STRIP_TEMPLATE (r);\n+      if (DECL_OVERLOADED_OPERATOR_P (r) && !DECL_CONV_FN_P (r))\n+\treturn boolean_true_node;\n+    }\n+\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_literal_operator.\n+   Returns: true if r represents a function that is a literal operator.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_literal_operator (const_tree r)\n+{\n+  /* No MAYBE_BASELINK_FUNCTIONS here because a literal operator\n+     must be a non-member function.  */\n+  if (TREE_CODE (r) == FUNCTION_DECL && UDLIT_OPER_P (DECL_NAME (r)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_special_member_function.\n+   Returns: true if r represents a function that is a special member function.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_special_member_function (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && special_memfn_p (r) != sfk_none)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_constructor.\n+   Returns: true if r represents a function that is a constructor.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_constructor (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_default_constructor.\n+   Returns: true if r represents a function that is a default constructor.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_default_constructor (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && default_ctor_p (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_copy_constructor.\n+   Returns: true if r represents a function that is a copy constructor.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_copy_constructor (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_COPY_CONSTRUCTOR_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_move_constructor.\n+   Returns: true if r represents a function that is a move constructor.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_move_constructor (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL && DECL_MOVE_CONSTRUCTOR_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_assignment.\n+   Returns: true if r represents a function that is an assignment operator.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_assignment (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL\n+      && DECL_ASSIGNMENT_OPERATOR_P (r)\n+      && DECL_OVERLOADED_OPERATOR_IS (r, NOP_EXPR))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_copy_assignment.\n+   Returns: true if r represents a function that is a copy assignment\n+   operator.  Otherwise, false.  */\n+\n+static tree\n+eval_is_copy_assignment (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL\n+      && special_function_p (r) == sfk_copy_assignment)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_move_assignment.\n+   Returns: true if r represents a function that is a move assignment\n+   operator.  Otherwise, false.  */\n+\n+static tree\n+eval_is_move_assignment (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL\n+      && special_function_p (r) == sfk_move_assignment)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_destructor.\n+   Returns: true if r represents a function that is a destructor.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_destructor (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL\n+      && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_conversion_function_template.\n+   Returns: true if r represents a conversion function template.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_conversion_function_template (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+\n+  if (DECL_FUNCTION_TEMPLATE_P (r) && DECL_CONV_FN_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_operator_function_template.\n+   Returns: true if r represents an operator function template.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_operator_function_template (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+\n+  if (DECL_FUNCTION_TEMPLATE_P (r))\n+    {\n+      r = STRIP_TEMPLATE (r);\n+      if (DECL_OVERLOADED_OPERATOR_P (r) && !DECL_CONV_FN_P (r))\n+\treturn boolean_true_node;\n+    }\n+\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_literal_operator_template.\n+   Returns: true if r represents a literal operator template.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_literal_operator_template (tree r)\n+{\n+  /* No MAYBE_BASELINK_FUNCTIONS here because a literal operator\n+     template must be a non-member function template.  */\n+  r = OVL_FIRST (r);\n+\n+  if (DECL_FUNCTION_TEMPLATE_P (r) && UDLIT_OPER_P (DECL_NAME (r)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_constructor_template.\n+   Returns: true if r represents a function that is an operator function\n+   template.  Otherwise, false.  */\n+\n+static tree\n+eval_is_constructor_template (tree r)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+\n+  if (DECL_FUNCTION_TEMPLATE_P (r) && DECL_CONSTRUCTOR_P (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::operator_of.\n+   Returns: The value of the enumerator from the operators whose corresponding\n+   operator-function-id is the unqualified name of the entity represented by\n+   r.\n+   Throws: meta::exception unless r represents an operator function or\n+   operator function template.  */\n+\n+static tree\n+eval_operator_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t  bool *non_constant_p, tree *jump_target, tree ret_type,\n+\t\t  tree fun)\n+{\n+  if (eval_is_operator_function (r) == boolean_false_node)\n+    return throw_exception (loc, ctx,\n+\t\t\t    \"reflection does not represent an operator \"\n+\t\t\t    \"function\", fun, non_constant_p, jump_target);\n+  r = maybe_get_reflection_fndecl (r);\n+  r = STRIP_TEMPLATE (r);\n+  maybe_init_meta_operators (loc);\n+  int i = IDENTIFIER_ASSIGN_OP_P (DECL_NAME (r)) ? 1 : 0;\n+  int j = IDENTIFIER_CP_INDEX (DECL_NAME (r));\n+  return build_int_cst (ret_type, meta_operators[i][j]);\n+}\n+\n+/* Helper to build a string literal containing '\\0' terminated NAME.\n+   ELT_TYPE must be either char_type_node or char8_type_node, and the\n+   function takes care of converting the name from SOURCE_CHARSET\n+   to ordinary literal charset resp. UTF-8 and returning the string\n+   literal.  Returns NULL_TREE if the conversion failed.  */\n+\n+static tree\n+temp_string_literal (const char *name, tree elt_type)\n+{\n+  cpp_string istr, ostr;\n+  istr.len = strlen (name) + 1;\n+  istr.text = (const unsigned char *) name;\n+  if (!cpp_translate_string (parse_in, &istr, &ostr,\n+\t\t\t     elt_type == char_type_node\n+\t\t\t     ? CPP_STRING : CPP_UTF8STRING, false))\n+    return NULL_TREE;\n+  name = (const char *) ostr.text;\n+  tree ret = build_string_literal (strlen (name) + 1, name, elt_type);\n+  free (const_cast <char *> (name));\n+  return ret;\n+}\n+\n+/* Process std::meta::{,u8}symbol_of.\n+   Returns: A string_view or u8string_view containing the characters of the\n+   operator symbol name corresponding to op, respectively encoded with the\n+   ordinary literal encoding or with UTF-8.\n+   Throws: meta::exception unless the value of op corresponds to one of the\n+   enumerators in operators.  */\n+\n+static tree\n+eval_symbol_of (location_t loc, const constexpr_ctx *ctx, tree expr,\n+\t\tbool *non_constant_p, tree *jump_target, tree elt_type,\n+\t\ttree ret_type, tree fun)\n+{\n+  maybe_init_meta_operators (loc);\n+  if (!tree_fits_uhwi_p (expr))\n+    {\n+    fail:\n+      return throw_exception (loc, ctx,\n+\t\t\t      \"operators argument is not a valid operator\",\n+\t\t\t      fun, non_constant_p, jump_target);\n+    }\n+  unsigned HOST_WIDE_INT val = tree_to_uhwi (expr);\n+  for (int i = 0; i < 2; ++i)\n+    for (int j = OVL_OP_ERROR_MARK + 1; j < OVL_OP_MAX; ++j)\n+      if (ovl_op_info[i][j].meta_name && meta_operators[i][j] == val)\n+\t{\n+\t  const char *name = ovl_op_info[i][j].name;\n+\t  char buf[64];\n+\t  if (const char *sp = strchr (name, ' '))\n+\t    {\n+\t      memcpy (buf, name, sp - name);\n+\t      strcpy (buf + (sp - name), sp + 1);\n+\t      name = buf;\n+\t    }\n+\t  tree str = temp_string_literal (name, elt_type);\n+\t  /* Basic character set ought to be better convertible\n+\t     into ordinary literal character set and must be always\n+\t     convertible into UTF-8.  */\n+\t  gcc_checking_assert (str);\n+\t  releasing_vec args (make_tree_vector_single (str));\n+\t  tree r = build_special_member_call (NULL_TREE,\n+\t\t\t\t\t      complete_ctor_identifier,\n+\t\t\t\t\t      &args, ret_type, LOOKUP_NORMAL,\n+\t\t\t\t\t      tf_warning_or_error);\n+\t  return build_cplus_new (ret_type, r, tf_warning_or_error);\n+\t}\n+  goto fail;\n+}\n+\n+/* has-type (exposition only).\n+   Returns: true if r represents a value, annotation, object, variable,\n+   function whose type does not contain an undeduced placeholder type and\n+   that is not a constructor or destructor, enumerator, non-static data\n+   member, unnamed bit-field, direct base class relationship, data member\n+   description, or function parameter.  Otherwise, false.  */\n+\n+static bool\n+has_type (tree r, reflect_kind kind)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL)\n+    {\n+      if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))\n+\treturn false;\n+      if (undeduced_auto_decl (r))\n+\treturn false;\n+      return true;\n+    }\n+  if (CONSTANT_CLASS_P (r)\n+      || eval_is_variable (r, kind) == boolean_true_node\n+      || eval_is_enumerator (r) == boolean_true_node\n+      || TREE_CODE (r) == FIELD_DECL\n+      || eval_is_annotation (r, kind) == boolean_true_node\n+      || eval_is_function_parameter (r, kind) == boolean_true_node\n+      || eval_is_object (kind) == boolean_true_node\n+      || eval_is_value (kind) == boolean_true_node\n+      || kind == REFLECT_BASE\n+      || kind == REFLECT_DATA_MEMBER_SPEC)\n+    return true;\n+  return false;\n+}\n+\n+/* Helper function for eval_type_of.  Assuming has_type is true, return\n+   the std::meta::type_of type (rather than reflection thereof).  */\n+\n+static tree\n+type_of (tree r, reflect_kind kind)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == PARM_DECL && kind == REFLECT_PARM)\n+    {\n+      r = maybe_update_function_parm (r);\n+      tree fn = DECL_CONTEXT (r);\n+      tree args = FUNCTION_FIRST_USER_PARM (fn);\n+      tree type = FUNCTION_FIRST_USER_PARMTYPE (fn);\n+      while (r != args)\n+\t{\n+\t  args = DECL_CHAIN (args);\n+\t  type = TREE_CHAIN (type);\n+\t}\n+      r = TREE_VALUE (type);\n+    }\n+  else if (kind == REFLECT_BASE)\n+    r = BINFO_TYPE (r);\n+  else if (kind == REFLECT_DATA_MEMBER_SPEC)\n+    r = TREE_VEC_ELT (r, 0);\n+  else if (eval_is_annotation (r, kind) == boolean_true_node)\n+    {\n+      r = TREE_TYPE (TREE_VALUE (TREE_VALUE (r)));\n+      if (CLASS_TYPE_P (r))\n+\t{\n+\t  int quals = cp_type_quals (r);\n+\t  quals |= TYPE_QUAL_CONST;\n+\t  r = cp_build_qualified_type (r, quals);\n+\t}\n+    }\n+  else if (TREE_CODE (r) == FIELD_DECL && DECL_BIT_FIELD_TYPE (r))\n+    r = DECL_BIT_FIELD_TYPE (r);\n+  else\n+    r = TREE_TYPE (r);\n+  return strip_typedefs (r);\n+}\n+\n+/* Process std::meta::type_of.  Returns:\n+   -- If r represents the ith parameter of a function F, then the ith type\n+      in the parameter-type-list of F.\n+   -- Otherwise, if r represents a value, object, variable, function,\n+      non-static data member, or unnamed bit-field, then the type of what is\n+      represented by r.\n+   -- Otherwise, if r represents an annotation, then type_of(constant_of(r)).\n+   -- Otherwise, if r represents an enumerator N of an enumeration E, then:\n+      -- If E is defined by a declaration D that precedes a point P in the\n+\t evaluation context and P does not occur within an enum-specifier of\n+\t D, then a reflection of E.\n+      -- Otherwise, a reflection of the type of N prior to the closing brace\n+\t of the enum-specifier as specified in [dcl.enum].\n+   -- Otherwise, if r represents a direct base class relationship (D,B), then\n+      a reflection of B.\n+   -- Otherwise, for a data member description (T,N,A,W,NUA), a reflection of\n+      the type T.  */\n+\n+static tree\n+eval_type_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t      reflect_kind kind, bool *non_constant_p, tree *jump_target,\n+\t      tree fun)\n+{\n+  if (!has_type (r, kind))\n+    return throw_exception (loc, ctx, \"reflection does not have a type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return get_reflection_raw (loc, type_of (r, kind));\n+}\n+\n+/* Process std::meta::source_location_of.\n+   Returns: If r represents a value, a type other than a class type or an\n+   enumeration type, the global namespace, or a data member description,\n+   then source_location{}.  Otherwise, an implementation-defined\n+   source_location value.  */\n+\n+static tree\n+eval_source_location_of (location_t loc, tree r, reflect_kind kind,\n+\t\t\t tree std_source_location)\n+{\n+  if (!NON_UNION_CLASS_TYPE_P (std_source_location))\n+    {\n+      error_at (loc, \"%qT is not a class type\", std_source_location);\n+      return error_mark_node;\n+    }\n+  location_t rloc = UNKNOWN_LOCATION;\n+  if (kind == REFLECT_BASE)\n+    {\n+      /* We don't track location_t of the base specifiers, so at least\n+\t for now use location_t of the base parent (i.e. the derived\n+\t class).  */\n+      tree c = r;\n+      /* Looping needed for multiple virtual inheritance.  */\n+      while (BINFO_INHERITANCE_CHAIN (c))\n+\tc = BINFO_INHERITANCE_CHAIN (c);\n+      r = BINFO_TYPE (c);\n+    }\n+  if (OVERLOAD_TYPE_P (r) || (TYPE_P (r) && typedef_variant_p (r)))\n+    rloc = DECL_SOURCE_LOCATION (TYPE_NAME (r));\n+  else if (DECL_P (r) && r != global_namespace)\n+    rloc = DECL_SOURCE_LOCATION (r);\n+  else if (eval_is_annotation (r, kind) == boolean_true_node)\n+    rloc = EXPR_LOCATION (TREE_VALUE (TREE_VALUE (r)));\n+  tree decl = NULL_TREE, field = NULL_TREE;\n+  if (rloc != UNKNOWN_LOCATION)\n+    {\n+      /* Make sure __builtin_source_location (which depends on\n+\t std::source_location::__impl) will work without errors.  */\n+      tree name = get_identifier (\"__impl\");\n+      decl = lookup_qualified_name (std_source_location, name);\n+      if (TREE_CODE (decl) != TYPE_DECL)\n+\tdecl = NULL_TREE;\n+      else\n+\t{\n+\t  name = get_identifier (\"__builtin_source_location\");\n+\t  decl = lookup_qualified_name (global_namespace, name);\n+\t  if (TREE_CODE (decl) != FUNCTION_DECL\n+\t      || !fndecl_built_in_p (decl, BUILT_IN_FRONTEND)\n+\t      || DECL_FE_FUNCTION_CODE (decl) != CP_BUILT_IN_SOURCE_LOCATION\n+\t      || !require_deduced_type (decl, tf_warning_or_error))\n+\t    decl = NULL_TREE;\n+\t}\n+    }\n+  if (decl)\n+    {\n+      field = TYPE_FIELDS (std_source_location);\n+      field = next_aggregate_field (field);\n+      /* Make sure std::source_location has exactly a single non-static\n+\t data member (_M_impl in libstdc++, __ptr_ in libc++) with pointer\n+\t type.  Return {._M_impl = &*.Lsrc_locN}.  */\n+      if (field != NULL_TREE\n+\t  && POINTER_TYPE_P (TREE_TYPE (field))\n+\t  && !next_aggregate_field (DECL_CHAIN (field)))\n+\t{\n+\t  tree call = build_call_nary (TREE_TYPE (TREE_TYPE (decl)), decl, 0);\n+\t  SET_EXPR_LOCATION (call, rloc);\n+\t  call = fold_builtin_source_location (call);\n+\t  return build_constructor_single (std_source_location, field, call);\n+\t}\n+    }\n+  return build_constructor (std_source_location, nullptr);\n+}\n+\n+/* If R is (const T &) &foo, get foo.  */\n+\n+static tree\n+maybe_get_reference_referent (tree r)\n+{\n+  if (TREE_CODE (r) == NOP_EXPR\n+      && TYPE_REF_P (TREE_TYPE (r))\n+      && TREE_CODE (TREE_OPERAND (r, 0)) == ADDR_EXPR)\n+    {\n+      STRIP_NOPS (r);\n+      r = TREE_OPERAND (r, 0);\n+    }\n+  return r;\n+}\n+\n+/* Process std::meta::object_of.\n+   Returns:\n+   -- If r represents an object, then r.\n+   -- Otherwise, if r represents a reference, then a reflection of the object\n+      referred to by that reference.\n+   -- Otherwise, r represents a variable; a reflection of the object declared\n+      by that variable.\n+   Throws: meta::exception unless r is a reflection representing either\n+   -- an object with static storage duration, or\n+   -- a variable that either declares or refers to such an object, and if that\n+      variable is a reference R, then either\n+      -- R is usable in constant expressions, or\n+      -- the lifetime of R began within the core constant expression currently\n+\t under evaluation.  */\n+\n+static tree\n+eval_object_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\treflect_kind kind, bool *non_constant_p, tree *jump_target,\n+\t\ttree fun)\n+{\n+  tree orig = r;\n+  if (TYPE_REF_P (TREE_TYPE (r)))\n+    r = DECL_INITIAL (r);\n+  r = maybe_get_reference_referent (r);\n+  // TODO check \"usable in constant expressions\"\n+  if (eval_has_static_storage_duration (orig, kind) == boolean_false_node\n+      && (orig == r\n+\t  || eval_has_static_storage_duration (r, kind) == boolean_false_node))\n+    return throw_exception (loc, ctx, \"reflection does not represent an\"\n+\t\t\t\t      \" object with static storage duration,\"\n+\t\t\t\t      \" or a reference to such an object\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return get_reflection_raw (loc, r, REFLECT_OBJECT);\n+}\n+\n+/* Process std::meta::constant_of.\n+   Let R be a constant expression of type info such that R == r is true.\n+   If r represents an annotation, then let C be its underlying constant.\n+   Effects: Equivalent to:\n+     if constexpr (is_annotation(R)) {\n+       return C;\n+     } else if constexpr (is_array_type(type_of(R)) {\n+       return reflect_constant_array([: R :]);\n+     } else if constexpr (is_function_type(type_of(R)) {\n+       return reflect_function([: R :]);\n+     } else {\n+       return reflect_constant([: R :]);\n+     }\n+   Throws: meta::exception unless either r represents an annotation or\n+   [: R :] is a valid splice-expression.  */\n+\n+static tree\n+eval_constant_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t  reflect_kind kind, bool *non_constant_p, bool *overflow_p,\n+\t\t  tree *jump_target, tree fun)\n+{\n+  tree type;\n+  if (has_type (r, kind))\n+    type = type_of (r, kind);\n+  else\n+    type = maybe_strip_typedefs (r);\n+\n+  /* So that outer_automatic_var_p works below in check_splice_expr.  */\n+  temp_override<tree> ovr (current_function_decl);\n+  current_function_decl = cxx_constexpr_caller (ctx);\n+\n+  if (eval_is_annotation (r, kind) == boolean_true_node)\n+    r = tree_strip_any_location_wrapper (TREE_VALUE (TREE_VALUE (r)));\n+  else if (eval_is_array_type (loc, type) == boolean_true_node)\n+    {\n+      const tsubst_flags_t complain = (cxx_constexpr_quiet_p (ctx)\n+\t\t\t\t       ? tf_none : tf_warning_or_error);\n+      /* Create a call to reflect_constant_array so that we can simply\n+\t let eval_reflect_constant_array do its job.  */\n+      tree name = get_identifier (\"reflect_constant_array\");\n+      tree call = lookup_qualified_name (std_meta_node, name);\n+      if (error_operand_p (call) || !is_overloaded_fn (call))\n+\t{\n+\t  if (complain)\n+\t    error_at (loc, \"couldn%'t look up %<%D::%D%>\", std_meta_node, name);\n+\t  *non_constant_p = true;\n+\t  return NULL_TREE;\n+\t}\n+      /* We want the argument to be a CONSTRUCTOR or a STRING_CST.  */\n+      r = cxx_eval_constant_expression (ctx, r, vc_prvalue, non_constant_p,\n+\t\t\t\t\toverflow_p, jump_target);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      releasing_vec args (make_tree_vector_single (r));\n+      call = finish_call_expr (call, &args, /*disallow_virtual=*/true,\n+\t\t\t       /*koenig_p=*/false, complain);\n+      if (call == error_mark_node)\n+\t{\n+\t  *non_constant_p = true;\n+\t  return NULL_TREE;\n+\t}\n+      return eval_reflect_constant_array (loc, ctx, call, non_constant_p,\n+\t\t\t\t\t  overflow_p, jump_target, fun);\n+    }\n+  else if (eval_is_function_type (type) == boolean_true_node)\n+    return eval_reflect_function (loc, ctx, type, r, non_constant_p,\n+\t\t\t\t  jump_target, fun);\n+  else if (!check_splice_expr (loc, UNKNOWN_LOCATION, r,\n+\t\t\t       /*address_p=*/false,\n+\t\t\t       /*member_access_p=*/false,\n+\t\t\t       /*complain_p=*/false)\n+\t   /* One cannot query the value of a function/function template.\n+\t      ??? But if [:^^X:] where X is a template is OK, should we\n+\t      really throw?  */\n+\t   || eval_is_function (r) == boolean_true_node\n+\t   || eval_is_template (r) == boolean_true_node)\n+    return throw_exception (loc, ctx, \"reflection does not represent an \"\n+\t\t\t\t      \"annotation or a valid argument to \"\n+\t\t\t\t      \"a splice-expression\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+\n+  r = cxx_eval_constant_expression (ctx, r, vc_prvalue, non_constant_p,\n+\t\t\t\t    overflow_p, jump_target);\n+  if (*jump_target || *non_constant_p)\n+    return NULL_TREE;\n+  /* Figure out the type for reflect_constant.  */\n+  type = TREE_TYPE (convert_from_reference (r));\n+  type = type_decays_to (type);\n+  type = cv_unqualified (type);\n+\n+  return eval_reflect_constant (loc, ctx, type, r, non_constant_p, jump_target,\n+\t\t\t\tfun);\n+}\n+\n+/* Process std::meta::dealias.\n+   Returns: If r represents an entity, then a reflection representing the\n+   underlying entity of what r represents.  Otherwise, r.\n+   This implements LWG 4427 so we do not throw.  */\n+\n+static tree\n+eval_dealias (location_t loc, tree r, reflect_kind kind)\n+{\n+  r = maybe_strip_typedefs (r);\n+  if (TREE_CODE (r) == NAMESPACE_DECL)\n+    r = ORIGINAL_NAMESPACE (r);\n+  return get_reflection_raw (loc, r, kind);\n+}\n+\n+/* Process std::meta::is_noexcept.\n+   Returns: true if r represents a noexcept function type or a function\n+   with a non-throwing exception specification ([except.spec]).\n+   Otherwise, false.\n+   Note: If r represents a function template that is declared noexcept,\n+   is_noexcept (r) is still false because in general such queries\n+   for templates cannot be answered.  */\n+\n+static tree\n+eval_is_noexcept (tree r)\n+{\n+  if (eval_is_function (r) == boolean_true_node)\n+    {\n+      r = maybe_get_reflection_fndecl (r);\n+      maybe_instantiate_noexcept (r);\n+      if (TYPE_NOTHROW_P (TREE_TYPE (r)))\n+\treturn boolean_true_node;\n+      else\n+\treturn boolean_false_node;\n+    }\n+\n+  if (eval_is_type (r) == boolean_true_node\n+      && eval_is_function_type (r) == boolean_true_node)\n+    {\n+      if (TYPE_NOTHROW_P (r))\n+\treturn boolean_true_node;\n+      else\n+\treturn boolean_false_node;\n+    }\n+\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_const.\n+   Let T be type_of(r) if has-type(r) is true.  Otherwise, let T be dealias(r).\n+   Returns: true if T represents a const type, or a const-qualified function\n+   type.  Otherwise, false.  */\n+\n+static tree\n+eval_is_const (tree r, reflect_kind kind)\n+{\n+  if (has_type (r, kind))\n+    r = type_of (r, kind);\n+  else\n+    r = maybe_strip_typedefs (r);\n+  r = strip_array_types (r);\n+  if (TREE_CODE (r) == METHOD_TYPE)\n+    {\n+      if (type_memfn_quals (r) & TYPE_QUAL_CONST)\n+\treturn boolean_true_node;\n+    }\n+  else if (TYPE_P (r) && TYPE_READONLY (r))\n+    return boolean_true_node;\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_volatile.\n+   Let T be type_of(r) if has-type(r) is true.  Otherwise, let T be dealias(r).\n+   Returns: true if T represents a volatile type, or a volatile-qualified\n+   function type.  Otherwise, false.  */\n+\n+static tree\n+eval_is_volatile (tree r, reflect_kind kind)\n+{\n+  if (has_type (r, kind))\n+    r = type_of (r, kind);\n+  else\n+    r = maybe_strip_typedefs (r);\n+  r = strip_array_types (r);\n+  if (TREE_CODE (r) == METHOD_TYPE)\n+    {\n+      if (type_memfn_quals (r) & TYPE_QUAL_VOLATILE)\n+\treturn boolean_true_node;\n+    }\n+  else if (TYPE_P (r) && TYPE_VOLATILE (r))\n+    return boolean_true_node;\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_template_arguments.\n+   Returns: true if r represents a specialization of a function template,\n+   variable template, class template, or an alias template.  Otherwise,\n+   false.  */\n+\n+static tree\n+eval_has_template_arguments (tree r)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  /* Presumably for\n+       typedef cls_tmpl<int> TYPE;\n+     'has_template_arguments (^^TYPE)' should be false?  */\n+  if (TYPE_P (r) && typedef_variant_p (r) && !TYPE_ALIAS_P (r))\n+    return boolean_false_node;\n+  if (primary_template_specialization_p (r)\n+      || variable_template_specialization_p (r))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::template_of.\n+   Returns: A reflection of the template of the specialization represented\n+   by r.\n+   Throws: meta::exception unless has_template_arguments(r) is true.  */\n+\n+static tree\n+eval_template_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t  bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  if (eval_has_template_arguments (r) != boolean_true_node)\n+    return throw_exception_notargs (loc, ctx, fun, non_constant_p, jump_target);\n+\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TYPE_P (r) && typedef_variant_p (r))\n+    r = TI_TEMPLATE (TYPE_ALIAS_TEMPLATE_INFO (r));\n+  else if (CLASS_TYPE_P (r) && CLASSTYPE_TEMPLATE_INFO (r))\n+    r = CLASSTYPE_TI_TEMPLATE (r);\n+  else if (VAR_OR_FUNCTION_DECL_P (r) && DECL_TEMPLATE_INFO (r))\n+    r = DECL_TI_TEMPLATE (r);\n+  else\n+    gcc_assert (false);\n+\n+  gcc_assert (TREE_CODE (r) == TEMPLATE_DECL);\n+  return get_reflection_raw (loc, r);\n+}\n+\n+/* Process std::meta::has_parent\n+   Returns:\n+   -- If r represents the global namespace, then false.\n+   -- Otherwise, if r represents an entity that has C language linkage,\n+      then false.\n+   -- Otherwise, if r represents an entity that has a language linkage\n+      other than C++ language linkage, then an implementation-defined value.\n+   -- Otherwise, if r represents a type that is neither a class nor enumeration\n+      type, then false.\n+   -- Otherwise, if r represents an entity or direct base class relationship,\n+      then true.\n+   -- Otherwise, false.  */\n+\n+static tree\n+eval_has_parent (tree r, reflect_kind kind)\n+{\n+  if (kind == REFLECT_OBJECT\n+      || CONSTANT_CLASS_P (r)\n+      || r == global_namespace\n+      || kind == REFLECT_DATA_MEMBER_SPEC)\n+    return boolean_false_node;\n+  if (TYPE_P (r))\n+    {\n+      if (TYPE_NAME (r)\n+\t  && DECL_P (TYPE_NAME (r))\n+\t  && DECL_LANGUAGE (TYPE_NAME (r)) == lang_c)\n+\treturn boolean_false_node;\n+      else if (OVERLOAD_TYPE_P (r) || typedef_variant_p (r))\n+\treturn boolean_true_node;\n+      else\n+\treturn boolean_false_node;\n+    }\n+  r = maybe_get_reflection_fndecl (r);\n+  if (kind == REFLECT_BASE)\n+    return boolean_true_node;\n+  if (!DECL_P (r))\n+    return boolean_false_node;\n+  if (TREE_CODE (r) != NAMESPACE_DECL && DECL_LANGUAGE (r) == lang_c)\n+    return boolean_false_node;\n+  return boolean_true_node;\n+}\n+\n+/* Process std::meta::parent_of.\n+   Returns:\n+   -- If r represents a non-static data member that is a direct member of an\n+      anonymous union, or an unnamed bit-field declared within the\n+      member-specification of such a union, then a reflection representing the\n+      innermost enclosing anonymous union.\n+   -- Otherwise, if r represents an enumerator, then a reflection representing\n+      the corresponding enumeration type.\n+   -- Otherwise, if r represents a direct base class relationship (D,B), then\n+      a reflection representing D.\n+   -- Otherwise, let E be a class, function, or namespace whose class scope,\n+      function parameter scope, or namespace scope, respectively, is the\n+      innermost such scope that either is, or encloses, the target scope of a\n+      declaration of what is represented by r.\n+      -- If E is the function call operator of a closure type for a\n+\t consteval-block-declaration, then parent_of(parent_of(^^E)).\n+      -- Otherwise, ^^E.  */\n+\n+static tree\n+eval_parent_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\treflect_kind kind, bool *non_constant_p, tree *jump_target,\n+\t\ttree fun)\n+{\n+  if (eval_has_parent (r, kind) != boolean_true_node)\n+    return throw_exception (loc, ctx, \"reflection does not represent an \"\n+\t\t\t\t      \"entity with parent\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  tree c;\n+  r = maybe_get_reflection_fndecl (r);\n+  if (TYPE_P (r))\n+    {\n+      if (TYPE_NAME (r) && DECL_P (TYPE_NAME (r)))\n+\tc = CP_DECL_CONTEXT (TYPE_NAME (r));\n+      else\n+\tc = CP_TYPE_CONTEXT (r);\n+    }\n+  else if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))\n+    {\n+      tree v = DECL_VALUE_EXPR (r);\n+      if (v != error_mark_node && TREE_CODE (v) == COMPONENT_REF)\n+\tc = CP_DECL_CONTEXT (TREE_OPERAND (v, 1));\n+      else\n+\tc = CP_DECL_CONTEXT (r);\n+    }\n+  else if (kind == REFLECT_BASE)\n+    {\n+      c = r;\n+      /* Looping needed for multiple virtual inheritance.  */\n+      while (BINFO_INHERITANCE_CHAIN (c))\n+\tc = BINFO_INHERITANCE_CHAIN (c);\n+      c = BINFO_TYPE (c);\n+    }\n+  else\n+    c = CP_DECL_CONTEXT (r);\n+  tree lam;\n+  while (LAMBDA_FUNCTION_P (c)\n+\t && (lam = CLASSTYPE_LAMBDA_EXPR (CP_DECL_CONTEXT (c)))\n+\t && LAMBDA_EXPR_CONSTEVAL_BLOCK_P (lam))\n+    c = CP_TYPE_CONTEXT (CP_DECL_CONTEXT (c));\n+  return get_reflection_raw (loc, c);\n+}\n+\n+/* Build std::vector<info>{ ELTS }.  */\n+\n+static tree\n+get_vector_of_info_elts (vec<constructor_elt, va_gc> *elts)\n+{\n+  tree ctor = build_constructor (init_list_type_node, elts);\n+  CONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;\n+  TREE_CONSTANT (ctor) = true;\n+  TREE_STATIC (ctor) = true;\n+  tree type = get_vector_info ();\n+  if (!type)\n+    return error_mark_node;\n+  tree r = finish_compound_literal (type, ctor, tf_warning_or_error,\n+\t\t\t\t    fcl_functional);\n+  if (TREE_CODE (r) == TARGET_EXPR)\n+    r = TARGET_EXPR_INITIAL (r);\n+  return r;\n+}\n+\n+/* Process std::meta::parameters_of.\n+   Returns:\n+   -- If r represents a function F, then a vector containing reflections of\n+      the parameters of F, in the order in which they appear in a declaration\n+      of F.\n+   -- Otherwise, r represents a function type T; a vector containing\n+      reflections of the types in parameter-type-list of T, in the order in\n+      which they appear in the parameter-type-list.\n+\n+   Throws: meta::exception unless r represents a function or a function\n+   type.  */\n+\n+static tree\n+eval_parameters_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t    bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  if (eval_is_function (r) != boolean_true_node\n+      && (eval_is_type (r) != boolean_true_node\n+\t  || eval_is_function_type (r) != boolean_true_node))\n+    return throw_exception_nofn (loc, ctx, fun, non_constant_p, jump_target);\n+\n+  r = maybe_get_reflection_fndecl (r);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  tree args = (TREE_CODE (r) == FUNCTION_DECL\n+\t       ? FUNCTION_FIRST_USER_PARM (r)\n+\t       : TYPE_ARG_TYPES (r));\n+  for (tree arg = args; arg && arg != void_list_node; arg = TREE_CHAIN (arg))\n+    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t    get_reflection_raw (location_of (arg), arg,\n+\t\t\t\t\t\tREFLECT_PARM));\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Process std::meta::variable_of.\n+   Returns: The reflection of the parameter variable corresponding to r.\n+\n+   Throws: meta::exception unless\n+   -- represents a parameter of a function F and\n+   -- there is a point P in the evaluation context for which the innermost\n+      non-block scope enclosing P is the function parameter scope associated\n+      with F.  */\n+\n+static tree\n+eval_variable_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t  reflect_kind kind, bool *non_constant_p, tree *jump_target,\n+\t\t  tree fun)\n+{\n+  if (eval_is_function_parameter (r, kind) == boolean_false_node\n+      || DECL_CONTEXT (r) != current_function_decl)\n+    return throw_exception (loc, ctx, \"reflection does not represent \"\n+\t\t\t\t      \"parameter of current function\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  r = maybe_update_function_parm (r);\n+  return get_reflection_raw (loc, r, REFLECT_UNDEF);\n+}\n+\n+/* Process std::meta::return_type_of.\n+   Returns: The reflection of the return type of the function or function type\n+   represented by r.\n+\n+   Throws: meta::exception unless either r represents a function and\n+   has-type(r) is true or r represents a function type.  */\n+\n+static tree\n+eval_return_type_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t     reflect_kind kind, bool *non_constant_p, tree *jump_target,\n+\t\t     tree fun)\n+{\n+  if ((eval_is_function (r) != boolean_true_node || !has_type (r, kind))\n+      && (eval_is_type (r) != boolean_true_node\n+\t  || eval_is_function_type (r) != boolean_true_node))\n+    return throw_exception_nofn (loc, ctx, fun, non_constant_p, jump_target);\n+\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (TREE_CODE (r) == FUNCTION_DECL)\n+    r = TREE_TYPE (r);\n+  r = TREE_TYPE (r);\n+  return get_reflection_raw (loc, r, REFLECT_UNDEF);\n+}\n+\n+/* Process std::meta::offset_of.\n+   Let V be the offset in bits from the beginning of a complete object of the\n+   type represented by parent_of(r) to the subobject associated with the\n+   entity represented by r.\n+   Returns: {V / CHAR_BIT, V % CHAR_BIT}.\n+   Throws: meta::exception unless r represents a non-static data member,\n+   unnamed bit-field, or direct base class relationship (D,B) for which either\n+   B is not a virtual base class or D is not an abstract class.  */\n+\n+static tree\n+eval_offset_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\treflect_kind kind, tree member_offset, bool *non_constant_p,\n+\t\ttree *jump_target, tree fun)\n+{\n+  tree byte_off = NULL_TREE, bit_off = NULL_TREE;\n+  if (kind == REFLECT_BASE)\n+    {\n+      tree d = r;\n+      /* Looping needed for multiple virtual inheritance.  */\n+      while (BINFO_INHERITANCE_CHAIN (d))\n+\td = BINFO_INHERITANCE_CHAIN (d);\n+      d = BINFO_TYPE (d);\n+      if (BINFO_VIRTUAL_P (r) && ABSTRACT_CLASS_TYPE_P (d))\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"reflection of virtual direct base \"\n+\t\t\t\t\"relationship with abstract derived \"\n+\t\t\t\t\"class\", fun, non_constant_p, jump_target);\n+      byte_off = BINFO_OFFSET (r);\n+    }\n+  else if (TREE_CODE (r) != FIELD_DECL)\n+    return throw_exception (loc, ctx, \"reflection unsuitable for offset\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  else\n+    bit_off = bit_position (r);\n+  if (TREE_CODE (bit_off ? bit_off : byte_off) != INTEGER_CST)\n+    return throw_exception (loc, ctx, \"non-constant offset for offset_of\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (TREE_CODE (member_offset) != RECORD_TYPE)\n+    {\n+    fail:\n+      error_at (loc, \"unexpected return type of %qs\", \"std::meta::offset_of\");\n+      return build_zero_cst (member_offset);\n+    }\n+  tree bytes = next_aggregate_field (TYPE_FIELDS (member_offset));\n+  if (!bytes || !INTEGRAL_TYPE_P (TREE_TYPE (bytes)))\n+    goto fail;\n+  tree bits = next_aggregate_field (DECL_CHAIN (bytes));\n+  if (!bits || !INTEGRAL_TYPE_P (TREE_TYPE (bits)))\n+    goto fail;\n+  if (next_aggregate_field (DECL_CHAIN (bits)))\n+    goto fail;\n+  tree bytesv;\n+  if (byte_off)\n+    bytesv = byte_off;\n+  else\n+    bytesv = size_binop (TRUNC_DIV_EXPR, bit_off, bitsize_unit_node);\n+  bytesv = fold_convert (TREE_TYPE (bytes), bytesv);\n+  tree bitsv;\n+  if (byte_off)\n+    bitsv = build_zero_cst (TREE_TYPE (bits));\n+  else\n+    {\n+      bitsv = size_binop (TRUNC_MOD_EXPR, bit_off, bitsize_unit_node);\n+      bitsv = fold_convert (TREE_TYPE (bits), bitsv);\n+    }\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  CONSTRUCTOR_APPEND_ELT (elts, bytes, bytesv);\n+  CONSTRUCTOR_APPEND_ELT (elts, bits, bitsv);\n+  return build_constructor (member_offset, elts);\n+}\n+\n+/* Process std::meta::size_of.\n+   Returns: If r represents\n+     -- a non-static data member of type T,\n+     -- a data member description (T,N,A,W,NUA), or\n+     -- dealias(r) represents a type T,\n+   then sizeof(T) if T is not a reference type and size_of(add_pointer(^^T))\n+   otherwise.  Otherwise, size_of(type_of(r)).\n+\n+   Throws: meta::exception unless all of the following conditions are met:\n+     -- dealias(r) is a reflection of a type, object, value, variable of\n+\tnon-reference type, non-static data member that is not a bit-field,\n+\tdirect base class relationship, or data member description\n+\t(T,N,A,W,NUA) where W is not _|_.\n+     -- If dealias(r) represents a type, then is_complete_type(r) is true.  */\n+\n+static tree\n+eval_size_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t      reflect_kind kind, tree ret_type, bool *non_constant_p,\n+\t      tree *jump_target, tree fun)\n+{\n+  if (eval_is_type (r) != boolean_true_node\n+      && eval_is_object (kind) != boolean_true_node\n+      && eval_is_value (kind) != boolean_true_node\n+      && (eval_is_variable (r, kind) != boolean_true_node\n+\t  || TYPE_REF_P (TREE_TYPE (r)))\n+      && (TREE_CODE (r) != FIELD_DECL || DECL_C_BIT_FIELD (r))\n+      && kind != REFLECT_BASE\n+      && (kind != REFLECT_DATA_MEMBER_SPEC || TREE_VEC_ELT (r, 3)))\n+    return throw_exception (loc, ctx, \"reflection not suitable for size_of\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (!INTEGRAL_TYPE_P (ret_type))\n+    {\n+      error_at (loc, \"unexpected return type of %qs\", \"std::meta::size_of\");\n+      return build_zero_cst (ret_type);\n+    }\n+  tree type;\n+  if (TYPE_P (r))\n+    type = r;\n+  else if (TREE_CODE (r) == FIELD_DECL)\n+    type = TREE_TYPE (r);\n+  else\n+    type = type_of (r, kind);\n+  if (!complete_type_or_maybe_complain (type, NULL_TREE, tf_none))\n+    return throw_exception (loc, ctx, \"reflection with incomplete type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  tree ret = c_sizeof_or_alignof_type (loc, type, true, false, 0);\n+  if (ret == error_mark_node)\n+    return throw_exception (loc, ctx, \"reflection with incomplete type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return fold_convert (ret_type, ret);\n+}\n+\n+/* Process std::meta::alignment_of.\n+   Returns:\n+   -- If dealias(r) represents a type T, then alignment_of(add_pointer(r)) if\n+      T is a reference type and the alignment requirement of T otherwise.\n+   -- Otherwise, if dealias(r) represents a variable or object, then the\n+      alignment requirement of the variable or object.\n+   -- Otherwise, if r represents a direct base class relationship, then\n+      alignment_of(type_of(r)).\n+   -- Otherwise, if r represents a non-static data member M of a class C,\n+      then the alignment of the direct member subobject corresponding to M of a\n+      complete object of type C.\n+   -- Otherwise, r represents a data member description (T,N,A,W,NUA).\n+      If A is not _|_, then the value A.  Otherwise, alignment_of(^^T).\n+   Throws: meta::exception unless all of the following conditions are met:\n+   -- dealias(r) is a reflection of a type, object, variable of non-reference\n+      type, non-static data member that is not a bit-field, direct base class\n+      relationship, or data member description (T,N,A,W,NUA) where W is _|_.\n+   -- If dealias(r) represents a type, then is_complete_type(r) is true.  */\n+\n+static tree\n+eval_alignment_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t   reflect_kind kind, tree ret_type, bool *non_constant_p,\n+\t\t   tree *jump_target, tree fun)\n+{\n+  if (eval_is_type (r) != boolean_true_node\n+      && eval_is_object (kind) != boolean_true_node\n+      && (eval_is_variable (r, kind) != boolean_true_node\n+\t  || TYPE_REF_P (TREE_TYPE (r)))\n+      && (TREE_CODE (r) != FIELD_DECL || DECL_C_BIT_FIELD (r))\n+      && kind != REFLECT_BASE\n+      && (kind != REFLECT_DATA_MEMBER_SPEC || TREE_VEC_ELT (r, 3)))\n+    return throw_exception (loc, ctx, \"reflection not suitable for alignment_of\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (!INTEGRAL_TYPE_P (ret_type))\n+    {\n+      error_at (loc, \"unexpected return type of %qs\", \"std::meta::alignment_of\");\n+      return build_zero_cst (ret_type);\n+    }\n+  tree type;\n+  if (kind == REFLECT_DATA_MEMBER_SPEC)\n+    {\n+      if (TREE_VEC_ELT (r, 2))\n+\treturn fold_convert (ret_type, TREE_VEC_ELT (r, 2));\n+      else\n+\ttype = TREE_VEC_ELT (r, 0);\n+    }\n+  else if (kind == REFLECT_BASE)\n+    type = BINFO_TYPE (r);\n+  else if (TREE_CODE (r) == FIELD_DECL\n+\t   || eval_is_variable (r, kind) == boolean_true_node\n+\t   || (eval_is_object (kind) == boolean_true_node\n+\t       && DECL_P (r)\n+\t       && TREE_CODE (r) != FUNCTION_DECL))\n+    return build_int_cst (ret_type, MAX (DECL_ALIGN (r) / BITS_PER_UNIT, 1));\n+  else if (TYPE_P (r))\n+    type = r;\n+  else if (eval_is_object (kind) == boolean_true_node)\n+    {\n+      if (TREE_CODE (r) == COMPONENT_REF)\n+\treturn build_int_cst (ret_type, MAX (DECL_ALIGN (TREE_OPERAND (r, 1))\n+\t\t\t\t\t     / BITS_PER_UNIT, 1));\n+      else\n+\ttype = TREE_TYPE (r);\n+    }\n+  else\n+    gcc_unreachable ();\n+  if (TYPE_REF_P (type))\n+    type = ptr_type_node;\n+  if (!complete_type_or_maybe_complain (type, NULL_TREE, tf_none))\n+    return throw_exception (loc, ctx, \"reflection with incomplete type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (FUNC_OR_METHOD_TYPE_P (type))\n+    return throw_exception (loc, ctx, \"alignment_of on function type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  tree ret = c_sizeof_or_alignof_type (loc, type, false, true, 0);\n+  if (ret == error_mark_node)\n+    return throw_exception (loc, ctx, \"reflection with incomplete type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return fold_convert (ret_type, ret);\n+}\n+\n+/* Process std::meta::bit_size_of.\n+   Returns:\n+     -- If r represents an unnamed bit-field or a non-static data member that\n+\tis a bit-field with width W, then W.\n+     -- Otherwise, if r represents a data member description (T,N,A,W,NUA)\n+\tand W is not _|_, then W.\n+     -- Otherwise, CHAR_BIT * size_of(r).\n+\n+   Throws: meta::exception unless all of the following conditions are met:\n+\n+     -- dealias(r) is a reflection of a type, object, value, variable of\n+\tnon-reference type, non-static data member, unnamed bit-field, direct\n+\tbase class relationship, or data member description.\n+     -- If dealias(r) represents a type T, there is a point within the\n+\tevaluation context from which T is not incomplete.  */\n+\n+static tree\n+eval_bit_size_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t  reflect_kind kind, tree ret_type, bool *non_constant_p,\n+\t\t  tree *jump_target, tree fun)\n+{\n+  if (eval_is_type (r) != boolean_true_node\n+      && eval_is_object (kind) != boolean_true_node\n+      && eval_is_value (kind) != boolean_true_node\n+      && (eval_is_variable (r, kind) != boolean_true_node\n+\t  || TYPE_REF_P (TREE_TYPE (r)))\n+      && TREE_CODE (r) != FIELD_DECL\n+      && kind != REFLECT_BASE\n+      && kind != REFLECT_DATA_MEMBER_SPEC)\n+    return throw_exception (loc, ctx,\n+\t\t\t    \"reflection not suitable for bit_size_of\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (!INTEGRAL_TYPE_P (ret_type))\n+    {\n+      error_at (loc, \"unexpected return type of %qs\",\n+\t\t\"std::meta::bit_size_of\");\n+      return build_zero_cst (ret_type);\n+    }\n+  tree type;\n+  if (TREE_CODE (r) == FIELD_DECL && DECL_C_BIT_FIELD (r))\n+    return fold_convert (ret_type, DECL_SIZE (r));\n+  else if (TYPE_P (r))\n+    type = r;\n+  else if (TREE_CODE (r) == FIELD_DECL)\n+    type = TREE_TYPE (r);\n+  else if (kind == REFLECT_DATA_MEMBER_SPEC && TREE_VEC_ELT (r, 3))\n+    return fold_convert (ret_type, TREE_VEC_ELT (r, 3));\n+  else\n+    type = type_of (r, kind);\n+  if (!complete_type_or_maybe_complain (type, NULL_TREE, tf_none))\n+    return throw_exception (loc, ctx, \"reflection with incomplete type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  tree ret = c_sizeof_or_alignof_type (loc, type, true, false, 0);\n+  if (ret == error_mark_node)\n+    return throw_exception (loc, ctx, \"reflection with incomplete type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  ret = size_binop (MULT_EXPR, ret, size_int (BITS_PER_UNIT));\n+  return fold_convert (ret_type, ret);\n+}\n+\n+/* Process std::meta::has_identifier.\n+   Returns:\n+   -- If r represents an entity that has a typedef name for linkage purposes,\n+      then true.\n+   -- Otherwise, if r represents an unnamed entity, then false.\n+   -- Otherwise, if r represents a type alias, then !has_template_arguments(r).\n+   -- Otherwise, if r represents a type, then true if\n+      -- r represents a cv-unqualified class type and has_template_arguments(r)\n+\t is false, or\n+      -- r represents a cv-unqualified enumeration type.\n+      Otherwise, false.\n+   -- Otherwise, if r represents a class type, then !has_template_arguments(r).\n+   -- Otherwise, if r represents a function, then true if\n+      has_template_arguments(r) is false and the function is not a constructor,\n+      destructor, operator function, or conversion function.  Otherwise, false.\n+   -- Otherwise, if r represents a template, then true if r does not represent\n+      a constructor template, operator function template, or conversion\n+      function template.  Otherwise, false.\n+   -- Otherwise, if r represents the ith parameter of a function F that is an\n+      (implicit or explicit) specialization of a templated function T and the\n+      ith parameter of the instantiated declaration of T whose template\n+      arguments are those of F would be instantiated from a pack, then false.\n+   -- Otherwise, if r represents the parameter P of a function F, then let S\n+      be the set of declarations, ignoring any explicit instantiations, that\n+      precede some point in the evaluation context and that declare either F\n+      or a templated function of which F is a specialization; true if\n+      -- there is a declaration D in S that introduces a name N for either P\n+\t or the parameter corresponding to P in the templated function that\n+\t D declares and\n+      -- no declaration in S does so using any name other than N.\n+      Otherwise, false.\n+   -- Otherwise, if r represents a variable, then false if the declaration of\n+      that variable was instantiated from a function parameter pack.\n+      Otherwise, !has_template_arguments(r).\n+   -- Otherwise, if r represents a structured binding, then false if the\n+      declaration of that structured binding was instantiated from a\n+      structured binding pack.  Otherwise, true.\n+   -- Otherwise, if r represents an enumerator, non-static-data member,\n+      namespace, or namespace alias, then true.\n+   -- Otherwise, if r represents a direct base class relationship, then\n+      has_identifier(type_of(r)).\n+   -- Otherwise, r represents a data member description (T,N,A,W,NUA); true if\n+      N is not _|_.  Otherwise, false.  */\n+\n+static tree\n+eval_has_identifier (tree r, reflect_kind kind)\n+{\n+  r = maybe_get_reflection_fndecl (r);\n+  if (kind == REFLECT_BASE)\n+    {\n+      r = type_of (r, kind);\n+      kind = REFLECT_UNDEF;\n+    }\n+  if (DECL_P (r)\n+      && kind != REFLECT_PARM\n+      && (!DECL_NAME (r) || IDENTIFIER_ANON_P (DECL_NAME (r))))\n+    return boolean_false_node;\n+  if (TYPE_P (r) && (!TYPE_NAME (r)\n+\t\t     || (TYPE_ANON_P (r) && !typedef_variant_p (r))\n+\t\t     || (DECL_P (TYPE_NAME (r))\n+\t\t\t && !DECL_NAME (TYPE_NAME (r)))))\n+    return boolean_false_node;\n+  if (eval_is_type_alias (r) == boolean_true_node\n+      || (CLASS_TYPE_P (r) && !cv_qualified_p (r)))\n+    {\n+      if (eval_has_template_arguments (r) == boolean_true_node)\n+\treturn boolean_false_node;\n+      else\n+\treturn boolean_true_node;\n+    }\n+  if (TYPE_P (r))\n+    {\n+      if (TREE_CODE (r) == ENUMERAL_TYPE && !cv_qualified_p (r))\n+\treturn boolean_true_node;\n+      else\n+\treturn boolean_false_node;\n+    }\n+  if (eval_is_function (r) == boolean_true_node)\n+    {\n+      if (eval_has_template_arguments (r) == boolean_true_node\n+\t  || eval_is_constructor (r) == boolean_true_node\n+\t  || eval_is_destructor (r) == boolean_true_node\n+\t  || eval_is_operator_function (r) == boolean_true_node\n+\t  || eval_is_conversion_function (r) == boolean_true_node)\n+\treturn boolean_false_node;\n+      else\n+\treturn boolean_true_node;\n+    }\n+  if (eval_is_template (r) == boolean_true_node)\n+    {\n+      if (eval_is_constructor_template (r) == boolean_true_node\n+\t  || eval_is_operator_function_template (r) == boolean_true_node\n+\t  || eval_is_conversion_function_template (r) == boolean_true_node)\n+\treturn boolean_false_node;\n+      else\n+\treturn boolean_true_node;\n+    }\n+  if (eval_is_function_parameter (r, kind) == boolean_true_node)\n+    {\n+      r = maybe_update_function_parm (r);\n+      if (MULTIPLE_NAMES_PARM_P (r))\n+\treturn boolean_false_node;\n+      if (DECL_NAME (r))\n+\t{\n+\t  if (strchr (IDENTIFIER_POINTER (DECL_NAME (r)), '#'))\n+\t    return boolean_false_node;\n+\t  else\n+\t    return boolean_true_node;\n+\t}\n+      if (lookup_attribute (\"old parm name\", DECL_ATTRIBUTES (r)))\n+\treturn boolean_true_node;\n+      else\n+\treturn boolean_false_node;\n+    }\n+  if (eval_is_variable (r, kind) == boolean_true_node)\n+    {\n+      if (strchr (IDENTIFIER_POINTER (DECL_NAME (r)), '#'))\n+\treturn boolean_false_node;\n+      if (eval_has_template_arguments (r) == boolean_true_node)\n+\treturn boolean_false_node;\n+      else\n+\treturn boolean_true_node;\n+    }\n+  if (eval_is_structured_binding (r, kind) == boolean_true_node)\n+    {\n+      if (strchr (IDENTIFIER_POINTER (DECL_NAME (r)), '#'))\n+\treturn boolean_false_node;\n+      else\n+\treturn boolean_true_node;\n+    }\n+  if (eval_is_enumerator (r) == boolean_true_node\n+      || TREE_CODE (r) == FIELD_DECL\n+      || (TREE_CODE (r) == NAMESPACE_DECL && r != global_namespace))\n+    return boolean_true_node;\n+  if (kind == REFLECT_DATA_MEMBER_SPEC && TREE_VEC_ELT (r, 1))\n+    return boolean_true_node;\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::{,u8}identifier_of.\n+   Let E be UTF-8 for u8identifier_of, and otherwise the ordinary literal\n+   encoding.\n+   Returns: An NTMBS, encoded with E, determined as follows:\n+   -- If r represents an entity with a typedef name for linkage purposes,\n+      then that name.\n+   -- Otherwise, if r represents a literal operator or literal operator\n+      template, then the ud-suffix of the operator or operator template.\n+   -- Otherwise, if r represents the parameter P of a function F, then let S\n+      be the set of declarations, ignoring any explicit instantiations, that\n+      precede some point in the evaluation context and that declare either F\n+      or a templated function of which F is a specialization; the name that\n+      was introduced by a declaration in S for the parameter corresponding\n+      to P.\n+   -- Otherwise, if r represents an entity, then the identifier introduced by\n+      the declaration of that entity.\n+   -- Otherwise, if r represents a direct base class relationship, then\n+      identifier_of(type_of(r)) or u8identifier_of(type_of(r)), respectively.\n+   -- Otherwise, r represents a data member description (T,N,A,W,NUA);\n+      a string_view or u8string_view, respectively, containing the identifier\n+      N.\n+   Throws: meta::exception unless has_identifier(r) is true and the identifier\n+   that would be returned (see above) is representable by E.  */\n+\n+static tree\n+eval_identifier_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t    reflect_kind kind, bool *non_constant_p, tree *jump_target,\n+\t\t    tree elt_type, tree ret_type, tree fun)\n+{\n+  if (eval_has_identifier (r, kind) == boolean_false_node)\n+    return throw_exception (loc, ctx,\n+\t\t\t    \"reflection with has_identifier false\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  r = maybe_get_reflection_fndecl (r);\n+  const char *name = NULL;\n+  if (kind == REFLECT_BASE)\n+    {\n+      r = type_of (r, kind);\n+      kind = REFLECT_UNDEF;\n+    }\n+  if (eval_is_function_parameter (r, kind) == boolean_true_node)\n+    {\n+      r = maybe_update_function_parm (r);\n+      if (DECL_NAME (r))\n+\tname = IDENTIFIER_POINTER (DECL_NAME (r));\n+      else\n+\t{\n+\t  tree opn = lookup_attribute (\"old parm name\", DECL_ATTRIBUTES (r));\n+\t  opn = TREE_VALUE (TREE_VALUE (opn));\n+\t  name = IDENTIFIER_POINTER (opn);\n+\t}\n+    }\n+  else if (DECL_P (r) && UDLIT_OPER_P (DECL_NAME (r)))\n+    name = UDLIT_OP_SUFFIX (DECL_NAME (r));\n+  else if (DECL_P (r))\n+    name = IDENTIFIER_POINTER (DECL_NAME (r));\n+  else if (TYPE_P (r))\n+    {\n+      if (DECL_P (TYPE_NAME (r)))\n+\tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (r)));\n+      else\n+\tname = IDENTIFIER_POINTER (TYPE_NAME (r));\n+    }\n+  else if (kind == REFLECT_DATA_MEMBER_SPEC)\n+    name = IDENTIFIER_POINTER (TREE_VEC_ELT (r, 1));\n+  else\n+    gcc_unreachable ();\n+  tree str = temp_string_literal (name, elt_type);\n+  if (str == NULL_TREE)\n+    {\n+      if (elt_type == char_type_node)\n+\treturn throw_exception (loc, ctx, \"identifier_of not representable\"\n+\t\t\t\t\t  \" in ordinary literal encoding\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      else\n+\treturn throw_exception (loc, ctx, \"u8identifier_of not representable\"\n+\t\t\t\t\t  \" in UTF-8\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+    }\n+  releasing_vec args (make_tree_vector_single (str));\n+  tree ret = build_special_member_call (NULL_TREE, complete_ctor_identifier,\n+\t\t\t\t\t&args, ret_type, LOOKUP_NORMAL,\n+\t\t\t\t\ttf_warning_or_error);\n+  return build_cplus_new (ret_type, ret, tf_warning_or_error);\n+}\n+\n+/* Process std::meta::{,u8}display_string_of.\n+   Returns: An implementation-defined string_view or u8string_view,\n+   respectively.\n+   Recommended practice: Where possible, implementations should return a\n+   string suitable for identifying the represented construct.  */\n+\n+static tree\n+eval_display_string_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t\treflect_kind kind, bool *non_constant_p,\n+\t\t\ttree *jump_target, tree elt_type, tree ret_type,\n+\t\t\ttree fun)\n+{\n+#if __GNUC__ >= 10\n+#pragma GCC diagnostic push\n+#pragma GCC diagnostic ignored \"-Wformat\"\n+#pragma GCC diagnostic ignored \"-Wformat-diag\"\n+#endif\n+  r = maybe_get_reflection_fndecl (r);\n+  pretty_printer pp, *refpp = global_dc->get_reference_printer ();\n+  pp_format_decoder (&pp) = pp_format_decoder (refpp);\n+  pp.set_format_postprocessor (pp_format_postprocessor (refpp)->clone ());\n+  if (r == unknown_type_node)\n+    pp_printf (&pp, \"<null reflection>\");\n+  else if (TYPE_P (r))\n+    pp_printf (&pp, \"%T\", r);\n+  else if (kind == REFLECT_PARM)\n+    {\n+      r = maybe_update_function_parm (r);\n+      tree fn = DECL_CONTEXT (r);\n+      if (DECL_NAME (r))\n+\tpp_printf (&pp, \"<parameter %D of %D>\", r, fn);\n+      else\n+\t{\n+\t  int idx = 1;\n+\t  for (tree args = FUNCTION_FIRST_USER_PARM (fn);\n+\t       r != args; args = DECL_CHAIN (args))\n+\t    ++idx;\n+\t  pp_printf (&pp, \"<unnamed parameter %d of %D>\", idx, fn);\n+\t}\n+    }\n+  else if (kind == REFLECT_VALUE || kind == REFLECT_OBJECT)\n+    pp_printf (&pp, \"%E\", r);\n+  else if (DECL_P (r) && (DECL_NAME (r) || TREE_CODE (r) == NAMESPACE_DECL))\n+    pp_printf (&pp, \"%D\", r);\n+  else if (TREE_CODE (r) == FIELD_DECL)\n+    pp_printf (&pp, \"%T::<unnamed bit-field>\", DECL_CONTEXT (r));\n+  else if (kind == REFLECT_BASE)\n+    {\n+      tree c = r;\n+      /* Looping needed for multiple virtual inheritance.  */\n+      while (BINFO_INHERITANCE_CHAIN (c))\n+\tc = BINFO_INHERITANCE_CHAIN (c);\n+      pp_printf (&pp, \"(%T, %T)\", BINFO_TYPE (c), BINFO_TYPE (r));\n+    }\n+  else if (kind == REFLECT_DATA_MEMBER_SPEC)\n+    pp_printf (&pp, \"(%T, %E, %E, %E, %s)\", TREE_VEC_ELT (r, 0),\n+\t       TREE_VEC_ELT (r, 1), TREE_VEC_ELT (r, 2), TREE_VEC_ELT (r, 3),\n+\t       TREE_VEC_ELT (r, 4) == boolean_true_node\n+\t       ? \"true\" : \"false\");\n+  else if (eval_is_annotation (r, kind) == boolean_true_node)\n+    pp_printf (&pp, \"[[=%E]]\",\n+\t       tree_strip_any_location_wrapper (TREE_VALUE (TREE_VALUE (r))));\n+  else\n+    pp_string (&pp, \"<unsupported reflection>\");\n+#if __GNUC__ >= 10\n+#pragma GCC diagnostic pop\n+#endif\n+  tree str = temp_string_literal (pp_formatted_text (&pp), elt_type);\n+  if (str == NULL_TREE)\n+    {\n+      if (elt_type == char_type_node)\n+\treturn throw_exception (loc, ctx, \"identifier_of not representable\"\n+\t\t\t\t\t  \" in ordinary literal encoding\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      else\n+\treturn throw_exception (loc, ctx, \"u8identifier_of not representable\"\n+\t\t\t\t\t  \" in UTF-8\", fun, non_constant_p,\n+\t\t\t\t\t  jump_target);\n+    }\n+  releasing_vec args (make_tree_vector_single (str));\n+  tree ret = build_special_member_call (NULL_TREE, complete_ctor_identifier,\n+\t\t\t\t\t&args, ret_type, LOOKUP_NORMAL,\n+\t\t\t\t\ttf_warning_or_error);\n+  return build_cplus_new (ret_type, ret, tf_warning_or_error);\n+}\n+\n+/* Determine the reflection kind for R.  */\n+\n+static reflect_kind\n+get_reflection_kind (tree r)\n+{\n+  if (eval_is_type (r) == boolean_true_node\n+      || eval_is_template (r) == boolean_true_node\n+      || eval_is_function (r) == boolean_true_node)\n+    return REFLECT_UNDEF;\n+  return obvalue_p (r) ? REFLECT_OBJECT : REFLECT_VALUE;\n+}\n+\n+/* Get the reflection of template argument ARG as per\n+   std::meta::template_arguments_of.  */\n+\n+static tree\n+get_reflection_of_targ (tree arg)\n+{\n+  const location_t loc = location_of (arg);\n+  /* canonicalize_type_argument already strip_typedefs.  */\n+  arg = STRIP_REFERENCE_REF (arg);\n+  arg = maybe_get_reference_referent (arg);\n+  return get_reflection_raw (loc, arg, get_reflection_kind (arg));\n+}\n+\n+/* Process std::meta::template_arguments_of.\n+   Returns: A vector containing reflections of the template arguments of the\n+   template specialization represented by r, in the order in which they appear\n+   in the corresponding template argument list.\n+   For a given template argument A, its corresponding reflection R is\n+   determined as follows:\n+\n+   -- If A denotes a type or type alias, then R is a reflection representing\n+      the underlying entity of A.\n+   -- Otherwise, if A denotes a class template, variable template, concept,\n+      or alias template, then R is a reflection representing A.\n+   -- Otherwise, A is a constant template argument.  Let P be the\n+      corresponding template parameter.\n+      -- If P has reference type, then R is a reflection representing the\n+\t object or function referred to by A.\n+      -- Otherwise, if P has class type, then R represents the corresponding\n+\t template parameter object.\n+      -- Otherwise, R is a reflection representing the value of A.\n+\n+   Throws: meta::exception unless has_template_arguments(r) is true.  */\n+\n+static tree\n+eval_template_arguments_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t\t    bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  if (eval_has_template_arguments (r) != boolean_true_node)\n+    return throw_exception_notargs (loc, ctx, fun, non_constant_p, jump_target);\n+\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  tree args = NULL_TREE;\n+  if (TYPE_P (r) && typedef_variant_p (r))\n+    {\n+      if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (r))\n+\targs = INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo));\n+    }\n+  else\n+    args = get_template_innermost_arguments (r);\n+  gcc_assert (args);\n+  for (tree arg : tree_vec_range (args))\n+    {\n+      if (ARGUMENT_PACK_P (arg))\n+\t{\n+\t  tree pargs = ARGUMENT_PACK_ARGS (arg);\n+\t  for (tree a : tree_vec_range (pargs))\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t    get_reflection_of_targ (a));\n+\t}\n+      else\n+\tCONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, get_reflection_of_targ (arg));\n+    }\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Helper for eval_remove_const to build non-const type.  */\n+\n+static tree\n+remove_const (tree type)\n+{\n+  return cp_build_qualified_type (type,\n+\t\t\t\t  cp_type_quals (type) & ~TYPE_QUAL_CONST);\n+}\n+\n+/* Process std::meta::annotations_of and annotations_of_with_type.\n+   Let E be\n+   -- the corresponding base-specifier if item represents a direct base class\n+      relationship,\n+   -- otherwise, the entity represented by item.\n+   Returns: A vector containing all of the reflections R representing each\n+   annotation applying to each declaration of E that precedes either some\n+   point in the evaluation context or a point immediately following the\n+   class-specifier of the outermost class for which such a point is in a\n+   complete-class context.\n+   For any two reflections R1 and R2 in the returned vector, if the annotation\n+   represented by R1 precedes the annotation represented by R2, then R1\n+   appears before R2.\n+   If R1 and R2 represent annotations from the same translation unit T, any\n+   element in the returned vector between R1 and R2 represents an annotation\n+   from T.\n+\n+   Throws: meta::exception unless item represents a type, type alias,\n+   variable, function, namespace, enumerator, direct base class relationship,\n+   or non-static data member.  */\n+\n+static tree\n+eval_annotations_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t     reflect_kind kind, tree type, bool *non_constant_p,\n+\t\t     tree *jump_target, tree fun)\n+{\n+  if (!(eval_is_type (r) == boolean_true_node\n+\t|| eval_is_type_alias (r) == boolean_true_node\n+\t|| eval_is_variable (r, kind) == boolean_true_node\n+\t|| eval_is_function (r) == boolean_true_node\n+\t|| eval_is_namespace (r) == boolean_true_node\n+\t|| eval_is_enumerator (r) == boolean_true_node\n+\t|| eval_is_base (r, kind) == boolean_true_node\n+\t|| eval_is_nonstatic_data_member (r) == boolean_true_node))\n+    return throw_exception (loc, ctx,\n+\t\t\t    \"reflection does not represent a type,\"\n+\t\t\t    \" type alias, variable, function, namespace,\"\n+\t\t\t    \" enumerator, direct base class relationship,\"\n+\t\t\t    \" or non-static data member\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+\n+  if (type)\n+    {\n+      type = maybe_strip_typedefs (type);\n+      if (!TYPE_P (type)\n+\t  || !complete_type_or_maybe_complain (type, NULL_TREE, tf_none))\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"reflection does not represent a complete\"\n+\t\t\t\t\" type or type alias\", fun, non_constant_p,\n+\t\t\t\tjump_target);\n+      type = remove_const (type);\n+    }\n+\n+  if (kind == REFLECT_BASE)\n+    {\n+      gcc_assert (TREE_CODE (r) == TREE_BINFO);\n+      tree c = r, binfo = r, base_binfo;\n+      /* Looping needed for multiple virtual inheritance.  */\n+      while (BINFO_INHERITANCE_CHAIN (c))\n+\tc = BINFO_INHERITANCE_CHAIN (c);\n+\n+      r = NULL_TREE;\n+      for (unsigned ix = 0; BINFO_BASE_ITERATE (c, ix, base_binfo); ix++)\n+\tif (base_binfo == binfo)\n+\t  {\n+\t    if (ix + BINFO_BASE_BINFOS (c)->length ()\n+\t\t< vec_safe_length (BINFO_BASE_ACCESSES (c)))\n+\t      r = BINFO_BASE_ACCESS (c, ix + BINFO_BASE_BINFOS (c)->length ());\n+\t    break;\n+\t  }\n+    }\n+  else if (TYPE_P (r))\n+    r = TYPE_ATTRIBUTES (r);\n+  else if (DECL_P (r))\n+    r = DECL_ATTRIBUTES (r);\n+  else\n+    gcc_unreachable ();\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  for (tree a = r; (a = lookup_attribute (\"internal \", \"annotation \", a));\n+       a = TREE_CHAIN (a))\n+    {\n+      gcc_checking_assert (TREE_CODE (TREE_VALUE (a)) == TREE_LIST);\n+      tree val = TREE_VALUE (TREE_VALUE (a));\n+      if (type)\n+\t{\n+\t  tree at = TREE_TYPE (val);\n+\t  if (at == error_mark_node)\n+\t    continue;\n+\t  if (at != type && !same_type_p (remove_const (at), type))\n+\t    continue;\n+\t}\n+      CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t      get_reflection_raw (location_of (val), a,\n+\t\t\t\t\t\t  REFLECT_ANNOTATION));\n+    }\n+  if (elts)\n+    {\n+      /* Reverse the order.  */\n+      unsigned l = elts->length ();\n+      constructor_elt *ptr = elts->address ();\n+\n+      for (unsigned i = 0; i < l / 2; i++)\n+\tstd::swap (ptr[i], ptr[l - i - 1]);\n+    }\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Process std::meta::reflect_constant.\n+   Mandates: is_copy_constructible_v<T> is true and T is a cv-unqualified\n+   structural type that is not a reference type.\n+   Let V be:\n+   -- if T is a class type, then an object that is template-argument-equivalent\n+      to the value of expr;\n+   -- otherwise, the value of expr.\n+   Returns: template_arguments_of(^^TCls<V>)[0], with TCls as defined below.\n+   Throws: meta::exception unless the template-id TCls<V> would be valid given\n+   the invented template\n+     template<T P> struct TCls;  */\n+\n+static tree\n+eval_reflect_constant (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t       tree expr, bool *non_constant_p, tree *jump_target,\n+\t\t       tree fun)\n+{\n+  if (!structural_type_p (type)\n+      || CP_TYPE_VOLATILE_P (type)\n+      || CP_TYPE_CONST_P (type)\n+      || TYPE_REF_P (type))\n+    {\n+      error_at (loc, \"%qT must be a cv-unqualified structural type that is \"\n+\t\t\"not a reference type\", type);\n+      return error_mark_node;\n+    }\n+  expr = convert_reflect_constant_arg (type, convert_from_reference (expr));\n+  if (expr == error_mark_node)\n+    return throw_exception (loc, ctx, \"reflect_constant failed\", fun,\n+\t\t\t    non_constant_p, jump_target);\n+  return get_reflection_raw (loc, expr, get_reflection_kind (expr));\n+}\n+\n+/* Process std::meta::reflect_object.\n+   Mandates: T is an object type.\n+   Returns: A reflection of the object designated by expr.\n+   Throws: meta::exception unless expr is suitable for use as a constant\n+   template argument for a constant template parameter of type T&.  */\n+\n+static tree\n+eval_reflect_object (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t     tree expr, bool *non_constant_p, tree *jump_target,\n+\t\t     tree fun)\n+{\n+  if (eval_is_object_type (loc, type) != boolean_true_node)\n+    {\n+      error_at (loc, \"%qT must be an object type\", TREE_TYPE (type));\n+      return error_mark_node;\n+    }\n+  type = cp_build_reference_type (type, /*rval=*/false);\n+  tree e = convert_reflect_constant_arg (type, convert_from_reference (expr));\n+  if (e == error_mark_node)\n+    return throw_exception (loc, ctx, \"reflect_object failed\", fun,\n+\t\t\t    non_constant_p, jump_target);\n+  /* We got (const T &) &foo.  Get the referent, since we want the object\n+     designated by EXPR.  */\n+  expr = maybe_get_reference_referent (expr);\n+  return get_reflection_raw (loc, expr, REFLECT_OBJECT);\n+}\n+\n+/* Process std::meta::reflect_function.\n+   Mandates: T is a function type.\n+   Returns: A reflection of the function designated by fn.\n+   Throws: meta::exception unless fn is suitable for use as a constant\n+   template argument for a constant template parameter of type T&.  */\n+\n+static tree\n+eval_reflect_function (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t       tree expr, bool *non_constant_p, tree *jump_target,\n+\t\t       tree fun)\n+{\n+  if (eval_is_function_type (type) != boolean_true_node)\n+    {\n+      error_at (loc, \"%qT must be a function type\", TREE_TYPE (type));\n+      return error_mark_node;\n+    }\n+  type = cp_build_reference_type (type, /*rval=*/false);\n+  tree e = convert_reflect_constant_arg (type, convert_from_reference (expr));\n+  if (e == error_mark_node)\n+    return throw_exception (loc, ctx, \"reflect_function failed\", fun,\n+\t\t\t    non_constant_p, jump_target);\n+  /* We got (void (&<Ta885>) (void)) fn.  Get the function.  */\n+  expr = maybe_get_reference_referent (expr);\n+  return get_reflection_raw (loc, expr);\n+}\n+\n+/* Reflection type traits [meta.reflection.traits].\n+\n+   Every function and function template declared in this subclause throws\n+   an exception of type meta::exception unless the following conditions are\n+   met:\n+   -- For every parameter p of type info, is_type(p) is true.\n+   -- For every parameter r whose type is constrained on reflection_range,\n+      ranges::all_of(r, is_type) is true.  */\n+\n+/* Evaluate reflection type traits for which we have corresponding built-in\n+   traits.  KIND says which trait we are interested in; TYPE1 and TYPE2 are\n+   arguments to the trait.  */\n+\n+static tree\n+eval_type_trait (location_t loc, tree type1, tree type2, cp_trait_kind kind)\n+{\n+  tree r = finish_trait_expr (loc, kind, type1, type2);\n+  STRIP_ANY_LOCATION_WRAPPER (r);\n+  return r;\n+}\n+\n+/* Like above, but for type traits that take only one type.  */\n+\n+static tree\n+eval_type_trait (location_t loc, tree type, cp_trait_kind kind)\n+{\n+  return eval_type_trait (loc, type, NULL_TREE, kind);\n+}\n+\n+/* Process std::meta::is_function_type.  */\n+\n+static tree\n+eval_is_function_type (tree type)\n+{\n+  if (FUNC_OR_METHOD_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_void_type.  */\n+\n+static tree\n+eval_is_void_type (tree type)\n+{\n+  if (VOID_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_null_pointer_type.  */\n+\n+static tree\n+eval_is_null_pointer_type (tree type)\n+{\n+  if (NULLPTR_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_integral_type.  */\n+\n+static tree\n+eval_is_integral_type (tree type)\n+{\n+  if (CP_INTEGRAL_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_floating_point_type.  */\n+\n+static tree\n+eval_is_floating_point_type (tree type)\n+{\n+  if (FLOAT_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_array_type.  */\n+\n+static tree\n+eval_is_array_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_ARRAY);\n+}\n+\n+/* Process std::meta::is_pointer_type.  */\n+\n+static tree\n+eval_is_pointer_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_POINTER);\n+}\n+\n+/* Process std::meta::is_lvalue_reference_type.  */\n+\n+static tree\n+eval_is_lvalue_reference_type (tree type)\n+{\n+  if (TYPE_REF_P (type) && !TYPE_REF_IS_RVALUE (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_rvalue_reference_type.  */\n+\n+static tree\n+eval_is_rvalue_reference_type (tree type)\n+{\n+  if (TYPE_REF_P (type) && TYPE_REF_IS_RVALUE (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_member_object_pointer_type.  */\n+\n+static tree\n+eval_is_member_object_pointer_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_MEMBER_OBJECT_POINTER);\n+}\n+\n+/* Process std::meta::is_member_function_pointer_type.  */\n+\n+static tree\n+eval_is_member_function_pointer_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_MEMBER_FUNCTION_POINTER);\n+}\n+\n+/* Process std::meta::is_enum_type.  */\n+\n+static tree\n+eval_is_enum_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_ENUM);\n+}\n+\n+/* Process std::meta::is_union_type.  */\n+\n+static tree\n+eval_is_union_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_UNION);\n+}\n+\n+/* Process std::meta::is_class_type.  */\n+\n+static tree\n+eval_is_class_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_CLASS);\n+}\n+\n+/* Process std::meta::is_reflection_type.  */\n+\n+static tree\n+eval_is_reflection_type (tree type)\n+{\n+  if (REFLECTION_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_reference_type.  */\n+\n+static tree\n+eval_is_reference_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_REFERENCE);\n+}\n+\n+/* Process std::meta::is_arithmetic_type.  */\n+\n+static tree\n+eval_is_arithmetic_type (tree type)\n+{\n+  if (ARITHMETIC_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_object_type.  */\n+\n+static tree\n+eval_is_object_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_OBJECT);\n+}\n+\n+/* Process std::meta::is_scalar_type.  */\n+\n+static tree\n+eval_is_scalar_type (tree type)\n+{\n+  if (SCALAR_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_fundamental_type.  */\n+\n+static tree\n+eval_is_fundamental_type (tree type)\n+{\n+  if (ARITHMETIC_TYPE_P (type)\n+      || VOID_TYPE_P (type)\n+      || NULLPTR_TYPE_P (type)\n+      || REFLECTION_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_compound_type.  */\n+\n+static tree\n+eval_is_compound_type (tree type)\n+{\n+  if (eval_is_fundamental_type (type) == boolean_false_node)\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_member_pointer_type.  */\n+\n+static tree\n+eval_is_member_pointer_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_MEMBER_POINTER);\n+}\n+\n+/* Process std::meta::is_const_type.  */\n+\n+static tree\n+eval_is_const_type (tree type)\n+{\n+  if (CP_TYPE_CONST_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_volatile_type.  */\n+\n+static tree\n+eval_is_volatile_type (tree type)\n+{\n+  if (CP_TYPE_VOLATILE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_trivially_copyable_type.  */\n+\n+static tree\n+eval_is_trivially_copyable_type (tree type)\n+{\n+  if (trivially_copyable_p (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_standard_layout_type.  */\n+\n+static tree\n+eval_is_standard_layout_type (tree type)\n+{\n+  if (std_layout_type_p (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_empty_type.  */\n+\n+static tree\n+eval_is_empty_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_EMPTY);\n+}\n+\n+/* Process std::meta::is_polymorphic_type.  */\n+\n+static tree\n+eval_is_polymorphic_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_POLYMORPHIC);\n+}\n+\n+/* Process std::meta::is_abstract_type.  */\n+\n+static tree\n+eval_is_abstract_type (tree type)\n+{\n+  if (ABSTRACT_CLASS_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_final_type.  */\n+\n+static tree\n+eval_is_final_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_FINAL);\n+}\n+\n+/* Process std::meta::is_final.\n+   Returns: true if r represents a final class or a final member function.\n+   Otherwise, false.  */\n+\n+static tree\n+eval_is_final (tree r)\n+{\n+  if (eval_is_function (r) == boolean_true_node)\n+    {\n+      r = maybe_get_reflection_fndecl (r);\n+      if (TREE_CODE (r) == FUNCTION_DECL && DECL_FINAL_P (r))\n+\treturn boolean_true_node;\n+      else\n+\treturn boolean_false_node;\n+    }\n+\n+  if (eval_is_type (r) == boolean_true_node\n+      && CLASS_TYPE_P (r)\n+      && CLASSTYPE_FINAL (r))\n+    return boolean_true_node;\n+\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_aggregate_type.  */\n+\n+static tree\n+eval_is_aggregate_type (tree type)\n+{\n+  if (CP_AGGREGATE_TYPE_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_consteval_only_type.  */\n+\n+static tree\n+eval_is_consteval_only_type (tree type)\n+{\n+  if (consteval_only_p (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_signed_type.  */\n+\n+static tree\n+eval_is_signed_type (tree type)\n+{\n+  if (ARITHMETIC_TYPE_P (type) && !TYPE_UNSIGNED (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_unsigned_type.  */\n+\n+static tree\n+eval_is_unsigned_type (tree type)\n+{\n+  if (ARITHMETIC_TYPE_P (type) && TYPE_UNSIGNED (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_bounded_array_type.  */\n+\n+static tree\n+eval_is_bounded_array_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_BOUNDED_ARRAY);\n+}\n+\n+/* Process std::meta::is_unbounded_array_type.  */\n+\n+static tree\n+eval_is_unbounded_array_type (tree type)\n+{\n+  if (array_of_unknown_bound_p (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_scoped_enum_type.  */\n+\n+static tree\n+eval_is_scoped_enum_type (tree type)\n+{\n+  if (SCOPED_ENUM_P (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_constructible_type.  */\n+\n+static tree\n+eval_is_constructible_type (tree type, tree tvec)\n+{\n+  if (is_xible (INIT_EXPR, type, tvec))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_default_constructible_type.  */\n+\n+static tree\n+eval_is_default_constructible_type (tree type)\n+{\n+  if (is_xible (INIT_EXPR, type, make_tree_vec (0)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_copy_constructible_type.  */\n+\n+static tree\n+eval_is_copy_constructible_type (tree type)\n+{\n+  tree arg = make_tree_vec (1);\n+  tree ctype\n+    = cp_build_qualified_type (type, cp_type_quals (type) | TYPE_QUAL_CONST);\n+  TREE_VEC_ELT (arg, 0) = cp_build_reference_type (ctype, /*rval=*/false);\n+  if (is_xible (INIT_EXPR, type, arg))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_move_constructible_type.  */\n+\n+static tree\n+eval_is_move_constructible_type (tree type)\n+{\n+  tree arg = make_tree_vec (1);\n+  TREE_VEC_ELT (arg, 0) = cp_build_reference_type (type, /*rval=*/true);\n+  if (is_xible (INIT_EXPR, type, arg))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_assignable_type.  */\n+\n+static tree\n+eval_is_assignable_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_ASSIGNABLE);\n+}\n+\n+/* Process std::meta::is_copy_assignable_type.  */\n+\n+static tree\n+eval_is_copy_assignable_type (tree type)\n+{\n+  tree type1 = cp_build_reference_type (type, /*rval=*/false);\n+  tree type2\n+    = cp_build_qualified_type (type, cp_type_quals (type) | TYPE_QUAL_CONST);\n+  type2 = cp_build_reference_type (type2, /*rval=*/false);\n+  if (is_xible (MODIFY_EXPR, type1, type2))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_move_assignable_type.  */\n+\n+static tree\n+eval_is_move_assignable_type (tree type)\n+{\n+  tree type1 = cp_build_reference_type (type, /*rval=*/false);\n+  tree type2 = cp_build_reference_type (type, /*rval=*/true);\n+  if (is_xible (MODIFY_EXPR, type1, type2))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_destructible_type.  */\n+\n+static tree\n+eval_is_destructible_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_DESTRUCTIBLE);\n+}\n+\n+/* Process std::meta::is_trivially_constructible_type.  */\n+\n+static tree\n+eval_is_trivially_constructible_type (tree type, tree tvec)\n+{\n+  if (is_trivially_xible (INIT_EXPR, type, tvec))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_trivially_default_constructible_type.  */\n+\n+static tree\n+eval_is_trivially_default_constructible_type (tree type)\n+{\n+  if (is_trivially_xible (INIT_EXPR, type, make_tree_vec (0)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_trivially_copy_constructible_type.  */\n+\n+static tree\n+eval_is_trivially_copy_constructible_type (tree type)\n+{\n+  tree arg = make_tree_vec (1);\n+  tree ctype\n+    = cp_build_qualified_type (type, cp_type_quals (type) | TYPE_QUAL_CONST);\n+  TREE_VEC_ELT (arg, 0) = cp_build_reference_type (ctype, /*rval=*/false);\n+  if (is_trivially_xible (INIT_EXPR, type, arg))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_trivially_move_constructible_type.  */\n+\n+static tree\n+eval_is_trivially_move_constructible_type (tree type)\n+{\n+  tree arg = make_tree_vec (1);\n+  TREE_VEC_ELT (arg, 0) = cp_build_reference_type (type, /*rval=*/true);\n+  if (is_trivially_xible (INIT_EXPR, type, arg))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_trivially_assignable_type.  */\n+\n+static tree\n+eval_is_trivially_assignable_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_TRIVIALLY_ASSIGNABLE);\n+}\n+\n+/* Process std::meta::is_trivially_copy_assignable_type.  */\n+\n+static tree\n+eval_is_trivially_copy_assignable_type (tree type)\n+{\n+  tree type1 = cp_build_reference_type (type, /*rval=*/false);\n+  tree type2\n+    = cp_build_qualified_type (type, cp_type_quals (type) | TYPE_QUAL_CONST);\n+  type2 = cp_build_reference_type (type2, /*rval=*/false);\n+  if (is_trivially_xible (MODIFY_EXPR, type1, type2))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_trivially_move_assignable_type.  */\n+\n+static tree\n+eval_is_trivially_move_assignable_type (tree type)\n+{\n+  tree type1 = cp_build_reference_type (type, /*rval=*/false);\n+  tree type2 = cp_build_reference_type (type, /*rval=*/true);\n+  if (is_trivially_xible (MODIFY_EXPR, type1, type2))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_trivially_destructible_type.  */\n+\n+static tree\n+eval_is_trivially_destructible_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_TRIVIALLY_DESTRUCTIBLE);\n+}\n+\n+/* Process std::meta::is_nothrow_constructible_type.  */\n+\n+static tree\n+eval_is_nothrow_constructible_type (tree type, tree tvec)\n+{\n+  if (is_nothrow_xible (INIT_EXPR, type, tvec))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_nothrow_default_constructible_type.  */\n+\n+static tree\n+eval_is_nothrow_default_constructible_type (tree type)\n+{\n+  if (is_nothrow_xible (INIT_EXPR, type, make_tree_vec (0)))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_nothrow_copy_constructible_type.  */\n+\n+static tree\n+eval_is_nothrow_copy_constructible_type (tree type)\n+{\n+  tree arg = make_tree_vec (1);\n+  tree ctype\n+    = cp_build_qualified_type (type, cp_type_quals (type) | TYPE_QUAL_CONST);\n+  TREE_VEC_ELT (arg, 0) = cp_build_reference_type (ctype, /*rval=*/false);\n+  if (is_nothrow_xible (INIT_EXPR, type, arg))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_nothrow_move_constructible_type.  */\n+\n+static tree\n+eval_is_nothrow_move_constructible_type (tree type)\n+{\n+  tree arg = make_tree_vec (1);\n+  TREE_VEC_ELT (arg, 0) = cp_build_reference_type (type, /*rval=*/true);\n+  if (is_nothrow_xible (INIT_EXPR, type, arg))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_nothrow_assignable_type.  */\n+\n+static tree\n+eval_is_nothrow_assignable_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_NOTHROW_ASSIGNABLE);\n+}\n+\n+/* Process std::meta::is_nothrow_copy_assignable_type.  */\n+\n+static tree\n+eval_is_nothrow_copy_assignable_type (tree type)\n+{\n+  tree type1 = cp_build_reference_type (type, /*rval=*/false);\n+  tree type2\n+    = cp_build_qualified_type (type, cp_type_quals (type) | TYPE_QUAL_CONST);\n+  type2 = cp_build_reference_type (type2, /*rval=*/false);\n+  if (is_nothrow_xible (MODIFY_EXPR, type1, type2))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_nothrow_move_assignable_type.  */\n+\n+static tree\n+eval_is_nothrow_move_assignable_type (tree type)\n+{\n+  tree type1 = cp_build_reference_type (type, /*rval=*/false);\n+  tree type2 = cp_build_reference_type (type, /*rval=*/true);\n+  if (is_nothrow_xible (MODIFY_EXPR, type1, type2))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::is_nothrow_destructible_type.  */\n+\n+static tree\n+eval_is_nothrow_destructible_type (location_t loc, tree type)\n+{\n+  return eval_type_trait (loc, type, CPTK_IS_NOTHROW_DESTRUCTIBLE);\n+}\n+\n+/* Process std::meta::has_virtual_destructor.  */\n+\n+static tree\n+eval_has_virtual_destructor (tree type)\n+{\n+  if (type_has_virtual_destructor (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::has_unique_object_representations.  */\n+\n+static tree\n+eval_has_unique_object_representations (tree type)\n+{\n+  if (type_has_unique_obj_representations (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::reference_constructs_from_temporary.  */\n+\n+static tree\n+eval_reference_constructs_from_temporary (location_t loc, tree type1,\n+\t\t\t\t\t  tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2,\n+\t\t\t  CPTK_REF_CONSTRUCTS_FROM_TEMPORARY);\n+}\n+\n+/* Process std::meta::reference_converts_from_temporary.  */\n+\n+static tree\n+eval_reference_converts_from_temporary (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_REF_CONVERTS_FROM_TEMPORARY);\n+}\n+\n+/* Process std::meta::rank.  */\n+\n+static tree\n+eval_rank (tree type)\n+{\n+  size_t rank = 0;\n+  for (; TREE_CODE (type) == ARRAY_TYPE; type = TREE_TYPE (type))\n+    ++rank;\n+  return build_int_cst (size_type_node, rank);\n+}\n+\n+/* Process std::meta::extent.  */\n+\n+static tree\n+eval_extent (location_t loc, tree type, tree i)\n+{\n+  size_t rank = tree_to_uhwi (i);\n+  while (rank && TREE_CODE (type) == ARRAY_TYPE)\n+    {\n+      --rank;\n+      type = TREE_TYPE (type);\n+    }\n+  if (rank\n+      || TREE_CODE (type) != ARRAY_TYPE\n+      || eval_is_bounded_array_type (loc, type) == boolean_false_node)\n+     return size_zero_node;\n+  return size_binop (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (type)),\n+\t\t     size_one_node);\n+}\n+\n+/* Process std::meta::is_same_type.  */\n+\n+static tree\n+eval_is_same_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_SAME);\n+}\n+\n+/* Process std::meta::is_base_of_type.  */\n+\n+static tree\n+eval_is_base_of_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_BASE_OF);\n+}\n+\n+/* Process std::meta::is_virtual_base_of_type.  */\n+\n+static tree\n+eval_is_virtual_base_of_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_VIRTUAL_BASE_OF);\n+}\n+\n+/* Process std::meta::is_convertible_type.  */\n+\n+static tree\n+eval_is_convertible_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_CONVERTIBLE);\n+}\n+\n+/* Process std::meta::is_nothrow_convertible_type.  */\n+\n+static tree\n+eval_is_nothrow_convertible_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_NOTHROW_CONVERTIBLE);\n+}\n+\n+/* Process std::meta::is_layout_compatible_type.  */\n+\n+static tree\n+eval_is_layout_compatible_type (location_t loc, tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2, CPTK_IS_LAYOUT_COMPATIBLE);\n+}\n+\n+/* Process std::meta::is_pointer_interconvertible_base_of_type.  */\n+\n+static tree\n+eval_is_pointer_interconvertible_base_of_type (location_t loc,\n+\t\t\t\t\t       tree type1, tree type2)\n+{\n+  return eval_type_trait (loc, type1, type2,\n+\t\t\t  CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF);\n+}\n+\n+/* Process std::meta::is_invocable_type.  */\n+\n+static tree\n+eval_is_invocable_type (location_t loc, tree type, tree tvec)\n+{\n+  tree r = finish_trait_expr (loc, CPTK_IS_INVOCABLE, type, tvec);\n+  STRIP_ANY_LOCATION_WRAPPER (r);\n+  return r;\n+}\n+\n+/* Helper for various eval_* type trait functions which can't use builtin\n+   trait and have to instantiate std::NAME<ARGS>::value.  */\n+\n+static tree\n+finish_library_value_trait (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t    const char *name, tree args, tree call,\n+\t\t\t    bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  tree inst = lookup_template_class (get_identifier (name), args,\n+\t\t\t\t     /*in_decl*/NULL_TREE, /*context*/std_node,\n+\t\t\t\t     tf_warning_or_error);\n+  inst = complete_type (inst);\n+  if (inst == error_mark_node\n+      || !COMPLETE_TYPE_P (inst)\n+      || !CLASS_TYPE_P (inst))\n+    {\n+      if (!cxx_constexpr_quiet_p (ctx))\n+\terror_at (loc, \"couldn%'t instantiate %<std::%s<%T>%>\",\n+\t\t  name, args);\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  tree val = lookup_qualified_name (inst, value_identifier,\n+\t\t\t\t    LOOK_want::NORMAL, /*complain*/false);\n+  if (val == error_mark_node)\n+    return throw_exception (loc, ctx, \"value member missing\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (VAR_P (val) || TREE_CODE (val) == CONST_DECL)\n+    val = maybe_constant_value (val, NULL_TREE, mce_true);\n+  if (TREE_CODE (TREE_TYPE (call)) == BOOLEAN_TYPE)\n+    {\n+      if (integer_zerop (val))\n+\treturn boolean_false_node;\n+      else if (integer_nonzerop (val))\n+\treturn boolean_true_node;\n+      else\n+\treturn throw_exception (loc, ctx, \"unexpected value of value member\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+    }\n+  else if (TREE_CODE (val) == INTEGER_CST)\n+    {\n+      val = build_converted_constant_expr (TREE_TYPE (call), val, tf_none);\n+      if (TREE_CODE (val) == INTEGER_CST)\n+\treturn val;\n+    }\n+  return throw_exception (loc, ctx, \"unexpected value of value member\",\n+\t\t\t  fun, non_constant_p, jump_target);\n+}\n+\n+/* Process std::meta::is_{,nothrow_}invocable_r_type.  */\n+\n+static tree\n+eval_is_invocable_r_type (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t  tree tres, tree type, tree tvec, tree call,\n+\t\t\t  bool *non_constant_p, tree *jump_target, tree fun,\n+\t\t\t  const char *name)\n+{\n+  /* Create std::is_invocable_r<TYPE>::value.  */\n+  tree args = make_tree_vec (TREE_VEC_LENGTH (tvec) + 2);\n+  TREE_VEC_ELT (args, 0) = tres;\n+  TREE_VEC_ELT (args, 1) = type;\n+  for (int i = 0; i < TREE_VEC_LENGTH (tvec); ++i)\n+    TREE_VEC_ELT (args, i + 2) = TREE_VEC_ELT (tvec, i);\n+  return finish_library_value_trait (loc, ctx, name, args, call,\n+\t\t\t\t     non_constant_p, jump_target, fun);\n+}\n+\n+/* Process std::meta::is_nothrow_invocable_type.  */\n+\n+static tree\n+eval_is_nothrow_invocable_type (location_t loc, tree type, tree tvec)\n+{\n+  tree r = finish_trait_expr (loc, CPTK_IS_NOTHROW_INVOCABLE, type, tvec);\n+  STRIP_ANY_LOCATION_WRAPPER (r);\n+  return r;\n+}\n+\n+/* Process std::meta::is_{,nothrow_}swappable_with_type.  */\n+\n+static tree\n+eval_is_swappable_with_type (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t     tree type1, tree type2, tree call,\n+\t\t\t     bool *non_constant_p, tree *jump_target, tree fun,\n+\t\t\t     const char *name)\n+{\n+  /* Create std::is_swappable_with<TYPE>::value.  */\n+  tree args = make_tree_vec (2);\n+  TREE_VEC_ELT (args, 0) = type1;\n+  TREE_VEC_ELT (args, 1) = type2;\n+  return finish_library_value_trait (loc, ctx, name, args, call,\n+\t\t\t\t     non_constant_p, jump_target, fun);\n+}\n+\n+/* Process std::meta::is_{,nothrow_}swappable_type.  */\n+\n+static tree\n+eval_is_swappable_type (location_t loc, const constexpr_ctx *ctx,\n+\t\t\ttree type, tree call, bool *non_constant_p,\n+\t\t\ttree *jump_target, tree fun, const char *name)\n+{\n+  /* Create std::is_swappable<TYPE>::value.  */\n+  tree args = make_tree_vec (1);\n+  TREE_VEC_ELT (args, 0) = type;\n+  return finish_library_value_trait (loc, ctx, name, args, call,\n+\t\t\t\t     non_constant_p, jump_target, fun);\n+}\n+\n+/* Process std::meta::remove_cvref.  */\n+\n+static tree\n+eval_remove_cvref (location_t loc, tree type)\n+{\n+  if (TYPE_REF_P (type))\n+    type = TREE_TYPE (type);\n+  type = finish_trait_type (CPTK_REMOVE_CV, type, NULL_TREE, tf_none);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::decay.  */\n+\n+static tree\n+eval_decay (location_t loc, tree type)\n+{\n+  type = finish_trait_type (CPTK_DECAY, type, NULL_TREE, tf_none);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Helper for various eval_* type trait functions which can't use builtin\n+   trait and have to instantiate std::NAME<ARGS>::type.  */\n+\n+static tree\n+finish_library_type_trait (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t   const char *name, tree args, tree call,\n+\t\t\t   bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  tree inst = lookup_template_class (get_identifier (name), args,\n+\t\t\t\t     /*in_decl*/NULL_TREE,\n+\t\t\t\t     /*context*/std_node,\n+\t\t\t\t     tf_warning_or_error);\n+  if (inst == error_mark_node)\n+    {\n+      if (!cxx_constexpr_quiet_p (ctx))\n+\terror_at (loc, \"couldn%'t instantiate %<std::%s<%T>%>\",\n+\t\t  name, args);\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  tree type = make_typename_type (inst, type_identifier,\n+\t\t\t\t  none_type, tf_none);\n+  if (type == error_mark_node)\n+    return throw_exception (loc, ctx, \"type member missing\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::common_{type,reference}.  */\n+\n+static tree\n+eval_common_type (location_t loc, const constexpr_ctx *ctx, tree tvec,\n+\t\t  tree call, bool *non_constant_p, tree *jump_target, tree fun,\n+\t\t  const char *name)\n+{\n+  return finish_library_type_trait (loc, ctx, name, tvec, call,\n+\t\t\t\t    non_constant_p, jump_target, fun);\n+}\n+\n+/* Process std::meta::underlying_type.  */\n+\n+static tree\n+eval_underlying_type (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t      bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  if (TREE_CODE (type) != ENUMERAL_TYPE || !COMPLETE_TYPE_P (type))\n+    return throw_exception (loc, ctx, \"reflection does not represent \"\n+\t\t\t\t      \"a complete enumeration type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  type = finish_underlying_type (type);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::invoke_result.  */\n+\n+static tree\n+eval_invoke_result (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t    tree tvec, tree call, bool *non_constant_p,\n+\t\t    tree *jump_target, tree fun)\n+{\n+  tree args = make_tree_vec (TREE_VEC_LENGTH (tvec) + 1);\n+  TREE_VEC_ELT (args, 0) = type;\n+  for (int i = 0; i < TREE_VEC_LENGTH (tvec); ++i)\n+    TREE_VEC_ELT (args, i + 1) = TREE_VEC_ELT (tvec, i);\n+  return finish_library_type_trait (loc, ctx, \"invoke_result\", args, call,\n+\t\t\t\t    non_constant_p, jump_target, fun);\n+}\n+\n+/* Process std::meta::unwrap_{reference,ref_decay}.  */\n+\n+static tree\n+eval_unwrap_reference (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t       tree call, bool *non_constant_p, tree *jump_target,\n+\t\t       tree fun, const char *name)\n+{\n+  tree args = make_tree_vec (1);\n+  TREE_VEC_ELT (args, 0) = type;\n+  return finish_library_type_trait (loc, ctx, name, args, call,\n+\t\t\t\t    non_constant_p, jump_target, fun);\n+}\n+\n+/* Process std::meta::type_order.  */\n+\n+static tree\n+eval_type_order (tree type1, tree type2)\n+{\n+  return type_order_value (strip_typedefs (type1), strip_typedefs (type2));\n+}\n+\n+/* Process std::meta::enumerators_of.\n+   Returns: A vector containing the reflections of each enumerator of the\n+   enumeration represented by dealias(type_enum), in the order in which they\n+   are declared.\n+   Throws: meta::exception unless dealias(type_enum) represents an enumeration\n+   type, and is_enumerable_type(type_enum) is true.  */\n+\n+static tree\n+eval_enumerators_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t     bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  if (TREE_CODE (r) != ENUMERAL_TYPE\n+      || eval_is_enumerable_type (r) == boolean_false_node)\n+    return throw_exception (loc, ctx, \"reflection does not represent an \"\n+\t\t\t\t      \"enumerable enumeration type\", fun,\n+\t\t\t    non_constant_p, jump_target);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  for (tree t = TYPE_VALUES (r); t; t = TREE_CHAIN (t))\n+    {\n+      tree e = TREE_VALUE (t);\n+      CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t      get_reflection_raw (location_of (e), e));\n+    }\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Process std::meta::remove_const.\n+   Returns: a reflection representing the type denoted by\n+   std::remove_const_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_remove_const (location_t loc, tree type)\n+{\n+  return get_reflection_raw (loc, strip_typedefs (remove_const (type)));\n+}\n+\n+/* Process std::meta::remove_volatile.\n+   Returns: a reflection representing the type denoted by\n+   std::remove_volatile_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_remove_volatile (location_t loc, tree type)\n+{\n+  int quals = cp_type_quals (type);\n+  quals &= ~TYPE_QUAL_VOLATILE;\n+  type = cp_build_qualified_type (type, quals);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::remove_cv.\n+   Returns: a reflection representing the type denoted by\n+   std::remove_cv_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_remove_cv (location_t loc, tree type)\n+{\n+  type = finish_trait_type (CPTK_REMOVE_CV, type, NULL_TREE, tf_none);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::add_const.\n+   Returns: a reflection representing the type denoted by\n+   std::add_const_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_add_const (location_t loc, tree type)\n+{\n+  if (!TYPE_REF_P (type) && !FUNC_OR_METHOD_TYPE_P (type))\n+    {\n+      int quals = cp_type_quals (type);\n+      quals |= TYPE_QUAL_CONST;\n+      type = cp_build_qualified_type (type, quals);\n+    }\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::add_volatile.\n+   Returns: a reflection representing the type denoted by\n+   std::add_volatile_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_add_volatile (location_t loc, tree type)\n+{\n+  if (!TYPE_REF_P (type) && !FUNC_OR_METHOD_TYPE_P (type))\n+    {\n+      int quals = cp_type_quals (type);\n+      quals |= TYPE_QUAL_VOLATILE;\n+      type = cp_build_qualified_type (type, quals);\n+    }\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::add_cv.\n+   Returns: a reflection representing the type denoted by\n+   std::add_cv_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_add_cv (location_t loc, tree type)\n+{\n+  if (!TYPE_REF_P (type) && !FUNC_OR_METHOD_TYPE_P (type))\n+    {\n+      int quals = cp_type_quals (type);\n+      quals |= (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);\n+      type = cp_build_qualified_type (type, quals);\n+    }\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::remove_reference.\n+   Returns: a reflection representing the type denoted by\n+   std::remove_reference_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_remove_reference (location_t loc, tree type)\n+{\n+  if (TYPE_REF_P (type))\n+    type = TREE_TYPE (type);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::add_lvalue_reference.\n+   Returns: a reflection representing the type denoted by\n+   std::add_lvalue_reference_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_add_lvalue_reference (location_t loc, tree type)\n+{\n+  type = finish_trait_type (CPTK_ADD_LVALUE_REFERENCE, type, NULL_TREE, tf_none);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::add_rvalue_reference.\n+   Returns: a reflection representing the type denoted by\n+   std::add_rvalue_reference_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_add_rvalue_reference (location_t loc, tree type)\n+{\n+  type = finish_trait_type (CPTK_ADD_RVALUE_REFERENCE, type, NULL_TREE, tf_none);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::make_signed and std::meta::make_unsigned.\n+   Returns: a reflection representing the type denoted by\n+   std::make_signed_t<T> or std::make_unsigned_t<T>, respectively, where T is\n+   the type or type alias represented by type.  */\n+\n+static tree\n+eval_make_signed (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t  bool unsignedp, bool *non_constant_p, tree *jump_target,\n+\t\t  tree fun)\n+{\n+  if (!INTEGRAL_TYPE_P (type) || TREE_CODE (type) == BOOLEAN_TYPE)\n+    return throw_exception (loc, ctx, \"reflection represents non-integral \"\n+\t\t\t\t      \"or bool type\", fun, non_constant_p,\n+\t\t\t\t      jump_target);\n+  tree ret = type;\n+  if (TREE_CODE (type) == ENUMERAL_TYPE\n+      || TYPE_MAIN_VARIANT (type) == wchar_type_node\n+      || TYPE_MAIN_VARIANT (type) == char8_type_node\n+      || TYPE_MAIN_VARIANT (type) == char16_type_node\n+      || TYPE_MAIN_VARIANT (type) == char32_type_node)\n+    {\n+      tree unit = TYPE_SIZE_UNIT (type);\n+      tree types[] = {\n+\tsigned_char_type_node,\n+\tshort_integer_type_node,\n+\tinteger_type_node,\n+\tlong_integer_type_node,\n+\tlong_long_integer_type_node };\n+      ret = NULL_TREE;\n+      for (unsigned i = 0; i < ARRAY_SIZE (types); ++i)\n+\tif (tree_int_cst_equal (TYPE_SIZE_UNIT (types[i]), unit))\n+\t  {\n+\t    ret = c_common_signed_or_unsigned_type (unsignedp, types[i]);\n+\t    break;\n+\t  }\n+      if (!ret)\n+\tret = c_common_type_for_size (TYPE_PRECISION (type), unsignedp);\n+    }\n+  else if (TYPE_MAIN_VARIANT (type) == char_type_node)\n+    ret = unsignedp ? unsigned_char_type_node : signed_char_type_node;\n+  else if (unsignedp ^ (!!TYPE_UNSIGNED (type)))\n+    ret = c_common_signed_or_unsigned_type (unsignedp, type);\n+  if (ret != type)\n+    {\n+      int quals = cp_type_quals (type);\n+      quals &= (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);\n+      ret = cp_build_qualified_type (ret, quals);\n+    }\n+  else\n+    ret = strip_typedefs (type);\n+  return get_reflection_raw (loc, ret);\n+}\n+\n+/* Process std::meta::remove_extent.\n+   Returns: a reflection representing the type denoted by\n+   std::remove_extent_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_remove_extent (location_t loc, tree type)\n+{\n+  if (TREE_CODE (type) == ARRAY_TYPE)\n+    type = TREE_TYPE (type);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::remove_all_extents.\n+   Returns: a reflection representing the type denoted by\n+   std::remove_all_extents_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_remove_all_extents (location_t loc, tree type)\n+{\n+  type = strip_array_types (type);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::remove_pointer.\n+   Returns: a reflection representing the type denoted by\n+   std::remove_pointer_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_remove_pointer (location_t loc, tree type)\n+{\n+  if (TYPE_PTR_P (type))\n+    type = TREE_TYPE (type);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::add_pointer.\n+   Returns: a reflection representing the type denoted by\n+   std::add_pointer_t<T>, where T is the type or type alias\n+   represented by type.  */\n+\n+static tree\n+eval_add_pointer (location_t loc, tree type)\n+{\n+  type = finish_trait_type (CPTK_ADD_POINTER, type, NULL_TREE, tf_none);\n+  type = strip_typedefs (type);\n+  return get_reflection_raw (loc, type);\n+}\n+\n+/* Process std::meta::is_lvalue_reference_qualified and\n+   std::meta::is_rvalue_reference_qualified.\n+   Let T be type_of(r) if has-type(r) is true.  Otherwise, let T be\n+   dealias(r).\n+   Returns: true if T represents an lvalue- or rvalue-qualified\n+   function type, respectively.  Otherwise, false.\n+   RVALUE_P is true if we're processing is_rvalue_*, false if we're\n+   processing is_lvalue_*.  */\n+\n+static tree\n+eval_is_lrvalue_reference_qualified (tree r, reflect_kind kind,\n+\t\t\t\t     bool rvalue_p)\n+{\n+  if (has_type (r, kind))\n+    r = type_of (r, kind);\n+  else\n+    r = maybe_strip_typedefs (r);\n+  if (FUNC_OR_METHOD_TYPE_P (r) && FUNCTION_REF_QUALIFIED (r))\n+    if (rvalue_p == FUNCTION_RVALUE_QUALIFIED (r))\n+      return boolean_true_node;\n+\n+  return boolean_false_node;\n+}\n+\n+/* Process std::meta::can_substitute.\n+   Let Z be the template represented by templ and let Args... be a sequence of\n+   prvalue constant expressions that compute the reflections held by the\n+   elements of arguments, in order.\n+   Returns: true if Z<[:Args:]...> is a valid template-id that does not name\n+   a function whose type contains an undeduced placeholder type.\n+   Otherwise, false.\n+   Throws: meta::exception unless templ represents a template, and every\n+   reflection in arguments represents a construct usable as a template\n+   argument.  */\n+\n+static tree\n+eval_can_substitute (location_t loc, const constexpr_ctx *ctx,\n+\t\t     tree r, tree rvec, bool *non_constant_p, tree *jump_target,\n+\t\t     tree fun)\n+{\n+  if (eval_is_template (r) != boolean_true_node)\n+    return throw_exception (loc, ctx,\n+\t\t\t    \"reflection does not represent a template\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  for (int i = 0; i < TREE_VEC_LENGTH (rvec); ++i)\n+    {\n+      tree ra = TREE_VEC_ELT (rvec, i);\n+      tree a = REFLECT_EXPR_HANDLE (ra);\n+      reflect_kind kind = REFLECT_EXPR_KIND (ra);\n+      // TODO: It is unclear on what kinds of reflections we should throw\n+      // and what kinds of exceptions should merely result in can_substitute\n+      // returning false.\n+      if (a == unknown_type_node\n+\t  || kind == REFLECT_PARM\n+\t  || eval_is_namespace (a) == boolean_true_node\n+\t  || eval_is_constructor (a) == boolean_true_node\n+\t  || eval_is_destructor (a) == boolean_true_node\n+\t  || eval_is_annotation (a, kind) == boolean_true_node\n+\t  || (TREE_CODE (a) == FIELD_DECL && !DECL_UNNAMED_BIT_FIELD (a))\n+\t  || kind == REFLECT_DATA_MEMBER_SPEC\n+\t  || kind == REFLECT_BASE)\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"invalid argument to can_substitute\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      else if (!TYPE_P (a) && eval_is_template (a) == boolean_false_node)\n+\t{\n+\t  if (!has_type (a, kind))\n+\t    return throw_exception (loc, ctx,\n+\t\t\t\t    \"invalid argument to can_substitute\",\n+\t\t\t\t    fun, non_constant_p, jump_target);\n+\t}\n+      a = resolve_nondeduced_context (a, tf_warning_or_error);\n+      TREE_VEC_ELT (rvec, i) = a;\n+    }\n+  if (DECL_TYPE_TEMPLATE_P (r) || DECL_TEMPLATE_TEMPLATE_PARM_P (r))\n+    {\n+      tree type = lookup_template_class (r, rvec, NULL_TREE, NULL_TREE,\n+\t\t\t\t\t tf_none);\n+      if (type == error_mark_node)\n+\treturn boolean_false_node;\n+      else\n+\treturn boolean_true_node;\n+    }\n+  else if (concept_definition_p (r))\n+    {\n+      tree c = build_concept_check (r, rvec, tf_none);\n+      if (c == error_mark_node)\n+\treturn boolean_false_node;\n+      else\n+\treturn boolean_true_node;\n+    }\n+  else if (variable_template_p (r))\n+    {\n+      tree var = lookup_template_variable (r, rvec, tf_none);\n+      if (var == error_mark_node)\n+\treturn boolean_false_node;\n+      var = finish_template_variable (var, tf_none);\n+      if (var == error_mark_node)\n+\treturn boolean_false_node;\n+      else\n+\treturn boolean_true_node;\n+    }\n+  else\n+    {\n+      tree fn = lookup_template_function (r, rvec);\n+      if (fn == error_mark_node)\n+\treturn boolean_false_node;\n+      fn = resolve_nondeduced_context_or_error (fn, tf_none);\n+      if (fn == error_mark_node)\n+\treturn boolean_false_node;\n+      return boolean_true_node;\n+    }\n+}\n+\n+/* Process std::meta::substitute.\n+   Let Z be the template represented by templ and let Args... be a sequence of\n+   prvalue constant expressions that compute the reflections held by the\n+   elements of arguments, in order.\n+   Returns: ^^Z<[:Args:]...>.\n+   Throws: meta::exception unless can_substitute(templ, arguments) is true.  */\n+\n+static tree\n+eval_substitute (location_t loc, const constexpr_ctx *ctx,\n+\t\t tree r, tree rvec, bool *non_constant_p, tree *jump_target,\n+\t\t tree fun)\n+{\n+  tree cs = eval_can_substitute (loc, ctx, r, rvec, non_constant_p, jump_target,\n+\t\t\t\t fun);\n+  if (*jump_target)\n+    return cs;\n+  if (cs == boolean_false_node)\n+    return throw_exception (loc, ctx, \"can_substitute returned false\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  tree ret = NULL_TREE;\n+  if (DECL_TYPE_TEMPLATE_P (r) || DECL_TEMPLATE_TEMPLATE_PARM_P (r))\n+    ret = lookup_template_class (r, rvec, NULL_TREE, NULL_TREE, tf_none);\n+  else if (concept_definition_p (r))\n+    {\n+      ret = build_concept_check (r, rvec, tf_none);\n+      ret = evaluate_concept_check (ret);\n+      return get_reflection_raw (loc, ret, REFLECT_VALUE);\n+    }\n+  else if (variable_template_p (r))\n+    {\n+      ret = lookup_template_variable (r, rvec, tf_none);\n+      ret = finish_template_variable (ret, tf_none);\n+    }\n+  else\n+    ret = lookup_template_function (r, rvec);\n+  return get_reflection_raw (loc, ret);\n+}\n+\n+/* Process std::meta::tuple_size.\n+   Returns: tuple_size_v<T>, where T is the type represented by\n+   dealias(type).  */\n+\n+static tree\n+eval_tuple_size (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t tree call, bool *non_constant_p, tree *jump_target,\n+\t\t tree fun)\n+{\n+  type = strip_typedefs (type);\n+\n+  /* Create std::tuple_size<TYPE>::value.  */\n+  tree args = make_tree_vec (1);\n+  TREE_VEC_ELT (args, 0) = type;\n+  return finish_library_value_trait (loc, ctx, \"tuple_size\", args, call,\n+\t\t\t\t     non_constant_p, jump_target, fun);\n+}\n+\n+/* Process std::meta::tuple_element.\n+   Returns: A reflection representing the type denoted by\n+   tuple_element_t<I, T>, where T is the type represented by dealias(type)\n+   and I is a constant equal to index.  */\n+\n+static tree\n+eval_tuple_element (location_t loc, const constexpr_ctx *ctx, tree i,\n+\t\t    tree type, tree call, bool *non_constant_p,\n+\t\t    tree *jump_target, tree fun)\n+{\n+  type = strip_typedefs (type);\n+  /* Create std::tuple_element<I,TYPE>::type.  */\n+  tree args = make_tree_vec (2);\n+  TREE_VEC_ELT (args, 0) = i;\n+  TREE_VEC_ELT (args, 1) = type;\n+  return finish_library_type_trait (loc, ctx, \"tuple_element\",\n+\t\t\t\t    args, call, non_constant_p, jump_target,\n+\t\t\t\t    fun);\n+}\n+\n+/* Process std::meta::variant_size.\n+   Returns: variant_size_v<T>, where T is the type represented by\n+   dealias(type).  */\n+\n+static tree\n+eval_variant_size (location_t loc, const constexpr_ctx *ctx, tree type,\n+\t\t   tree call, bool *non_constant_p, tree *jump_target,\n+\t\t   tree fun)\n+{\n+  type = strip_typedefs (type);\n+\n+  /* Create std::variant_size<TYPE>::value.  */\n+  tree args = make_tree_vec (1);\n+  TREE_VEC_ELT (args, 0) = type;\n+  return finish_library_value_trait (loc, ctx, \"variant_size\", args, call,\n+\t\t\t\t     non_constant_p, jump_target, fun);\n+}\n+\n+/* Process std::meta::variant_alternative.\n+   Returns: A reflection representing the type denoted by\n+   variant_alternative_t<I, T>, where T is the type represented by\n+   dealias(type) and I is a constant equal to index.  */\n+\n+static tree\n+eval_variant_alternative (location_t loc, const constexpr_ctx *ctx, tree i,\n+\t\t\t  tree type, tree call, bool *non_constant_p,\n+\t\t\t  tree *jump_target, tree fun)\n+{\n+  type = strip_typedefs (type);\n+  /* Create std::variant_alternative<I,TYPE>::type.  */\n+  tree args = make_tree_vec (2);\n+  TREE_VEC_ELT (args, 0) = i;\n+  TREE_VEC_ELT (args, 1) = type;\n+  return finish_library_type_trait (loc, ctx, \"variant_alternative\",\n+\t\t\t\t    args, call, non_constant_p, jump_target,\n+\t\t\t\t    fun);\n+}\n+\n+/* Process std::meta::data_member_spec.\n+   Returns: A reflection of a data member description (T,N,A,W,NUA) where\n+   -- T is the type represented by dealias(type),\n+   -- N is either the identifier encoded by options.name or _|_ if\n+      options.name does not contain a value,\n+   -- A is either the alignment value held by options.alignment or _|_ if\n+      options.alignment does not contain a value,\n+   -- W is either the value held by options.bit_width or _|_ if\n+      options.bit_width does not contain a value, and\n+   -- NUA is the value held by options.no_unique_address.\n+   Throws: meta::exception unless the following conditions are met:\n+   -- dealias(type) represents either an object type or a reference type;\n+   -- if options.name contains a value, then:\n+      -- holds_alternative<u8string>(options.name->contents) is true and\n+\t get<u8string>(options.name->contents) contains a valid identifier\n+\t that is not a keyword when interpreted with UTF-8, or\n+      -- holds_alternative<string>(options.name->contents) is true and\n+\t get<string>(options.name->contents) contains a valid identifier\n+\t that is not a keyword when interpreted with the ordinary literal\n+\t encoding;\n+   -- if options.name does not contain a value, then options.bit_width\n+      contains a value;\n+   -- if options.bit_width contains a value V, then\n+      -- is_integral_type(type) || is_enum_type(type) is true,\n+      -- options.alignment does not contain a value,\n+      -- options.no_unique_address is false,\n+      -- V is not negative, and\n+      -- if V equals 0, then options.name does not contain a value; and\n+   -- if options.alignment contains a value, it is an alignment value not less\n+      than alignment_of(type).  */\n+\n+static tree\n+eval_data_member_spec (location_t loc, const constexpr_ctx *ctx,\n+\t\t       tree type, tree opts, bool *non_constant_p,\n+\t\t       bool *overflow_p, tree *jump_target, tree fun)\n+{\n+  type = strip_typedefs (type);\n+  if (!TYPE_OBJ_P (type) && !TYPE_REF_P (type))\n+    return throw_exception (loc, ctx, \"type is not object or reference type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  opts = convert_from_reference (opts);\n+  if (!CLASS_TYPE_P (TREE_TYPE (opts)))\n+    {\n+    fail:\n+      error_at (loc, \"unexpected %<data_member_options%> argument\");\n+      *non_constant_p = true;\n+      return NULL_TREE;\n+    }\n+  tree args[5] = { type, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };\n+  for (tree field = next_aggregate_field (TYPE_FIELDS (TREE_TYPE (opts)));\n+       field; field = next_aggregate_field (DECL_CHAIN (field)))\n+    if (tree name = DECL_NAME (field))\n+      {\n+\tif (id_equal (name, \"name\"))\n+\t  args[1] = field;\n+\telse if (id_equal (name, \"alignment\"))\n+\t  args[2] = field;\n+\telse if (id_equal (name, \"bit_width\"))\n+\t  args[3] = field;\n+\telse if (id_equal (name, \"no_unique_address\"))\n+\t  args[4] = field;\n+      }\n+  for (int i = 1; i < 5; ++i)\n+    {\n+      if (args[i] == NULL_TREE)\n+\tgoto fail;\n+      tree opt = build3 (COMPONENT_REF, TREE_TYPE (args[i]), opts, args[i],\n+\t\t\t NULL_TREE);\n+      if (i == 4)\n+\t{\n+\t  /* The no_unique_address handling is simple.  */\n+\t  if (TREE_CODE (TREE_TYPE (opt)) != BOOLEAN_TYPE)\n+\t    goto fail;\n+\t  opt = cxx_eval_constant_expression (ctx, opt, vc_prvalue,\n+\t\t\t\t\t      non_constant_p, overflow_p,\n+\t\t\t\t\t      jump_target);\n+\t  if (*jump_target || *non_constant_p)\n+\t    return NULL_TREE;\n+\t  if (TREE_CODE (opt) != INTEGER_CST)\n+\t    goto fail;\n+\t  if (integer_zerop (opt))\n+\t    args[i] = boolean_false_node;\n+\t  else\n+\t    args[i] = boolean_true_node;\n+\t  continue;\n+\t}\n+      /* Otherwise the member is optional<something>.  */\n+      if (!CLASS_TYPE_P (TREE_TYPE (opt)))\n+\tgoto fail;\n+      tree has_value = build_static_cast (loc, boolean_type_node, opt,\n+\t\t\t\t\t  tf_warning_or_error);\n+      if (error_operand_p (has_value))\n+\tgoto fail;\n+      has_value = cxx_eval_constant_expression (ctx, has_value, vc_prvalue,\n+\t\t\t\t\t\tnon_constant_p, overflow_p,\n+\t\t\t\t\t\tjump_target);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      if (TREE_CODE (has_value) != INTEGER_CST)\n+\tgoto fail;\n+      if (integer_zerop (has_value))\n+\t{\n+\t  /* If it doesn't have value, store NULL_TREE.  */\n+\t  args[i] = NULL_TREE;\n+\t  continue;\n+\t}\n+      tree deref = build_new_op (loc, INDIRECT_REF, LOOKUP_NORMAL, opt,\n+\t\t\t\t NULL_TREE, tf_warning_or_error);\n+      if (error_operand_p (deref))\n+\tgoto fail;\n+      if (i != 1)\n+\t{\n+\t  /* For alignment and bit_width otherwise it should be int.  */\n+\t  if (TYPE_MAIN_VARIANT (TREE_TYPE (deref)) != integer_type_node)\n+\t    goto fail;\n+\t  deref = cxx_eval_constant_expression (ctx, deref, vc_prvalue,\n+\t\t\t\t\t\tnon_constant_p, overflow_p,\n+\t\t\t\t\t\tjump_target);\n+\t  if (*jump_target || *non_constant_p)\n+\t    return NULL_TREE;\n+\t  if (TREE_CODE (deref) != INTEGER_CST)\n+\t    goto fail;\n+\t  args[i] = deref;\n+\t  continue;\n+\t}\n+      /* Otherwise it is a name.  */\n+      if (!CLASS_TYPE_P (TREE_TYPE (deref)))\n+\tgoto fail;\n+      tree fields[3] = { NULL_TREE, NULL_TREE, NULL_TREE };\n+      for (tree field = next_aggregate_field (TYPE_FIELDS (TREE_TYPE (deref)));\n+\t   field; field = next_aggregate_field (DECL_CHAIN (field)))\n+\tif (tree name = DECL_NAME (field))\n+\t  {\n+\t    if (id_equal (name, \"_M_is_u8\"))\n+\t      fields[0] = field;\n+\t    else if (id_equal (name, \"_M_u8s\"))\n+\t      fields[1] = field;\n+\t    else if (id_equal (name, \"_M_s\"))\n+\t      fields[2] = field;\n+\t  }\n+      for (int j = 0; j < 3; ++j)\n+\t{\n+\t  if (fields[j] == NULL_TREE)\n+\t    goto fail;\n+\t  if (j && j == (fields[0] == boolean_true_node ? 2 : 1))\n+\t    continue;\n+\t  tree f = build3 (COMPONENT_REF, TREE_TYPE (fields[j]), deref,\n+\t\t\t   fields[j], NULL_TREE);\n+\t  if (j == 0)\n+\t    {\n+\t      /* The _M_is_u8 handling is simple.  */\n+\t      if (TREE_CODE (TREE_TYPE (f)) != BOOLEAN_TYPE)\n+\t\tgoto fail;\n+\t      f = cxx_eval_constant_expression (ctx, f, vc_prvalue,\n+\t\t\t\t\t\tnon_constant_p, overflow_p,\n+\t\t\t\t\t\tjump_target);\n+\t      if (*jump_target || *non_constant_p)\n+\t\treturn NULL_TREE;\n+\t      if (TREE_CODE (f) != INTEGER_CST)\n+\t\tgoto fail;\n+\t      if (integer_zerop (f))\n+\t\tfields[0] = boolean_false_node;\n+\t      else\n+\t\tfields[0] = boolean_true_node;\n+\t      continue;\n+\t    }\n+\t  /* _M_u8s/_M_s handling is the same except for encoding.  */\n+\t  if (!CLASS_TYPE_P (TREE_TYPE (f)))\n+\t    goto fail;\n+\t  tree fns = lookup_qualified_name (TREE_TYPE (f),\n+\t\t\t\t\t    get_identifier (\"c_str\"));\n+\t  if (error_operand_p (fns))\n+\t    goto fail;\n+\t  f = build_new_method_call (f, fns, NULL, NULL_TREE, LOOKUP_NORMAL,\n+\t\t\t\t     NULL, tf_warning_or_error);\n+\t  if (error_operand_p (f))\n+\t    goto fail;\n+\t  f = cxx_eval_constant_expression (ctx, f, vc_prvalue,\n+\t\t\t\t\t    non_constant_p, overflow_p,\n+\t\t\t\t\t    jump_target);\n+\t  if (*jump_target || *non_constant_p)\n+\t    return NULL_TREE;\n+\t  STRIP_NOPS (f);\n+\t  if (TREE_CODE (f) != ADDR_EXPR)\n+\t    goto fail;\n+\t  f = TREE_OPERAND (f, 0);\n+\t  f = cxx_eval_constant_expression (ctx, f, vc_prvalue,\n+\t\t\t\t\t    non_constant_p, overflow_p,\n+\t\t\t\t\t    jump_target);\n+\t  if (*jump_target || *non_constant_p)\n+\t    return NULL_TREE;\n+\t  if (TREE_CODE (f) != CONSTRUCTOR\n+\t      || TREE_CODE (TREE_TYPE (f)) != ARRAY_TYPE)\n+\t    goto fail;\n+\t  tree eltt = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (f)));\n+\t  if (eltt != (j == 1 ? char8_type_node : char_type_node))\n+\t    goto fail;\n+\t  tree field, value;\n+\t  unsigned k;\n+\t  unsigned HOST_WIDE_INT l = 0;\n+\t  bool ntmbs = false;\n+\t  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (f), k, field, value)\n+\t    if (!tree_fits_shwi_p (value))\n+\t      goto fail;\n+\t    else if (field == NULL_TREE)\n+\t      {\n+\t\tif (integer_zerop (value))\n+\t\t  {\n+\t\t    ntmbs = true;\n+\t\t    break;\n+\t\t  }\n+\t\t++l;\n+\t      }\n+\t    else if (TREE_CODE (field) == RANGE_EXPR)\n+\t      {\n+\t\ttree lo = TREE_OPERAND (field, 0);\n+\t\ttree hi = TREE_OPERAND (field, 1);\n+\t\tif (!tree_fits_uhwi_p (lo) || !tree_fits_uhwi_p (hi))\n+\t\t  goto fail;\n+\t\tif (integer_zerop (value))\n+\t\t  {\n+\t\t    l = tree_to_uhwi (lo);\n+\t\t    ntmbs = true;\n+\t\t    break;\n+\t\t  }\n+\t\tl = tree_to_uhwi (hi) + 1;\n+\t      }\n+\t    else if (tree_fits_uhwi_p (field))\n+\t      {\n+\t\tl = tree_to_uhwi (field);\n+\t\tif (integer_zerop (value))\n+\t\t  {\n+\t\t    ntmbs = true;\n+\t\t    break;\n+\t\t  }\n+\t\t++l;\n+\t      }\n+\t    else\n+\t      goto fail;\n+\t  if (!ntmbs || l > INT_MAX - 1)\n+\t    goto fail;\n+\t  char *namep;\n+\t  unsigned len = l;\n+\t  if (l < 64)\n+\t    namep = XALLOCAVEC (char, l + 1);\n+\t  else\n+\t    namep = XNEWVEC (char, l + 1);\n+\t  memset (namep, 0, l + 1);\n+\t  l = 0;\n+\t  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (f), k, field, value)\n+\t    if (field == NULL_TREE)\n+\t      {\n+\t\tif (integer_zerop (value))\n+\t\t  break;\n+\t\tnamep[l] = tree_to_shwi (value);\n+\t\t++l;\n+\t      }\n+\t    else if (TREE_CODE (field) == RANGE_EXPR)\n+\t      {\n+\t\ttree lo = TREE_OPERAND (field, 0);\n+\t\ttree hi = TREE_OPERAND (field, 1);\n+\t\tif (integer_zerop (value))\n+\t\t  break;\n+\t\tunsigned HOST_WIDE_INT m = tree_to_uhwi (hi);\n+\t\tfor (l = tree_to_uhwi (lo); l <= m; ++l)\n+\t\t  namep[l] = tree_to_shwi (value);\n+\t      }\n+\t    else\n+\t      {\n+\t\tl = tree_to_uhwi (field);\n+\t\tnamep[l++] = tree_to_shwi (value);\n+\t      }\n+\t  namep[len] = '\\0';\n+\t  /* Convert namep from execution charset to SOURCE_CHARSET.  */\n+\t  cpp_string istr, ostr;\n+\t  istr.len = strlen (namep) + 1;\n+\t  istr.text = (const unsigned char *) namep;\n+\t  if (!cpp_translate_string (parse_in, &istr, &ostr,\n+\t\t\t\t     j == 2 ? CPP_STRING : CPP_UTF8STRING,\n+\t\t\t\t     true))\n+\t    {\n+\t      if (len >= 64)\n+\t\tXDELETEVEC (namep);\n+\t      if (j == 1)\n+\t\treturn throw_exception (loc, ctx,\n+\t\t\t\t\t\"conversion from ordinary literal \"\n+\t\t\t\t\t\"encoding to source charset \"\n+\t\t\t\t\t\"failed\", fun, non_constant_p,\n+\t\t\t\t\tjump_target);\n+\t      else\n+\t\treturn throw_exception (loc, ctx,\n+\t\t\t\t\t\"conversion from UTF-8 encoding to \"\n+\t\t\t\t\t\"source charset failed\",\n+\t\t\t\t\tfun, non_constant_p, jump_target);\n+\t    }\n+\t  if (len >= 64)\n+\t    XDELETEVEC (namep);\n+\t  if (!cpp_valid_identifier (parse_in, ostr.text))\n+\t    return throw_exception (loc, ctx,\n+\t\t\t\t    \"name is not a valid identifier\",\n+\t\t\t\t    fun, non_constant_p, jump_target);\n+\t  args[i] = get_identifier ((const char *) ostr.text);\n+\t  switch (get_identifier_kind (args[i]))\n+\t    {\n+\t    case cik_keyword:\n+\t      return throw_exception (loc, ctx, \"name is a keyword\",\n+\t\t\t\t      fun, non_constant_p, jump_target);\n+\t    case cik_trait:\n+\t      return throw_exception (loc, ctx, \"name is a built-in trait\",\n+\t\t\t\t      fun, non_constant_p, jump_target);\n+\t    default:\n+\t      break;\n+\t    }\n+\t}\n+    }\n+  if (args[1] == NULL_TREE && args[3] == NULL_TREE)\n+    return throw_exception (loc, ctx,\n+\t\t\t    \"neither name nor bit_width specified\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (args[3])\n+    {\n+      if (!CP_INTEGRAL_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"bit_width specified with non-integral \"\n+\t\t\t\t\"and non-enumeration type\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      if (args[2])\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"both alignment and bit_width specified\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      if (args[4] == boolean_true_node)\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"bit_width specified with \"\n+\t\t\t\t\"no_unique_address true\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      if (integer_zerop (args[3]) && args[1])\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"bit_width 0 with specified name\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      if (tree_int_cst_sgn (args[3]) < 0)\n+\treturn throw_exception (loc, ctx, \"bit_width is negative\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+    }\n+  if (args[2])\n+    {\n+      if (!integer_pow2p (args[2]))\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"alignment is not power of two\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      if (tree_int_cst_sgn (args[2]) < 0)\n+\treturn throw_exception (loc, ctx, \"alignment is negative\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+      tree al = cxx_sizeof_or_alignof_type (loc, type, ALIGNOF_EXPR, true,\n+\t\t\t\t\t    tf_none);\n+      if (TREE_CODE (al) == INTEGER_CST\n+\t  && wi::to_widest (al) > wi::to_widest (args[2]))\n+\treturn throw_exception (loc, ctx,\n+\t\t\t\t\"alignment is smaller than alignment_of\",\n+\t\t\t\tfun, non_constant_p, jump_target);\n+    }\n+  tree ret = make_tree_vec (5);\n+  for (int i = 0; i < 5; ++i)\n+    TREE_VEC_ELT (ret, i) = args[i];\n+  return get_reflection_raw (loc, ret, REFLECT_DATA_MEMBER_SPEC);\n+}\n+\n+/* Process std::meta::define_aggregate.\n+   Let C be the type represented by class_type and r_K be the Kth reflection\n+   value in mdescrs.\n+   For every r_K in mdescrs, let (T_K,N_K,A_K,W_K,NUA_K) be the corresponding\n+   data member description represented by r_K.\n+   Constant When:\n+   -- class_type represents a cv-unqualified class type;\n+   -- C is incomplete from every point in the evaluation context;\n+   -- is_data_member_spec(r_K) is true for every r_K;\n+   -- is_complete_type(T_K) is true for every r_K; and\n+   -- for every pair (r_K,r_L) where K<L, if N_K is not _|_ and N_L is not\n+      _|_, then either:\n+      -- N_K is not the same identifier as N_L or\n+      -- N_K is the identifier _ (U+005F LOW LINE).\n+   Effects: Produces an injected declaration D that defines C and has\n+   properties as follows:\n+   -- The target scope of D is the scope to which C belongs.\n+   -- The locus of D follows immediately after the core constant expression\n+      currently under evaluation.\n+   -- The characteristic sequence of D is the sequence of reflection values\n+      r_K.\n+   -- If C is a specialization of a templated class T, and C is not a local\n+      class, then D is an explicit specialization of T.\n+   -- For each r_K, there is a corresponding entity M_K with public access\n+      belonging to the class scope of D with the following properties:\n+      -- If N_K is _|_, M_K is an unnamed bit-field.\n+\t Otherwise, M_K is a non-static data member whose name is the\n+\t identifier N_K.\n+      -- The type of M_K is T_K.\n+      -- M_K is declared with the attribute [[no_unique_address]] if and only\n+\t if NUA_K is true.\n+      -- If W_K is not _|_, M_K is a bit-field whose width is that value.\n+\t Otherwise, M_K is not a bit-field.\n+      -- If A_K is not _|_, M_K has the alignment-specifier alignas(A_K).\n+\t Otherwise, M_K has no alignment-specifier.\n+   -- For every r_L in mdescrs such that K<L, the declaration corresponding to\n+      r_K precedes the declaration corresponding to r_L.\n+   Returns: class_type.\n+   Remarks: If C is a specialization of a templated class and it has not been\n+   instantiated, C is treated as an explicit specialization.  */\n+\n+static tree\n+eval_define_aggregate (location_t loc, const constexpr_ctx *ctx,\n+\t\t       tree type, tree rvec, tree call, bool *non_constant_p)\n+{\n+  tree orig_type = type;\n+  if (!CLASS_TYPE_P (type))\n+    {\n+      if (!cxx_constexpr_quiet_p (ctx))\n+\terror_at (loc, \"first %<define_aggregate%> argument is not a class \"\n+\t\t       \"type reflection\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  if (typedef_variant_p (type))\n+    {\n+      if (!cxx_constexpr_quiet_p (ctx))\n+\terror_at (loc, \"first %<define_aggregate%> argument is a reflection \"\n+\t\t       \"of a type alias\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  if (cv_qualified_p (type))\n+    {\n+      if (!cxx_constexpr_quiet_p (ctx))\n+\terror_at (loc, \"first %<define_aggregate%> argument is not a \"\n+\t\t       \"cv-unqualified class type reflection\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  if (COMPLETE_TYPE_P (type))\n+    {\n+      if (!cxx_constexpr_quiet_p (ctx))\n+\terror_at (loc, \"first %<define_aggregate%> argument is a complete \"\n+\t\t       \"class type reflection\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  hash_set<tree> nameset;\n+  for (int i = 0; i < TREE_VEC_LENGTH (rvec); ++i)\n+    {\n+      tree ra = TREE_VEC_ELT (rvec, i);\n+      tree a = REFLECT_EXPR_HANDLE (ra);\n+      if (REFLECT_EXPR_KIND (ra) != REFLECT_DATA_MEMBER_SPEC)\n+\t{\n+\t  if (!cxx_constexpr_quiet_p (ctx))\n+\t    error_at (loc, \"%<define_aggregate%> argument not a data member \"\n+\t\t\t   \"description\");\n+\t  *non_constant_p = true;\n+\t  return call;\n+\t}\n+      if (eval_is_complete_type (TREE_VEC_ELT (a, 0)) != boolean_true_node)\n+\t{\n+\t  if (!cxx_constexpr_quiet_p (ctx))\n+\t    error_at (loc, \"%<define_aggregate%> argument data member \"\n+\t\t\t   \"description without complete type\");\n+\t  *non_constant_p = true;\n+\t  return call;\n+\t}\n+      if (TREE_VEC_ELT (a, 1)\n+\t  && !id_equal (TREE_VEC_ELT (a, 1), \"_\")\n+\t  && nameset.add (TREE_VEC_ELT (a, 1)))\n+\t{\n+\t  if (!cxx_constexpr_quiet_p (ctx))\n+\t    error_at (loc, \"name %qD used in multiple data member \"\n+\t\t\t   \"descriptions\", TREE_VEC_ELT (a, 1));\n+\t  *non_constant_p = true;\n+\t  return call;\n+\t}\n+      if (TYPE_WARN_IF_NOT_ALIGN (type)\n+\t  && TREE_VEC_ELT (a, 3))\n+\t{\n+\t  if (!cxx_constexpr_quiet_p (ctx))\n+\t    error_at (loc, \"cannot declare bit-field in \"\n+\t\t\t   \"%<warn_if_not_aligned%> type\");\n+\t  *non_constant_p = true;\n+\t  return call;\n+\t}\n+    }\n+  tree consteval_block = cxx_constexpr_consteval_block (ctx);\n+  if (consteval_block == NULL_TREE)\n+    {\n+      if (!cxx_constexpr_quiet_p (ctx))\n+\terror_at (loc, \"%<define_aggregate%> not evaluated from \"\n+\t\t       \"%<consteval%> block\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  iloc_sentinel ils = loc;\n+  type = strip_typedefs (type);\n+  type = TYPE_MAIN_VARIANT (type);\n+  tree cscope = NULL_TREE, tscope = NULL_TREE;\n+  for (tree c = TYPE_CONTEXT (CP_DECL_CONTEXT (consteval_block)); c;\n+       c = get_containing_scope (c))\n+    {\n+      if (c == type)\n+\t{\n+\t  auto_diagnostic_group d;\n+\t  error_at (loc, \"%<define_aggregate%> evaluated from \"\n+\t\t\t \"%<consteval%> block enclosed by %qT being \"\n+\t\t\t \"defined\", type);\n+\t  inform (DECL_SOURCE_LOCATION (consteval_block),\n+\t\t  \"%<consteval%> block defined here\");\n+\t  return get_reflection_raw (loc, orig_type);\n+\t}\n+      if (cscope == NULL_TREE\n+\t  && (TYPE_P (c) || TREE_CODE (c) == FUNCTION_DECL))\n+\tcscope = c;\n+    }\n+  for (tree c = TYPE_CONTEXT (type); c; c = get_containing_scope (c))\n+    {\n+      if (c == consteval_block)\n+\t{\n+\t  auto_diagnostic_group d;\n+\t  error_at (loc, \"%<define_aggregate%> evaluated from \"\n+\t\t\t \"%<consteval%> block which encloses %qT being \"\n+\t\t\t \"defined\", type);\n+\t  inform (DECL_SOURCE_LOCATION (consteval_block),\n+\t\t  \"%<consteval%> block defined here\");\n+\t  return get_reflection_raw (loc, orig_type);\n+\t}\n+      if (tscope == NULL_TREE\n+\t  && (TYPE_P (c) || TREE_CODE (c) == FUNCTION_DECL))\n+\ttscope = c;\n+    }\n+  if (cscope != tscope)\n+    {\n+      auto_diagnostic_group d;\n+      if (cscope && tscope)\n+\t{\n+\t  for (tree c = tscope; c; c = get_containing_scope (c))\n+\t    if (c == cscope)\n+\t      {\n+\t\tif (DECL_P (tscope))\n+\t\t  error_at (loc, \"%qD intervenes between %qT scope and \"\n+\t\t\t\t \"%<consteval%> block %<define_aggregate%> \"\n+\t\t\t\t \"is evaluated from\", tscope, type);\n+\t\telse\n+\t\t  error_at (loc, \"%qT intervenes between %qT scope and \"\n+\t\t\t\t \"%<consteval%> block %<define_aggregate%> \"\n+\t\t\t\t \"is evaluated from\", tscope, type);\n+\t\tcscope = NULL_TREE;\n+\t\ttscope = NULL_TREE;\n+\t\tbreak;\n+\t      }\n+\t  for (tree c = cscope; c; c = get_containing_scope (c))\n+\t    if (c == tscope)\n+\t      {\n+\t\tif (DECL_P (cscope))\n+\t\t  error_at (loc, \"%qD intervenes between %<consteval%> block \"\n+\t\t\t\t \"%<define_aggregate%> is evaluated from and \"\n+\t\t\t\t \"%qT scope\", cscope, type);\n+\t\telse\n+\t\t  error_at (loc, \"%qT intervenes between %<consteval%> block \"\n+\t\t\t\t \"%<define_aggregate%> is evaluated from and \"\n+\t\t\t\t \"%qT scope\", cscope, type);\n+\t\tcscope = NULL_TREE;\n+\t\ttscope = NULL_TREE;\n+\t\tbreak;\n+\t      }\n+\t  if (cscope && tscope)\n+\t    {\n+\t      if (DECL_P (cscope) && DECL_P (tscope))\n+\t\terror_at (loc, \"%<define_aggregate%> evaluated from \"\n+\t\t\t       \"%<consteval%> block enclosed by %qD while \"\n+\t\t\t       \"%qT type being defined is enclosed by %qD\",\n+\t\t\t  cscope, type, tscope);\n+\t      else if (DECL_P (cscope))\n+\t\terror_at (loc, \"%<define_aggregate%> evaluated from \"\n+\t\t\t       \"%<consteval%> block enclosed by %qD while \"\n+\t\t\t       \"%qT type being defined is enclosed by %qT\",\n+\t\t\t  cscope, type, tscope);\n+\t      else if (DECL_P (tscope))\n+\t\terror_at (loc, \"%<define_aggregate%> evaluated from \"\n+\t\t\t       \"%<consteval%> block enclosed by %qT while \"\n+\t\t\t       \"%qT type being defined is enclosed by %qD\",\n+\t\t\t  cscope, type, tscope);\n+\t      else if (tscope)\n+\t\terror_at (loc, \"%<define_aggregate%> evaluated from \"\n+\t\t\t       \"%<consteval%> block enclosed by %qT while \"\n+\t\t\t       \"%qT type being defined is enclosed by %qT\",\n+\t\t\t  cscope, type, tscope);\n+\t    }\n+\t}\n+      else if (cscope && DECL_P (cscope))\n+\terror_at (loc, \"%qD intervenes between %<consteval%> block \"\n+\t\t       \"%<define_aggregate%> is evaluated from and %qT scope\",\n+\t\t  cscope, type);\n+      else if (cscope)\n+\terror_at (loc, \"%qT intervenes between %<consteval%> block \"\n+\t\t       \"%<define_aggregate%> is evaluated from and %qT scope\",\n+\t\t  cscope, type);\n+      else if (tscope && DECL_P (tscope))\n+\terror_at (loc, \"%qD intervenes between %qT scope and %<consteval%> \"\n+\t\t       \"block %<define_aggregate%> is evaluated from\",\n+\t\t  tscope, type);\n+      else\n+\terror_at (loc, \"%qT intervenes between %qT scope and %<consteval%> \"\n+\t\t       \"block %<define_aggregate%> is evaluated from\",\n+\t\t  tscope, type);\n+      inform (DECL_SOURCE_LOCATION (consteval_block),\n+\t      \"%<consteval%> block defined here\");\n+      return get_reflection_raw (loc, orig_type);\n+    }\n+  if (primary_template_specialization_p (type))\n+    {\n+      type = maybe_process_partial_specialization (type);\n+      if (type == error_mark_node)\n+\t{\n+\t  *non_constant_p = true;\n+\t  return call;\n+\t}\n+    }\n+  if (!TYPE_BINFO (type))\n+    xref_basetypes (type, NULL_TREE);\n+  pushclass (type);\n+  gcc_assert (!TYPE_FIELDS (type));\n+  tree fields = NULL_TREE;\n+  for (int i = 0; i < TREE_VEC_LENGTH (rvec); ++i)\n+    {\n+      tree ra = TREE_VEC_ELT (rvec, i);\n+      tree a = REFLECT_EXPR_HANDLE (ra);\n+      tree f = build_decl (cp_expr_loc_or_input_loc (ra), FIELD_DECL,\n+\t\t\t   TREE_VEC_ELT (a, 1), TREE_VEC_ELT (a, 0));\n+      DECL_CHAIN (f) = fields;\n+      DECL_IN_AGGR_P (f) = 1;\n+      DECL_CONTEXT (f) = type;\n+      TREE_PUBLIC (f) = 1;\n+      /* Bit-field.  */\n+      if (TREE_VEC_ELT (a, 3))\n+\t{\n+\t  /* Temporarily stash the width in DECL_BIT_FIELD_REPRESENTATIVE.\n+\t     check_bitfield_decl picks it from there later and sets DECL_SIZE\n+\t     accordingly.  */\n+\t  DECL_BIT_FIELD_REPRESENTATIVE (f) = TREE_VEC_ELT (a, 3);\n+\t  SET_DECL_C_BIT_FIELD (f);\n+\t  DECL_NONADDRESSABLE_P (f) = 1;\n+\t  /* If this bit-field is unnamed, it's padding.  */\n+\t  if (!TREE_VEC_ELT (a, 1))\n+\t    DECL_PADDING_P (f) = 1;\n+\t}\n+      else if (TREE_VEC_ELT (a, 2))\n+\t{\n+\t  SET_DECL_ALIGN (f, tree_to_uhwi (TREE_VEC_ELT (a, 2))\n+\t\t\t      * BITS_PER_UNIT);\n+\t  DECL_USER_ALIGN (f) = 1;\n+\t}\n+      if (TREE_VEC_ELT (a, 4) == boolean_true_node)\n+\t{\n+\t  tree attr = build_tree_list (NULL_TREE,\n+\t\t\t\t       get_identifier (\"no_unique_address\"));\n+\t  attr = build_tree_list (attr, NULL_TREE);\n+\t  cplus_decl_attributes (&f, attr, 0);\n+\t}\n+      fields = f;\n+    }\n+  TYPE_FIELDS (type) = fields;\n+  finish_struct (type, NULL_TREE);\n+  return get_reflection_raw (loc, orig_type);\n+}\n+\n+/* Implement std::meta::reflect_constant_string.\n+   Let CharT be ranges::range_value_t<R>.\n+   Mandates: CharT is one of char, wchar_t, char8_t, char16_t, char32_t.\n+   Let V be the pack of values of type CharT whose elements are the\n+   corresponding elements of r, except that if r refers to a string literal\n+   object, then V does not include the trailing null terminator of r.\n+   Let P be the template parameter object of type\n+   const CharT[sizeof...(V) + 1] initialized with {V..., CharT()}.\n+   Returns: ^^P.  */\n+\n+static tree\n+eval_reflect_constant_string (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t      tree call, bool *non_constant_p,\n+\t\t\t      bool *overflow_p, tree *jump_target, tree fun)\n+{\n+  tree str = get_range_elts (loc, ctx, call, 0, non_constant_p, overflow_p,\n+\t\t\t     jump_target, REFLECT_CONSTANT_STRING, fun);\n+  if (*jump_target || *non_constant_p)\n+    return NULL_TREE;\n+  tree decl = get_template_parm_object (str,\n+\t\t\t\t\tmangle_template_parm_object (str));\n+  DECL_MERGEABLE (decl) = 1;\n+  return get_reflection_raw (loc, decl);\n+}\n+\n+/* Implement std::meta::reflect_constant_array.\n+   Let T be ranges::range_value_t<R>.\n+   Mandates: T is a structural type,\n+   is_constructible_v<T, ranges::range_reference_t<R>> is true, and\n+   is_copy_constructible_v<T> is true.\n+   Let V be the pack of values of type info of the same size as r, where the\n+   ith element is reflect_constant(e_i), where e_i is the ith element of r.\n+   Let P be\n+   -- If sizeof...(V) > 0 is true, then the template parameter object of type\n+      const T[sizeof...(V)] initialized with {[:V:]...}.\n+   -- Otherwise, the template parameter object of type array<T, 0> initialized\n+      with {}.\n+   Returns: ^^P.  */\n+\n+static tree\n+eval_reflect_constant_array (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t     tree call, bool *non_constant_p,\n+\t\t\t     bool *overflow_p, tree *jump_target, tree fun)\n+{\n+  tree str = get_range_elts (loc, ctx, call, 0, non_constant_p, overflow_p,\n+\t\t\t     jump_target, REFLECT_CONSTANT_ARRAY, fun);\n+  if (*jump_target || *non_constant_p)\n+    return NULL_TREE;\n+  tree decl = get_template_parm_object (str,\n+\t\t\t\t\tmangle_template_parm_object (str));\n+  DECL_MERGEABLE (decl) = 1;\n+  return get_reflection_raw (loc, decl);\n+}\n+\n+/* Process std::meta::is_implicit_lifetime_type.  */\n+\n+static tree\n+eval_is_implicit_lifetime_type (tree type)\n+{\n+  if (implicit_lifetime_type_p (type))\n+    return boolean_true_node;\n+  else\n+    return boolean_false_node;\n+}\n+\n+/* Process std::meta::access_context::current.  */\n+\n+static tree\n+eval_access_context_current (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t     tree call, bool *non_constant_p)\n+{\n+  tree scope = cxx_constexpr_caller (ctx);\n+  /* Ignore temporary current_function_decl changes caused by\n+     push_access_scope.  */\n+  if (scope == NULL_TREE && current_function_decl)\n+    scope = current_function_decl_without_access_scope ();\n+  if (scope && DECL_INHERITED_CTOR (scope))\n+    scope = DECL_CONTEXT (scope);\n+  if (scope == NULL_TREE)\n+    {\n+      if (cxx_constexpr_manifestly_const_eval (ctx) != mce_true)\n+\t{\n+\t  /* Outside of functions limit this to manifestly constant-evaluation\n+\t     so that we don't fold it prematurely.  */\n+\t  if (!cxx_constexpr_quiet_p (ctx))\n+\t    error_at (loc, \"%<access_context::current%> used outside of \"\n+\t\t\t   \"manifestly constant-evaluation\");\n+\t  *non_constant_p = true;\n+\t  return call;\n+\t}\n+      if (current_class_type)\n+\tscope = current_class_type;\n+      else if (current_namespace)\n+\tscope = current_namespace;\n+      else\n+\tscope = global_namespace;\n+    }\n+  tree lam;\n+  while (LAMBDA_FUNCTION_P (scope)\n+\t && (lam = CLASSTYPE_LAMBDA_EXPR (CP_DECL_CONTEXT (scope)))\n+\t && LAMBDA_EXPR_CONSTEVAL_BLOCK_P (lam))\n+    scope = CP_TYPE_CONTEXT (CP_DECL_CONTEXT (scope));\n+  tree access_context = TREE_TYPE (call);\n+  if (TREE_CODE (access_context) != RECORD_TYPE)\n+    {\n+    fail:\n+      error_at (loc, \"unexpected return type of %qs\",\n+\t\t\"std::meta::access_context::current\");\n+      return build_zero_cst (access_context);\n+    }\n+  tree scopef = next_aggregate_field (TYPE_FIELDS (access_context));\n+  if (!scopef || !REFLECTION_TYPE_P (TREE_TYPE (scopef)))\n+    goto fail;\n+  tree classf = next_aggregate_field (DECL_CHAIN (scopef));\n+  if (!classf || !REFLECTION_TYPE_P (TREE_TYPE (classf)))\n+    goto fail;\n+  if (next_aggregate_field (DECL_CHAIN (classf)))\n+    goto fail;\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  CONSTRUCTOR_APPEND_ELT (elts, scopef, get_reflection_raw (loc, scope));\n+  CONSTRUCTOR_APPEND_ELT (elts, classf, get_null_reflection ());\n+  return build_constructor (access_context, elts);\n+}\n+\n+/* Helper function to extract scope and designating class from\n+   access_context ACTX.  */\n+\n+static bool\n+extract_access_context (location_t loc, tree actx, tree *scope,\n+\t\t\ttree *designating_class)\n+{\n+  if (TREE_CODE (actx) != CONSTRUCTOR\n+      || CONSTRUCTOR_NELTS (actx) != 2\n+      || !REFLECT_EXPR_P (CONSTRUCTOR_ELT (actx, 0)->value)\n+      || !REFLECT_EXPR_P (CONSTRUCTOR_ELT (actx, 1)->value))\n+    {\n+      error_at (loc, \"invalid %<access_context%> argument\");\n+      return false;\n+    }\n+  *scope = REFLECT_EXPR_HANDLE (CONSTRUCTOR_ELT (actx, 0)->value);\n+  *designating_class = REFLECT_EXPR_HANDLE (CONSTRUCTOR_ELT (actx, 1)->value);\n+  if (*scope == unknown_type_node)\n+    *scope = NULL_TREE;\n+  else if (TREE_CODE (*scope) != FUNCTION_DECL\n+\t   && TREE_CODE (*scope) != NAMESPACE_DECL\n+\t   && !CLASS_TYPE_P (*scope))\n+    {\n+      error_at (loc, \"unexpected %<access_context::scope()%>\");\n+      return false;\n+    }\n+  else if (CLASS_TYPE_P (*scope))\n+    *scope = TYPE_MAIN_VARIANT (*scope);\n+  if (*designating_class == unknown_type_node)\n+    *designating_class = NULL_TREE;\n+  else if (!CLASS_TYPE_P (*designating_class)\n+\t   || !COMPLETE_TYPE_P (*designating_class))\n+    {\n+      error_at (loc, \"unexpected %<access_context::designating_class()%>\");\n+      return false;\n+    }\n+  else\n+    *designating_class = TYPE_MAIN_VARIANT (*designating_class);\n+  return true;\n+}\n+\n+/* Process std::meta::is_accessible.\n+   Let PARENT-CLS(r) be:\n+   -- If parent_of(r) represents a class C, then C.\n+   -- Otherwise, PARENT-CLS(parent_of(r)).\n+   Let DESIGNATING-CLS(r, ctx) be:\n+   -- If ctx.designating_class() represents a class C, then C.\n+   -- Otherwise, PARENT-CLS(r).\n+   Returns:\n+   -- If r represents an unnamed bit-field F, then is_accessible(r_H, ctx),\n+      where r_H represents a hypothetical non-static data member of the class\n+      represented by PARENT-CLS(r) with the same access as F.\n+   -- Otherwise, if r does not represent a class member or a direct base class\n+      relationship, then true.\n+   -- Otherwise, if r represents\n+      -- a class member that is not a (possibly indirect or variant) member of\n+\t DESIGNATING-CLS(r, ctx) or\n+      -- a direct base class relationship such that parent_of(r) does not\n+\t represent DESIGNATING-CLS(r, ctx) or a (direct or indirect) base\n+\t class thereof,\n+      then false.\n+   -- Otherwise, if ctx.scope() is the null reflection, then true.\n+   -- Otherwise, letting P be a program point whose immediate scope is the\n+      function parameter scope, class scope, or namespace scope corresponding\n+      to the function, class, or namespace represented by ctx.scope():\n+      -- If r represents a direct base class relationship (D,B), then true if\n+\t base class B of DESIGNATING-CLS(r, ctx) is accessible at P;\n+\t otherwise false.\n+      -- Otherwise, r represents a class member M; true if M would be\n+\t accessible at P with the designating class (as DESIGNATING-CLS(r, ctx)\n+\t if the effect of any using-declarations were ignored.  Otherwise,\n+\t false.\n+   Throws: meta::exception if r represents a class member for which\n+   PARENT-CLS(r) is an incomplete class.  */\n+\n+static tree\n+eval_is_accessible (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t    reflect_kind kind, tree actx, tree call,\n+\t\t    bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  tree scope = NULL_TREE, designating_class = NULL_TREE, c;\n+  if (!extract_access_context (loc, actx, &scope, &designating_class))\n+    {\n+      *non_constant_p = true;\n+      return call;\n+    }\n+\n+  if (eval_is_class_member (r) == boolean_true_node)\n+    {\n+      r = maybe_get_reflection_fndecl (r);\n+      c = r;\n+      if (TREE_CODE (r) == CONST_DECL && UNSCOPED_ENUM_P (DECL_CONTEXT (r)))\n+\tc = DECL_CONTEXT (r);\n+      if (TYPE_P (c))\n+\t{\n+\t  if (TYPE_NAME (c) && DECL_P (TYPE_NAME (c)))\n+\t    c = CP_DECL_CONTEXT (TYPE_NAME (c));\n+\t  else\n+\t    c = CP_TYPE_CONTEXT (c);\n+\t}\n+      else if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))\n+\t{\n+\t  tree v = DECL_VALUE_EXPR (r);\n+\t  if (v != error_mark_node && TREE_CODE (v) == COMPONENT_REF)\n+\t    c = CP_DECL_CONTEXT (TREE_OPERAND (v, 1));\n+\t  else\n+\t    c = CP_DECL_CONTEXT (r);\n+\t}\n+      else\n+\tc = CP_DECL_CONTEXT (r);\n+    }\n+  else if (kind == REFLECT_BASE)\n+    {\n+      c = r;\n+      /* Looping needed for multiple virtual inheritance.  */\n+      while (BINFO_INHERITANCE_CHAIN (c))\n+\tc = BINFO_INHERITANCE_CHAIN (c);\n+      c = BINFO_TYPE (c);\n+      r = BINFO_TYPE (r);\n+    }\n+  else\n+    return boolean_true_node;\n+  if (!CLASS_TYPE_P (c) || !COMPLETE_TYPE_P (c))\n+    return throw_exception (loc, ctx,\n+\t\t\t    \"incomplete parent class\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (designating_class)\n+    {\n+      tree p = c;\n+      while (ANON_AGGR_TYPE_P (p) && p != designating_class)\n+\tp = CP_TYPE_CONTEXT (p);\n+      if (p != designating_class\n+\t  && (!CLASS_TYPE_P (p)\n+\t      || !DERIVED_FROM_P (p, designating_class)))\n+\treturn boolean_false_node;\n+    }\n+  if (scope == NULL_TREE)\n+    return boolean_true_node;\n+  if (designating_class == NULL_TREE)\n+    designating_class = c;\n+  if (TREE_CODE (scope) == NAMESPACE_DECL)\n+    push_to_top_level ();\n+  else if (TYPE_P (scope))\n+    push_access_scope (TYPE_NAME (scope));\n+  else\n+    push_access_scope (scope);\n+  tree ret = boolean_false_node;\n+  if (kind == REFLECT_BASE)\n+    {\n+      if (accessible_base_p (designating_class, r, /*consider_local_p=*/true))\n+\tret = boolean_true_node;\n+    }\n+  else\n+    {\n+      tree o = TYPE_P (r) ? TYPE_NAME (r) : r;\n+      if (accessible_p (TYPE_BINFO (designating_class), o,\n+\t\t\t/*consider_local_p=*/true))\n+\tret = boolean_true_node;\n+    }\n+  if (TREE_CODE (scope) == NAMESPACE_DECL)\n+    pop_from_top_level ();\n+  else if (TYPE_P (scope))\n+    pop_access_scope (TYPE_NAME (scope));\n+  else\n+    pop_access_scope (scope);\n+  return ret;\n+}\n+\n+/* Returns true if R is C-members-of-representable from\n+   current point P.  */\n+\n+static bool\n+members_of_representable_p (tree c, tree r)\n+{\n+  if (TREE_CODE (r) == CONST_DECL)\n+    return false;\n+  if (LAMBDA_TYPE_P (c) && !LAMBDA_FUNCTION_P (r))\n+    return false;\n+  if (TYPE_P (r))\n+    {\n+      if (CP_DECL_CONTEXT (TYPE_NAME (r)) != c)\n+\treturn false;\n+      if (LAMBDA_TYPE_P (r))\n+\treturn false;\n+      if (OVERLOAD_TYPE_P (r))\n+\treturn true;\n+      if (typedef_variant_p (r))\n+\treturn true;\n+    }\n+  else if (DECL_P (r))\n+    {\n+      if (CP_DECL_CONTEXT (r) != c)\n+\treturn false;\n+      if (DECL_CLASS_TEMPLATE_P (r)\n+\t  || DECL_FUNCTION_TEMPLATE_P (r)\n+\t  || variable_template_p (r)\n+\t  || DECL_ALIAS_TEMPLATE_P (r)\n+\t  || concept_definition_p (r)\n+\t  || TREE_CODE (r) == FIELD_DECL\n+\t  || TREE_CODE (r) == NAMESPACE_DECL)\n+\treturn true;\n+      if (VAR_P (r) && !undeduced_auto_decl (r))\n+\treturn true;\n+      if (TREE_CODE (r) == FUNCTION_DECL)\n+\t{\n+\t  if (undeduced_auto_decl (r))\n+\t    return false;\n+\t  return true;\n+\t}\n+    }\n+  return false;\n+}\n+\n+/* Callback for vector qsort to compare members by ascending DECL_UID.  */\n+\n+static int\n+members_cmp (const void *a, const void *b)\n+{\n+  const constructor_elt *ea = (const constructor_elt *) a;\n+  const constructor_elt *eb = (const constructor_elt *) b;\n+  tree vala = REFLECT_EXPR_HANDLE (ea->value);\n+  tree valb = REFLECT_EXPR_HANDLE (eb->value);\n+  if (TYPE_P (vala))\n+    vala = TYPE_NAME (vala);\n+  if (TYPE_P (valb))\n+    valb = TYPE_NAME (valb);\n+  if (DECL_UID (vala) < DECL_UID (valb))\n+    return -1;\n+  if (DECL_UID (vala) > DECL_UID (valb))\n+    return 1;\n+  gcc_assert (ea == eb);\n+  return 0;\n+}\n+\n+/* Enumerate members of namespace NS for eval_members_of.  */\n+\n+static vec<constructor_elt, va_gc> *\n+namespace_members_of (location_t loc, tree ns)\n+{\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  hash_set<tree> *seen = nullptr;\n+  for (tree o : *DECL_NAMESPACE_BINDINGS (ns))\n+    {\n+      if (TREE_CODE (o) == OVERLOAD && OVL_LOOKUP_P (o))\n+\t{\n+\t  if (TREE_TYPE (o))\n+\t    {\n+\t      tree m = TREE_TYPE (TREE_TYPE (o));\n+\t      if (members_of_representable_p (ns, m))\n+\t\tCONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t\tget_reflection_raw (loc, m));\n+\t    }\n+\t  if (OVL_DEDUP_P (o) || !OVL_FUNCTION (o))\n+\t    continue;\n+\t  o = OVL_FUNCTION (o);\n+\t}\n+      for (ovl_iterator iter (o); iter; ++iter)\n+\t{\n+\t  if (iter.hidden_p ())\n+\t    continue;\n+\t  tree b = *iter;\n+\t  tree m = b;\n+\n+\t  if (VAR_P (b) && DECL_ANON_UNION_VAR_P (b))\n+\t    {\n+\t      /* TODO: This doesn't handle namespace N { static union {}; }\n+\t\t but we pedwarn on that, so perhaps it doesn't need to be\n+\t\t handled.  */\n+\t      tree v = DECL_VALUE_EXPR (b);\n+\t      gcc_assert (v && TREE_CODE (v) == COMPONENT_REF);\n+\t      tree var = TREE_OPERAND (v, 0);\n+\t      tree type = TREE_TYPE (var);\n+\t      if (!seen)\n+\t\tseen = new hash_set<tree>;\n+\t      if (members_of_representable_p (ns, type) && !seen->add (type))\n+\t\tCONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t\tget_reflection_raw (loc, type));\n+\t      if (members_of_representable_p (ns, var) && !seen->add (var))\n+\t\tCONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t\tget_reflection_raw (loc, var));\n+\t      continue;\n+\t    }\n+\t  if (TREE_CODE (b) == TYPE_DECL)\n+\t    m = TREE_TYPE (b);\n+\t  if (!members_of_representable_p (ns, m))\n+\t    continue;\n+\t  if (DECL_DECOMPOSITION_P (m) && !DECL_DECOMP_IS_BASE (m))\n+\t    {\n+\t      tree base = DECL_DECOMP_BASE (m);\n+\t      if (!seen)\n+\t\tseen = new hash_set<tree>;\n+\t      if (members_of_representable_p (ns, base) && !seen->add (base))\n+\t\tCONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t\tget_reflection_raw (loc, base));\n+\t      if (!DECL_HAS_VALUE_EXPR_P (m))\n+\t\tCONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t\tget_reflection_raw (loc, m,\n+\t\t\t\t\t\t\t    REFLECT_VAR));\n+\t      continue;\n+\t    }\n+\t  /* I don't see much point in calling eval_is_accessible here,\n+\t     won't it always return true?  */\n+\t  CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t  get_reflection_raw (loc, m));\n+\t}\n+    }\n+  delete seen;\n+  if (elts)\n+    elts->qsort (members_cmp);\n+  return elts;\n+}\n+\n+/* Enumerate members of class R for eval_*members_of.  KIND is\n+   0 for members_of, 1 for static_data_members_of, 2 for\n+   nonstatic_data_members_of and 3 for has_inaccessible_nonstatic_data_members.\n+   For KIND 3 don't append any elts except for the first one for\n+   which is_accessible returned false.  */\n+\n+static vec<constructor_elt, va_gc> *\n+class_members_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t  tree actx, tree call, bool *non_constant_p,\n+\t\t  tree *jump_target, int kind, tree fun)\n+{\n+  if (kind == 0)\n+    {\n+      if (modules_p ())\n+\tlazy_load_pendings (TYPE_NAME (r));\n+      if (CLASSTYPE_LAZY_DEFAULT_CTOR (r))\n+\tlazily_declare_fn (sfk_constructor, r);\n+      if (CLASSTYPE_LAZY_COPY_CTOR (r))\n+\tlazily_declare_fn (sfk_copy_constructor, r);\n+      if (CLASSTYPE_LAZY_MOVE_CTOR (r))\n+\tlazily_declare_fn (sfk_move_constructor, r);\n+      if (CLASSTYPE_LAZY_DESTRUCTOR (r))\n+\tlazily_declare_fn (sfk_destructor, r);\n+      if (CLASSTYPE_LAZY_COPY_ASSIGN (r))\n+\tlazily_declare_fn (sfk_copy_assignment, r);\n+      if (CLASSTYPE_LAZY_MOVE_ASSIGN (r))\n+\tlazily_declare_fn (sfk_move_assignment, r);\n+    }\n+  auto_vec <tree, 8> implicitly_declared;\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  for (tree field = TYPE_FIELDS (r); field; field = DECL_CHAIN (field))\n+    {\n+      tree m = field;\n+      if (TREE_CODE (field) == FIELD_DECL && DECL_ARTIFICIAL (field))\n+\tcontinue; /* Ignore bases.  */\n+      else if (DECL_SELF_REFERENCE_P (field))\n+\tcontinue;\n+      else if (TREE_CODE (field) == TYPE_DECL)\n+\tm = TREE_TYPE (field);\n+      else if (TREE_CODE (field) == FUNCTION_DECL)\n+\t{\n+\t  /* Ignore cloned cdtors.  */\n+\t  if (DECL_COMPLETE_CONSTRUCTOR_P (field)\n+\t      || DECL_BASE_CONSTRUCTOR_P (field)\n+\t      || DECL_COMPLETE_DESTRUCTOR_P (field)\n+\t      || DECL_BASE_DESTRUCTOR_P (field)\n+\t      || DECL_DELETING_DESTRUCTOR_P (field))\n+\t    continue;\n+\t  /* Ignore functions with unsatisfied constraints.  */\n+\t  if (!constraints_satisfied_p (field))\n+\t    continue;\n+\t  if (special_function_p (field) == sfk_comparison\n+\t      && undeduced_auto_decl (field)\n+\t      && DECL_DEFAULTED_FN (field)\n+\t      && DECL_INITIAL (field) == NULL_TREE)\n+\t    {\n+\t      ++function_depth;\n+\t      maybe_synthesize_method (field);\n+\t      --function_depth;\n+\t    }\n+\t}\n+      if (members_of_representable_p (r, m))\n+\t{\n+\t  if (kind == 1\n+\t      && eval_is_variable (m, REFLECT_UNDEF) != boolean_true_node)\n+\t    continue; /* For static_data_members_of only include\n+\t\t\t is_variable.  */\n+\t  else if ((kind == 2 || kind == 3)\n+\t\t   && eval_is_nonstatic_data_member (m) != boolean_true_node)\n+\t    continue; /* For nonstatic_data_members_of only include\n+\t\t\t is_nonstatic_data_member.  */\n+\t  tree a = eval_is_accessible (loc, ctx, m, REFLECT_UNDEF, actx, call,\n+\t\t\t\t       non_constant_p, jump_target, fun);\n+\t  if (*jump_target || *non_constant_p)\n+\t    return nullptr;\n+\t  if (a == boolean_false_node)\n+\t    {\n+\t      if (kind == 3 && elts == nullptr)\n+\t\tCONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, boolean_true_node);\n+\t      continue;\n+\t    }\n+\t  gcc_assert (a == boolean_true_node);\n+\t  if (kind == 0\n+\t      && TREE_CODE (m) == FUNCTION_DECL\n+\t      && DECL_ARTIFICIAL (m))\n+\t    {\n+\t      /* Implicitly-declared special members or operator== members\n+\t\t appear after any user declared members.  */\n+\t      implicitly_declared.safe_push (m);\n+\t      continue;\n+\t    }\n+\t  else if (kind == 3)\n+\t    continue;\n+\t  CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t  get_reflection_raw (loc, m));\n+\t}\n+    }\n+  /* TYPE_DECLs in TYPE_FIELDS come after other decls, so for members_of\n+     the declaration order is not preserved.  */\n+  if (kind == 0 && elts)\n+    elts->qsort (members_cmp);\n+  if (kind == 0 && !implicitly_declared.is_empty ())\n+    {\n+      gcc_assert (implicitly_declared.length () <= 8);\n+      for (tree m : implicitly_declared)\n+\tif (default_ctor_p (m))\n+\t  {\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t    get_reflection_raw (loc, m));\n+\t    break;\n+\t  }\n+      for (tree m : implicitly_declared)\n+\tif (DECL_COPY_CONSTRUCTOR_P (m))\n+\t  {\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t    get_reflection_raw (loc, m));\n+\t    break;\n+\t  }\n+      for (tree m : implicitly_declared)\n+\tif (special_function_p (m) == sfk_copy_assignment)\n+\t  {\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t    get_reflection_raw (loc, m));\n+\t    break;\n+\t  }\n+      for (tree m : implicitly_declared)\n+\tif (DECL_MOVE_CONSTRUCTOR_P (m))\n+\t  {\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t    get_reflection_raw (loc, m));\n+\t    break;\n+\t  }\n+      for (tree m : implicitly_declared)\n+\tif (special_function_p (m) == sfk_move_assignment)\n+\t  {\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t    get_reflection_raw (loc, m));\n+\t    break;\n+\t  }\n+      for (tree m : implicitly_declared)\n+\tif (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (m))\n+\t  {\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t    get_reflection_raw (loc, m));\n+\t    break;\n+\t  }\n+      for (tree m : implicitly_declared)\n+\tif (DECL_OVERLOADED_OPERATOR_IS (m, EQ_EXPR))\n+\t  {\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t\t    get_reflection_raw (loc, m));\n+\t    break;\n+\t  }\n+    }\n+  return elts;\n+}\n+\n+/* Enumerate bases of class R for eval_*of.  KIND is 0 for\n+   bases_of and 1 for has_inaccessible_bases.  */\n+\n+static vec<constructor_elt, va_gc> *\n+class_bases_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\ttree actx, tree call, bool *non_constant_p,\n+\t\ttree *jump_target, int kind, tree fun)\n+{\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  tree binfo = TYPE_BINFO (r), base_binfo;\n+  for (unsigned i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)\n+    {\n+      tree a = eval_is_accessible (loc, ctx, base_binfo, REFLECT_BASE, actx,\n+\t\t\t\t   call, non_constant_p, jump_target, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn nullptr;\n+      if (a == boolean_false_node)\n+\t{\n+\t  if (kind == 1 && elts == nullptr)\n+\t    CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, boolean_true_node);\n+\t  continue;\n+\t}\n+      gcc_assert (a == boolean_true_node);\n+      if (kind == 1)\n+\tcontinue;\n+      CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE,\n+\t\t\t      get_reflection_raw (loc, base_binfo,\n+\t\t\t\t\t\t  REFLECT_BASE));\n+    }\n+  return elts;\n+}\n+\n+/* Implement std::meta::members_of.\n+   A declaration D members-of-precedes a point P if D precedes either P or the\n+   point immediately following the class-specifier of the outermost class for\n+   which P is in a complete-class context.\n+   A declaration D of a member M of a class or namespace Q is\n+   Q-members-of-eligible if\n+   -- the host scope of D is the class scope or namespace scope associated\n+      with Q,\n+   -- D is not a friend declaration,\n+   -- M is not a closure type,\n+   -- M is not a specialization of a template,\n+   -- if Q is a class that is not a closure type, then M is a direct member of\n+      Q that is not a variant member of a nested anonymous union of Q, and\n+   -- if Q is a closure type, then M is a function call operator or function\n+      call operator template.\n+   It is implementation-defined whether declarations of other members of a\n+   closure type Q are Q-members-of-eligible.\n+   A member M of a class or namespace Q is Q-members-of-representable from a\n+   point P if a Q-members-of-eligible declaration of M members-of-precedes P,\n+   and M is\n+   -- a class or enumeration type\n+   -- a type alias\n+   -- a class template, function template, variable template, alias template,\n+      or concept,\n+   -- a variable or reference V for which the type of V does not contain an\n+      undeduced placeholder type,\n+   -- a function F for which\n+      -- the type of F does not contain an undeduced placeholder type,\n+      -- the constraints (if any) of F are satisfied, and\n+      -- if F is a prospective destructor, F is the selected destructor,\n+   -- a non-static data member,\n+   -- a namespace, or\n+   -- a namespace alias.\n+   Returns: A vector containing reflections of all members M of the entity Q\n+   represented by dealias(r) for which\n+   -- M is Q-members-of-representable from some point in the evaluation\n+      context and\n+   -- is_accessible(^^M, ctx) is true.\n+   If dealias(r) represents a class C, then the vector also contains\n+   reflections representing all unnamed bit-fields B whose declarations\n+   inhabit the class scope corresponding to C for which\n+   is_accessible(^^B, ctx) is true.\n+   Reflections of class members and unnamed bit-fields that are declared\n+   appear in the order in which they are declared.\n+   Throws: meta::exception unless dealias(r) is a reflection representing\n+   either a class type that is complete from some point in the evaluation\n+   context or a namespace.  */\n+\n+static tree\n+eval_members_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t tree actx, tree call, bool *non_constant_p,\n+\t\t tree *jump_target, tree fun)\n+{\n+  r = maybe_strip_typedefs (r);\n+  if (TREE_CODE (r) == NAMESPACE_DECL)\n+    r = ORIGINAL_NAMESPACE (r);\n+  vec<constructor_elt, va_gc> *elts;\n+  if (TREE_CODE (r) == NAMESPACE_DECL)\n+    elts = namespace_members_of (loc, r);\n+  else if (CLASS_TYPE_P (r)\n+\t   && complete_type_or_maybe_complain (r, NULL_TREE, tf_none))\n+    {\n+      elts = class_members_of (loc, ctx, r, actx, call, non_constant_p,\n+\t\t\t       jump_target, 0, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+    }\n+  else\n+    return throw_exception (loc, ctx,\n+\t\t\t    \"neither complete class type nor namespace\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Implement std::meta::bases_of.\n+   Returns: Let C be the class represented by dealias(type).\n+   A vector containing the reflections of all the direct base class\n+   relationships B, if any, of C such that is_accessible(^^B, ctx) is true.\n+   The direct base class relationships appear in the order in which the\n+   corresponding base classes appear in the base-specifier-list of C.\n+   Throws: meta::exception unless dealias(type) represents a class type that\n+   is complete from some point in the evaluation context.  */\n+\n+static tree\n+eval_bases_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t       tree actx, tree call, bool *non_constant_p,\n+\t       tree *jump_target, tree fun)\n+{\n+  r = maybe_strip_typedefs (r);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  if (CLASS_TYPE_P (r)\n+      && complete_type_or_maybe_complain (r, NULL_TREE, tf_none))\n+    {\n+      elts = class_bases_of (loc, ctx, r, actx, call, non_constant_p,\n+\t\t\t     jump_target, 0, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+    }\n+  else\n+    return throw_exception (loc, ctx, \"not a complete class type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Implement std::meta::static_data_members_of.\n+   Returns: A vector containing each element e of members_of(type, ctx) such\n+   that is_variable(e) is true, preserving their order.\n+   Throws: meta::exception unless dealias(type) represents a class type that\n+   is complete from some point in the evaluation context.  */\n+\n+static tree\n+eval_static_data_members_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t\t     tree actx, tree call, bool *non_constant_p,\n+\t\t\t     tree *jump_target, tree fun)\n+{\n+  r = maybe_strip_typedefs (r);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  if (CLASS_TYPE_P (r)\n+      && complete_type_or_maybe_complain (r, NULL_TREE, tf_none))\n+    {\n+      elts = class_members_of (loc, ctx, r, actx, call, non_constant_p,\n+\t\t\t       jump_target, 1, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+    }\n+  else\n+    return throw_exception (loc, ctx, \"not a complete class type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Implement std::meta::nonstatic_data_members_of.\n+   Returns: A vector containing each element e of members_of(type, ctx) such\n+   that is_nonstatic_data_member(e) is true, preserving their order.\n+   Throws: meta::exception unless dealias(type) represents a class type that\n+   is complete from some point in the evaluation context.  */\n+\n+static tree\n+eval_nonstatic_data_members_of (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t\ttree r, tree actx, tree call,\n+\t\t\t\tbool *non_constant_p, tree *jump_target,\n+\t\t\t\ttree fun)\n+{\n+  r = maybe_strip_typedefs (r);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  if (CLASS_TYPE_P (r)\n+      && complete_type_or_maybe_complain (r, NULL_TREE, tf_none))\n+    {\n+      elts = class_members_of (loc, ctx, r, actx, call, non_constant_p,\n+\t\t\t       jump_target, 2, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+    }\n+  else\n+    return throw_exception (loc, ctx, \"not a complete class type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Implement std::meta::subobjects_of.\n+   Returns: A vector containing each element of bases_of(type, ctx) followed\n+   by each element of nonstatic_data_members_of(type, ctx), preserving their\n+   order.\n+   Throws: meta::exception unless dealias(type) represents a class type that\n+   is complete from some point in the evaluation context.  */\n+\n+static tree\n+eval_subobjects_of (location_t loc, const constexpr_ctx *ctx, tree r,\n+\t\t    tree actx, tree call, bool *non_constant_p,\n+\t\t    tree *jump_target, tree fun)\n+{\n+  r = maybe_strip_typedefs (r);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  if (CLASS_TYPE_P (r)\n+      && complete_type_or_maybe_complain (r, NULL_TREE, tf_none))\n+    {\n+      elts = class_bases_of (loc, ctx, r, actx, call, non_constant_p,\n+\t\t\t     jump_target, 0, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      vec<constructor_elt, va_gc> *elts2\n+\t= class_members_of (loc, ctx, r, actx, call, non_constant_p,\n+\t\t\t    jump_target, 2, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      if (elts == nullptr)\n+\telts = elts2;\n+      else if (elts2)\n+\tvec_safe_splice (elts, elts2);\n+    }\n+  else\n+    return throw_exception (loc, ctx, \"not a complete class type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  return get_vector_of_info_elts (elts);\n+}\n+\n+/* Implement std::meta::has_inaccessible_nonstatic_data_members.\n+   Returns: true if is_accessible(R, ctx) is false for any R in\n+   nonstatic_data_members_of(r, access_context::unchecked()).\n+   Otherwise, false.\n+   Throws: meta::exception if\n+   -- the evaluation of\n+      nonstatic_data_members_of(r, access_context::unchecked()) would exit via\n+      an exception and or\n+   -- r represents a closure type.  */\n+\n+static tree\n+eval_has_inaccessible_nonstatic_data_members (location_t loc,\n+\t\t\t\t\t      const constexpr_ctx *ctx,\n+\t\t\t\t\t      tree r, tree actx, tree call,\n+\t\t\t\t\t      bool *non_constant_p,\n+\t\t\t\t\t      tree *jump_target, tree fun)\n+{\n+  r = maybe_strip_typedefs (r);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  if (CLASS_TYPE_P (r)\n+      && complete_type_or_maybe_complain (r, NULL_TREE, tf_none))\n+    {\n+      if (LAMBDA_TYPE_P (r))\n+\treturn throw_exception (loc, ctx, \"closure type\", fun,\n+\t\t\t\tnon_constant_p, jump_target);\n+      elts = class_members_of (loc, ctx, r, actx, call, non_constant_p,\n+\t\t\t       jump_target, 3, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+    }\n+  else\n+    return throw_exception (loc, ctx, \"not a complete class type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (elts == nullptr)\n+    return boolean_false_node;\n+  else\n+    return boolean_true_node;\n+}\n+\n+/* Implement std::meta::has_inaccessible_bases.\n+   Returns: true if is_accessible(R, ctx) is false for any R in\n+   bases_of(r, access_context::unchecked()).  Otherwise, false.\n+   Throws: meta::exception if the evaluation of\n+   bases_of(r, access_context::unchecked()) would exit via an exception.  */\n+\n+static tree\n+eval_has_inaccessible_bases (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t     tree r, tree actx, tree call,\n+\t\t\t     bool *non_constant_p, tree *jump_target,\n+\t\t\t     tree fun)\n+{\n+  r = maybe_strip_typedefs (r);\n+  vec<constructor_elt, va_gc> *elts = nullptr;\n+  if (CLASS_TYPE_P (r)\n+      && complete_type_or_maybe_complain (r, NULL_TREE, tf_none))\n+    {\n+      elts = class_bases_of (loc, ctx, r, actx, call, non_constant_p,\n+\t\t\t     jump_target, 1, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+    }\n+  else\n+    return throw_exception (loc, ctx, \"not a complete class type\",\n+\t\t\t    fun, non_constant_p, jump_target);\n+  if (elts == nullptr)\n+    return boolean_false_node;\n+  else\n+    return boolean_true_node;\n+}\n+\n+/* Implement std::meta::has_inaccessible_subobjects.\n+   Effects: Equivalent to:\n+   return has_inaccessible_bases(r, ctx)\n+\t  || has_inaccessible_nonstatic_data_members(r, ctx);  */\n+\n+static tree\n+eval_has_inaccessible_subobjects (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t\t  tree r, tree actx, tree call,\n+\t\t\t\t  bool *non_constant_p, tree *jump_target,\n+\t\t\t\t  tree fun)\n+{\n+  tree b = eval_has_inaccessible_bases (loc, ctx, r, actx, call,\n+\t\t\t\t\tnon_constant_p, jump_target, fun);\n+  if (*jump_target || *non_constant_p)\n+    return NULL_TREE;\n+  if (b == boolean_true_node)\n+    return b;\n+  return eval_has_inaccessible_nonstatic_data_members (loc, ctx, r, actx,\n+\t\t\t\t\t\t       call, non_constant_p,\n+\t\t\t\t\t\t       jump_target, fun);\n+}\n+\n+/* Implement std::meta::exception::_S_exception_cvt_to_utf8.  This is\n+   an implementation specific metafunction which translates string_view\n+   into u8string_view for use in std::meta::exception constructors.\n+   On translation failure returns an empty u8string_view.  */\n+\n+static tree\n+eval_exception__S_exception_cvt_to_utf8 (location_t loc,\n+\t\t\t\t\t const constexpr_ctx *ctx,\n+\t\t\t\t\t tree call, bool *non_constant_p,\n+\t\t\t\t\t bool *overflow_p, tree *jump_target,\n+\t\t\t\t\t tree fun)\n+{\n+  tree str = get_range_elts (loc, ctx, call, 0, non_constant_p, overflow_p,\n+\t\t\t     jump_target, REFLECT_CONSTANT_STRING, fun);\n+  if (*jump_target || *non_constant_p)\n+    return NULL_TREE;\n+  if (TREE_CODE (str) != STRING_CST\n+      || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (str))) != char_type_node)\n+    {\n+      error_at (loc, \"unexpected argument to %<_S_exception_cvt_to_utf8%>\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  /* We need to translate the string twice for the theoretical case\n+     of non-UTF8 SOURCE_CHARSET.  First translate from exec charset to\n+     SOURCE_CHARSET...  */\n+  cpp_string istr, ostr;\n+  istr.len = TREE_STRING_LENGTH (str) + 1;\n+  istr.text = (const unsigned char *) TREE_STRING_POINTER (str);\n+  const char *name;\n+  if (!cpp_translate_string (parse_in, &istr, &ostr, CPP_STRING, true))\n+    {\n+      ostr.text = NULL;\n+      name = \"\";\n+    }\n+  else\n+    name = (const char *) ostr.text;\n+  /* And then let temp_string_literal translate from SOURCE_CHARSET to\n+     UTF-8.  */\n+  str = temp_string_literal (name, char8_type_node);\n+  free (const_cast <unsigned char *> (ostr.text));\n+  if (str == NULL_TREE)\n+    {\n+      str = temp_string_literal (\"\", char8_type_node);\n+      gcc_assert (str);\n+    }\n+  releasing_vec args (make_tree_vector_single (str));\n+  tree ret = build_special_member_call (NULL_TREE, complete_ctor_identifier,\n+\t\t\t\t\t&args, TREE_TYPE (call), LOOKUP_NORMAL,\n+\t\t\t\t\ttf_warning_or_error);\n+  return build_cplus_new (TREE_TYPE (call), ret, tf_warning_or_error);\n+}\n+\n+/* Implement std::meta::exception::_S_exception_cvt_from_utf8.  This is\n+   an implementation specific metafunction which translates u8string_view\n+   into string_view for use in std::meta::exception constructors.\n+   On translation failure returns an empty string_view.  */\n+\n+static tree\n+eval_exception__S_exception_cvt_from_utf8 (location_t loc,\n+\t\t\t\t\t   const constexpr_ctx *ctx,\n+\t\t\t\t\t   tree call, bool *non_constant_p,\n+\t\t\t\t\t   bool *overflow_p, tree *jump_target,\n+\t\t\t\t\t   tree fun)\n+{\n+  tree str = get_range_elts (loc, ctx, call, 0, non_constant_p, overflow_p,\n+\t\t\t     jump_target, REFLECT_CONSTANT_STRING, fun);\n+  if (*jump_target || *non_constant_p)\n+    return NULL_TREE;\n+  if (TREE_CODE (str) != STRING_CST\n+      || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (str))) != char8_type_node)\n+    {\n+      error_at (loc, \"unexpected argument to %<_S_exception_cvt_from_utf8%>\");\n+      *non_constant_p = true;\n+      return call;\n+    }\n+  /* We need to translate the string twice for the theoretical case\n+     of non-UTF8 SOURCE_CHARSET.  First translate from UTF-8 to\n+     SOURCE_CHARSET...  */\n+  cpp_string istr, ostr;\n+  istr.len = TREE_STRING_LENGTH (str) + 1;\n+  istr.text = (const unsigned char *) TREE_STRING_POINTER (str);\n+  const char *name;\n+  if (!cpp_translate_string (parse_in, &istr, &ostr, CPP_UTF8STRING, true))\n+    {\n+      ostr.text = NULL;\n+      name = \"\";\n+    }\n+  else\n+    name = (const char *) ostr.text;\n+  /* And then let temp_string_literal translate from SOURCE_CHARSET to\n+     exec charset.  */\n+  str = temp_string_literal (name, char_type_node);\n+  free (const_cast <unsigned char *> (ostr.text));\n+  if (str == NULL_TREE)\n+    {\n+      str = temp_string_literal (\"\", char_type_node);\n+      gcc_assert (str);\n+    }\n+  releasing_vec args (make_tree_vector_single (str));\n+  tree ret = build_special_member_call (NULL_TREE, complete_ctor_identifier,\n+\t\t\t\t\t&args, TREE_TYPE (call), LOOKUP_NORMAL,\n+\t\t\t\t\ttf_warning_or_error);\n+  return build_cplus_new (TREE_TYPE (call), ret, tf_warning_or_error);\n+}\n+\n+/* Helper for eval_extract, extracting a reference.\n+   Returns: If r represents an object O, then a reference to O.\n+   Otherwise, a reference to the object declared, or referred to, by the\n+   variable represented by r.\n+   Throws: meta::exception unless\n+   -- r represents a variable or object of type U,\n+   -- is_convertible_v<remove_reference_t<U>(*)[],\n+      remove_reference_t<T>(*)[]> is true, and\n+   -- If r represents a variable, then either that variable is usable in\n+      constant expressions or its lifetime began within the core constant\n+      expression currently under evaluation.  */\n+\n+static tree\n+extract_ref (location_t loc, const constexpr_ctx *ctx, tree T, tree r,\n+\t     reflect_kind kind, bool *non_constant_p, tree *jump_target,\n+\t     tree fun)\n+{\n+  auto adjust_type = [](tree type) -> tree\n+    {\n+      if (TYPE_REF_P (type))\n+\ttype = TREE_TYPE (type);\n+      type = build_cplus_array_type (type, NULL_TREE);\n+      return build_pointer_type (type);\n+    };\n+\n+  const bool var_p = eval_is_variable (r, kind) == boolean_true_node;\n+  if (var_p || eval_is_object (kind) == boolean_true_node)\n+    {\n+      /* The wording is saying that U is the type of r.  */\n+      tree U = TREE_TYPE (r);\n+      if (is_convertible (adjust_type (U), adjust_type (T))\n+\t  && (!var_p || is_constant_expression (r)))\n+\t{\n+\t  if (TYPE_REF_P (TREE_TYPE (r)))\n+\t    {\n+\t      r = DECL_INITIAL (r);\n+\t      r = maybe_get_reference_referent (r);\n+\t    }\n+\t  return build_address (r);\n+\t}\n+    }\n+\n+  return throw_exception (loc, ctx, \"value cannot be extracted\", fun,\n+\t\t\t  non_constant_p, jump_target);\n+}\n+\n+/* Helper for extract_value.  Return true iff we can extract value of\n+   type U using type T.  */\n+\n+static bool\n+can_extract_value_p (tree T, tree U)\n+{\n+  if (POINTER_TYPE_P (U)\n+      && (similar_type_p (T, U)\n+\t  || (FUNCTION_POINTER_TYPE_P (T) && FUNCTION_POINTER_TYPE_P (U)))\n+      && is_convertible (U, T))\n+    return true;\n+  else if (same_type_ignoring_top_level_qualifiers_p (T, U))\n+    return true;\n+  else if (TREE_CODE (U) == ARRAY_TYPE\n+\t   && POINTER_TYPE_P (T)\n+\t   && is_convertible (U, T))\n+    {\n+      /* remove_extent_t<U> */\n+      U = TREE_TYPE (U);\n+      U = strip_typedefs (U);\n+      /* remove_extent_t<U>* */\n+      U = build_pointer_type (U);\n+      return similar_type_p (T, U);\n+    }\n+  else if (LAMBDA_TYPE_P (U)\n+\t   && FUNCTION_POINTER_TYPE_P (T)\n+\t   && is_convertible (U, T))\n+    return true;\n+  return false;\n+}\n+\n+/* Helper for eval_extract, extracting a value.\n+   Let U be the type of the value or object that r represents.\n+   Returns: static_cast<T>([:R:]), where R is a constant expression of\n+   type info such that R == r is true.\n+   Throws: meta::exception unless\n+   -- U is a pointer type, T and U are either similar or both function pointer\n+      types, and is_convertible_v<U, T> is true,\n+   -- U is not a pointer type and the cv-unqualified types of T and U are the\n+      same,\n+   -- U is an array type, T is a pointer type, remove_extent_t<U>* and T are\n+      similar types, and the value r represents is convertible to T, or\n+   -- U is a closure type, T is a function pointer type, and the value that r\n+      represents is convertible to T.  */\n+\n+static tree\n+extract_value (location_t loc, const constexpr_ctx *ctx, tree T, tree r,\n+\t       bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  if (REFLECT_EXPR_P (r))\n+    {\n+      r = REFLECT_EXPR_HANDLE (r);\n+      if (can_extract_value_p (T, TREE_TYPE (r)))\n+\treturn build_static_cast (loc, T, r, tf_none);\n+    }\n+  return throw_exception (loc, ctx, \"value cannot be extracted\", fun,\n+\t\t\t  non_constant_p, jump_target);\n+}\n+\n+/* Helper for extract_member_or_function.  Return true iff we can\n+   extract NSDM R of kind KIND using type T.  */\n+\n+static bool\n+can_extract_member_or_function_p (tree T, tree r, reflect_kind kind)\n+{\n+  if (eval_is_nonstatic_data_member (r) == boolean_true_node)\n+    {\n+      if (eval_is_bit_field (r, kind) == boolean_true_node)\n+\treturn false;\n+      /* static union { int m; }; extract<int>(^^m); is invalid.  */\n+      if (VAR_P (r) && DECL_ANON_UNION_VAR_P (r))\n+\treturn false;\n+      /* Create the X C::* type.  */\n+      tree type = build_offset_type (CP_DECL_CONTEXT (r), TREE_TYPE (r));\n+      if (similar_type_p (type, T) && is_convertible (type, T))\n+\treturn true;\n+      return false;\n+    }\n+  else if (DECL_IOBJ_MEMBER_FUNCTION_P (r))\n+    {\n+      tree F = TREE_TYPE (r);\n+      F = build_pointer_type (F);\n+      F = build_ptrmemfunc_type (F);\n+      if (same_type_p (T, F))\n+\treturn true;\n+      return false;\n+    }\n+  else if (TREE_CODE (r) == FUNCTION_DECL)\n+    {\n+      tree F = TREE_TYPE (r);\n+      F = build_pointer_type (F);\n+      if (same_type_p (T, F))\n+\treturn true;\n+      return false;\n+    }\n+\n+  return false;\n+}\n+\n+/* Helper for eval_extract, extracting a NSDM or function.\n+   Returns:\n+   -- If T is a pointer type, then a pointer value pointing to the function\n+      represented by r.\n+   -- Otherwise, a pointer-to-member value designating the non-static data\n+      member or function represented by r.\n+   Throws: meta::exception unless\n+   -- r represents a non-static data member with type X, that is not\n+      a bit-field, that is a direct member of class C, T and X C::*\n+      are similar types, and is_convertible_v<X C::*, T> is true;\n+   -- r represents an implicit object member function with type F or\n+      F noexcept that is a direct member of a class C, and T is F C::*; or\n+   -- r represents a non-member function, static member function, or\n+      explicit object member function of function type F or F noexcept, and\n+      T is F*.  */\n+\n+static tree\n+extract_member_or_function (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t    tree T, tree r, reflect_kind kind,\n+\t\t\t    bool *non_constant_p, tree *jump_target, tree fun)\n+{\n+  r = MAYBE_BASELINK_FUNCTIONS (r);\n+  if (!can_extract_member_or_function_p (T, r, kind))\n+    return throw_exception (loc, ctx, \"value cannot be extracted\", fun,\n+\t\t\t    non_constant_p, jump_target);\n+\n+  const tsubst_flags_t complain = (cxx_constexpr_quiet_p (ctx)\n+\t\t\t\t   ? tf_none : tf_warning_or_error);\n+  if (POINTER_TYPE_P (T))\n+    return build_address (r);\n+  else\n+    {\n+      if (!mark_used (r, complain))\n+\t{\n+\t  *non_constant_p = true;\n+\t  return NULL_TREE;\n+\t}\n+      r = build_offset_ref (DECL_CONTEXT (r), r, /*address_p=*/true, complain);\n+      r = cp_build_addr_expr (r, complain);\n+      r = cp_convert (T, r, complain);\n+      return r;\n+    }\n+}\n+\n+/* Process std::meta::extract.\n+   Let U be remove_cv_t<T>.\n+   Effects: Equivalent to:\n+     if constexpr (is_reference_type(^^T)) {\n+       return extract-ref<T>(r);\n+     } else if constexpr (is_nonstatic_data_member(r) || is_function(r)) {\n+       return extract-member-or-function<U>(r);\n+     } else {\n+       return extract-value<U>(constant_of(r));\n+     }\n+  */\n+\n+static tree\n+eval_extract (location_t loc, const constexpr_ctx *ctx, tree type, tree r,\n+\t      reflect_kind kind, bool *non_constant_p, bool *overflow_p,\n+\t      tree *jump_target, tree fun)\n+{\n+  if (eval_is_reference_type (loc, type) == boolean_true_node)\n+    return extract_ref (loc, ctx, type, r, kind, non_constant_p, jump_target,\n+\t\t\tfun);\n+  type = cv_unqualified (type);\n+  if (eval_is_nonstatic_data_member (r) == boolean_true_node\n+      || eval_is_function (r) == boolean_true_node)\n+    return extract_member_or_function (loc, ctx, type, r, kind, non_constant_p,\n+\t\t\t\t       jump_target, fun);\n+  else\n+    {\n+      r = eval_constant_of (loc, ctx, r, kind, non_constant_p, overflow_p,\n+\t\t\t    jump_target, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      return extract_value (loc, ctx, type, r, non_constant_p, jump_target,\n+\t\t\t    fun);\n+    }\n+}\n+\n+#include \"metafns.h\"\n+\n+/* Expand a call to a metafunction FUN.  CALL is the CALL_EXPR.\n+   JUMP_TARGET is set if we are throwing std::meta::exception.  */\n+\n+tree\n+process_metafunction (const constexpr_ctx *ctx, tree fun, tree call,\n+\t\t      bool *non_constant_p, bool *overflow_p,\n+\t\t      tree *jump_target)\n+{\n+  tree name = DECL_NAME (fun);\n+  const char *ident = IDENTIFIER_POINTER (name);\n+  const location_t loc = cp_expr_loc_or_input_loc (call);\n+  const metafn_info *minfo\n+    = metafn_lookup::find (ident, IDENTIFIER_LENGTH (name));\n+  if (minfo == NULL)\n+    {\n+    not_found:\n+      error_at (loc, \"unknown metafunction %qD\", fun);\n+      *non_constant_p = true;\n+      return NULL_TREE;\n+    }\n+  tree h = NULL_TREE, h1 = NULL_TREE, hvec = NULL_TREE, expr = NULL_TREE;\n+  tree type = NULL_TREE, info;\n+  reflect_kind kind = REFLECT_UNDEF;\n+  switch ((minfo->kind >> 5) & 31)\n+    {\n+    case METAFN_KIND_ARG_VOID:\n+      break;\n+    case METAFN_KIND_ARG_INFO:\n+    case METAFN_KIND_ARG_TINFO:\n+      info = get_info (ctx, call, 0, non_constant_p, overflow_p, jump_target);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      h = REFLECT_EXPR_HANDLE (info);\n+      kind = REFLECT_EXPR_KIND (info);\n+      if (((minfo->kind >> 5) & 31) == METAFN_KIND_ARG_TINFO)\n+\t{\n+\t  if (eval_is_type (h) != boolean_true_node)\n+\t    return throw_exception_nontype (loc, ctx, fun, non_constant_p,\n+\t\t\t\t\t    jump_target);\n+\t}\n+      else\n+\t{\n+\t  /* There still could be a TEMPLATE_ID_EXPR denoting a function\n+\t     template.  */\n+\t  h = resolve_nondeduced_context (h, tf_warning_or_error);\n+\t}\n+      break;\n+    case METAFN_KIND_ARG_REFLECTION_RANGE:\n+    case METAFN_KIND_ARG_UNSIGNED:\n+    case METAFN_KIND_ARG_ACCESS_CONTEXT:\n+    case METAFN_KIND_ARG_DATA_MEMBER_OPTIONS:\n+    default:\n+      gcc_unreachable ();\n+    case METAFN_KIND_ARG_REFLECTION_RANGET:\n+      hvec = get_type_info_vec (loc, ctx, call, 0, non_constant_p,\n+\t\t\t\toverflow_p, jump_target, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      break;\n+    case METAFN_KIND_ARG_INPUT_RANGE:\n+      /* Handled in eval_reflect_constant_*.  */\n+      break;\n+    case METAFN_KIND_ARG_TEMPLATE_PARM:\n+    case METAFN_KIND_ARG_TEMPLATE_PARM_REF:\n+      type = TREE_VEC_ELT (get_template_innermost_arguments (fun), 0);\n+      /* FALLTHRU */\n+    case METAFN_KIND_ARG_SIZE_T:\n+    case METAFN_KIND_ARG_OPERATORS:\n+      expr = get_nth_callarg (call, 0);\n+      expr = cxx_eval_constant_expression (ctx, expr, vc_prvalue,\n+\t\t\t\t\t   non_constant_p, overflow_p,\n+\t\t\t\t\t   jump_target);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      break;\n+    }\n+  switch ((minfo->kind >> 10) & 31)\n+    {\n+    case METAFN_KIND_ARG_VOID:\n+      break;\n+    case METAFN_KIND_ARG_INFO:\n+    case METAFN_KIND_ARG_TINFO:\n+      info = get_info (ctx, call, 1, non_constant_p, overflow_p, jump_target);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      h1 = REFLECT_EXPR_HANDLE (info);\n+      if (((minfo->kind >> 10) & 31) == METAFN_KIND_ARG_TINFO)\n+\t{\n+\t  if (eval_is_type (h1) != boolean_true_node)\n+\t    return throw_exception_nontype (loc, ctx, fun, non_constant_p,\n+\t\t\t\t\t    jump_target);\n+\t}\n+      break;\n+    case METAFN_KIND_ARG_SIZE_T:\n+    case METAFN_KIND_ARG_OPERATORS:\n+    case METAFN_KIND_ARG_INPUT_RANGE:\n+    case METAFN_KIND_ARG_TEMPLATE_PARM:\n+    case METAFN_KIND_ARG_TEMPLATE_PARM_REF:\n+    default:\n+      gcc_unreachable ();\n+    case METAFN_KIND_ARG_REFLECTION_RANGE:\n+      hvec = get_info_vec (loc, ctx, call, 1, non_constant_p, overflow_p,\n+\t\t\t   jump_target, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      break;\n+    case METAFN_KIND_ARG_REFLECTION_RANGET:\n+      hvec = get_type_info_vec (loc, ctx, call, 1, non_constant_p,\n+\t\t\t\toverflow_p, jump_target, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      break;\n+    case METAFN_KIND_ARG_UNSIGNED:\n+    case METAFN_KIND_ARG_ACCESS_CONTEXT:\n+    case METAFN_KIND_ARG_DATA_MEMBER_OPTIONS:\n+      expr = get_nth_callarg (call, 1);\n+      expr = cxx_eval_constant_expression (ctx, expr, vc_prvalue,\n+\t\t\t\t\t   non_constant_p, overflow_p,\n+\t\t\t\t\t   jump_target);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      break;\n+    }\n+  switch ((minfo->kind >> 15) & 31)\n+    {\n+    case METAFN_KIND_ARG_VOID:\n+      break;\n+    default:\n+      gcc_unreachable ();\n+    case METAFN_KIND_ARG_REFLECTION_RANGET:\n+      hvec = get_type_info_vec (loc, ctx, call, 2, non_constant_p,\n+\t\t\t\toverflow_p, jump_target, fun);\n+      if (*jump_target || *non_constant_p)\n+\treturn NULL_TREE;\n+      break;\n+    }\n+\n+  switch (minfo->code)\n+    {\n+    case METAFN_OPERATOR_OF:\n+      return eval_operator_of (loc, ctx, h, non_constant_p, jump_target,\n+\t\t\t       TREE_TYPE (call), fun);\n+    case METAFN_SYMBOL_OF:\n+      return eval_symbol_of (loc, ctx, expr, non_constant_p, jump_target,\n+\t\t\t     char_type_node, TREE_TYPE (call), fun);\n+    case METAFN_U8SYMBOL_OF:\n+      return eval_symbol_of (loc, ctx, expr, non_constant_p, jump_target,\n+\t\t\t     char8_type_node, TREE_TYPE (call), fun);\n+    case METAFN_HAS_IDENTIFIER:\n+      return eval_has_identifier (h, kind);\n+    case METAFN_IDENTIFIER_OF:\n+      return eval_identifier_of (loc, ctx, h, kind, non_constant_p, jump_target,\n+\t\t\t\t char_type_node, TREE_TYPE (call), fun);\n+    case METAFN_U8IDENTIFIER_OF:\n+      return eval_identifier_of (loc, ctx, h, kind, non_constant_p, jump_target,\n+\t\t\t\t char8_type_node, TREE_TYPE (call), fun);\n+    case METAFN_DISPLAY_STRING_OF:\n+      return eval_display_string_of (loc, ctx, h, kind, non_constant_p,\n+\t\t\t\t     jump_target, char_type_node,\n+\t\t\t\t     TREE_TYPE (call), fun);\n+    case METAFN_U8DISPLAY_STRING_OF:\n+      return eval_display_string_of (loc, ctx, h, kind, non_constant_p,\n+\t\t\t\t     jump_target, char8_type_node,\n+\t\t\t\t     TREE_TYPE (call), fun);\n+    case METAFN_SOURCE_LOCATION_OF:\n+      return eval_source_location_of (loc, h, kind, TREE_TYPE (call));\n+    case METAFN_TYPE_OF:\n+      return eval_type_of (loc, ctx, h, kind, non_constant_p, jump_target, fun);\n+    case METAFN_OBJECT_OF:\n+      return eval_object_of (loc, ctx, h, kind, non_constant_p, jump_target,\n+\t\t\t     fun);\n+    case METAFN_CONSTANT_OF:\n+      return eval_constant_of (loc, ctx, h, kind, non_constant_p, overflow_p,\n+\t\t\t       jump_target, fun);\n+    case METAFN_IS_PUBLIC:\n+      return eval_is_public (h, kind);\n+    case METAFN_IS_PROTECTED:\n+      return eval_is_protected (h, kind);\n+    case METAFN_IS_PRIVATE:\n+      return eval_is_private (h, kind);\n+    case METAFN_IS_VIRTUAL:\n+      return eval_is_virtual (h, kind);\n+    case METAFN_IS_PURE_VIRTUAL:\n+      return eval_is_pure_virtual (h);\n+    case METAFN_IS_OVERRIDE:\n+      return eval_is_override (h);\n+    case METAFN_IS_FINAL:\n+      return eval_is_final (h);\n+    case METAFN_IS_DELETED:\n+      return eval_is_deleted (h);\n+    case METAFN_IS_DEFAULTED:\n+      return eval_is_defaulted (h);\n+    case METAFN_IS_USER_PROVIDED:\n+      return eval_is_user_provided (h);\n+    case METAFN_IS_USER_DECLARED:\n+      return eval_is_user_declared (h);\n+    case METAFN_IS_EXPLICIT:\n+      return eval_is_explicit (h);\n+    case METAFN_IS_NOEXCEPT:\n+      return eval_is_noexcept (h);\n+    case METAFN_IS_BIT_FIELD:\n+      return eval_is_bit_field (h, kind);\n+    case METAFN_IS_ENUMERATOR:\n+      return eval_is_enumerator (h);\n+    case METAFN_IS_ANNOTATION:\n+      return eval_is_annotation (h, kind);\n+    case METAFN_IS_CONST:\n+      return eval_is_const (h, kind);\n+    case METAFN_IS_VOLATILE:\n+      return eval_is_volatile (h, kind);\n+    case METAFN_IS_MUTABLE_MEMBER:\n+      return eval_is_mutable_member (h);\n+    case METAFN_IS_LVALUE_REFERENCE_QUALIFIED:\n+      return eval_is_lrvalue_reference_qualified (h, kind, /*rvalue_p=*/false);\n+    case METAFN_IS_RVALUE_REFERENCE_QUALIFIED:\n+      return eval_is_lrvalue_reference_qualified (h, kind, /*rvalue_p=*/true);\n+    case METAFN_HAS_STATIC_STORAGE_DURATION:\n+      return eval_has_static_storage_duration (h, kind);\n+    case METAFN_HAS_THREAD_STORAGE_DURATION:\n+      return eval_has_thread_storage_duration (h, kind);\n+    case METAFN_HAS_AUTOMATIC_STORAGE_DURATION:\n+      return eval_has_automatic_storage_duration (h, kind);\n+    case METAFN_HAS_INTERNAL_LINKAGE:\n+      return eval_has_internal_linkage (h, kind);\n+    case METAFN_HAS_MODULE_LINKAGE:\n+      return eval_has_module_linkage (h, kind);\n+    case METAFN_HAS_EXTERNAL_LINKAGE:\n+      return eval_has_external_linkage (h, kind);\n+    case METAFN_HAS_C_LANGUAGE_LINKAGE:\n+      return eval_has_c_language_linkage (h, kind);\n+    case METAFN_HAS_LINKAGE:\n+      return eval_has_linkage (h, kind);\n+    case METAFN_IS_COMPLETE_TYPE:\n+      return eval_is_complete_type (h);\n+    case METAFN_IS_ENUMERABLE_TYPE:\n+      return eval_is_enumerable_type (h);\n+    case METAFN_IS_VARIABLE:\n+      return eval_is_variable (h, kind);\n+    case METAFN_IS_TYPE:\n+      return eval_is_type (h);\n+    case METAFN_IS_NAMESPACE:\n+      return eval_is_namespace (h);\n+    case METAFN_IS_TYPE_ALIAS:\n+      return eval_is_type_alias (h);\n+    case METAFN_IS_NAMESPACE_ALIAS:\n+      return eval_is_namespace_alias (h);\n+    case METAFN_IS_FUNCTION:\n+      return eval_is_function (h);\n+    case METAFN_IS_CONVERSION_FUNCTION:\n+      return eval_is_conversion_function (h);\n+    case METAFN_IS_OPERATOR_FUNCTION:\n+      return eval_is_operator_function (h);\n+    case METAFN_IS_LITERAL_OPERATOR:\n+      return eval_is_literal_operator (h);\n+    case METAFN_IS_SPECIAL_MEMBER_FUNCTION:\n+      return eval_is_special_member_function (h);\n+    case METAFN_IS_CONSTRUCTOR:\n+      return eval_is_constructor (h);\n+    case METAFN_IS_DEFAULT_CONSTRUCTOR:\n+      return eval_is_default_constructor (h);\n+    case METAFN_IS_COPY_CONSTRUCTOR:\n+      return eval_is_copy_constructor (h);\n+    case METAFN_IS_MOVE_CONSTRUCTOR:\n+      return eval_is_move_constructor (h);\n+    case METAFN_IS_ASSIGNMENT:\n+      return eval_is_assignment (h);\n+    case METAFN_IS_COPY_ASSIGNMENT:\n+      return eval_is_copy_assignment (h);\n+    case METAFN_IS_MOVE_ASSIGNMENT:\n+      return eval_is_move_assignment (h);\n+    case METAFN_IS_DESTRUCTOR:\n+      return eval_is_destructor (h);\n+    case METAFN_IS_FUNCTION_PARAMETER:\n+      return eval_is_function_parameter (h, kind);\n+    case METAFN_IS_EXPLICIT_OBJECT_PARAMETER:\n+      return eval_is_explicit_object_parameter (h, kind);\n+    case METAFN_HAS_DEFAULT_ARGUMENT:\n+      return eval_has_default_argument (h, kind);\n+    case METAFN_HAS_ELLIPSIS_PARAMETER:\n+      return eval_has_ellipsis_parameter (h);\n+    case METAFN_IS_TEMPLATE:\n+      return eval_is_template (h);\n+    case METAFN_IS_FUNCTION_TEMPLATE:\n+      return eval_is_function_template (h);\n+    case METAFN_IS_VARIABLE_TEMPLATE:\n+      return eval_is_variable_template (h);\n+    case METAFN_IS_CLASS_TEMPLATE:\n+      return eval_is_class_template (h);\n+    case METAFN_IS_ALIAS_TEMPLATE:\n+      return eval_is_alias_template (h);\n+    case METAFN_IS_CONVERSION_FUNCTION_TEMPLATE:\n+      return eval_is_conversion_function_template (h);\n+    case METAFN_IS_OPERATOR_FUNCTION_TEMPLATE:\n+      return eval_is_operator_function_template (h);\n+    case METAFN_IS_LITERAL_OPERATOR_TEMPLATE:\n+      return eval_is_literal_operator_template (h);\n+    case METAFN_IS_CONSTRUCTOR_TEMPLATE:\n+      return eval_is_constructor_template (h);\n+    case METAFN_IS_CONCEPT:\n+      return eval_is_concept (h);\n+    case METAFN_IS_VALUE:\n+      return eval_is_value (kind);\n+    case METAFN_IS_OBJECT:\n+      return eval_is_object (kind);\n+    case METAFN_IS_STRUCTURED_BINDING:\n+      return eval_is_structured_binding (h, kind);\n+    case METAFN_IS_CLASS_MEMBER:\n+      return eval_is_class_member (h);\n+    case METAFN_IS_NAMESPACE_MEMBER:\n+      return eval_is_namespace_member (h);\n+    case METAFN_IS_NONSTATIC_DATA_MEMBER:\n+      return eval_is_nonstatic_data_member (h);\n+    case METAFN_IS_STATIC_MEMBER:\n+      return eval_is_static_member (h);\n+    case METAFN_IS_BASE:\n+      return eval_is_base (h, kind);\n+    case METAFN_HAS_DEFAULT_MEMBER_INITIALIZER:\n+      return eval_has_default_member_initializer (h);\n+    case METAFN_HAS_PARENT:\n+      return eval_has_parent (h, kind);\n+    case METAFN_PARENT_OF:\n+      return eval_parent_of (loc, ctx, h, kind, non_constant_p, jump_target,\n+\t\t\t     fun);\n+    case METAFN_DEALIAS:\n+      return eval_dealias (loc, h, kind);\n+    case METAFN_HAS_TEMPLATE_ARGUMENTS:\n+      return eval_has_template_arguments (h);\n+    case METAFN_TEMPLATE_OF:\n+      return eval_template_of (loc, ctx, h, non_constant_p, jump_target, fun);\n+    case METAFN_TEMPLATE_ARGUMENTS_OF:\n+      return eval_template_arguments_of (loc, ctx, h, non_constant_p,\n+\t\t\t\t\t jump_target, fun);\n+    case METAFN_PARAMETERS_OF:\n+      return eval_parameters_of (loc, ctx, h, non_constant_p, jump_target,\n+\t\t\t\t fun);\n+    case METAFN_VARIABLE_OF:\n+      return eval_variable_of (loc, ctx, h, kind, non_constant_p, jump_target,\n+\t\t\t       fun);\n+    case METAFN_RETURN_TYPE_OF:\n+      return eval_return_type_of (loc, ctx, h, kind, non_constant_p,\n+\t\t\t\t  jump_target, fun);\n+    case METAFN_IS_ACCESSIBLE:\n+      return eval_is_accessible (loc, ctx, h, kind, expr, call,\n+\t\t\t\t non_constant_p, jump_target, fun);\n+    case METAFN_HAS_INACCESSIBLE_NONSTATIC_DATA_MEMBERS:\n+      return eval_has_inaccessible_nonstatic_data_members (loc, ctx, h, expr,\n+\t\t\t\t\t\t\t   call,\n+\t\t\t\t\t\t\t   non_constant_p,\n+\t\t\t\t\t\t\t   jump_target, fun);\n+    case METAFN_HAS_INACCESSIBLE_BASES:\n+      return eval_has_inaccessible_bases (loc, ctx, h, expr, call,\n+\t\t\t\t\t  non_constant_p, jump_target, fun);\n+    case METAFN_HAS_INACCESSIBLE_SUBOBJECTS:\n+      return eval_has_inaccessible_subobjects (loc, ctx, h, expr, call,\n+\t\t\t\t\t       non_constant_p, jump_target,\n+\t\t\t\t\t       fun);\n+    case METAFN_MEMBERS_OF:\n+      return eval_members_of (loc, ctx, h, expr, call, non_constant_p,\n+\t\t\t      jump_target, fun);\n+    case METAFN_BASES_OF:\n+      return eval_bases_of (loc, ctx, h, expr, call, non_constant_p,\n+\t\t\t    jump_target, fun);\n+    case METAFN_STATIC_DATA_MEMBERS_OF:\n+      return eval_static_data_members_of (loc, ctx, h, expr, call,\n+\t\t\t\t\t  non_constant_p, jump_target,\n+\t\t\t\t\t  fun);\n+    case METAFN_NONSTATIC_DATA_MEMBERS_OF:\n+      return eval_nonstatic_data_members_of (loc, ctx, h, expr, call,\n+\t\t\t\t\t     non_constant_p, jump_target,\n+\t\t\t\t\t     fun);\n+    case METAFN_SUBOBJECTS_OF:\n+      return eval_subobjects_of (loc, ctx, h, expr, call, non_constant_p,\n+\t\t\t\t jump_target, fun);\n+    case METAFN_ENUMERATORS_OF:\n+      return eval_enumerators_of (loc, ctx, h, non_constant_p, jump_target,\n+\t\t\t\t  fun);\n+    case METAFN_OFFSET_OF:\n+      return eval_offset_of (loc, ctx, h, kind, TREE_TYPE (call),\n+\t\t\t     non_constant_p, jump_target, fun);\n+    case METAFN_SIZE_OF:\n+      return eval_size_of (loc, ctx, h, kind, TREE_TYPE (call), non_constant_p,\n+\t\t\t   jump_target, fun);\n+    case METAFN_ALIGNMENT_OF:\n+      return eval_alignment_of (loc, ctx, h, kind, TREE_TYPE (call),\n+\t\t\t\tnon_constant_p, jump_target, fun);\n+    case METAFN_BIT_SIZE_OF:\n+      return eval_bit_size_of (loc, ctx, h, kind, TREE_TYPE (call),\n+\t\t\t       non_constant_p, jump_target, fun);\n+    case METAFN_EXTRACT:\n+      {\n+\ttype = TREE_VEC_ELT (get_template_innermost_arguments (fun), 0);\n+\treturn eval_extract (loc, ctx, type, h, kind, non_constant_p,\n+\t\t\t     overflow_p, jump_target, fun);\n+      }\n+    case METAFN_CAN_SUBSTITUTE:\n+      return eval_can_substitute (loc, ctx, h, hvec, non_constant_p,\n+\t\t\t\t  jump_target, fun);\n+    case METAFN_SUBSTITUTE:\n+      return eval_substitute (loc, ctx, h, hvec, non_constant_p, jump_target,\n+\t\t\t      fun);\n+    case METAFN_REFLECT_CONSTANT:\n+      return eval_reflect_constant (loc, ctx, type, expr, non_constant_p,\n+\t\t\t\t    jump_target, fun);\n+    case METAFN_REFLECT_OBJECT:\n+      return eval_reflect_object (loc, ctx, type, expr, non_constant_p,\n+\t\t\t\t  jump_target, fun);\n+    case METAFN_REFLECT_FUNCTION:\n+      return eval_reflect_function (loc, ctx, type, expr, non_constant_p,\n+\t\t\t\t    jump_target, fun);\n+    case METAFN_REFLECT_CONSTANT_STRING:\n+      return eval_reflect_constant_string (loc, ctx, call, non_constant_p,\n+\t\t\t\t\t   overflow_p, jump_target, fun);\n+    case METAFN_REFLECT_CONSTANT_ARRAY:\n+      return eval_reflect_constant_array (loc, ctx, call, non_constant_p,\n+\t\t\t\t\t  overflow_p, jump_target, fun);\n+    case METAFN_DATA_MEMBER_SPEC:\n+      return eval_data_member_spec (loc, ctx, h, expr, non_constant_p,\n+\t\t\t\t    overflow_p, jump_target, fun);\n+    case METAFN_IS_DATA_MEMBER_SPEC:\n+      return eval_is_data_member_spec (h, kind);\n+    case METAFN_DEFINE_AGGREGATE:\n+      return eval_define_aggregate (loc, ctx, h, hvec, call, non_constant_p);\n+    case METAFN_IS_VOID_TYPE:\n+      return eval_is_void_type (h);\n+    case METAFN_IS_NULL_POINTER_TYPE:\n+      return eval_is_null_pointer_type (h);\n+    case METAFN_IS_INTEGRAL_TYPE:\n+      return eval_is_integral_type (h);\n+    case METAFN_IS_FLOATING_POINT_TYPE:\n+      return eval_is_floating_point_type (h);\n+    case METAFN_IS_ARRAY_TYPE:\n+      return eval_is_array_type (loc, h);\n+    case METAFN_IS_POINTER_TYPE:\n+      return eval_is_pointer_type (loc, h);\n+    case METAFN_IS_LVALUE_REFERENCE_TYPE:\n+      return eval_is_lvalue_reference_type (h);\n+    case METAFN_IS_RVALUE_REFERENCE_TYPE:\n+      return eval_is_rvalue_reference_type (h);\n+    case METAFN_IS_MEMBER_OBJECT_POINTER_TYPE:\n+      return eval_is_member_object_pointer_type (loc, h);\n+    case METAFN_IS_MEMBER_FUNCTION_POINTER_TYPE:\n+      return eval_is_member_function_pointer_type (loc, h);\n+    case METAFN_IS_ENUM_TYPE:\n+      return eval_is_enum_type (loc, h);\n+    case METAFN_IS_UNION_TYPE:\n+      return eval_is_union_type (loc, h);\n+    case METAFN_IS_CLASS_TYPE:\n+      return eval_is_class_type (loc, h);\n+    case METAFN_IS_FUNCTION_TYPE:\n+      return eval_is_function_type (h);\n+    case METAFN_IS_REFLECTION_TYPE:\n+      return eval_is_reflection_type (h);\n+    case METAFN_IS_REFERENCE_TYPE:\n+      return eval_is_reference_type (loc, h);\n+    case METAFN_IS_ARITHMETIC_TYPE:\n+      return eval_is_arithmetic_type (h);\n+    case METAFN_IS_FUNDAMENTAL_TYPE:\n+      return eval_is_fundamental_type (h);\n+    case METAFN_IS_OBJECT_TYPE:\n+      return eval_is_object_type (loc, h);\n+    case METAFN_IS_SCALAR_TYPE:\n+      return eval_is_scalar_type (h);\n+    case METAFN_IS_COMPOUND_TYPE:\n+      return eval_is_compound_type (h);\n+    case METAFN_IS_MEMBER_POINTER_TYPE:\n+      return eval_is_member_pointer_type (loc, h);\n+    case METAFN_IS_CONST_TYPE:\n+      return eval_is_const_type (h);\n+    case METAFN_IS_VOLATILE_TYPE:\n+      return eval_is_volatile_type (h);\n+    case METAFN_IS_TRIVIALLY_COPYABLE_TYPE:\n+      return eval_is_trivially_copyable_type (h);\n+    case METAFN_IS_STANDARD_LAYOUT_TYPE:\n+      return eval_is_standard_layout_type (h);\n+    case METAFN_IS_EMPTY_TYPE:\n+      return eval_is_empty_type (loc, h);\n+    case METAFN_IS_POLYMORPHIC_TYPE:\n+      return eval_is_polymorphic_type (loc, h);\n+    case METAFN_IS_ABSTRACT_TYPE:\n+      return eval_is_abstract_type (h);\n+    case METAFN_IS_FINAL_TYPE:\n+      return eval_is_final_type (loc, h);\n+    case METAFN_IS_AGGREGATE_TYPE:\n+      return eval_is_aggregate_type (h);\n+    case METAFN_IS_CONSTEVAL_ONLY_TYPE:\n+      return eval_is_consteval_only_type (h);\n+    case METAFN_IS_SIGNED_TYPE:\n+      return eval_is_signed_type (h);\n+    case METAFN_IS_UNSIGNED_TYPE:\n+      return eval_is_unsigned_type (h);\n+    case METAFN_IS_BOUNDED_ARRAY_TYPE:\n+      return eval_is_bounded_array_type (loc, h);\n+    case METAFN_IS_UNBOUNDED_ARRAY_TYPE:\n+      return eval_is_unbounded_array_type (h);\n+    case METAFN_IS_SCOPED_ENUM_TYPE:\n+      return eval_is_scoped_enum_type (h);\n+    case METAFN_IS_CONSTRUCTIBLE_TYPE:\n+      return eval_is_constructible_type (h, hvec);\n+    case METAFN_IS_DEFAULT_CONSTRUCTIBLE_TYPE:\n+      return eval_is_default_constructible_type (h);\n+    case METAFN_IS_COPY_CONSTRUCTIBLE_TYPE:\n+      return eval_is_copy_constructible_type (h);\n+    case METAFN_IS_MOVE_CONSTRUCTIBLE_TYPE:\n+      return eval_is_move_constructible_type (h);\n+    case METAFN_IS_ASSIGNABLE_TYPE:\n+      return eval_is_assignable_type (loc, h, h1);\n+    case METAFN_IS_COPY_ASSIGNABLE_TYPE:\n+      return eval_is_copy_assignable_type (h);\n+    case METAFN_IS_MOVE_ASSIGNABLE_TYPE:\n+      return eval_is_move_assignable_type (h);\n+    case METAFN_IS_SWAPPABLE_WITH_TYPE:\n+      return eval_is_swappable_with_type (loc, ctx, h, h1, call,\n+\t\t\t\t\t  non_constant_p, jump_target, fun,\n+\t\t\t\t\t  \"is_swappable_with\");\n+    case METAFN_IS_SWAPPABLE_TYPE:\n+      return eval_is_swappable_type (loc, ctx, h, call, non_constant_p,\n+\t\t\t\t     jump_target, fun, \"is_swappable\");\n+    case METAFN_IS_DESTRUCTIBLE_TYPE:\n+      return eval_is_destructible_type (loc, h);\n+    case METAFN_IS_TRIVIALLY_CONSTRUCTIBLE_TYPE:\n+      return eval_is_trivially_constructible_type (h, hvec);\n+    case METAFN_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_TYPE:\n+      return eval_is_trivially_default_constructible_type (h);\n+    case METAFN_IS_TRIVIALLY_COPY_CONSTRUCTIBLE_TYPE:\n+      return eval_is_trivially_copy_constructible_type (h);\n+    case METAFN_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE_TYPE:\n+      return eval_is_trivially_move_constructible_type (h);\n+    case METAFN_IS_TRIVIALLY_ASSIGNABLE_TYPE:\n+      return eval_is_trivially_assignable_type (loc, h, h1);\n+    case METAFN_IS_TRIVIALLY_COPY_ASSIGNABLE_TYPE:\n+      return eval_is_trivially_copy_assignable_type (h);\n+    case METAFN_IS_TRIVIALLY_MOVE_ASSIGNABLE_TYPE:\n+      return eval_is_trivially_move_assignable_type (h);\n+    case METAFN_IS_TRIVIALLY_DESTRUCTIBLE_TYPE:\n+      return eval_is_trivially_destructible_type (loc, h);\n+    case METAFN_IS_NOTHROW_CONSTRUCTIBLE_TYPE:\n+      return eval_is_nothrow_constructible_type (h, hvec);\n+    case METAFN_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE_TYPE:\n+      return eval_is_nothrow_default_constructible_type (h);\n+    case METAFN_IS_NOTHROW_COPY_CONSTRUCTIBLE_TYPE:\n+      return eval_is_nothrow_copy_constructible_type (h);\n+    case METAFN_IS_NOTHROW_MOVE_CONSTRUCTIBLE_TYPE:\n+      return eval_is_nothrow_move_constructible_type (h);\n+    case METAFN_IS_NOTHROW_ASSIGNABLE_TYPE:\n+      return eval_is_nothrow_assignable_type (loc, h, h1);\n+    case METAFN_IS_NOTHROW_COPY_ASSIGNABLE_TYPE:\n+      return eval_is_nothrow_copy_assignable_type (h);\n+    case METAFN_IS_NOTHROW_MOVE_ASSIGNABLE_TYPE:\n+      return eval_is_nothrow_move_assignable_type (h);\n+    case METAFN_IS_NOTHROW_SWAPPABLE_WITH_TYPE:\n+      return eval_is_swappable_with_type (loc, ctx, h, h1, call,\n+\t\t\t\t\t  non_constant_p, jump_target, fun,\n+\t\t\t\t\t  \"is_nothrow_swappable_with\");\n+    case METAFN_IS_NOTHROW_SWAPPABLE_TYPE:\n+      return eval_is_swappable_type (loc, ctx, h, call, non_constant_p,\n+\t\t\t\t     jump_target, fun, \"is_nothrow_swappable\");\n+    case METAFN_IS_NOTHROW_DESTRUCTIBLE_TYPE:\n+      return eval_is_nothrow_destructible_type (loc, h);\n+    case METAFN_IS_IMPLICIT_LIFETIME_TYPE:\n+      return eval_is_implicit_lifetime_type (h);\n+    case METAFN_HAS_VIRTUAL_DESTRUCTOR:\n+      return eval_has_virtual_destructor (h);\n+    case METAFN_HAS_UNIQUE_OBJECT_REPRESENTATIONS:\n+      return eval_has_unique_object_representations (h);\n+    case METAFN_REFERENCE_CONSTRUCTS_FROM_TEMPORARY:\n+      return eval_reference_constructs_from_temporary (loc, h, h1);\n+    case METAFN_REFERENCE_CONVERTS_FROM_TEMPORARY:\n+      return eval_reference_converts_from_temporary (loc, h, h1);\n+    case METAFN_RANK:\n+      return eval_rank (h);\n+    case METAFN_EXTENT:\n+      return eval_extent (loc, h, expr);\n+    case METAFN_IS_SAME_TYPE:\n+      return eval_is_same_type (loc, h, h1);\n+    case METAFN_IS_BASE_OF_TYPE:\n+      return eval_is_base_of_type (loc, h, h1);\n+    case METAFN_IS_VIRTUAL_BASE_OF_TYPE:\n+      return eval_is_virtual_base_of_type (loc, h, h1);\n+    case METAFN_IS_CONVERTIBLE_TYPE:\n+      return eval_is_convertible_type (loc, h, h1);\n+    case METAFN_IS_NOTHROW_CONVERTIBLE_TYPE:\n+      return eval_is_nothrow_convertible_type (loc, h, h1);\n+    case METAFN_IS_LAYOUT_COMPATIBLE_TYPE:\n+      return eval_is_layout_compatible_type (loc, h, h1);\n+    case METAFN_IS_POINTER_INTERCONVERTIBLE_BASE_OF_TYPE:\n+      return eval_is_pointer_interconvertible_base_of_type (loc, h, h1);\n+    case METAFN_IS_INVOCABLE_TYPE:\n+      return eval_is_invocable_type (loc, h, hvec);\n+    case METAFN_IS_INVOCABLE_R_TYPE:\n+      return eval_is_invocable_r_type (loc, ctx, h, h1, hvec, call,\n+\t\t\t\t       non_constant_p, jump_target, fun,\n+\t\t\t\t       \"is_invocable_r\");\n+    case METAFN_IS_NOTHROW_INVOCABLE_TYPE:\n+      return eval_is_nothrow_invocable_type (loc, h, hvec);\n+    case METAFN_IS_NOTHROW_INVOCABLE_R_TYPE:\n+      return eval_is_invocable_r_type (loc, ctx, h, h1, hvec, call,\n+\t\t\t\t       non_constant_p, jump_target, fun,\n+\t\t\t\t       \"is_nothrow_invocable_r\");\n+    case METAFN_REMOVE_CONST:\n+      return eval_remove_const (loc, h);\n+    case METAFN_REMOVE_VOLATILE:\n+      return eval_remove_volatile (loc, h);\n+    case METAFN_REMOVE_CV:\n+      return eval_remove_cv (loc, h);\n+    case METAFN_ADD_CONST:\n+      return eval_add_const (loc, h);\n+    case METAFN_ADD_VOLATILE:\n+      return eval_add_volatile (loc, h);\n+    case METAFN_ADD_CV:\n+      return eval_add_cv (loc, h);\n+    case METAFN_REMOVE_REFERENCE:\n+      return eval_remove_reference (loc, h);\n+    case METAFN_ADD_LVALUE_REFERENCE:\n+      return eval_add_lvalue_reference (loc, h);\n+    case METAFN_ADD_RVALUE_REFERENCE:\n+      return eval_add_rvalue_reference (loc, h);\n+    case METAFN_MAKE_SIGNED:\n+      return eval_make_signed (loc, ctx, h, false, non_constant_p, jump_target,\n+\t\t\t       fun);\n+    case METAFN_MAKE_UNSIGNED:\n+      return eval_make_signed (loc, ctx, h, true, non_constant_p, jump_target,\n+\t\t\t       fun);\n+    case METAFN_REMOVE_EXTENT:\n+      return eval_remove_extent (loc, h);\n+    case METAFN_REMOVE_ALL_EXTENTS:\n+      return eval_remove_all_extents (loc, h);\n+    case METAFN_REMOVE_POINTER:\n+      return eval_remove_pointer (loc, h);\n+    case METAFN_ADD_POINTER:\n+      return eval_add_pointer (loc, h);\n+    case METAFN_REMOVE_CVREF:\n+      return eval_remove_cvref (loc, h);\n+    case METAFN_DECAY:\n+      return eval_decay (loc, h);\n+    case METAFN_COMMON_TYPE:\n+      return eval_common_type (loc, ctx, hvec, call, non_constant_p,\n+\t\t\t       jump_target, fun, ident);\n+    case METAFN_COMMON_REFERENCE:\n+      return eval_common_type (loc, ctx, hvec, call, non_constant_p,\n+\t\t\t       jump_target, fun, ident);\n+    case METAFN_UNDERLYING_TYPE:\n+      return eval_underlying_type (loc, ctx, h, non_constant_p, jump_target,\n+\t\t\t\t   fun);\n+    case METAFN_INVOKE_RESULT:\n+      return eval_invoke_result (loc, ctx, h, hvec, call, non_constant_p,\n+\t\t\t\t jump_target, fun);\n+    case METAFN_UNWRAP_REFERENCE:\n+      return eval_unwrap_reference (loc, ctx, h, call, non_constant_p,\n+\t\t\t\t    jump_target, fun, ident);\n+    case METAFN_UNWRAP_REF_DECAY:\n+      return eval_unwrap_reference (loc, ctx, h, call, non_constant_p,\n+\t\t\t\t    jump_target, fun, ident);\n+    case METAFN_TUPLE_SIZE:\n+      return eval_tuple_size (loc, ctx, h, call, non_constant_p, jump_target,\n+\t\t\t      fun);\n+    case METAFN_TUPLE_ELEMENT:\n+      return eval_tuple_element (loc, ctx, expr, h1, call,\n+\t\t\t\t non_constant_p, jump_target, fun);\n+    case METAFN_VARIANT_SIZE:\n+      return eval_variant_size (loc, ctx, h, call, non_constant_p,\n+\t\t\t\tjump_target, fun);\n+    case METAFN_VARIANT_ALTERNATIVE:\n+      return eval_variant_alternative (loc, ctx, expr, h1, call,\n+\t\t\t\t       non_constant_p, jump_target, fun);\n+    case METAFN_TYPE_ORDER:\n+      return eval_type_order (h, h1);\n+    case METAFN_ANNOTATIONS_OF:\n+      return eval_annotations_of (loc, ctx, h, kind, NULL_TREE, non_constant_p,\n+\t\t\t\t  jump_target, fun);\n+    case METAFN_ANNOTATIONS_OF_WITH_TYPE:\n+      return eval_annotations_of (loc, ctx, h, kind, h1, non_constant_p,\n+\t\t\t\t  jump_target, fun);\n+    /* Special metafunctions.  */\n+    case METAFN_ACCESS_CONTEXT_CURRENT:\n+      if (DECL_CLASS_SCOPE_P (fun)\n+\t  && TYPE_NAME (DECL_CONTEXT (fun))\n+\t  && TREE_CODE (TYPE_NAME (DECL_CONTEXT (fun))) == TYPE_DECL\n+\t  && DECL_NAME (TYPE_NAME (DECL_CONTEXT (fun)))\n+\t  && id_equal (DECL_NAME (TYPE_NAME (DECL_CONTEXT (fun))),\n+\t\t       \"access_context\"))\n+\treturn eval_access_context_current (loc, ctx, call, non_constant_p);\n+      goto not_found;\n+    case METAFN_EXCEPTION__S_EXCEPTION_CVT_TO_UTF8:\n+    case METAFN_EXCEPTION__S_EXCEPTION_CVT_FROM_UTF8:\n+      if (DECL_CLASS_SCOPE_P (fun)\n+\t  && TYPE_NAME (DECL_CONTEXT (fun))\n+\t  && TREE_CODE (TYPE_NAME (DECL_CONTEXT (fun))) == TYPE_DECL\n+\t  && DECL_NAME (TYPE_NAME (DECL_CONTEXT (fun)))\n+\t  && id_equal (DECL_NAME (TYPE_NAME (DECL_CONTEXT (fun))),\n+\t\t       \"exception\"))\n+\t{\n+\t  if (minfo->code == METAFN_EXCEPTION__S_EXCEPTION_CVT_TO_UTF8)\n+\t    return eval_exception__S_exception_cvt_to_utf8 (loc, ctx, call,\n+\t\t\t\t\t\t\t    non_constant_p,\n+\t\t\t\t\t\t\t    overflow_p,\n+\t\t\t\t\t\t\t    jump_target, fun);\n+\t  else\n+\t    return eval_exception__S_exception_cvt_from_utf8 (loc, ctx, call,\n+\t\t\t\t\t\t\t      non_constant_p,\n+\t\t\t\t\t\t\t      overflow_p,\n+\t\t\t\t\t\t\t      jump_target,\n+\t\t\t\t\t\t\t      fun);\n+\t}\n+      goto not_found;\n+    }\n+  goto not_found;\n+}\n+\n+/* Splice reflection REFL; i.e., return its entity.  */\n+\n+tree\n+splice (tree refl)\n+{\n+  if (refl == error_mark_node)\n+    return error_mark_node;\n+\n+  /* Who in the world am I?  That's the great puzzle and we have to wait\n+     until instantiation to find out.  */\n+  if (instantiation_dependent_expression_p (refl))\n+    return build_nt (SPLICE_EXPR, refl);\n+\n+  /* [basic.splice] \"The constant-expression of a splice-specifier shall\n+     be a converted constant expression of type std::meta::info.\"  */\n+  refl = build_converted_constant_expr (meta_info_type_node, refl,\n+\t\t\t\t\ttf_warning_or_error);\n+\n+  if (processing_template_decl)\n+    refl = fold_non_dependent_expr (refl, tf_warning_or_error, true);\n+  else\n+    refl = cxx_constant_value (refl);\n+  if (!REFLECT_EXPR_P (refl))\n+    /* I don't wanna do your dirty work no more.  */\n+    return error_mark_node;\n+\n+  /* We are bringing some entity from the unevaluated expressions world\n+     to possibly outside of that, mark it used.  */\n+  if (!mark_used (REFLECT_EXPR_HANDLE (refl)))\n+    return error_mark_node;\n+\n+  refl = REFLECT_EXPR_HANDLE (refl);\n+  /* Function templates are wrapped in OVERLOAD from name lookup\n+     and a lot of places assume that.  Furthermore, if reflection comes\n+     from ^^fntmpl, it is wrapped with OVERLOAD already, only when\n+     it comes from e.g. members_of it is not.  */\n+  if (DECL_FUNCTION_TEMPLATE_P (refl))\n+    refl = ovl_make (refl, NULL_TREE);\n+\n+  return refl;\n+}\n+\n+/* A walker for consteval_only_p.  It cannot be a lambda, because we\n+   have to call this recursively, sigh.  */\n+\n+static tree\n+consteval_only_type_r (tree *tp, int *walk_subtrees, void *data)\n+{\n+  tree t = *tp;\n+  /* Types can contain themselves recursively, hence this.  */\n+  auto visited = static_cast<hash_set<tree> *>(data);\n+\n+  if (!TYPE_P (t))\n+    return NULL_TREE;\n+\n+  if (REFLECTION_TYPE_P (t))\n+    return t;\n+\n+  if (typedef_variant_p (t))\n+    {\n+      *walk_subtrees = 0;\n+      if (tree r = cp_walk_tree (&TYPE_MAIN_VARIANT (t), consteval_only_type_r,\n+\t\t\t\t visited, visited))\n+\treturn r;\n+      return NULL_TREE;\n+    }\n+\n+  if (RECORD_OR_UNION_TYPE_P (t))\n+    {\n+      /* Don't walk template arguments; A<info>::type isn't a consteval-only\n+\t type.  */\n+      *walk_subtrees = 0;\n+      /* So we have to walk the fields manually.  */\n+      for (tree member = TYPE_FIELDS (t);\n+\t   member; member = DECL_CHAIN (member))\n+\tif (TREE_CODE (member) == FIELD_DECL)\n+\t  if (tree r = cp_walk_tree (&TREE_TYPE (member),\n+\t\t\t\t     consteval_only_type_r, visited, visited))\n+\t    return r;\n+    }\n+\n+  return NULL_TREE;\n+}\n+\n+/* True if T is a consteval-only type as per [basic.types.general]:\n+   \"A type is consteval-only if it is either std::meta::info or a type\n+   compounded from a consteval-only type\", or something that has\n+   a consteval-only type.  */\n+\n+// <https://cplusplus.github.io/CWG/issues/3101.html> changes the def\n+// <https://cplusplus.github.io/LWG/lwg-active.html#4422>\n+// meta::access_context should be a consteval-only type\n+\n+bool\n+consteval_only_p (tree t)\n+{\n+  if (!flag_reflection)\n+    return false;\n+\n+  /* cp_walk_tree walks template arguments, but\n+     std::initializer_list<std::meta::info>::size_type should be fine,\n+     or a nullptr constant, and similar.  */\n+  if (TREE_CODE (t) == INTEGER_CST)\n+    return false;\n+\n+  if (!TYPE_P (t))\n+    t = TREE_TYPE (t);\n+\n+  if (!t)\n+    return false;\n+\n+  /* We need the complete type otherwise we'd have no fields for class\n+     templates and thus come up with zilch for things like\n+       template<typename T>\n+       struct X : T { };\n+     which could be consteval-only, depending on T.  */\n+  t = complete_type (t);\n+\n+  /* Classes with std::meta::info members are also consteval-only.  */\n+  hash_set<tree> visited;\n+  return !!cp_walk_tree (&t, consteval_only_type_r, &visited, &visited);\n+}\n+\n+/* Detect if a consteval-only expression EXPR or a consteval-only\n+   variable EXPR not declared constexpr/constinit is used outside\n+   a manifestly constant-evaluated context.  E.g.:\n+\n+     void f() {\n+       constexpr auto r = ^^int;  // OK\n+       [: r :] i = 42;  // still OK\n+       auto z = r;  // bad\n+     }\n+\n+   But\n+\n+     consteval void g() {\n+       constexpr auto r = ^^int;\n+       auto z = r;\n+     }\n+\n+   is OK.  If COMPLAIN, emit an error; otherwise we're in the search-only\n+   mode.  Return true if we found a problematic expression.  */\n+\n+bool\n+check_out_of_consteval_use (tree expr, bool complain/*=true*/)\n+{\n+  if (!flag_reflection || in_immediate_context ())\n+    return false;\n+\n+  /* Don't complain if we're generating the body for a synthesized method.  */\n+  if (current_function_decl)\n+    {\n+      if (DECL_CONSTRUCTOR_P (current_function_decl)\n+\t  && DECL_ARTIFICIAL (current_function_decl))\n+\treturn false;\n+      if (decl_in_std_meta_p (current_function_decl))\n+\treturn false;\n+    }\n+\n+  auto walker = [](tree *tp, int *walk_subtrees, void *) -> tree\n+    {\n+      tree t = *tp;\n+\n+      /* No need to look into types or unevaluated operands.  */\n+      if (TYPE_P (t)\n+\t  || unevaluated_p (TREE_CODE (t))\n+\t  /* Don't walk INIT_EXPRs, because we'd emit bogus errors about\n+\t     member initializers.  */\n+\t  || TREE_CODE (t) == INIT_EXPR\n+\t  || TREE_CODE (t) == BIND_EXPR\n+\t  || TREE_CODE (t) == DECL_EXPR)\n+\t{\n+\t  *walk_subtrees = false;\n+\t  return NULL_TREE;\n+\t}\n+\n+      /* A subexpression of a manifestly constant-evaluated expression is\n+\t an immediate function context.  For example,\n+\n+\t   consteval void foo (std::meta::info) { }\n+\t   void g() { foo (^^void); }\n+\n+\t is all good.  */\n+      if (tree decl = cp_get_callee_fndecl_nofold (t))\n+\tif (immediate_invocation_p (decl))\n+\t  {\n+\t    *walk_subtrees = false;\n+\t    return NULL_TREE;\n+\t  }\n+\n+      if (VAR_P (t)\n+\t  && (DECL_DECLARED_CONSTEXPR_P (t) || DECL_DECLARED_CONSTINIT_P (t)))\n+\t/* This is fine, don't bother checking the type.  */\n+\treturn NULL_TREE;\n+\n+      /* Now check the type to see if we are dealing with a consteval-only\n+\t expression.  */\n+      if (!consteval_only_p (t))\n+\treturn NULL_TREE;\n+\n+      if (current_function_decl\n+\t  /* Already escalated.  */\n+\t  && (DECL_IMMEDIATE_FUNCTION_P (current_function_decl)\n+\t      /* These functions are magic.  */\n+\t      || is_std_allocator_allocate (current_function_decl)))\n+\t{\n+\t  *walk_subtrees = false;\n+\t  return NULL_TREE;\n+\t}\n+\n+      /* We might have to escalate if we are in an immediate-escalating\n+\t function.  */\n+      if (immediate_escalating_function_p (current_function_decl))\n+\t{\n+\t  promote_function_to_consteval (current_function_decl);\n+\t  *walk_subtrees = false;\n+\t  return NULL_TREE;\n+\t}\n+\n+      *walk_subtrees = false;\n+      return t;\n+    };\n+\n+  if (tree t = cp_walk_tree_without_duplicates (&expr, walker, nullptr))\n+    {\n+      if (complain)\n+\t{\n+\t  if (VAR_P (t))\n+\t    {\n+\t      auto_diagnostic_group d;\n+\t      error_at (cp_expr_loc_or_input_loc (t),\n+\t\t\t\"consteval-only variable %qD not declared %<constexpr%> \"\n+\t\t\t\"used outside a constant-evaluated context\", t);\n+\t      if (TREE_STATIC (t) || CP_DECL_THREAD_LOCAL_P (t))\n+\t\tinform (DECL_SOURCE_LOCATION (t), \"add %<constexpr%> or \"\n+\t\t\t\"%<constinit%>\");\n+\t      else\n+\t\tinform (DECL_SOURCE_LOCATION (t), \"add %<constexpr%>\");\n+\t    }\n+\t  else\n+\t    error_at (cp_expr_loc_or_input_loc (t),\n+\t\t      \"consteval-only expressions are only allowed in \"\n+\t\t      \"a constant-evaluated context\");\n+\t}\n+      return true;\n+    }\n+\n+  return false;\n+}\n+\n+/* Return true if the reflections LHS and RHS are equal.  */\n+\n+bool\n+compare_reflections (tree lhs, tree rhs)\n+{\n+  reflect_kind kind;\n+  do\n+    {\n+      if (REFLECT_EXPR_KIND (lhs) != REFLECT_EXPR_KIND (rhs))\n+\treturn false;\n+      kind = REFLECT_EXPR_KIND (lhs);\n+      lhs = REFLECT_EXPR_HANDLE (lhs);\n+      rhs = REFLECT_EXPR_HANDLE (rhs);\n+    }\n+  while (REFLECT_EXPR_P (lhs) && REFLECT_EXPR_P (rhs));\n+\n+  lhs = resolve_nondeduced_context (lhs, tf_warning_or_error);\n+  rhs = resolve_nondeduced_context (rhs, tf_warning_or_error);\n+\n+  /* TEMPLATE_DECLs are wrapped in an OVERLOAD.  When we have\n+\n+       template_of (^^fun_tmpl<int>) == ^^fun_tmpl\n+\n+     the RHS will be OVERLOAD<TEMPLATE_DECL> but the LHS will\n+     only be TEMPLATE_DECL.  They should compare equal, though.  */\n+  // ??? Can we do something better?\n+  lhs = maybe_get_reflection_fndecl (lhs);\n+  rhs = maybe_get_reflection_fndecl (rhs);\n+  if (kind == REFLECT_PARM)\n+    {\n+      lhs = maybe_update_function_parm (lhs);\n+      rhs = maybe_update_function_parm (rhs);\n+    }\n+  else if (kind == REFLECT_DATA_MEMBER_SPEC)\n+    return (TREE_VEC_ELT (lhs, 0) == TREE_VEC_ELT (rhs, 0)\n+\t    && TREE_VEC_ELT (lhs, 1) == TREE_VEC_ELT (rhs, 1)\n+\t    && tree_int_cst_equal (TREE_VEC_ELT (lhs, 2),\n+\t\t\t\t   TREE_VEC_ELT (rhs, 2))\n+\t    && tree_int_cst_equal (TREE_VEC_ELT (lhs, 3),\n+\t\t\t\t   TREE_VEC_ELT (rhs, 3))\n+\t    && TREE_VEC_ELT (lhs, 4) == TREE_VEC_ELT (rhs, 4));\n+\n+  if (lhs == rhs)\n+    return true;\n+\n+  /* Some trees are not shared.  */\n+  if (TREE_CODE (lhs) == TREE_CODE (rhs))\n+    switch (TREE_CODE (lhs))\n+      {\n+      case ARRAY_REF:\n+      case COMPONENT_REF:\n+\treturn (TREE_TYPE (lhs) == TREE_TYPE (rhs)\n+\t\t&& TREE_OPERAND (lhs, 0) == TREE_OPERAND (rhs, 0)\n+\t\t&& TREE_OPERAND (lhs, 1) == TREE_OPERAND (rhs, 1)\n+\t\t&& TREE_OPERAND (lhs, 2) == TREE_OPERAND (rhs, 2));\n+      case REAL_CST:\n+\treturn cp_tree_equal (lhs, rhs);\n+      default:\n+\tbreak;\n+      }\n+\n+  if (TYPE_P (lhs) && TYPE_P (rhs))\n+    if (!typedef_variant_p (lhs) && !typedef_variant_p (rhs))\n+      return same_type_p (lhs, rhs);\n+\n+  return false;\n+}\n+\n+/* Return true if T is a valid splice-type-specifier.\n+   [dcl.type.splice]: For a splice-type-specifier of the form\n+   \"typename[opt] splice-specifier\", the splice-specifier shall designate\n+   a type, a class template, or an alias template.\n+   For a splice-type-specifier of the form\n+   \"typename[opt] splice-specialization-specifier\", the splice-specifier\n+   of the splice-specialization-specifier shall designate a template T\n+   that is either a class template or an alias template.  */\n+\n+bool\n+valid_splice_type_p (const_tree t)\n+{\n+  return TYPE_P (t);\n+}\n+\n+/* Return true if T is a valid splice-scope-specifier.\n+   [basic.lookup.qual.general]: If a splice-scope-specifier is followed\n+   by a ::, it shall either be a dependent splice-scope-specifier or it\n+   shall designate a namespace, class, enumeration, or dependent type.  */\n+\n+bool\n+valid_splice_scope_p (const_tree t)\n+{\n+  return (CLASS_TYPE_P (t)\n+\t  || TREE_CODE (t) == ENUMERAL_TYPE\n+\t  || TREE_CODE (t) == NAMESPACE_DECL);\n+}\n+\n+/* Check a function DECL for CWG 3115: Every function of consteval-only\n+   type shall be an immediate function.  */\n+\n+void\n+check_consteval_only_fn (tree decl)\n+{\n+  if (!DECL_IMMEDIATE_FUNCTION_P (decl)\n+      && consteval_only_p (decl)\n+      /* But if the function can be escalated, merrily we roll along.  */\n+      && !immediate_escalating_function_p (decl)\n+      && !is_std_allocator_allocate (decl))\n+    error_at (DECL_SOURCE_LOCATION (decl),\n+\t      \"function of consteval-only type must be declared %qs\",\n+\t      \"consteval\");\n+}\n+\n+/* Check if T is a valid result of splice-expression.  ADDRESS_P is true if\n+   we are taking the address of the splice.  MEMBER_ACCESS_P is true if this\n+   splice is used in foo.[: bar :] or foo->[: bar :] context.  COMPLAIN_P is\n+   true if any errors should be emitted.  Returns true is no problems are\n+   found, false otherwise.  */\n+\n+bool\n+check_splice_expr (location_t loc, location_t start_loc, tree t,\n+\t\t   bool address_p, bool member_access_p, bool complain_p)\n+{\n+  /* We may not have gotten an expression.  */\n+  if (TREE_CODE (t) == TYPE_DECL\n+      || TREE_CODE (t) == NAMESPACE_DECL\n+      || TYPE_P (t))\n+    {\n+      if (complain_p)\n+\t{\n+\t  if (TYPE_P (t))\n+\t    {\n+\t      auto_diagnostic_group d;\n+\t      error_at (loc, \"expected a reflection of an expression instead \"\n+\t\t\t\"of type %qT\", t);\n+\t      if (start_loc != UNKNOWN_LOCATION)\n+\t\t{\n+\t\t  rich_location richloc (line_table, start_loc);\n+\t\t  richloc.add_fixit_insert_before (start_loc, \"typename\");\n+\t\t  inform (&richloc, \"add %<typename%> to denote a type \"\n+\t\t\t  \"outside a type-only context\");\n+\t\t}\n+\t      else\n+\t\tinform (loc, \"add %<typename%> to denote a type outside \"\n+\t\t\t\"a type-only context\");\n+\t    }\n+\t  else\n+\t    error_at (loc, \"expected a reflection of an expression instead \"\n+\t\t      \"of %qD\", t);\n+\t}\n+      return false;\n+    }\n+  /* [expr.prim.splice]/2 For a splice-expression of the form\n+     splice-specifier, the expression is ill-formed if it is:  */\n+  /* -- a constructor or a destructor  */\n+  if (TREE_CODE (t) == FUNCTION_DECL\n+      && (DECL_CONSTRUCTOR_P (t) || DECL_DESTRUCTOR_P (t)))\n+    {\n+      if (complain_p)\n+\terror_at (loc, \"cannot use constructor or destructor in a splice \"\n+\t\t  \"expression\");\n+      return false;\n+    }\n+  /* -- an unnamed bit-field  */\n+  if (TREE_CODE (t) == FIELD_DECL && DECL_UNNAMED_BIT_FIELD (t))\n+    {\n+      if (complain_p)\n+\terror_at (loc, \"cannot use an unnamed bit-field in a splice \"\n+\t\t  \"expression\");\n+      return false;\n+    }\n+  /* Class members may not be implicitly referenced through a splice.\n+     But taking the address is fine, and so is class member access a la\n+     foo.[: ^^S::bar :].  */\n+  if (!address_p\n+      && !member_access_p\n+      && ((DECL_P (t) && DECL_NONSTATIC_MEMBER_P (t))\n+\t  || (VAR_P (t) && DECL_ANON_UNION_VAR_P (t))))\n+    {\n+      if (complain_p)\n+\terror_at (loc, \"cannot implicitly reference a class member through \"\n+\t\t  \"a splice\");\n+      return false;\n+    }\n+  /* [expr.unary.op]/3.1 \"If the operand [of unary &] is a qualified-id or\n+     splice-expression designating a non-static member m, other than an\n+     explicit object member function, m shall be a direct member of some\n+     class C that is not an anonymous union.\"  */\n+  if (address_p && VAR_P (t) && DECL_ANON_UNION_VAR_P (t))\n+    {\n+      if (complain_p)\n+\terror_at (loc, \"unary %<&%> applied to an anonymous union member %qD \"\n+\t\t  \"that is not a direct member of a named class\", t);\n+      return false;\n+    }\n+\n+  /* [expr.prim.splice]/2: \"The expression is ill-formed if S [the construct\n+     designated by splice-specifier] is\n+     -- a local entity such that there is a lambda scope that intervenes\n+     between the expression and the point at which S was introduced\"\n+     This also checks ODR violations (reflect/odr1.C).  */\n+  if (outer_automatic_var_p (t)\n+      && process_outer_var_ref (t, tf_none) == error_mark_node)\n+    {\n+      /* Not letting process_outer_var_ref emit the error so that we can\n+\t say \"in a splice expression\".  */\n+      if (complain_p)\n+\t{\n+\t  auto_diagnostic_group d;\n+\t  error_at (loc, \"use of local variable with automatic storage from \"\n+\t\t    \"containing function in a splice expression\");\n+\t  inform (DECL_SOURCE_LOCATION (t), \"%q#D declared here\", t);\n+\t}\n+      return false;\n+    }\n+\n+  /* If we had a reflect_kind here, we could just check for\n+     REFLECT_ANNOTATION and be done with it.  But we don't have it yet (TODO),\n+     so do it the suboptimal way.  */\n+  if (TREE_CODE (t) == TREE_LIST\n+      && TREE_PURPOSE (t)\n+      && get_attribute_namespace (t) == internal_identifier\n+      && get_attribute_name (t) == annotation_identifier)\n+    {\n+      if (complain_p)\n+\terror_at (loc, \"cannot use an annotation in a splice expression\");\n+      return false;\n+    }\n+\n+  /* Same, but with REFLECT_DATA_MEMBER_SPEC.  */\n+  if (TREE_CODE (t) == TREE_VEC)\n+    {\n+      if (complain_p)\n+\terror_at (loc, \"cannot use a data member specification in a \"\n+\t\t  \"splice expression\");\n+      return false;\n+    }\n+\n+  return true;\n+}\n+\n+/* Create a new SPLICE_SCOPE tree.  EXPR is its SPLICE_SCOPE_EXPR, and\n+   TYPE_P says if it should have SPLICE_SCOPE_TYPE_P set.  */\n+\n+tree\n+make_splice_scope (tree expr, bool type_p)\n+{\n+  tree t = cxx_make_type (SPLICE_SCOPE);\n+  SPLICE_SCOPE_EXPR (t) = expr;\n+  SPLICE_SCOPE_TYPE_P (t) = type_p;\n+  return t;\n+}\n+\n+/* Return true if T is a splice expression; that is, it is either [:T:] or\n+   [:T:]<arg>.  */\n+\n+bool\n+dependent_splice_p (const_tree t)\n+{\n+  return (TREE_CODE (t) == SPLICE_EXPR\n+\t  || (TREE_CODE (t) == TEMPLATE_ID_EXPR\n+\t      && TREE_CODE (TREE_OPERAND (t, 0)) == SPLICE_EXPR));\n+}\n+\n+/* Annotation index for mangling.  */\n+\n+static GTY(()) int annotation_idx;\n+\n+/* Helper function for mangle.cc (write_reflection).\n+   Determine 2 letter manling prefix and store it into prefix.\n+   Additionally return the reflection handle possibly adjusted so that\n+   write_reflection can mangle the operands of it if any are needed.  */\n+\n+tree\n+reflection_mangle_prefix (tree refl, char prefix[3])\n+{\n+  tree h = REFLECT_EXPR_HANDLE (refl);\n+  reflect_kind kind = REFLECT_EXPR_KIND (refl);\n+  if (h == unknown_type_node)\n+    {\n+      strcpy (prefix, \"nu\");\n+      return NULL_TREE;\n+    }\n+  if (eval_is_value (kind) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"vl\");\n+      if (VAR_P (h) && DECL_NTTP_OBJECT_P (h))\n+\th = tparm_object_argument (h);\n+      return h;\n+    }\n+  if (eval_is_object (kind) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"ob\");\n+      return h;\n+    }\n+  if (eval_is_variable (h, kind) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"vr\");\n+      return h;\n+    }\n+  if (eval_is_structured_binding (h, kind) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"sb\");\n+      return h;\n+    }\n+  if (eval_is_function (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"fn\");\n+      return maybe_get_reflection_fndecl (h);\n+    }\n+  if (eval_is_function_parameter (h, kind) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"pa\");\n+      return maybe_update_function_parm (h);\n+    }\n+  if (eval_is_enumerator (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"en\");\n+      return h;\n+    }\n+  if (eval_is_annotation (h, kind) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"an\");\n+      if (TREE_PURPOSE (TREE_VALUE (h)) == NULL_TREE)\n+\tTREE_PURPOSE (TREE_VALUE (h))\n+\t  = build_int_cst (integer_type_node, annotation_idx++);\n+      return TREE_PURPOSE (TREE_VALUE (h));\n+    }\n+  if (eval_is_type_alias (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"ta\");\n+      return h;\n+    }\n+  if (eval_is_type (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"ty\");\n+      return h;\n+    }\n+  if (eval_is_nonstatic_data_member (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"dm\");\n+      return h;\n+    }\n+  if (TREE_CODE (h) == FIELD_DECL && DECL_UNNAMED_BIT_FIELD (h))\n+    {\n+      strcpy (prefix, \"un\");\n+      return h;\n+    }\n+  if (eval_is_class_template (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"ct\");\n+      return h;\n+    }\n+  if (eval_is_function_template (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"ft\");\n+      h = maybe_get_reflection_fndecl (h);\n+      return h;\n+    }\n+  if (eval_is_variable_template (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"vt\");\n+      return h;\n+    }\n+  if (eval_is_alias_template (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"at\");\n+      return h;\n+    }\n+  if (eval_is_concept (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"co\");\n+      return h;\n+    }\n+  if (eval_is_namespace_alias (h) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"na\");\n+      return h;\n+    }\n+  if (eval_is_namespace (h) == boolean_true_node)\n+    {\n+      if (h == global_namespace)\n+\t{\n+\t  strcpy (prefix, \"ng\");\n+\t  return NULL_TREE;\n+\t}\n+      strcpy (prefix, \"ns\");\n+      return h;\n+    }\n+  if (eval_is_base (h, kind) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"ba\");\n+      return h;\n+    }\n+  if (eval_is_data_member_spec (h, kind) == boolean_true_node)\n+    {\n+      strcpy (prefix, \"ds\");\n+      return h;\n+    }\n+  // TODO: nothing should make it through here, but unfortunately\n+  // reflections of function template specializations aren't\n+  // is_function right now.\n+  // gcc_unreachable ();\n+  strcpy (prefix, \"ER\");\n+  return NULL_TREE;\n+}\n+\n+#include \"gt-cp-reflect.h\"\n",
    "prefixes": [
        "3/9",
        "v2"
    ]
}