Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.0/patches/2175266/?format=api
{ "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" ] }