{"id":2175267,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2175267/?format=json","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/1.0/projects/17/?format=json","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":"<aULeH32QBOdlw0Zf@redhat.com>","date":"2025-12-17T16:45:19","name":"[1/9,v2] c++: C++26 Reflection [PR120775]","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"18f2ebcdaa854d751d89df2a47ac6b4ad19d1543","submitter":{"id":14370,"url":"http://patchwork.ozlabs.org/api/1.0/people/14370/?format=json","name":"Marek Polacek","email":"polacek@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/aULeH32QBOdlw0Zf@redhat.com/mbox/","series":[{"id":485726,"url":"http://patchwork.ozlabs.org/api/1.0/series/485726/?format=json","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/2175267/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=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=FNmFk7qW;\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=fail reason=\"signature verification failed\" (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=FNmFk7qW","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 4dWfrD0R2fz1xty\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 18 Dec 2025 03:48:28 +1100 (AEDT)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id E5EA14BA2E2F\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 17 Dec 2025 16:48:25 +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 AA60E4BA2E22\n for <gcc-patches@gcc.gnu.org>; Wed, 17 Dec 2025 16:45:31 +0000 (GMT)","from mail-qt1-f197.google.com (mail-qt1-f197.google.com\n [209.85.160.197]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-2-K8_lipbIP3OMSbj4r273yQ-1; Wed, 17 Dec 2025 11:45:29 -0500","by mail-qt1-f197.google.com with SMTP id\n d75a77b69052e-4edad69b4e8so17507581cf.1\n for <gcc-patches@gcc.gnu.org>; Wed, 17 Dec 2025 08:45:29 -0800 (PST)","from redhat.com ([2603:7000:9500:10::1db4])\n by smtp.gmail.com with ESMTPSA id\n d75a77b69052e-4f345b16f72sm38829881cf.3.2025.12.17.08.45.21\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 17 Dec 2025 08:45:21 -0800 (PST)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org E5EA14BA2E2F","OpenDKIM Filter v2.11.0 sourceware.org AA60E4BA2E22"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org AA60E4BA2E22","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org AA60E4BA2E22","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1765989931; cv=none;\n b=jszI45JAvN68CoupU4r808lmVdMqSuiafc4AtYVJbM0Q07MnTvU9/vZiptixT5WbPjm7B9kw9dw1GzoaiL5/+LnGG0QWXKzm5J4yujeLP2QBFJbvHw5K4yR+8pR4RBmJragG/YRqgIszWOIGbBRuIPEOFQicK1BnK3cg2X4B7j0=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1765989931; c=relaxed/simple;\n bh=k5MXpBYD6ZTPAOXFNQnicop16TEbGb/nTwThYC7kL3I=;\n h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version;\n b=NbXr7CYmKdt5NjninJG1vEn8srS2ixteHWv+qPc0xX02SqTswn3cmV6ExGokRWFU5uzDAHNDpOfCO6nbdl6sjfqjKCuP24zmwbq04rMqYv0rULdVkjNmMFj79HnWibzob6O2yz1xsE4AfY3LFa1GvPQyAlItvxtDH2WCM1VpwqQ=","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=1765989931;\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=W89J2Kzej5NU16CW9lXlQVhRodbVKNQrTBfAkT4q9rE=;\n b=FNmFk7qWii2MIIkXoHpTFw+qRYJYZzNDAmciMtpWe1nCrIepgHZw/4Va3Nmqc94sZ5skOa\n TEj8wQgEmiuJUgU1cgttt3M0u6rNbhZ2cV5NaEgDdp1feB6xZjyphIGjoDoCLdcyTf+iid\n pzCPeMrnRByBJISZa4G+KkprkFfbKWs=","X-MC-Unique":"K8_lipbIP3OMSbj4r273yQ-1","X-Mimecast-MFC-AGG-ID":"K8_lipbIP3OMSbj4r273yQ_1765989929","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1765989928; x=1766594728;\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=0pcrsSkJY2YHDQKAILRN8iAzbkec8QIl9p7Qf3N6jDk=;\n b=vblDZZuJ6BAeatEFM19lhHrLwiaO6N+c7wdJl/l+uDWU+FQ/0/pc68wKpKJgukeJ+z\n UxhuqqUqEVvmYifK7x+EPIePQacx8luw966zkJ90gyI1XzzNw6LVzTWYtPh6OLJPYQ17\n FIfhpomi4qQtmxX/mP+RmG58KH5I7xT59hpfGsvQkp0mLBqiLZVoPQGWQOTpr47YiCao\n jA1+LRedKr4q7tPgzZzttYIRxbSDXq1A9Ns3JBfhbtaHFQc8w5decnSsNhvMuP94U7Qy\n dpoK3OPoUjV2NYvoEcCPW1odxJCRHwpnIZdQ9lI/NbUKR4CigQSGlu+iPKLHaDIyEmsW\n IFBw==","X-Gm-Message-State":"AOJu0YynnTFG8vttWWZYlxOGs077+VyKWyy3WwCIcpuJJhFQEOqqACvD\n WknF/BqmPAD1NueZZejCMfYPYB97oAadND84i4fcKZlyGq+jA6OisMkZgC7QxqSbXj8z38+nJIV\n VregKy+bZvGPlyYd79jvUrgbLrCvvC4Goy4JM+8JDV7Eeub/XoVraY+Y7hWkUYlDK46I7qq6QF4\n HYN7RnuBOzphiaBngyYWS5piyT03qQqYFb86vRIlhTYA==","X-Gm-Gg":"AY/fxX4D2191+cUSl0hVgfrL8s37XmiCiuBPo/3xiI4M+yJzAG/ApMKsRA0WzDiMcV3\n klVNJJt44tJVaeTweqY+gRCQQt1XB04AwuvPTs/XrPP0yzUEHpKNNThnyBa5XLNTp/ln8UuZOuG\n e0+v45UWEl/R/ki+H2LbthHm+WO4o42GFRF70h7QhtGHZF+LlUGcF259VUOUY6WxFUzAozJ9OFl\n CFBg/r9hAf4vSseUvd5Xax1LVkeG1k75OuIvSt8mmTKsUKu3RjL7l53ZKal2LfLwwy8OVkVqQPC\n X7PKbbgUZmfFMHnBOlq6LCS/fPCVKuxijDg9Z1eIjtb+QvovZvq6iCwWLbD2SHX9Rw==","X-Received":["by 2002:a05:622a:491:b0:4f0:2211:d08b with SMTP id\n d75a77b69052e-4f35f46abbamr507421cf.33.1765989925254;\n Wed, 17 Dec 2025 08:45:25 -0800 (PST)","by 2002:a05:622a:491:b0:4f0:2211:d08b with SMTP id\n d75a77b69052e-4f35f46abbamr504461cf.33.1765989922721;\n Wed, 17 Dec 2025 08:45:22 -0800 (PST)"],"X-Google-Smtp-Source":"\n AGHT+IHCFz27Rx19Cfen+UoRz0PUIHtXg/lXBkPT2QCIHIueLbdT7QnIqOihFg5xShCNWoJdq14jgg==","Date":"Wed, 17 Dec 2025 11:45:19 -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 1/9 v2] c++: C++26 Reflection [PR120775]","Message-ID":"<aULeH32QBOdlw0Zf@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":"Qstd5czxjM7PChGF84pLiAucyOxE1B7U9L_Khn6pG1s_1765989929","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 patch contains the middle-end, libcpp/, c-family/, and cp/ bits\n(besides reflect.cc and the gperf bits).\n\n-- >8 --","diff":"diff --git a/gcc/attribs.cc b/gcc/attribs.cc\nindex 51c7f46a00f..073fdde045b 100644\n--- a/gcc/attribs.cc\n+++ b/gcc/attribs.cc\n@@ -1458,6 +1458,10 @@ attribute_value_equal (const_tree attr1, const_tree attr2)\n       && TREE_VALUE (attr2) != NULL_TREE\n       && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)\n     {\n+      if (ATTR_UNIQUE_VALUE_P (TREE_VALUE (attr1))\n+\t  || ATTR_UNIQUE_VALUE_P (TREE_VALUE (attr2)))\n+\treturn false;\n+\n       /* Handle attribute format.  */\n       if (is_attribute_p (\"format\", get_attribute_name (attr1)))\n \t{\n@@ -1739,11 +1743,34 @@ merge_attributes (tree a1, tree a2)\n \tattributes = a2;\n       else\n \t{\n-\t  /* Pick the longest list, and hang on the other list.  */\n+\t  /* Pick the longest list, and hang on the other list,\n+\t     unless both lists contain ATTR_UNIQUE_VALUE_P values.\n+\t     In that case a1 list needs to go after the a2 list\n+\t     because attributes from a single declaration are stored\n+\t     in reverse order of their declarations.  */\n+\t  bool a1_unique_value_p = false, a2_unique_value_p = false;\n+\t  tree aa1 = a1, aa2 = a2;\n+\t  for (; aa1 && aa2; aa1 = TREE_CHAIN (aa1), aa2 = TREE_CHAIN (aa2))\n+\t    {\n+\t      if (!a1_unique_value_p\n+\t\t  && TREE_VALUE (aa1)\n+\t\t  && TREE_CODE (TREE_VALUE (aa1)) == TREE_LIST\n+\t\t  && ATTR_UNIQUE_VALUE_P (TREE_VALUE (aa1)))\n+\t\ta1_unique_value_p = true;\n+\t      if (!a2_unique_value_p\n+\t\t  && TREE_VALUE (aa2)\n+\t\t  && TREE_CODE (TREE_VALUE (aa2)) == TREE_LIST\n+\t\t  && ATTR_UNIQUE_VALUE_P (TREE_VALUE (aa2)))\n+\t\ta2_unique_value_p = true;\n+\t    }\n \n-\t  if (list_length (a1) < list_length (a2))\n-\t    attributes = a2, a2 = a1;\n+\t  if (aa2 && (!a1_unique_value_p || !a2_unique_value_p))\n+\t    {\n+\t      attributes = a2;\n+\t      a2 = a1;\n+\t    }\n \n+\t  tree a3 = NULL_TREE, *pa = &a3;\n \t  for (; a2 != 0; a2 = TREE_CHAIN (a2))\n \t    {\n \t      tree a;\n@@ -1756,10 +1783,15 @@ merge_attributes (tree a1, tree a2)\n \t      if (a == NULL_TREE)\n \t\t{\n \t\t  a1 = copy_node (a2);\n-\t\t  TREE_CHAIN (a1) = attributes;\n-\t\t  attributes = a1;\n+\t\t  *pa = a1;\n+\t\t  pa = &TREE_CHAIN (a1);\n \t\t}\n \t    }\n+\t  if (a3)\n+\t    {\n+\t      *pa = attributes;\n+\t      attributes = a3;\n+\t    }\n \t}\n     }\n   return attributes;\ndiff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc\nindex 28a034f6c06..353d5aac8ad 100644\n--- a/gcc/c-family/c-attribs.cc\n+++ b/gcc/c-family/c-attribs.cc\n@@ -715,14 +715,20 @@ attribute_takes_identifier_p (const_tree attr_id)\n {\n   const struct attribute_spec *spec = lookup_attribute_spec (attr_id);\n   if (spec == NULL)\n-    /* Unknown attribute that we'll end up ignoring, return true so we\n-       don't complain about an identifier argument.  */\n-    return true;\n+    {\n+      /* Unknown attribute that we'll end up ignoring, return true so we\n+\t don't complain about an identifier argument.  Except C++\n+\t annotations.  */\n+      if (c_dialect_cxx () && id_equal (attr_id, \"annotation \"))\n+\treturn false;\n+      return true;\n+    }\n   else if (!strcmp (\"mode\", spec->name)\n \t   || !strcmp (\"format\", spec->name)\n \t   || !strcmp (\"cleanup\", spec->name)\n \t   || !strcmp (\"access\", spec->name)\n-\t   || !strcmp (\"counted_by\", spec->name))\n+\t   || !strcmp (\"counted_by\", spec->name)\n+\t   || !strcmp (\"old parm name\", spec->name))\n     return true;\n   else\n     return targetm.attribute_takes_identifier_p (attr_id);\ndiff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc\nindex f3a3ad855e0..b4e2b95a812 100644\n--- a/gcc/c-family/c-cppbuiltin.cc\n+++ b/gcc/c-family/c-cppbuiltin.cc\n@@ -1116,6 +1116,10 @@ c_cpp_builtins (cpp_reader *pfile)\n \t  cpp_define (pfile, \"__cpp_pp_embed=202502L\");\n \t  cpp_define (pfile, \"__cpp_constexpr_virtual_inheritance=202506L\");\n \t  cpp_define (pfile, \"__cpp_expansion_statements=202506L\");\n+\t  if (flag_reflection)\n+\t    cpp_define (pfile, \"__cpp_impl_reflection=202506L\");\n+\t  else\n+\t    cpp_warn (pfile, \"__cpp_impl_reflection\");\n \t}\n       if (flag_concepts && cxx_dialect > cxx14)\n \tcpp_define (pfile, \"__cpp_concepts=202002L\");\ndiff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt\nindex a4cb755b0b9..7f24edcd704 100644\n--- a/gcc/c-family/c.opt\n+++ b/gcc/c-family/c.opt\n@@ -2329,6 +2329,10 @@ frange-for-ext-temps\n C++ ObjC++ Var(flag_range_for_ext_temps)\n Enable lifetime extension of range based for temporaries.\n \n+freflection\n+C++ ObjC++ Var(flag_reflection) Init(0)\n+Enable experimental C++26 Reflection.\n+\n freplace-objc-classes\n ObjC ObjC++ LTO Var(flag_replace_objc_classes)\n Used in Fix-and-Continue mode to indicate that object files may be swapped in at runtime.\ndiff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in\nindex 70cfe2b1663..37dd833df95 100644\n--- a/gcc/cp/Make-lang.in\n+++ b/gcc/cp/Make-lang.in\n@@ -107,7 +107,7 @@ CXX_AND_OBJCXX_OBJS = \\\n \tcp/method.o cp/module.o \\\n \tcp/name-lookup.o cp/optimize.o \\\n \tcp/parser.o cp/pt.o cp/ptree.o \\\n-\tcp/rtti.o \\\n+\tcp/reflect.o cp/rtti.o \\\n \tcp/search.o cp/semantics.o \\\n \tcp/tree.o cp/typeck.o cp/typeck2.o \\\n \tcp/vtable-class-hierarchy.o $(CXX_C_OBJS)\n@@ -188,6 +188,24 @@ endif\n # This is the file that depends on the generated header file.\n cp/name-lookup.o: $(srcdir)/cp/std-name-hint.h\n \n+ifeq ($(ENABLE_MAINTAINER_RULES), true)\n+# Special build rule.  This is a maintainer rule, that is only\n+# available when GCC is configured with --enable-maintainer-mode.  In\n+# other cases, it is not available to avoid triggering rebuilds if a\n+# user has the source checked out with unusual timestamps.\n+$(srcdir)/cp/metafns.h: $(srcdir)/cp/metafns.gperf\n+else\n+# We keep the rule so that you can still force a rebuild, even if you\n+# didn't configure GCC with --enable-maintainer-mode, by manually\n+# deleting the $(srcdir)/cp/metafns.h file.\n+$(srcdir)/cp/metafns.h:\n+endif\n+\tcd $(srcdir)/cp; gperf -o -C -E -k '1,4,5,11,14,$$' -D -N find -L C++ \\\n+\t\tmetafns.gperf --output-file metafns.h\n+\n+# This is the file that depends on the generated header file.\n+cp/reflect.o: $(srcdir)/cp/metafns.h\n+\n components_in_prev = \"bfd opcodes binutils fixincludes gas gcc gmp mpfr mpc isl gold intl ld libbacktrace libcpp libcody libdecnumber libiberty libiberty-linker-plugin libiconv zlib lto-plugin libctf libsframe\"\n components_in_prev_target = \"libstdc++-v3 libsanitizer libvtv libgcc libbacktrace libphobos zlib libgomp libatomic\"\n \ndiff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in\nindex 599d1364b35..b0653e8b795 100644\n--- a/gcc/cp/config-lang.in\n+++ b/gcc/cp/config-lang.in\n@@ -51,7 +51,7 @@ gtfiles=\"\\\n \\$(srcdir)/cp/mangle.cc \\$(srcdir)/cp/method.cc \\$(srcdir)/cp/module.cc \\\n \\$(srcdir)/cp/name-lookup.cc \\\n \\$(srcdir)/cp/parser.cc \\$(srcdir)/cp/pt.cc \\\n-\\$(srcdir)/cp/rtti.cc \\\n+\\$(srcdir)/cp/reflect.cc \\$(srcdir)/cp/rtti.cc \\\n \\$(srcdir)/cp/semantics.cc \\\n \\$(srcdir)/cp/tree.cc \\$(srcdir)/cp/typeck2.cc \\\n \\$(srcdir)/cp/vtable-class-hierarchy.cc \\\ndiff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc\nindex e091e8643a0..de9be778a13 100644\n--- a/gcc/cp/constexpr.cc\n+++ b/gcc/cp/constexpr.cc\n@@ -1200,15 +1200,29 @@ public:\n   /* If non-null, only allow modification of existing values of the variables\n      in this set.  Set by modifiable_tracker, below.  */\n   hash_set<tree> *modifiable;\n+  /* If cxx_eval_outermost_constant_expr is called on the consteval block\n+     operator (), this is the FUNCTION_DECL of that operator ().  */\n+  tree consteval_block;\n   /* Number of heap VAR_DECL deallocations.  */\n   unsigned heap_dealloc_count;\n   /* Number of uncaught exceptions.  */\n   unsigned uncaught_exceptions;\n+  /* Some metafunctions aren't dependent just on their arguments, but also\n+     on various other dependencies, e.g. has_identifier on a function parameter\n+     reflection can change depending on further declarations of corresponding\n+     function, is_complete_type depends on type definitions and template\n+     specializations in between the calls, define_aggregate even defines\n+     class types, etc.  Thus, we need to arrange for calls which call\n+     at least some metafunctions to be non-cacheable, because their behavior\n+     might not be the same.  Until we figure out which exact metafunctions\n+     need this and which don't, do it for all of them.  */\n+  bool metafns_called;\n \n   /* Constructor.  */\n   constexpr_global_ctx ()\n     : constexpr_ops_count (0), cleanups (NULL), modifiable (nullptr),\n-      heap_dealloc_count (0), uncaught_exceptions (0) {}\n+      consteval_block (NULL_TREE), heap_dealloc_count (0),\n+      uncaught_exceptions (0), metafns_called (false) {}\n \n   bool is_outside_lifetime (tree t)\n   {\n@@ -1322,6 +1336,42 @@ struct constexpr_ctx {\n   mce_value manifestly_const_eval;\n };\n \n+/* Return ctx->quiet.  For use in reflect.cc.  */\n+\n+bool\n+cxx_constexpr_quiet_p (const constexpr_ctx *ctx)\n+{\n+  return ctx->quiet;\n+}\n+\n+/* Return ctx->manifestly_const_eval.  For use in reflect.cc.  */\n+\n+mce_value\n+cxx_constexpr_manifestly_const_eval (const constexpr_ctx *ctx)\n+{\n+  return ctx->manifestly_const_eval;\n+}\n+\n+/* Return ctx->call->fundef->decl or NULL_TREE.  For use in\n+   reflect.cc.  */\n+\n+tree\n+cxx_constexpr_caller (const constexpr_ctx *ctx)\n+{\n+  if (ctx->call)\n+    return ctx->call->fundef->decl;\n+  else\n+    return NULL_TREE;\n+}\n+\n+/* Return ctx->global->consteval_block.  For use in reflect.cc.  */\n+\n+tree\n+cxx_constexpr_consteval_block (const constexpr_ctx *ctx)\n+{\n+  return ctx->global->consteval_block;\n+}\n+\n /* Predicates for the meaning of *jump_target.  */\n \n static bool\n@@ -1589,17 +1639,6 @@ save_fundef_copy (tree fun, tree copy)\n   *slot = copy;\n }\n \n-/* Whether our evaluation wants a prvalue (e.g. CONSTRUCTOR or _CST),\n-   a glvalue (e.g. VAR_DECL or _REF), or nothing.  */\n-\n-enum value_cat {\n-   vc_prvalue = 0,\n-   vc_glvalue = 1,\n-   vc_discard = 2\n-};\n-\n-static tree cxx_eval_constant_expression (const constexpr_ctx *, tree,\n-\t\t\t\t\t  value_cat, bool *, bool *, tree *);\n static tree cxx_eval_bare_aggregate (const constexpr_ctx *, tree,\n \t\t\t\t     value_cat, bool *, bool *, tree *);\n static tree cxx_fold_indirect_ref (const constexpr_ctx *, location_t, tree, tree,\n@@ -2034,6 +2073,10 @@ cxx_eval_cxa_builtin_fn (const constexpr_ctx *ctx, tree call,\n \t    {\n \t      if (type_build_dtor_call (TREE_TYPE (arg)))\n \t\t{\n+\t\t  /* So that we don't complain about out-of-consteval use.  */\n+\t\t  temp_override<tree> ovr (current_function_decl);\n+\t\t  if (ctx->call && ctx->call->fundef)\n+\t\t    current_function_decl = ctx->call->fundef->decl;\n \t\t  tree cleanup\n \t\t    = cxx_maybe_build_cleanup (arg, (ctx->quiet ? tf_none\n \t\t\t\t\t\t     : tf_warning_or_error));\n@@ -2457,6 +2500,22 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,\n \t}\n       new_call = fold_builtin_is_corresponding_member (loc, nargs, args);\n     }\n+  else if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_STRING_LITERAL,\n+\t\t\t      BUILT_IN_FRONTEND))\n+    {\n+      location_t loc = EXPR_LOCATION (t);\n+      if (nargs >= 1)\n+\t{\n+\t  tree arg = CALL_EXPR_ARG (t, 0);\n+\t  arg = cxx_eval_constant_expression (ctx, arg, 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)\n+\t    return NULL_TREE;\n+\t  args[0] = arg;\n+\t}\n+      new_call = fold_builtin_is_string_literal (loc, nargs, args);\n+    }\n   else\n     new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t),\n \t\t\t\t\tCALL_EXPR_FN (t), nargs, args);\n@@ -3184,12 +3243,14 @@ is_std_class (tree ctx, const char *name)\n bool\n is_std_allocator (tree ctx)\n {\n-  return is_std_class (ctx, \"allocator\");\n+  return (is_std_class (ctx, \"allocator\")\n+\t  || (flag_reflection\n+\t      && is_std_class (ctx, \"__new_allocator\")));\n }\n \n /* Return true if FNDECL is std::allocator<T>::{,de}allocate.  */\n \n-static inline bool\n+bool\n is_std_allocator_allocate (tree fndecl)\n {\n   tree name = DECL_NAME (fndecl);\n@@ -3670,6 +3731,43 @@ cxx_set_object_constness (const constexpr_ctx *ctx, tree object,\n     }\n }\n \n+/* Allocate an exception for OBJECT and throw it.  */\n+\n+tree\n+cxa_allocate_and_throw_exception (location_t loc, const constexpr_ctx *ctx,\n+\t\t\t\t  tree object)\n+{\n+  tree type = TREE_TYPE (object);\n+  /* This simulates a call to __cxa_allocate_exception.  We need\n+     (struct exception *) &heap -- memory on the heap so that\n+     it can survive the stack being unwound.  */\n+  tree arr = build_array_of_n_type (type, 1);\n+  tree var = cxa_allocate_exception (loc, ctx, arr, size_zero_node);\n+  DECL_NAME (var) = heap_identifier;\n+  ctx->global->put_value (var, NULL_TREE);\n+\n+  /* *(struct exception *) &heap  = exc{ ... }  */\n+  tree ptr = build_nop (build_pointer_type (type), build_address (var));\n+  object = cp_build_init_expr (cp_build_fold_indirect_ref (ptr), object);\n+  bool non_constant_p = false, overflow_p = false;\n+  tree jump_target = NULL_TREE;\n+  cxx_eval_constant_expression (ctx, object, vc_prvalue, &non_constant_p,\n+\t\t\t\t&overflow_p, &jump_target);\n+  if (non_constant_p)\n+    {\n+      if (!ctx->quiet)\n+\terror_at (loc, \"couldn%'t throw %qT\", type);\n+      return NULL_TREE;\n+    }\n+\n+  /* Now we can __cxa_throw.  */\n+  DECL_EXCEPTION_REFCOUNT (var)\n+    = size_binop (PLUS_EXPR, DECL_EXCEPTION_REFCOUNT (var), size_one_node);\n+  ++ctx->global->uncaught_exceptions;\n+\n+  return var;\n+}\n+\n /* Subroutine of cxx_eval_constant_expression.\n    Evaluate the call expression tree T in the context of OLD_CALL expression\n    evaluation.  */\n@@ -3752,6 +3850,35 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,\n   if (DECL_THUNK_P (fun))\n     return cxx_eval_thunk_call (ctx, t, fun, lval, non_constant_p, overflow_p,\n \t\t\t\tjump_target);\n+  if (metafunction_p (fun))\n+    {\n+      /* To be able to evaluate a metafunction, we may have to instantiate\n+\t constexpr functions.  If we're not allowed to instantiate, leave\n+\t this for later.  Don't evaluate metafunctions at all when mce_unknown,\n+\t otherwise we might fold those prematurely.  See\n+\t g++.dg/reflect/p2996-17.C.  */\n+      if (uid_sensitive_constexpr_evaluation_p ()\n+\t  || ctx->manifestly_const_eval == mce_unknown)\n+\t{\n+\t  *non_constant_p = true;\n+\t  return t;\n+\t}\n+      ctx->global->metafns_called = true;\n+      tree e = process_metafunction (ctx, fun, t, non_constant_p, overflow_p,\n+\t\t\t\t     jump_target);\n+      if (*jump_target)\n+\treturn NULL_TREE;\n+      if (*non_constant_p)\n+\treturn t;\n+      e = cxx_eval_constant_expression (ctx, e, vc_prvalue,\n+\t\t\t\t\tnon_constant_p, overflow_p,\n+\t\t\t\t\tjump_target);\n+      if (*jump_target)\n+\treturn NULL_TREE;\n+      if (*non_constant_p)\n+\treturn t;\n+      return e;\n+    }\n   bool non_constexpr_call = false;\n   if (!maybe_constexpr_fn (fun))\n     {\n@@ -4201,6 +4328,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,\n \t  call_ctx.call = &new_call;\n \t  unsigned save_heap_alloc_count = ctx->global->heap_vars.length ();\n \t  unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count;\n+\t  bool save_metafns_called = ctx->global->metafns_called;\n \n \t  /* Make sure we fold std::is_constant_evaluated to true in an\n \t     immediate function.  */\n@@ -4232,6 +4360,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,\n \t\treturn NULL_TREE;\n \t    }\n \n+\t  ctx->global->metafns_called = false;\n+\n \t  tree jmp_target = NULL_TREE;\n \t  cxx_eval_constant_expression (&call_ctx, body,\n \t\t\t\t\tvc_discard, non_constant_p, overflow_p,\n@@ -4265,6 +4395,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,\n \t\t}\n \t    }\n \n+\t  if (ctx->global->metafns_called)\n+\t    cacheable = false;\n+\t  ctx->global->metafns_called |= save_metafns_called;\n+\n \t  /* At this point, the object's constructor will have run, so\n \t     the object is no longer under construction, and its possible\n \t     'const' semantics now apply.  Make a note of this fact by\n@@ -4405,6 +4539,7 @@ reduced_constant_expression_p (tree t, tree sz /* = NULL_TREE */)\n   switch (TREE_CODE (t))\n     {\n     case PTRMEM_CST:\n+    case REFLECT_EXPR:\n       /* Even if we can't lower this yet, it's constant.  */\n       return true;\n \n@@ -4879,6 +5014,11 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,\n \tlhs = cplus_expand_constant (lhs);\n       else if (TREE_CODE (rhs) == PTRMEM_CST)\n \trhs = cplus_expand_constant (rhs);\n+      else if (REFLECT_EXPR_P (lhs) && REFLECT_EXPR_P (rhs))\n+\t{\n+\t  const bool eq = compare_reflections (lhs, rhs);\n+\t  r = constant_boolean_node (eq == is_code_eq, type);\n+\t}\n     }\n   if (r == NULL_TREE\n       && TREE_CODE_CLASS (code) == tcc_comparison\n@@ -8816,7 +8956,7 @@ merge_jump_target (location_t loc, const constexpr_ctx *ctx, tree r,\n /* FIXME unify with c_fully_fold */\n /* FIXME overflow_p is too global */\n \n-static tree\n+tree\n cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,\n \t\t\t      value_cat lval,\n \t\t\t      bool *non_constant_p, bool *overflow_p,\n@@ -9009,6 +9149,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,\n     case CASE_LABEL_EXPR:\n     case PREDICT_EXPR:\n     case OMP_DECLARE_MAPPER:\n+    case REFLECT_EXPR:\n       return t;\n \n     case PARM_DECL:\n@@ -9801,6 +9942,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,\n \t    return t;\n \t  }\n \n+\t/* This can happen for std::meta::info(^^int) where the cast has no\n+\t   meaning.  */\n+\tif (REFLECTION_TYPE_P (type) && REFLECT_EXPR_P (op))\n+\t  {\n+\t    r = op;\n+\t    break;\n+\t  }\n+\n \t/* [expr.const]: a conversion from type cv void* to a pointer-to-object\n \t   type cannot be part of a core constant expression as a resolution to\n \t   DR 1312.  */\n@@ -10374,7 +10523,7 @@ find_heap_var_refs (tree *tp, int *walk_subtrees, void */*data*/)\n /* Find immediate function decls in *TP if any.  */\n \n static tree\n-find_immediate_fndecl (tree *tp, int */*walk_subtrees*/, void */*data*/)\n+find_immediate_fndecl (tree *tp, int *walk_subtrees, void */*data*/)\n {\n   if (TREE_CODE (*tp) == FUNCTION_DECL && DECL_IMMEDIATE_FUNCTION_P (*tp))\n     return *tp;\n@@ -10382,6 +10531,8 @@ find_immediate_fndecl (tree *tp, int */*walk_subtrees*/, void */*data*/)\n       && TREE_CODE (PTRMEM_CST_MEMBER (*tp)) == FUNCTION_DECL\n       && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER (*tp)))\n     return PTRMEM_CST_MEMBER (*tp);\n+  if (REFLECT_EXPR_P (*tp))\n+    *walk_subtrees = 0;\n   return NULL_TREE;\n }\n \n@@ -10466,6 +10617,12 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,\n \t    return t;\n \t  else\n \t    is_consteval = true;\n+\t  tree lam;\n+\t  if (manifestly_const_eval == mce_true\n+\t      && LAMBDA_FUNCTION_P (fndecl)\n+\t      && (lam = CLASSTYPE_LAMBDA_EXPR (CP_DECL_CONTEXT (fndecl)))\n+\t      && LAMBDA_EXPR_CONSTEVAL_BLOCK_P (lam))\n+\t    global_ctx.consteval_block = fndecl;\n \t}\n     }\n   else if (cxx_dialect >= cxx20\n@@ -10682,6 +10839,37 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,\n       non_constant_p = true;\n     }\n \n+  /* Detect consteval-only smuggling: turning a consteval-only object\n+     into one that is not.  For instance, in\n+       struct B { };\n+       struct D : B { info r; };\n+       constexpr D d{^^::};\n+       constexpr const B &b = d; // #1\n+     #1 is wrong because D is a consteval-only type but B is not.  */\n+  if (flag_reflection\n+      && !non_constant_p\n+      && object\n+      && POINTER_TYPE_P (TREE_TYPE (object))\n+      && !consteval_only_p (object)\n+      && check_out_of_consteval_use (r, /*complain=*/false))\n+    {\n+      if (!allow_non_constant)\n+\t{\n+\t  if (TYPE_REF_P (TREE_TYPE (object)))\n+\t    error_at (cp_expr_loc_or_input_loc (t),\n+\t\t      \"reference into an object of consteval-only type is \"\n+\t\t      \"not a constant expression unless it also has \"\n+\t\t      \"consteval-only type\");\n+\t  else\n+\t    error_at (cp_expr_loc_or_input_loc (t),\n+\t\t      \"pointer into an object of consteval-only type is \"\n+\t\t      \"not a constant expression unless it also has \"\n+\t\t      \"consteval-only type\");\n+\t}\n+      r = t;\n+      non_constant_p = true;\n+    }\n+\n   if (!non_constant_p && !constexpr_dtor)\n     verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);\n \n@@ -11473,6 +11661,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,\n     case REQUIRES_EXPR:\n     case STATIC_ASSERT:\n     case DEBUG_BEGIN_STMT:\n+    case REFLECT_EXPR:\n       return true;\n \n     case RETURN_EXPR:\n@@ -12566,6 +12755,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,\n     case TU_LOCAL_ENTITY:\n       return false;\n \n+    /* A splice expression is dependent, but will be constant after\n+       substitution.  */\n+    case SPLICE_EXPR:\n+      return true;\n+\n     case NONTYPE_ARGUMENT_PACK:\n       {\n \ttree args = ARGUMENT_PACK_ARGS (t);\ndiff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc\nindex 92a3a780008..f45a8ad5bbd 100644\n--- a/gcc/cp/constraint.cc\n+++ b/gcc/cp/constraint.cc\n@@ -3316,6 +3316,9 @@ diagnose_trait_expr (location_t loc, tree expr, tree args)\n     case CPTK_IS_VOLATILE:\n       inform (loc, \"%qT is not a volatile type\", t1);\n       break;\n+    case CPTK_IS_CONSTEVAL_ONLY:\n+      inform (decl_loc, \"%qT is not consteval-only\", t1);\n+      break;\n     case CPTK_RANK:\n       inform (loc, \"%qT cannot yield a rank\", t1);\n       break;\ndiff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc\nindex 994d4deb0f1..9eb27deb923 100644\n--- a/gcc/cp/cp-gimplify.cc\n+++ b/gcc/cp/cp-gimplify.cc\n@@ -477,7 +477,7 @@ lvalue_has_side_effects (tree e)\n \n /* Return true if FN is an immediate-escalating function.  */\n \n-static bool\n+bool\n immediate_escalating_function_p (tree fn)\n {\n   if (!fn || !flag_immediate_escalation)\n@@ -515,7 +515,7 @@ unchecked_immediate_escalating_function_p (tree fn)\n \n /* Promote FN to an immediate function, including its clones.  */\n \n-static void\n+void\n promote_function_to_consteval (tree fn)\n {\n   SET_DECL_IMMEDIATE_FUNCTION_P (fn);\n@@ -847,6 +847,13 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)\n \n     case CALL_EXPR:\n       ret = GS_OK;\n+      /* At this point any function that takes/returns a consteval-only\n+\t expression is a problem.  */\n+      for (int i = 0; i < call_expr_nargs (*expr_p); ++i)\n+\tif (check_out_of_consteval_use (CALL_EXPR_ARG (*expr_p, i)))\n+\t  ret = GS_ERROR;\n+      if (consteval_only_p (TREE_TYPE (*expr_p)))\n+\tret = GS_ERROR;\n       if (flag_strong_eval_order == 2\n \t  && CALL_EXPR_FN (*expr_p)\n \t  && !CALL_EXPR_OPERATOR_SYNTAX (*expr_p)\n@@ -956,6 +963,13 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)\n \t\t\t  \"__builtin_eh_ptr_adjust_ref\");\n \t\t*expr_p = void_node;\n \t\tbreak;\n+\t      case CP_BUILT_IN_IS_STRING_LITERAL:\n+\t\t*expr_p\n+\t\t  = fold_builtin_is_string_literal (EXPR_LOCATION (*expr_p),\n+\t\t\t\t\t\t    call_expr_nargs (*expr_p),\n+\t\t\t\t\t\t    &CALL_EXPR_ARG (*expr_p,\n+\t\t\t\t\t\t\t\t    0));\n+\t\tbreak;\n \t      default:\n \t\tbreak;\n \t      }\n@@ -1284,6 +1298,23 @@ cp_build_init_expr_for_ctor (tree call, tree init)\n   return init;\n }\n \n+/* For every DECL_EXPR check if it declares a consteval-only variable and\n+   if so, overwrite it with a no-op.  The point here is not to leak\n+   consteval-only variables into the middle end.  */\n+\n+static tree\n+wipe_consteval_only_r (tree *stmt_p, int *, void *)\n+{\n+  if (TREE_CODE (*stmt_p) == DECL_EXPR)\n+    {\n+      tree d = DECL_EXPR_DECL (*stmt_p);\n+      if (VAR_P (d) && consteval_only_p (d))\n+\t/* Wipe the DECL_EXPR so that it doesn't get into gimple.  */\n+\t*stmt_p = void_node;\n+    }\n+  return NULL_TREE;\n+}\n+\n /* A walk_tree callback for cp_fold_function and cp_fully_fold_init to handle\n    immediate functions.  */\n \n@@ -1311,12 +1342,43 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_)\n       return NULL_TREE;\n     }\n \n+  /* Most invalid uses of consteval-only types should have been already\n+     detected at this point.  And the valid ones won't be needed\n+     anymore.  */\n+  if (flag_reflection && (data->flags & ff_genericize))\n+    {\n+      /* We still may have some wrong uses that persisted until now.  */\n+      if (complain && TREE_CODE (stmt) == STATEMENT_LIST)\n+\tfor (tree s : tsi_range (stmt))\n+\t  if (check_out_of_consteval_use (s))\n+\t    *stmt_p = void_node;\n+      /* We can't resolve all TEMPLATE_ID_EXPRs while creating reflections\n+\t because cp_parser_postfix_dot_deref_expression wants to see the\n+\t original TEMPLATE_ID_EXPR.  Resolve them now so that we don't crash\n+\t in gimple.  (The resolution shouldn't fail here because the bad ones\n+\t won't get this far.)  */\n+      if (REFLECT_EXPR_P (stmt))\n+\t{\n+\t  tree &h = REFLECT_EXPR_HANDLE (stmt);\n+\t  h = resolve_nondeduced_context (h, tf_none);\n+\t}\n+    }\n+\n   tree decl = NULL_TREE;\n   bool call_p = false;\n \n   /* We are looking for &fn or fn().  */\n   switch (code)\n     {\n+    case DECL_EXPR:\n+      /* Clear consteval-only DECL_EXPRs.  */\n+      if (flag_reflection)\n+\t{\n+\t  tree d = DECL_EXPR_DECL (stmt);\n+\t  if (VAR_P (d) && consteval_only_p (d))\n+\t    *stmt_p = void_node;\n+\t}\n+      break;\n     case CALL_EXPR:\n     case AGGR_INIT_EXPR:\n       if (tree fn = cp_get_callee (stmt))\n@@ -1335,8 +1397,15 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_)\n       if (IF_STMT_CONSTEVAL_P (stmt))\n \t{\n \t  if (!data->pset.add (stmt))\n-\t    cp_walk_tree (&ELSE_CLAUSE (stmt), cp_fold_immediate_r, data_,\n-\t\t\t  NULL);\n+\t    {\n+\t      cp_walk_tree (&ELSE_CLAUSE (stmt), cp_fold_immediate_r, data_,\n+\t\t\t    nullptr);\n+\t      if (flag_reflection)\n+\t\t/* Check & clear consteval-only DECL_EXPRs even here,\n+\t\t   because we wouldn't be walking this subtree otherwise.  */\n+\t\tcp_walk_tree (&THEN_CLAUSE (stmt), wipe_consteval_only_r,\n+\t\t\t      data_, nullptr);\n+\t    }\n \t  *walk_subtrees = 0;\n \t  return NULL_TREE;\n \t}\n@@ -1410,6 +1479,22 @@ cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_)\n \t  *walk_subtrees = 0;\n \t  return stmt;\n \t}\n+      /* If we called a consteval function and it evaluated to a consteval-only\n+\t expression, it could be a problem if we are outside a manifestly\n+\t constant-evaluated context.  */\n+      else if ((data->flags & ff_genericize)\n+\t       && check_out_of_consteval_use (e, complain))\n+\t{\n+\t  *stmt_p = void_node;\n+\t  if (complain & tf_error)\n+\t    return NULL_TREE;\n+\t  else\n+\t    {\n+\t      *walk_subtrees = 0;\n+\t      return stmt;\n+\t    }\n+\t}\n+\n       /* We've evaluated the consteval function call.  */\n       if (call_p)\n \t{\n@@ -1962,6 +2047,20 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)\n \t      cp_walk_tree (&DECL_INITIAL (decl), cp_genericize_r, data, NULL);\n \t  wtd->no_sanitize_p = no_sanitize_p;\n \t}\n+      if (flag_reflection)\n+\t/* Wipe consteval-only vars from BIND_EXPR_VARS and BLOCK_VARS.  */\n+\tfor (tree *p = &BIND_EXPR_VARS (stmt); *p; )\n+\t  {\n+\t    if (VAR_P (*p) && consteval_only_p (*p))\n+\t      {\n+\t\tif (BIND_EXPR_BLOCK (stmt)\n+\t\t    && *p == BLOCK_VARS (BIND_EXPR_BLOCK (stmt)))\n+\t\t  BLOCK_VARS (BIND_EXPR_BLOCK (stmt)) = DECL_CHAIN (*p);\n+\t\t*p = DECL_CHAIN (*p);\n+\t\tcontinue;\n+\t      }\n+\t    p = &DECL_CHAIN (*p);\n+\t  }\n       wtd->bind_expr_stack.safe_push (stmt);\n       cp_walk_tree (&BIND_EXPR_BODY (stmt),\n \t\t    cp_genericize_r, data, NULL);\ndiff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc\nindex 859c7d69746..b18e152bef8 100644\n--- a/gcc/cp/cp-objcp-common.cc\n+++ b/gcc/cp/cp-objcp-common.cc\n@@ -646,6 +646,8 @@ cp_common_init_ts (void)\n   MARK_TS_TYPE_NON_COMMON (TEMPLATE_TYPE_PARM);\n   MARK_TS_TYPE_NON_COMMON (TYPE_PACK_EXPANSION);\n   MARK_TS_TYPE_NON_COMMON (PACK_INDEX_TYPE);\n+  MARK_TS_TYPE_NON_COMMON (META_TYPE);\n+  MARK_TS_TYPE_NON_COMMON (SPLICE_SCOPE);\n \n   /* Statements.  */\n   MARK_TS_EXP (CLEANUP_STMT);\n@@ -696,6 +698,8 @@ cp_common_init_ts (void)\n   MARK_TS_EXP (VEC_INIT_EXPR);\n   MARK_TS_EXP (VEC_NEW_EXPR);\n   MARK_TS_EXP (SPACESHIP_EXPR);\n+  MARK_TS_EXP (SPLICE_EXPR);\n+  MARK_TS_EXP (REFLECT_EXPR);\n \n   /* Fold expressions.  */\n   MARK_TS_EXP (BINARY_LEFT_FOLD_EXPR);\ndiff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def\nindex c7fc40d0544..395cadc5767 100644\n--- a/gcc/cp/cp-trait.def\n+++ b/gcc/cp/cp-trait.def\n@@ -69,6 +69,7 @@ DEFTRAIT_EXPR (IS_BASE_OF, \"__is_base_of\", 2)\n DEFTRAIT_EXPR (IS_BOUNDED_ARRAY, \"__is_bounded_array\", 1)\n DEFTRAIT_EXPR (IS_CLASS, \"__is_class\", 1)\n DEFTRAIT_EXPR (IS_CONST, \"__is_const\", 1)\n+DEFTRAIT_EXPR (IS_CONSTEVAL_ONLY, \"__builtin_is_consteval_only\", 1)\n DEFTRAIT_EXPR (IS_CONSTRUCTIBLE, \"__is_constructible\", -1)\n DEFTRAIT_EXPR (IS_CONVERTIBLE, \"__is_convertible\", 2)\n DEFTRAIT_EXPR (IS_DESTRUCTIBLE, \"__is_destructible\", 1)\ndiff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def\nindex b1e369738fa..c050b55abb8 100644\n--- a/gcc/cp/cp-tree.def\n+++ b/gcc/cp/cp-tree.def\n@@ -586,6 +586,24 @@ DEFTREECODE (POSTCONDITION_STMT, \"postcondition_stmt\", tcc_statement, 4)\n    wasn't an exposure (e.g. in a non-inline function template).  */\n DEFTREECODE (TU_LOCAL_ENTITY, \"tu_local_entity\", tcc_exceptional, 0)\n \n+/* C++26 reflection expression.  */\n+DEFTREECODE (REFLECT_EXPR, \"reflect_expr\", tcc_expression, 1)\n+\n+/* Represents the std::meta::info type.  */\n+DEFTREECODE (META_TYPE, \"meta_type\", tcc_type, 0)\n+\n+/* Represents a dependent splice expression.  If SPLICE_EXPR_EXPRESSION_P\n+   is set, this tree represents a splice-expression (as opposed to\n+   a splice-specifier).  */\n+DEFTREECODE (SPLICE_EXPR, \"splice_expr\", tcc_expression, 1)\n+\n+/* Represents a dependent splice scope, or a dependent splice type\n+   (SPLICE_SCOPE_TYPE_P says which one it is).  Its operand can be accessed\n+   using SPLICE_SCOPE_EXPR.  The operand can be a SPLICE_EXPR or a\n+   TEMPLATE_ID_EXPR; the SPLICE_SCOPE is necessary to denote that this\n+   tree should expand to a type/scope.  */\n+DEFTREECODE (SPLICE_SCOPE, \"splice_scope\", tcc_type, 0)\n+\n /*\n Local variables:\n mode:c\ndiff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h\nindex 1f00898cfad..a3e3f05e4e9 100644\n--- a/gcc/cp/cp-tree.h\n+++ b/gcc/cp/cp-tree.h\n@@ -175,6 +175,7 @@ enum cp_tree_index\n     CPTI_FOR_END_IDENTIFIER,\n     CPTI_ABI_TAG_IDENTIFIER,\n     CPTI_ALIGNED_IDENTIFIER,\n+    CPTI_ANNOTATION_IDENTIFIER,\n     CPTI_BEGIN_IDENTIFIER,\n     CPTI_END_IDENTIFIER,\n     CPTI_GET_IDENTIFIER,\n@@ -211,6 +212,7 @@ enum cp_tree_index\n \n     /* We must find these via the global namespace.  */\n     CPTI_STD,\n+    CPTI_STD_META,\n     CPTI_ABI,\n \n     /* These are created at init time, but the library/headers provide\n@@ -236,6 +238,7 @@ enum cp_tree_index\n     CPTI_DCAST,\n \n     CPTI_PSEUDO_CONTRACT_VIOLATION,\n+    CPTI_META_INFO_TYPE,\n \n     CPTI_MAX\n };\n@@ -257,6 +260,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n #define vtbl_type_node\t\t\tcp_global_trees[CPTI_VTBL_TYPE]\n #define vtbl_ptr_type_node\t\tcp_global_trees[CPTI_VTBL_PTR_TYPE]\n #define std_node\t\t\tcp_global_trees[CPTI_STD]\n+#define std_meta_node\t\t\tcp_global_trees[CPTI_STD_META]\n #define abi_node\t\t\tcp_global_trees[CPTI_ABI]\n #define global_namespace\t\tcp_global_trees[CPTI_GLOBAL]\n #define const_type_info_type_node\tcp_global_trees[CPTI_CONST_TYPE_INFO_TYPE]\n@@ -266,6 +270,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n /* std::align_val_t */\n #define align_type_node\t\t\tcp_global_trees[CPTI_ALIGN_TYPE]\n #define pseudo_contract_violation_type\tcp_global_trees[CPTI_PSEUDO_CONTRACT_VIOLATION]\n+#define meta_info_type_node\t\tcp_global_trees[CPTI_META_INFO_TYPE]\n \n /* We cache these tree nodes so as to call get_identifier less frequently.\n    For identifiers for functions, including special member functions such\n@@ -329,6 +334,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n #define for_end_identifier\t\tcp_global_trees[CPTI_FOR_END_IDENTIFIER]\n #define abi_tag_identifier\t\tcp_global_trees[CPTI_ABI_TAG_IDENTIFIER]\n #define aligned_identifier\t\tcp_global_trees[CPTI_ALIGNED_IDENTIFIER]\n+#define annotation_identifier\t\tcp_global_trees[CPTI_ANNOTATION_IDENTIFIER]\n #define begin_identifier\t\tcp_global_trees[CPTI_BEGIN_IDENTIFIER]\n #define end_identifier\t\t\tcp_global_trees[CPTI_END_IDENTIFIER]\n #define get__identifier\t\t\tcp_global_trees[CPTI_GET_IDENTIFIER]\n@@ -454,6 +460,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n       MUST_NOT_THROW_NOEXCEPT_P (in MUST_NOT_THROW_EXPR)\n       CONSTEVAL_BLOCK_P (in STATIC_ASSERT)\n       LAMBDA_EXPR_CONSTEVAL_BLOCK_P (in LAMBDA_EXPR)\n+      SPLICE_EXPR_EXPRESSION_P (in SPLICE_EXPR)\n+      OLD_PARM_DECL_P (in PARM_DECL)\n+      COMPONENT_REF_SPLICE_P (in COMPONENT_REF)\n    1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE)\n       TI_PENDING_TEMPLATE_FLAG.\n       TEMPLATE_PARMS_FOR_INLINE.\n@@ -476,6 +485,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n       STATIC_INIT_DECOMP_BASE_P (in the TREE_LIST for {static,tls}_aggregates)\n       MUST_NOT_THROW_THROW_P (in MUST_NOT_THROW_EXPR)\n       LAMBDA_EXPR_CONST_QUAL_P (in LAMBDA_EXPR)\n+      SPLICE_EXPR_MEMBER_ACCESS_P (in SPLICE_EXPR)\n    2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE)\n       ICS_THIS_FLAG (in _CONV)\n       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)\n@@ -499,6 +509,8 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n       STATIC_INIT_DECOMP_NONBASE_P (in the TREE_LIST\n \t\t\t\t    for {static,tls}_aggregates)\n       MUST_NOT_THROW_CATCH_P (in MUST_NOT_THROW_EXPR)\n+      MULTIPLE_NAMES_PARM_P (in PARM_DECL)\n+      SPLICE_EXPR_ADDRESS_P (in SPLICE_EXPR)\n    3: IMPLICIT_RVALUE_P (in NON_LVALUE_EXPR or STATIC_CAST_EXPR)\n       ICS_BAD_FLAG (in _CONV)\n       FN_TRY_BLOCK_P (in TRY_BLOCK)\n@@ -541,6 +553,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];\n    1: TYPE_HAS_USER_CONSTRUCTOR.\n    2: TYPE_HAS_LATE_RETURN_TYPE (in FUNCTION_TYPE, METHOD_TYPE)\n       TYPE_PTRMEMFUNC_FLAG (in RECORD_TYPE)\n+      ENUM_BEING_DEFINED_P (in ENUMERAL_TYPE)\n    4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR\n    5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE)\n       ENUM_FIXED_UNDERLYING_TYPE_P (in ENUMERAL_TYPE)\n@@ -1883,6 +1896,98 @@ struct GTY(()) tree_tu_local_entity {\n #define REQUIRES_EXPR_EXTRA_ARGS(NODE) \\\n   TREE_OPERAND (TREE_CHECK (NODE, REQUIRES_EXPR), 2)\n \n+/* True iff TYPE is cv decltype(^^int).  */\n+#define REFLECTION_TYPE_P(TYPE) (TREE_CODE (TYPE) == META_TYPE)\n+\n+/* True if NODE is a REFLECT_EXPR.  */\n+#define REFLECT_EXPR_P(NODE) (TREE_CODE (NODE) == REFLECT_EXPR)\n+\n+/* The handle of a reflection expression.  */\n+#define REFLECT_EXPR_HANDLE(NODE) \\\n+  TREE_OPERAND (TREE_CHECK (NODE, REFLECT_EXPR), 0)\n+\n+/* Various kinds of reflections.  Sometimes we cannot simply look at the\n+   handle and figure out the kind from it.  For instance,\n+\n+     consteval void fn(int p) {\n+       constexpr auto rp = parameters_of(^^fn)[0];\n+       // is_variable(^^p) is true\n+       // is_function_parameter(^^p) is false\n+       // is_variable(rp) is false\n+       // is_function_parameter(rp) is true\n+     }\n+\n+   but we represent the handle p with a PARM_DECL in all cases.\n+\n+   The size is limited to addr_space_t because we only have 8 bits.  */\n+\n+enum reflect_kind : addr_space_t {\n+  /* Detect the category from the handle.  */\n+  REFLECT_UNDEF,\n+  /* The reflection represents an object.  */\n+  REFLECT_OBJECT,\n+  /* The reflection represents a value.  */\n+  REFLECT_VALUE,\n+  /* The reflection represents a variable.  Used for underlying\n+     variable of tuple structured binding.  */\n+  REFLECT_VAR,\n+  /* The reflection represents a function parameter.  */\n+  REFLECT_PARM,\n+  /* The reflection represents a data member description.  */\n+  REFLECT_DATA_MEMBER_SPEC,\n+  /* The reflection represents a direct base relationship.  */\n+  REFLECT_BASE,\n+  /* The reflection represents an annotation.  */\n+  REFLECT_ANNOTATION\n+};\n+\n+/* The reflect_kind of a REFLECT_EXPR.  */\n+#define REFLECT_EXPR_KIND(NODE) \\\n+  (static_cast<reflect_kind> \\\n+   (REFLECT_EXPR_CHECK (NODE)->base.u.bits.address_space))\n+\n+#define SET_REFLECT_EXPR_KIND(NODE, VAL) \\\n+  (REFLECT_EXPR_CHECK (NODE)->base.u.bits.address_space = VAL)\n+\n+/* True if this SPLICE_EXPR represents a splice-expression (as opposed to\n+   a splice-specifier), so it cannot expand to e.g. a type.  */\n+#define SPLICE_EXPR_EXPRESSION_P(NODE) \\\n+   TREE_LANG_FLAG_0 (SPLICE_EXPR_CHECK (NODE))\n+\n+/* Helper macro to set SPLICE_EXPR_EXPRESSION_P.  This macro handles\n+   dependent_splice_p trees: either [:T:] or [:T:]<arg>.  */\n+#define SET_SPLICE_EXPR_EXPRESSION_P(NODE) \\\n+  (SPLICE_EXPR_EXPRESSION_P (TREE_CODE (NODE) == SPLICE_EXPR \\\n+\t\t\t     ? NODE : TREE_OPERAND (NODE, 0)) = true)\n+\n+/* True if this SPLICE_EXPR is used in foo.[: bar :] or foo->[: bar :]\n+   context.  */\n+#define SPLICE_EXPR_MEMBER_ACCESS_P(NODE) \\\n+   TREE_LANG_FLAG_1 (SPLICE_EXPR_CHECK (NODE))\n+\n+/* Helper macro to set SPLICE_EXPR_MEMBER_ACCESS_P.  */\n+#define SET_SPLICE_EXPR_MEMBER_ACCESS_P(NODE, VAL) \\\n+  (SPLICE_EXPR_MEMBER_ACCESS_P (TREE_CODE (NODE) == SPLICE_EXPR \\\n+\t\t\t\t? NODE : TREE_OPERAND (NODE, 0)) = (VAL))\n+\n+/* True if we are taking the address of this SPLICE_EXPR.  */\n+#define SPLICE_EXPR_ADDRESS_P(NODE) \\\n+   TREE_LANG_FLAG_2 (SPLICE_EXPR_CHECK (NODE))\n+\n+/* Helper macro to set SPLICE_EXPR_ADDRESS_P.  */\n+#define SET_SPLICE_EXPR_ADDRESS_P(NODE, VAL) \\\n+  (SPLICE_EXPR_ADDRESS_P (TREE_CODE (NODE) == SPLICE_EXPR \\\n+\t\t\t  ? NODE : TREE_OPERAND (NODE, 0)) = (VAL))\n+\n+/* The expression in question for a SPLICE_SCOPE.  */\n+#define SPLICE_SCOPE_EXPR(NODE) \\\n+  (TYPE_VALUES_RAW (SPLICE_SCOPE_CHECK (NODE)))\n+\n+/* True if this splice represents a splice-type-specifier rather than\n+   a splice-scope-specifier.  */\n+#define SPLICE_SCOPE_TYPE_P(NODE) \\\n+  (SPLICE_SCOPE_CHECK (NODE))->type_common.string_flag\n+\n enum cp_tree_node_structure_enum {\n   TS_CP_GENERIC,\n   TS_CP_IDENTIFIER,\n@@ -2366,6 +2471,7 @@ enum languages { lang_c, lang_cplusplus };\n    || TREE_CODE (T) == DECLTYPE_TYPE\t\t\t\\\n    || TREE_CODE (T) == TRAIT_TYPE\t\t\t\\\n    || TREE_CODE (T) == DEPENDENT_OPERATOR_TYPE\t\t\\\n+   || TREE_CODE (T) == SPLICE_SCOPE\t\t\t\\\n    || TREE_CODE (T) == PACK_INDEX_TYPE)\n \n /* Nonzero if T is a class (or struct or union) type.  Also nonzero\n@@ -4372,6 +4478,11 @@ templated_operator_saved_lookups (tree t)\n #define REF_PARENTHESIZED_P(NODE) \\\n   TREE_LANG_FLAG_2 (TREE_CHECK5 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR, PAREN_EXPR))\n \n+/* True on a dependent COMPONENT_REF with a splice expression.  */\n+\n+#define COMPONENT_REF_SPLICE_P(NODE) \\\n+  TREE_LANG_FLAG_0 (COMPONENT_REF_CHECK (NODE))\n+\n /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a\n    constructor call, rather than an ordinary function call.  */\n #define AGGR_INIT_VIA_CTOR_P(NODE) \\\n@@ -4749,9 +4860,9 @@ get_vec_init_expr (tree t)\n \n /* [basic.types]\n \n-   Arithmetic types, enumeration types, pointer types,\n-   pointer-to-member types, and std::nullptr_t are collectively called\n-   scalar types.\n+   Arithmetic types, enumeration types, pointer types, pointer-to-member types,\n+   std::meta::info, std::nullptr_t and cv-qualified versions of these types\n+   are collectively called scalar types.\n \n    Keep these checks in ascending code order.  */\n #define SCALAR_TYPE_P(TYPE)\t\t\t\\\n@@ -4760,7 +4871,8 @@ get_vec_init_expr (tree t)\n    || ARITHMETIC_TYPE_P (TYPE)\t\t\t\\\n    || TYPE_PTR_P (TYPE)\t\t\t\t\\\n    || TYPE_PTRMEMFUNC_P (TYPE)                  \\\n-   || NULLPTR_TYPE_P (TYPE))\n+   || NULLPTR_TYPE_P (TYPE)\t\t\t\\\n+   || REFLECTION_TYPE_P (TYPE))\n \n /* Determines whether this type is a C++0x scoped enumeration\n    type. Scoped enumerations types are introduced via \"enum class\" or\n@@ -4801,6 +4913,11 @@ get_vec_init_expr (tree t)\n #define OPAQUE_ENUM_P(TYPE)\t\t\t\t\\\n   (TREE_CODE (TYPE) == ENUMERAL_TYPE && ENUM_IS_OPAQUE (TYPE))\n \n+/* Nonzero when the ENUMERAL_TYPE is being defined (enumerators parsed\n+   or instantiated).  */\n+#define ENUM_BEING_DEFINED_P(NODE) \\\n+  (TYPE_LANG_FLAG_2 (ENUMERAL_TYPE_CHECK (NODE)))\n+\n /* [dcl.init.aggr]\n \n    An aggregate is an array or a class with no user-provided\n@@ -5168,6 +5285,18 @@ get_vec_init_expr (tree t)\n #define DECL_ARRAY_PARAMETER_P(NODE) \\\n   DECL_LANG_FLAG_1 (PARM_DECL_CHECK (NODE))\n \n+/* Nonzero for PARM_DECL node means it is a parameter of an earlier\n+   declaration which is no longer in DECL_ARGUMENTS (DECL_CONTEXT (NODE))\n+   chain because a function definition has been parsed later.  */\n+#define OLD_PARM_DECL_P(NODE) \\\n+  TREE_LANG_FLAG_0 (PARM_DECL_CHECK (NODE))\n+\n+/* Nonzero for PARM_DECL node means it has different names on different\n+   declarations of the same FUNCTION_DECL.  If it is unnamed on one and\n+   named on another, that is still fine.  */\n+#define MULTIPLE_NAMES_PARM_P(NODE) \\\n+  TREE_LANG_FLAG_2 (PARM_DECL_CHECK (NODE))\n+\n /* Nonzero for a FIELD_DECL who's NSMDI is currently being\n    instantiated.  */\n #define DECL_INSTANTIATING_NSDMI_P(NODE) \\\n@@ -6029,6 +6158,8 @@ extern bool comparing_override_contracts;\n \n /* In parser.cc.  */\n \n+extern bool cp_preserve_using_decl;\n+\n /* Nonzero if we are parsing an unevaluated operand: an operand to\n    sizeof, typeof, or alignof.  This is a count since operands to\n    sizeof can be nested.  */\n@@ -6526,8 +6657,8 @@ enum ovl_op_flags {\n enum ovl_op_code {\n   OVL_OP_ERROR_MARK,\n   OVL_OP_NOP_EXPR,\n-#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS) OVL_OP_##CODE,\n-#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING) /* NOTHING */\n+#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, META) OVL_OP_##CODE,\n+#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, META) /* NOTHING */\n #include \"operators.def\"\n   OVL_OP_MAX\n };\n@@ -6542,6 +6673,9 @@ struct GTY(()) ovl_op_info_t {\n   const char *name;\n   /* The mangled name of the operator.  */\n   const char *mangled_name;\n+  /* The name of the std::meta::operators enumerator without\n+     the \"op_\" prefix if any (otherwise NULL).  */\n+  const char *meta_name;\n   /* The (regular) tree code.  */\n   enum tree_code tree_code : 16;\n   /* The (compressed) operator code.  */\n@@ -6933,6 +7067,7 @@ enum cp_built_in_function {\n   CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS,\n   CP_BUILT_IN_SOURCE_LOCATION,\n   CP_BUILT_IN_EH_PTR_ADJUST_REF,\n+  CP_BUILT_IN_IS_STRING_LITERAL,\n   CP_BUILT_IN_LAST\n };\n \n@@ -7844,6 +7979,7 @@ extern void remove_dummy_lambda_op (tree, tree);\n extern tree canonical_type_parameter\t\t(tree);\n extern void push_access_scope\t\t\t(tree);\n extern void pop_access_scope\t\t\t(tree);\n+extern tree current_function_decl_without_access_scope ();\n extern bool check_template_shadow\t\t(tree);\n extern tree get_innermost_template_args\t\t(tree, int);\n extern void maybe_begin_member_template_processing (tree);\n@@ -7963,6 +8099,7 @@ extern int processing_template_parmlist;\n extern bool dependent_type_p\t\t\t(tree);\n extern bool dependent_scope_p\t\t\t(tree);\n extern bool dependentish_scope_p\t\t(tree);\n+extern bool dependent_namespace_p\t\t(tree);\n extern bool any_dependent_template_arguments_p  (const_tree);\n extern bool any_erroneous_template_args_p       (const_tree);\n extern bool dependent_template_p\t\t(tree);\n@@ -8045,6 +8182,7 @@ extern tree add_outermost_template_args\t\t(tree, tree);\n extern tree add_extra_args\t\t\t(tree, tree, tsubst_flags_t, tree);\n extern tree build_extra_args\t\t\t(tree, tree, tsubst_flags_t);\n extern void finish_expansion_stmt\t\t(tree, tree, tsubst_flags_t, tree);\n+extern tree convert_reflect_constant_arg\t(tree, tree);\n \n /* in rtti.cc */\n /* A vector of all tinfo decls that haven't been emitted yet.  */\n@@ -8243,9 +8381,10 @@ extern tree finish_template_template_parm       (tree, tree);\n extern tree begin_class_definition\t\t(tree);\n extern void finish_template_decl\t\t(tree);\n extern tree finish_template_type\t\t(tree, tree, int);\n-extern tree finish_base_specifier\t\t(tree, tree, bool);\n+extern tree finish_base_specifier\t\t(tree, tree, bool, tree);\n extern void finish_member_declaration\t\t(tree);\n extern bool outer_automatic_var_p\t\t(tree);\n+extern bool parsing_lambda_declarator\t\t();\n extern tree process_outer_var_ref\t\t(tree, tsubst_flags_t, bool force_use = false);\n extern cp_expr finish_id_expression\t\t(tree, tree, tree,\n \t\t\t\t\t\t cp_id_kind *,\n@@ -8326,6 +8465,7 @@ extern tree finish_decltype_type                (tree, bool, tsubst_flags_t);\n extern tree fold_builtin_is_corresponding_member (location_t, int, tree *);\n extern bool pointer_interconvertible_base_of_p\t(tree, tree, bool = false);\n extern tree fold_builtin_is_pointer_inverconvertible_with_class (location_t, int, tree *);\n+extern tree fold_builtin_is_string_literal\t(location_t, int, tree *);\n extern tree finish_structured_binding_size\t(location_t, tree, tsubst_flags_t);\n extern tree finish_trait_expr\t\t\t(location_t, enum cp_trait_kind, tree, tree);\n extern tree finish_trait_type\t\t\t(enum cp_trait_kind, tree, tree, tsubst_flags_t);\n@@ -8540,6 +8680,7 @@ extern tree cxx_copy_lang_qualifiers\t\t(const_tree, const_tree);\n \n extern void cxx_print_statistics\t\t(void);\n extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t);\n+extern bool annotation_p\t\t\t(tree) ATTRIBUTE_PURE;\n \n /* in ptree.cc */\n extern void cxx_print_xnode\t\t\t(FILE *, tree, int);\n@@ -8593,7 +8734,7 @@ extern tree decay_conversion\t\t\t(tree,\n extern tree build_class_member_access_expr      (cp_expr, tree, tree, bool,\n \t\t\t\t\t\t tsubst_flags_t);\n extern tree finish_class_member_access_expr     (cp_expr, tree, bool,\n-\t\t\t\t\t\t tsubst_flags_t);\n+\t\t\t\t\t\t tsubst_flags_t, bool = false);\n extern tree lookup_destructor\t\t\t(tree, tree, tree, tsubst_flags_t);\n extern tree build_dependent_operator_type\t(tree, enum tree_code, bool);\n extern tree build_x_indirect_ref\t\t(location_t, tree,\n@@ -8902,6 +9043,8 @@ extern tree process_stmt_assume_attribute\t(tree, tree, location_t);\n extern bool simple_empty_class_p\t\t(tree, tree, tree_code);\n extern tree fold_builtin_source_location\t(const_tree);\n extern tree get_source_location_impl_type\t();\n+extern bool immediate_escalating_function_p\t(tree);\n+extern void promote_function_to_consteval\t(tree);\n extern tree cp_fold_immediate\t\t\t(tree *, mce_value,\n \t\t\t\t\t\t tree = current_function_decl);\n extern void process_and_check_pending_immediate_escalating_fns ();\n@@ -9058,6 +9201,7 @@ extern bool is_nondependent_static_init_expression (tree);\n extern bool is_static_init_expression    (tree);\n extern bool is_std_class (tree, const char *);\n extern bool is_std_allocator (tree);\n+extern bool is_std_allocator_allocate (tree);\n extern bool potential_rvalue_constant_expression (tree);\n extern bool require_potential_constant_expression (tree);\n extern bool require_constant_expression (tree);\n@@ -9099,6 +9243,24 @@ extern tree find_failing_clause\t\t\t(const constexpr_ctx *ctx, tree);\n extern void diagnose_failing_condition\t\t(tree, location_t, bool,\n \t\t\t\t\t\t const constexpr_ctx * = nullptr);\n extern bool replace_decl\t\t\t(tree *, tree, tree);\n+extern tree cxa_allocate_and_throw_exception\t(location_t, const constexpr_ctx *,\n+\t\t\t\t\t\t tree);\n+\n+/* Whether our evaluation wants a prvalue (e.g. CONSTRUCTOR or _CST),\n+   a glvalue (e.g. VAR_DECL or _REF), or nothing.  */\n+enum value_cat {\n+   vc_prvalue = 0,\n+   vc_glvalue = 1,\n+   vc_discard = 2\n+};\n+\n+extern tree cxx_eval_constant_expression\t(const constexpr_ctx *, tree,\n+\t\t\t\t\t\t value_cat, bool *, bool *,\n+\t\t\t\t\t\t tree *);\n+extern bool cxx_constexpr_quiet_p\t\t(const constexpr_ctx *);\n+extern mce_value cxx_constexpr_manifestly_const_eval (const constexpr_ctx *);\n+extern tree cxx_constexpr_caller\t\t(const constexpr_ctx *);\n+extern tree cxx_constexpr_consteval_block\t(const constexpr_ctx *);\n \n /* An RAII sentinel used to restrict constexpr evaluation so that it\n    doesn't do anything that causes extra DECL_UID generation.  */\n@@ -9142,6 +9304,27 @@ extern tree coro_get_ramp_function\t\t(tree);\n \n extern tree co_await_get_resume_call\t\t(tree await_expr);\n \n+\n+/* In reflect.cc */\n+extern void init_reflection ();\n+extern bool metafunction_p (tree) ATTRIBUTE_PURE;\n+extern tree process_metafunction (const constexpr_ctx *, tree, tree,\n+\t\t\t\t  bool *, bool *, tree *);\n+extern tree get_reflection (location_t, tree, reflect_kind = REFLECT_UNDEF);\n+extern tree get_null_reflection () ATTRIBUTE_PURE;\n+extern tree splice (tree);\n+extern bool check_out_of_consteval_use (tree, bool = true);\n+extern bool consteval_only_p (tree) ATTRIBUTE_PURE;\n+extern bool compare_reflections (tree, tree) ATTRIBUTE_PURE;\n+extern bool valid_splice_type_p (const_tree) ATTRIBUTE_PURE;\n+extern bool valid_splice_scope_p (const_tree) ATTRIBUTE_PURE;\n+extern bool check_splice_expr (location_t, location_t, tree, bool, bool, bool)\n+  ATTRIBUTE_PURE;\n+extern tree make_splice_scope (tree, bool);\n+extern bool dependent_splice_p (const_tree) ATTRIBUTE_PURE;\n+extern tree reflection_mangle_prefix (tree, char [3]);\n+extern void check_consteval_only_fn (tree);\n+\n /* Inline bodies.  */\n \n inline tree\ndiff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc\nindex 68d51b61375..78719260506 100644\n--- a/gcc/cp/cvt.cc\n+++ b/gcc/cp/cvt.cc\n@@ -1207,6 +1207,12 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)\n    if (concept_check_p (expr))\n      expr = evaluate_concept_check (expr);\n \n+  /* Detect using expressions of consteval-only types outside manifestly\n+     constant-evaluated contexts.  We are going to discard this expression,\n+     so we can't wait till cp_fold_immediate_r.  */\n+  if (check_out_of_consteval_use (expr))\n+    return error_mark_node;\n+\n   if (VOID_TYPE_P (TREE_TYPE (expr)))\n     return expr;\n \ndiff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc\nindex 4916bf66ee2..65f5e2816e3 100644\n--- a/gcc/cp/cxx-pretty-print.cc\n+++ b/gcc/cp/cxx-pretty-print.cc\n@@ -813,6 +813,7 @@ pp_cxx_delete_expression (cxx_pretty_printer *pp, tree t)\n       sizeof ... ( identifier )\n       new-expression\n       delete-expression\n+      reflect-expression\n \n    unary-operator: one of\n       *   &   +   -  !\n@@ -898,6 +899,19 @@ cxx_pretty_printer::unary_expression (tree t)\n       pp_cxx_cast_expression (this, TREE_OPERAND (t, 0));\n       break;\n \n+    case REFLECT_EXPR:\n+      {\n+\tpp_cxx_ws_string (this, \"^^\");\n+\ttree h = REFLECT_EXPR_HANDLE (t);\n+\tif (DECL_P (h))\n+\t  declaration (h);\n+\telse if (TYPE_P (h))\n+\t  type_id (h);\n+\telse\n+\t  expression (h);\n+      }\n+      break;\n+\n     default:\n       c_pretty_printer::unary_expression (t);\n       break;\n@@ -1184,6 +1198,7 @@ cxx_pretty_printer::expression (tree t)\n     case ALIGNOF_EXPR:\n     case NOEXCEPT_EXPR:\n     case UNARY_PLUS_EXPR:\n+    case REFLECT_EXPR:\n       unary_expression (t);\n       break;\n \n@@ -1427,6 +1442,10 @@ cxx_pretty_printer::simple_type_specifier (tree t)\n       pp_cxx_trait (this, t);\n       break;\n \n+    case META_TYPE:\n+      pp_cxx_ws_string (this, \"std::meta::info\");\n+      break;\n+\n     default:\n       c_pretty_printer::simple_type_specifier (t);\n       break;\n@@ -1923,6 +1942,7 @@ cxx_pretty_printer::type_id (tree t)\n     case NULLPTR_TYPE:\n     case TEMPLATE_ID_EXPR:\n     case OFFSET_TYPE:\n+    case META_TYPE:\n       pp_cxx_type_specifier_seq (this, t);\n       if (TYPE_PTRMEM_P (t))\n \tabstract_declarator (t);\ndiff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc\nindex 30f38f1e099..88d0a3fe59a 100644\n--- a/gcc/cp/decl.cc\n+++ b/gcc/cp/decl.cc\n@@ -134,6 +134,7 @@ static bool identify_goto (tree, location_t, const location_t *,\n    Namespaces,\n \n \ttree std_node;\n+\ttree std_meta_node;\n \ttree abi_node;\n \n    A FUNCTION_DECL which can call `abort'.  Not necessarily the\n@@ -3042,9 +3043,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)\n \n       /* Merge parameter attributes. */\n       tree oldarg, newarg;\n-      for (oldarg = DECL_ARGUMENTS(olddecl), newarg = DECL_ARGUMENTS(newdecl);\n-           oldarg && newarg;\n-           oldarg = DECL_CHAIN(oldarg), newarg = DECL_CHAIN(newarg))\n+      for (oldarg = DECL_ARGUMENTS (olddecl),\n+\t   newarg = DECL_ARGUMENTS (newdecl);\n+\t   oldarg && newarg;\n+\t   oldarg = DECL_CHAIN (oldarg), newarg = DECL_CHAIN (newarg))\n \t{\n           DECL_ATTRIBUTES (newarg)\n \t    = (*targetm.merge_decl_attributes) (oldarg, newarg);\n@@ -3062,6 +3064,62 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)\n \t\t      \"earlier declaration\");\n \t    }\n           DECL_ATTRIBUTES (oldarg) = DECL_ATTRIBUTES (newarg);\n+\t  /* Merge names for std::meta::has_identifier and\n+\t     std::meta::{,u8}identifier_of purposes.  If they are different\n+\t     and both oldarg and newarg are named, add flag to force that\n+\t     std::meta::has_identifier returns false.  If one is named and\n+\t     one is unnamed, if neither is a olddecl nor newdecl is definition,\n+\t     propagate DECL_NAME to both.  Otherwise stash the old name into\n+\t     \"old parm name\" artificial attribute.  */\n+\t  if (flag_reflection && DECL_NAME (oldarg) != DECL_NAME (newarg))\n+\t    {\n+\t      if (DECL_NAME (oldarg) && DECL_NAME (newarg))\n+\t\t{\n+\t\t  /* Different names.  */\n+\t\t  MULTIPLE_NAMES_PARM_P (oldarg) = 1;\n+\t\t  MULTIPLE_NAMES_PARM_P (newarg) = 1;\n+\t\t}\n+\t      else if (!new_defines_function\n+\t\t       && types_match\n+\t\t       && DECL_INITIAL (olddecl) == NULL_TREE)\n+\t\t{\n+\t\t  /* For 2 non-definitions with matching types,\n+\t\t     one is named and one unnamed, propagate name\n+\t\t     to both.  */\n+\t\t  if (DECL_NAME (oldarg))\n+\t\t    DECL_NAME (newarg) = DECL_NAME (oldarg);\n+\t\t  else\n+\t\t    DECL_NAME (oldarg) = DECL_NAME (newarg);\n+\t\t}\n+\t      /* Depending on which PARM_DECL we'll keep, look at the other\n+\t\t PARM_DECL's name.  */\n+\t      else if (tree name = ((new_defines_function || !types_match)\n+\t\t\t\t    ? DECL_NAME (oldarg) : DECL_NAME (newarg)))\n+\t\t{\n+\t\t  tree opn = lookup_attribute (\"old parm name\",\n+\t\t\t\t\t       DECL_ATTRIBUTES (oldarg));\n+\t\t  if (opn)\n+\t\t    {\n+\t\t      if (TREE_VALUE (TREE_VALUE (opn)) == name)\n+\t\t\t/* Name already in \"old parm name\" attribute.  */;\n+\t\t      else\n+\t\t\t{\n+\t\t\t  /* Different names.  */\n+\t\t\t  MULTIPLE_NAMES_PARM_P (oldarg) = 1;\n+\t\t\t  MULTIPLE_NAMES_PARM_P (newarg) = 1;\n+\t\t\t}\n+\t\t    }\n+\t\t  else\n+\t\t    {\n+\t\t      /* Save name into attribute.  */\n+\t\t      DECL_ATTRIBUTES (newarg)\n+\t\t\t= tree_cons (get_identifier (\"old parm name\"),\n+\t\t\t\t     tree_cons (NULL_TREE, name, NULL_TREE),\n+\t\t\t\t     DECL_ATTRIBUTES (newarg));\n+\t\t      DECL_ATTRIBUTES (oldarg) = DECL_ATTRIBUTES (newarg);\n+\t\t    }\n+\t\t}\n+\t    }\n \t}\n \n       if (DECL_TEMPLATE_INSTANTIATION (olddecl)\n@@ -3159,6 +3217,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)\n \t  if (tree contracts = DECL_CONTRACTS (newdecl))\n \t    remap_contracts (olddecl, newdecl, contracts, true);\n \n+\t  /* Mark the old PARM_DECLs in case std::meta::parameters_of has\n+\t     been called on the old declaration and reflections of those\n+\t     arguments are held across this point and used later.\n+\t     Such PARM_DECLs are no longer present in\n+\t     DECL_ARGUMENTS (DECL_CONTEXT (oldarg)) chain.  */\n+\t  for (tree oldarg = DECL_ARGUMENTS (olddecl);\n+\t       oldarg; oldarg = DECL_CHAIN (oldarg))\n+\t    OLD_PARM_DECL_P (oldarg) = 1;\n+\n \t  /* These need to be copied so that the names are available.\n \t     Note that if the types do match, we'll preserve inline\n \t     info and other bits, but if not, we won't.  */\n@@ -5329,6 +5396,7 @@ initialize_predefined_identifiers (void)\n     {\"heap []\", &heap_vec_identifier, cik_normal},\n     {\"omp\", &omp_identifier, cik_normal},\n     {\"internal \", &internal_identifier, cik_normal},\n+    {\"annotation \", &annotation_identifier, cik_normal},\n     {NULL, NULL, cik_normal}\n   };\n \n@@ -5511,6 +5579,15 @@ cxx_init_decl_processing (void)\n   /* Create the `std' namespace.  */\n   push_namespace (get_identifier (\"std\"));\n   std_node = current_namespace;\n+  if (flag_reflection)\n+    {\n+      /* Note that we haven't initialized void_type_node yet, so\n+\t std_meta_node will be initially typeless; its type will be\n+\t set a little later in init_reflection.  */\n+      push_namespace (get_identifier (\"meta\"), /*inline*/false);\n+      std_meta_node = current_namespace;\n+      pop_namespace ();\n+    }\n   pop_namespace ();\n \n   flag_noexcept_type = (cxx_dialect >= cxx17);\n@@ -5562,6 +5639,13 @@ cxx_init_decl_processing (void)\n       set_call_expr_flags (decl, ECF_NOTHROW | ECF_LEAF);\n     }\n \n+  decl\n+    = add_builtin_function (\"__builtin_is_string_literal\",\n+\t\t\t    bool_vaftype,\n+\t\t\t    CP_BUILT_IN_IS_STRING_LITERAL,\n+\t\t\t    BUILT_IN_FRONTEND, NULL, NULL_TREE);\n+  set_call_expr_flags (decl, ECF_CONST | ECF_NOTHROW | ECF_LEAF);\n+\n   integer_two_node = build_int_cst (NULL_TREE, 2);\n \n   /* Guess at the initial static decls size.  */\n@@ -5692,6 +5776,9 @@ cxx_init_decl_processing (void)\n   if (modules_p ())\n     init_modules (parse_in);\n \n+  if (flag_reflection)\n+    init_reflection ();\n+\n   make_fname_decl = cp_make_fname_decl;\n   start_fname_decls ();\n \n@@ -7219,6 +7306,10 @@ maybe_commonize_var (tree decl)\n   if (DECL_ARTIFICIAL (decl) && !DECL_DECOMPOSITION_P (decl))\n     return;\n \n+  /* These are not output at all.  */\n+  if (consteval_only_p (decl))\n+    return;\n+\n   /* Static data in a function with comdat linkage also has comdat\n      linkage.  */\n   if ((TREE_STATIC (decl)\n@@ -8576,6 +8667,16 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)\n \t  init = NULL_TREE;\n \t}\n     }\n+  else if (!init && REFLECTION_TYPE_P (type))\n+    {\n+      /* [dcl.init.general]: To default-initialize an object of type\n+\t std::meta::info means that the object is zero-initialized.  */\n+      DECL_INITIAL (decl)\n+\t= build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);\n+      DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;\n+      TREE_CONSTANT (decl) = true;\n+      init = NULL_TREE;\n+    }\n   else\n     {\n       if (CLASS_TYPE_P (core_type = strip_array_types (type))\n@@ -8695,6 +8796,14 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)\n   if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))\n     return;\n \n+  /* Don't output reflection variables.  */\n+  if (consteval_only_p (decl))\n+    {\n+      /* Disable assemble_variable.  */\n+      DECL_EXTERNAL (decl) = true;\n+      return;\n+    }\n+\n   /* We defer emission of local statics until the corresponding\n      DECL_EXPR is expanded.  But with constexpr its function might never\n      be expanded, so go ahead and tell cgraph about the variable now.  */\n@@ -9742,6 +9851,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,\n \t    }\n \t}\n \n+      /* Detect stuff like 'info r = ^^int;' outside a manifestly\n+\t constant-evaluated context.  */\n+      check_out_of_consteval_use (decl);\n+\n       /* If this is a local variable that will need a mangled name,\n \t register it now.  We must do this before processing the\n \t initializer for the variable, since the initialization might\n@@ -9750,7 +9863,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,\n \t variable.  */\n       if (DECL_FUNCTION_SCOPE_P (decl)\n \t  && TREE_STATIC (decl)\n-\t  && !DECL_ARTIFICIAL (decl))\n+\t  && !DECL_ARTIFICIAL (decl)\n+\t  && !consteval_only_p (decl))\n \t{\n \t  /* The variable holding an anonymous union will have had its\n \t     discriminator set in finish_anon_union, after which it's\n@@ -10279,7 +10393,7 @@ get_tuple_size (tree type)\n   inst = complete_type (inst);\n   if (inst == error_mark_node\n       || !COMPLETE_TYPE_P (inst)\n-      || !CLASS_TYPE_P (type))\n+      || !CLASS_TYPE_P (inst))\n     return NULL_TREE;\n   tree val = lookup_qualified_name (inst, value_identifier,\n \t\t\t\t    LOOK_want::NORMAL, /*complain*/false);\n@@ -12556,6 +12670,8 @@ grokfndecl (tree ctype,\n   if (DECL_CONSTRUCTOR_P (decl) && !grok_ctor_properties (ctype, decl))\n     return NULL_TREE;\n \n+  check_consteval_only_fn (decl);\n+\n   if (ctype == NULL_TREE || check)\n     return decl;\n \n@@ -18351,6 +18467,8 @@ xref_basetypes (tree ref, tree base_list)\n   unsigned max_vbases = 0; /* Maximum direct & indirect virtual bases.  */\n   unsigned max_bases = 0;  /* Maximum direct bases.  */\n   unsigned max_dvbases = 0; /* Maximum direct virtual bases.  */\n+  /* Highest direct base index with annotations.  */\n+  unsigned max_annotated_base = 0;\n   int i;\n   tree default_access;\n   tree igo_prev; /* Track Inheritance Graph Order.  */\n@@ -18388,6 +18506,8 @@ xref_basetypes (tree ref, tree base_list)\n       else\n \t{\n \t  max_bases++;\n+\t  if (TREE_CODE (TREE_PURPOSE (*basep)) == TREE_LIST)\n+\t    max_annotated_base = max_bases;\n \t  if (TREE_TYPE (*basep))\n \t    max_dvbases++;\n \t  if (CLASS_TYPE_P (basetype))\n@@ -18416,7 +18536,8 @@ xref_basetypes (tree ref, tree base_list)\n \n   if (max_bases)\n     {\n-      vec_alloc (BINFO_BASE_ACCESSES (binfo), max_bases);\n+      vec_alloc (BINFO_BASE_ACCESSES (binfo), max_bases + max_annotated_base);\n+      BINFO_BASE_ACCESSES (binfo)->quick_grow (max_bases + max_annotated_base);\n       /* A C++98 POD cannot have base classes.  */\n       CLASSTYPE_NON_LAYOUT_POD_P (ref) = true;\n \n@@ -18446,6 +18567,30 @@ xref_basetypes (tree ref, tree base_list)\n   for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))\n     {\n       tree access = TREE_PURPOSE (base_list);\n+      tree annotations = NULL_TREE;\n+      if (TREE_CODE (access) == TREE_LIST)\n+\t{\n+\t  annotations = TREE_VALUE (access);\n+\t  access = TREE_PURPOSE (access);\n+\t  for (tree *d = &annotations; *d; )\n+\t    {\n+\t      if (annotation_p (*d))\n+\t\t{\n+\t\t  tree name = get_attribute_name (*d);\n+\t\t  tree args = TREE_VALUE (*d);\n+\t\t  const attribute_spec *as\n+\t\t    = lookup_attribute_spec (TREE_PURPOSE (*d));\n+\t\t  bool no_add_attrs = false;\n+\t\t  as->handler (&binfo, name, args, 0, &no_add_attrs);\n+\t\t  if (no_add_attrs)\n+\t\t    {\n+\t\t      *d = TREE_CHAIN (*d);\n+\t\t      continue;\n+\t\t    }\n+\t\t}\n+\t      d = &TREE_CHAIN (*d);\n+\t    }\n+\t}\n       int via_virtual = TREE_TYPE (base_list) != NULL_TREE;\n       tree basetype = TREE_VALUE (base_list);\n \n@@ -18512,8 +18657,12 @@ xref_basetypes (tree ref, tree base_list)\n       if (!BINFO_INHERITANCE_CHAIN (base_binfo))\n \tBINFO_INHERITANCE_CHAIN (base_binfo) = binfo;\n \n+      unsigned len;\n+      len = BINFO_N_BASE_BINFOS (binfo);\n       BINFO_BASE_APPEND (binfo, base_binfo);\n-      BINFO_BASE_ACCESS_APPEND (binfo, access);\n+      BINFO_BASE_ACCESS (binfo, len) = access;\n+      if (len < max_annotated_base)\n+\tBINFO_BASE_ACCESS (binfo, max_bases + len) = annotations;\n       continue;\n \n     dropped_base:\n@@ -18529,6 +18678,17 @@ xref_basetypes (tree ref, tree base_list)\n \t  -= vec_safe_length (CLASSTYPE_VBASECLASSES (basetype));\n     }\n \n+  unsigned len = BINFO_N_BASE_BINFOS (binfo);\n+  if (len < max_bases)\n+    {\n+      if (len && max_annotated_base)\n+\tmemmove (&BINFO_BASE_ACCESS (binfo, len),\n+\t\t &BINFO_BASE_ACCESS (binfo, max_bases),\n+\t\t MIN (max_annotated_base, len) * sizeof (tree));\n+      BINFO_BASE_ACCESSES (binfo)->truncate (len + MIN (max_annotated_base,\n+\t\t\t\t\t\t\tlen));\n+    }\n+\n   if (CLASSTYPE_VBASECLASSES (ref)\n       && max_vbases == 0)\n     vec_free (CLASSTYPE_VBASECLASSES (ref));\n@@ -18798,6 +18958,8 @@ finish_enum_value_list (tree enumtype)\n   tree minnode, maxnode;\n   tree t;\n \n+  ENUM_BEING_DEFINED_P (enumtype) = 0;\n+\n   bool fixed_underlying_type_p\n     = ENUM_UNDERLYING_TYPE (enumtype) != NULL_TREE;\n \ndiff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc\nindex 8ec9740c8a9..25daf43945b 100644\n--- a/gcc/cp/decl2.cc\n+++ b/gcc/cp/decl2.cc\n@@ -1472,6 +1472,11 @@ is_late_template_attribute (tree attr, tree decl)\n     = lookup_attribute_spec (TREE_PURPOSE (attr));\n   tree arg;\n \n+  /* Handle all annotations as late, so that they aren't incorrectly\n+     reordered if some have dependent expressions and others don't.  */\n+  if (annotation_p (attr))\n+    return true;\n+\n   if (!spec)\n     /* Unknown attribute.  */\n     return false;\n@@ -1747,6 +1752,10 @@ cp_check_const_attributes (tree attributes)\n       if (cxx_contract_attribute_p (attr))\n \tcontinue;\n \n+      /* Annotation arguments are handled in handle_annotation_attribute.  */\n+      if (annotation_p (attr))\n+\tcontinue;\n+\n       tree arg;\n       /* As we implement alignas using gnu::aligned attribute and\n \t alignas argument is a constant expression, force manifestly\n@@ -2457,6 +2466,10 @@ maybe_make_one_only (tree decl)\n   if (! flag_weak)\n     return;\n \n+  /* These are not to be output.  */\n+  if (consteval_only_p (decl))\n+    return;\n+\n   /* We can't set DECL_COMDAT on functions, or cp_finish_file will think\n      we can get away with not emitting them if they aren't used.  We need\n      to for variables so that cp_finish_decl will update their linkage,\n@@ -2613,6 +2626,10 @@ var_finalized_p (tree var)\n void\n mark_needed (tree decl)\n {\n+  /* These are not to be output.  */\n+  if (consteval_only_p (decl))\n+    return;\n+\n   TREE_USED (decl) = 1;\n   if (TREE_CODE (decl) == FUNCTION_DECL)\n     {\n@@ -2831,7 +2848,7 @@ min_vis_r (tree *tp, int *walk_subtrees, void *data)\n /* walk_tree helper function for expr_visibility.  */\n \n static tree\n-min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data)\n+min_vis_expr_r (tree *tp, int *walk_subtrees, void *data)\n {\n   int *vis_p = (int *)data;\n   int tpvis = VISIBILITY_DEFAULT;\n@@ -2903,6 +2920,63 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data)\n       tpvis = type_visibility (DECL_CONTEXT (t));\n       break;\n \n+    case REFLECT_EXPR:\n+      tree r, c;\n+      r = REFLECT_EXPR_HANDLE (t);\n+      switch (REFLECT_EXPR_KIND (t))\n+\t{\n+\tcase REFLECT_BASE:\n+\t  /* For direct base class relationship, determine visibility\n+\t     from both D and B types.  */\n+\t  tpvis = type_visibility (BINFO_TYPE (r));\n+\t  if (tpvis > *vis_p)\n+\t    *vis_p = tpvis;\n+\t  c = r;\n+\t  /* Looping needed for multiple virtual inheritance.  */\n+\t  while (BINFO_INHERITANCE_CHAIN (c))\n+\t    c = BINFO_INHERITANCE_CHAIN (c);\n+\t  tpvis = type_visibility (BINFO_TYPE (c));\n+\t  *walk_subtrees = 0;\n+\t  break;\n+\tcase REFLECT_DATA_MEMBER_SPEC:\n+\t  /* For data member description determine visibility\n+\t     from the type.  */\n+\t  tpvis = type_visibility (TREE_VEC_ELT (r, 0));\n+\t  *walk_subtrees = 0;\n+\t  break;\n+\tcase REFLECT_PARM:\n+\t  /* For function parameter reflection determine visibility\n+\t     based on parent_of.  */\n+\t  tpvis = expr_visibility (DECL_CONTEXT (r));\n+\t  *walk_subtrees = 0;\n+\t  break;\n+\tcase REFLECT_ANNOTATION:\n+\t  /* Annotations are always local to the TU.  */\n+\t  tpvis = VISIBILITY_ANON;\n+\t  *walk_subtrees = 0;\n+\t  break;\n+\tcase REFLECT_OBJECT:\n+\t  r = get_base_address (r);\n+\t  gcc_fallthrough ();\n+\tdefault:\n+\t  if (TYPE_P (r))\n+\t    {\n+\t      tpvis = type_visibility (r);\n+\t      *walk_subtrees = 0;\n+\t      break;\n+\t    }\n+\t  if ((VAR_P (r) && decl_function_context (r))\n+\t      || TREE_CODE (r) == PARM_DECL)\n+\t    {\n+\t      /* Block scope variables are local to the TU.  */\n+\t      tpvis = VISIBILITY_ANON;\n+\t      *walk_subtrees = 0;\n+\t      break;\n+\t    }\n+\t  break;\n+\t}\n+      break;\n+\n     default:\n       break;\n     }\n@@ -4785,6 +4859,14 @@ prune_vars_needing_no_initialization (tree *vars)\n \t  continue;\n \t}\n \n+      /* Reflections are consteval-only types and we don't want them\n+\t to survive until gimplification.  */\n+      if (consteval_only_p (decl))\n+\t{\n+\t  var = &TREE_CHAIN (t);\n+\t  continue;\n+\t}\n+\n       /* This variable is going to need initialization and/or\n \t finalization, so we add it to the list.  */\n       *var = TREE_CHAIN (t);\n@@ -5133,6 +5215,12 @@ no_linkage_error (tree decl)\n     /* An imported decl is ok.  */\n     return;\n \n+  /* Metafunctions are magic and should be considered defined even though\n+     they have no bodies.  ??? This can't be checked in decl_defined_p;\n+     we'd get redefinition errors for some of our metafunctions.  */\n+  if (TREE_CODE (decl) == FUNCTION_DECL && metafunction_p (decl))\n+    return;\n+\n   tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);\n   if (t == NULL_TREE)\n     /* The type that got us on no_linkage_decls must have gotten a name for\n@@ -5807,7 +5895,9 @@ c_parse_final_cleanups (void)\n       /* Static data members are just like namespace-scope globals.  */\n       FOR_EACH_VEC_SAFE_ELT (pending_statics, i, decl)\n \t{\n-\t  if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl)\n+\t  if (consteval_only_p (decl)\n+\t      || var_finalized_p (decl)\n+\t      || DECL_REALLY_EXTERN (decl)\n \t      /* Don't write it out if we haven't seen a definition.  */\n \t      || DECL_IN_AGGR_P (decl))\n \t    continue;\n@@ -5849,6 +5939,8 @@ c_parse_final_cleanups (void)\n \t     should have synthesized it above.)  */\n \t  && !(header_module_p ()\n \t       && (DECL_DEFAULTED_FN (decl) || decl_tls_wrapper_p (decl)))\n+\t  /* Metafunctions are never defined.  */\n+\t  && !metafunction_p (decl)\n \t  /* Don't complain if the template was defined.  */\n \t  && !((DECL_TEMPLATE_INSTANTIATION (decl)\n \t\t|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))\ndiff --git a/gcc/cp/error.cc b/gcc/cp/error.cc\nindex 4e35a4fcbc2..8bb2476ee5f 100644\n--- a/gcc/cp/error.cc\n+++ b/gcc/cp/error.cc\n@@ -749,6 +749,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)\n \n     case TEMPLATE_DECL:\n     case NAMESPACE_DECL:\n+    case CONST_DECL:\n       dump_decl (pp, t, flags & ~TFF_DECL_SPECIFIERS);\n       break;\n \n@@ -877,6 +878,14 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)\n       pp_string (pp, \"std::nullptr_t\");\n       break;\n \n+    case META_TYPE:\n+      pp_string (pp, \"std::meta::info\");\n+      break;\n+\n+    case SPLICE_SCOPE:\n+      dump_expr (pp, SPLICE_SCOPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);\n+      break;\n+\n     default:\n       pp_unsupported_tree (pp, t);\n       /* Fall through.  */\n@@ -1136,6 +1145,8 @@ dump_type_prefix (cxx_pretty_printer *pp, tree t, int flags)\n     case FIXED_POINT_TYPE:\n     case NULLPTR_TYPE:\n     case PACK_INDEX_TYPE:\n+    case META_TYPE:\n+    case SPLICE_SCOPE:\n       dump_type (pp, t, flags);\n       pp->set_padding (pp_before);\n       break;\n@@ -1269,6 +1280,8 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t, int flags)\n     case FIXED_POINT_TYPE:\n     case NULLPTR_TYPE:\n     case PACK_INDEX_TYPE:\n+    case META_TYPE:\n+    case SPLICE_SCOPE:\n       break;\n \n     default:\n@@ -1615,9 +1628,14 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags)\n \ttree name = TREE_OPERAND (t, 0);\n \ttree args = TREE_OPERAND (t, 1);\n \n-\tif (!identifier_p (name))\n-\t  name = OVL_NAME (name);\n-\tdump_decl (pp, name, flags);\n+\tif (TREE_CODE (name) == SPLICE_EXPR)\n+\t  dump_expr (pp, name, flags);\n+\telse\n+\t  {\n+\t    if (!identifier_p (name))\n+\t      name = OVL_NAME (name);\n+\t    dump_decl (pp, name, flags);\n+\t  }\n \tpp_cxx_begin_template_argument_list (pp);\n \tif (args == error_mark_node)\n \t  pp_string (pp, M_(\"<template arguments error>\"));\n@@ -3311,6 +3329,27 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)\n \t}\n       break;\n \n+    case REFLECT_EXPR:\n+      {\n+\tpp_string (pp, \"^^\");\n+\ttree h = REFLECT_EXPR_HANDLE (t);\n+\tif (DECL_P (h))\n+\t  dump_decl (pp, h, flags);\n+\telse if (TYPE_P (h))\n+\t  dump_type (pp, h, flags);\n+\telse\n+\t  dump_expr (pp, h, flags);\n+\tbreak;\n+      }\n+\n+    case SPLICE_EXPR:\n+      pp_cxx_ws_string (pp, \"[:\");\n+      pp_cxx_whitespace (pp);\n+      dump_expr (pp, TREE_OPERAND (t, 0), flags);\n+      pp_cxx_whitespace (pp);\n+      pp_cxx_ws_string (pp, \":]\");\n+      break;\n+\n       /*  This list is incomplete, but should suffice for now.\n \t  It is very important that `sorry' does not call\n \t  `report_error_function'.  That could cause an infinite loop.  */\ndiff --git a/gcc/cp/init.cc b/gcc/cp/init.cc\nindex 1b7f3e6b41c..b63fca3313e 100644\n--- a/gcc/cp/init.cc\n+++ b/gcc/cp/init.cc\n@@ -178,6 +178,10 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,\n \n   if (type == error_mark_node)\n     ;\n+  else if (REFLECTION_TYPE_P (type))\n+    /* [dcl.init.general]: \"if T is std::meta::info, the object is initialized\n+       to a null reflection value\".  */\n+    init = get_null_reflection ();\n   else if (static_storage_p && zero_init_p (type))\n     /* In order to save space, we do not explicitly build initializers\n        for items that do not need them.  GCC's semantics are that\n@@ -993,6 +997,9 @@ perform_member_init (tree member, tree init, hash_set<tree> &uninitialized)\n   if (init == error_mark_node)\n     return;\n \n+  if (check_out_of_consteval_use (init))\n+    return;\n+\n   /* Effective C++ rule 12 requires that all data members be\n      initialized.  */\n   if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE)\ndiff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc\nindex c3e03afc841..e7fdb7f2e15 100644\n--- a/gcc/cp/lex.cc\n+++ b/gcc/cp/lex.cc\n@@ -85,12 +85,12 @@ cxx_finish (void)\n ovl_op_info_t ovl_op_info[2][OVL_OP_MAX] =\n   {\n     {\n-      {NULL_TREE, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0},\n-      {NULL_TREE, NULL, NULL, NOP_EXPR, OVL_OP_NOP_EXPR, 0},\n-#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS) \\\n-      {NULL_TREE, NAME, MANGLING, CODE, OVL_OP_##CODE, FLAGS},\n+      {NULL_TREE, NULL, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0},\n+      {NULL_TREE, NULL, NULL, NULL, NOP_EXPR, OVL_OP_NOP_EXPR, 0},\n+#define DEF_OPERATOR(NAME, CODE, MANGLING, FLAGS, META) \\\n+      {NULL_TREE, NAME, MANGLING, META, CODE, OVL_OP_##CODE, FLAGS},\n #define OPERATOR_TRANSITION }, {\t\t\t\\\n-      {NULL_TREE, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0},\n+      {NULL_TREE, NULL, NULL, NULL, ERROR_MARK, OVL_OP_ERROR_MARK, 0},\n #include \"operators.def\"\n     }\n   };\ndiff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc\nindex 761aae484c8..2ea515e12b9 100644\n--- a/gcc/cp/mangle.cc\n+++ b/gcc/cp/mangle.cc\n@@ -2439,6 +2439,7 @@ write_local_name (tree function, const tree local_entity,\n                                 # class member access\n      <type> ::= DT <expression> # decltype of an expression\n      <type> ::= Dn              # decltype of nullptr\n+     <type> ::= Dm\t\t# decltype of ^^int\n \n    TYPE is a type node.  */\n \n@@ -2716,6 +2717,11 @@ write_type (tree type)\n \t\t++is_builtin_type;\n \t      break;\n \n+\t    case META_TYPE:\n+\t      write_string (\"Dm\");\n+\t      ++is_builtin_type;\n+\t      break;\n+\n \t    case TYPEOF_TYPE:\n \t      sorry (\"mangling %<typeof%>, use %<decltype%> instead\");\n \t      break;\n@@ -3467,7 +3473,8 @@ write_expression (tree expr)\n     write_template_param (expr);\n   /* Handle literals.  */\n   else if (TREE_CODE_CLASS (code) == tcc_constant\n-\t   || code == CONST_DECL)\n+\t   || code == CONST_DECL\n+\t   || code == REFLECT_EXPR)\n     write_template_arg_literal (expr);\n   else if (code == EXCESS_PRECISION_EXPR\n \t   && TREE_CODE (TREE_OPERAND (expr, 0)) == REAL_CST)\n@@ -4104,6 +4111,137 @@ write_expression (tree expr)\n     }\n }\n \n+/* Non-terminal <reflection>.\n+\n+     <reflection> ::= nu\t\t\t\t# null reflection\n+\t\t  ::= vl <expression>\t\t\t# value\n+\t\t  ::= ob <expression>\t\t\t# object\n+\t\t  ::= vr <variable name>\t\t# variable\n+\t\t  ::= sb <sb name>\t\t\t# structured binding\n+\t\t  ::= fn <function encoding>\t\t# function\n+\t\t  ::= pa [ <nonnegative number> ] _ <encoding>\t# fn param\n+\t\t  ::= en <prefix> <unqualified-name>\t# enumerator\n+\t\t  ::= an [ <nonnegative number> ] _\t# annotation\n+\t\t  ::= ta <alias prefix>\t\t\t# type alias\n+\t\t  ::= ty <type>\t\t\t\t# type\n+\t\t  ::= dm <prefix> <unqualified-name>\t# ns data member\n+\t\t  ::= un <prefix> [ <nonnegative number> ] _ # unnamed bitfld\n+\t\t  ::= ct [ <prefix> ] <unqualified-name> # class template\n+\t\t  ::= ft [ <prefix> ] <unqualified-name> # function template\n+\t\t  ::= vt [ <prefix> ] <unqualified-name> # variable template\n+\t\t  ::= at [ <prefix> ] <unqualified-name> # alias template\n+\t\t  ::= co [ <prefix> ] <unqualified-name> # concept\n+\t\t  ::= na [ <prefix> ] <unqualified-name> # namespace alias\n+\t\t  ::= ns [ <prefix> ] <unqualified-name> # namespace\n+\t\t  ::= ng\t\t\t\t# ^^::\n+\t\t  ::= ba [ <nonnegative number> ] _ <type> # dir. base cls rel\n+\t\t  ::= ds <type> _ [ <unqualified-name> ] _\n+\t\t      [ <alignment number> ] _ [ <bit-width number> ] _\n+\t\t      [ n ]\t\t\t\t# data member spec  */\n+\n+static void\n+write_reflection (tree refl)\n+{\n+  char prefix[3];\n+  tree arg = reflection_mangle_prefix (refl, prefix);\n+  write_string (prefix);\n+  /* If there is no argument, nothing further needs to be mangled.  */\n+  if (arg == NULL_TREE)\n+    return;\n+  if (strcmp (prefix, \"vl\") == 0 || strcmp (prefix, \"ob\") == 0)\n+    write_expression (arg);\n+  else if (strcmp (prefix, \"vr\") == 0 || strcmp (prefix, \"sb\") == 0)\n+    write_name (arg, 0);\n+  else if (strcmp (prefix, \"fn\") == 0)\n+    write_encoding (arg);\n+  else if (strcmp (prefix, \"pa\") == 0)\n+    {\n+      tree fn = DECL_CONTEXT (arg);\n+      tree args = FUNCTION_FIRST_USER_PARM (fn);\n+      int idx = 0;\n+      while (arg != args)\n+\t{\n+\t  args = DECL_CHAIN (args);\n+\t  ++idx;\n+\t}\n+      write_compact_number (idx);\n+      write_encoding (fn);\n+    }\n+  else if (strcmp (prefix, \"en\") == 0)\n+    {\n+      write_prefix (decl_mangling_context (arg));\n+      write_unqualified_name (arg);\n+    }\n+  else if (strcmp (prefix, \"an\") == 0)\n+    write_compact_number (tree_to_uhwi (arg));\n+  else if (strcmp (prefix, \"ta\") == 0)\n+    {\n+      arg = TYPE_NAME (arg);\n+      write_prefix (arg);\n+    }\n+  else if (strcmp (prefix, \"ty\") == 0)\n+    write_type (arg);\n+  else if (strcmp (prefix, \"dm\") == 0)\n+    {\n+      write_prefix (decl_mangling_context (arg));\n+      write_unqualified_name (arg);\n+    }\n+  else if (strcmp (prefix, \"un\") == 0)\n+    {\n+      tree ctx = DECL_CONTEXT (arg);\n+      int idx = 0;\n+      for (tree f = TYPE_FIELDS (ctx); f; f = DECL_CHAIN (f))\n+\tif (f == arg)\n+\t  break;\n+\telse if (TREE_CODE (f) == FIELD_DECL && DECL_UNNAMED_BIT_FIELD (f))\n+\t  ++idx;\n+      write_prefix (decl_mangling_context (arg));\n+      write_compact_number (idx);\n+    }\n+  else if (strcmp (prefix, \"ct\") == 0\n+\t   || strcmp (prefix, \"ft\") == 0\n+\t   || strcmp (prefix, \"vt\") == 0\n+\t   || strcmp (prefix, \"at\") == 0\n+\t   || strcmp (prefix, \"co\") == 0\n+\t   || strcmp (prefix, \"na\") == 0\n+\t   || strcmp (prefix, \"ns\") == 0)\n+    {\n+      write_prefix (decl_mangling_context (arg));\n+      write_unqualified_name (arg);\n+    }\n+  else if (strcmp (prefix, \"ba\") == 0)\n+    {\n+      gcc_assert (TREE_CODE (arg) == TREE_BINFO);\n+      tree c = arg, base_binfo;\n+      while (BINFO_INHERITANCE_CHAIN (c))\n+\tc = BINFO_INHERITANCE_CHAIN (c);\n+\n+      unsigned idx;\n+      for (idx = 0; BINFO_BASE_ITERATE (c, idx, base_binfo); idx++)\n+\tif (base_binfo == arg)\n+\t  break;\n+      write_compact_number (idx);\n+      write_type (BINFO_TYPE (c));\n+    }\n+  else if (strcmp (prefix, \"ds\") == 0)\n+    {\n+      gcc_assert (TREE_CODE (arg) == TREE_VEC);\n+      write_type (TREE_VEC_ELT (arg, 0));\n+      write_char ('_');\n+      if (TREE_VEC_ELT (arg, 1))\n+\twrite_unqualified_id (TREE_VEC_ELT (arg, 1));\n+      write_char ('_');\n+      if (TREE_VEC_ELT (arg, 2))\n+\twrite_number (tree_to_shwi (TREE_VEC_ELT (arg, 2)), 0, 10);\n+      write_char ('_');\n+      if (TREE_VEC_ELT (arg, 3))\n+\twrite_number (tree_to_shwi (TREE_VEC_ELT (arg, 3)), 0, 10);\n+      write_char ('_');\n+      if (integer_nonzerop (TREE_VEC_ELT (arg, 4)))\n+\twrite_char ('n');\n+    }\n+}\n+\n /* Literal subcase of non-terminal <template-arg>.\n \n      \"Literal arguments, e.g. \"A<42L>\", are encoded with their type\n@@ -4192,6 +4330,10 @@ write_template_arg_literal (const tree value)\n \t  break;\n \t}\n \n+      case REFLECT_EXPR:\n+\twrite_reflection (value);\n+\tbreak;\n+\n       default:\n \tgcc_unreachable ();\n       }\n@@ -4273,7 +4415,8 @@ write_template_arg (tree node)\n     write_template_template_arg (node);\n   else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)\n \t   || code == CONST_DECL\n-\t   || null_member_pointer_value_p (node))\n+\t   || null_member_pointer_value_p (node)\n+\t   || code == REFLECT_EXPR)\n     write_template_arg_literal (node);\n   else if (code == EXCESS_PRECISION_EXPR\n \t   && TREE_CODE (TREE_OPERAND (node, 0)) == REAL_CST)\ndiff --git a/gcc/cp/module.cc b/gcc/cp/module.cc\nindex b0755e58d4b..02157efa2d0 100644\n--- a/gcc/cp/module.cc\n+++ b/gcc/cp/module.cc\n@@ -9748,6 +9748,10 @@ trees_out::type_node (tree type)\n \t    wu (nunits.coeffs[ix]);\n \t}\n       break;\n+\n+    case META_TYPE:\n+      /* No additional data.  */\n+      break;\n     }\n \n   tree_node (TYPE_ATTRIBUTES (type));\n@@ -10577,6 +10581,11 @@ trees_in::tree_node (bool is_use)\n \t\tres = build_vector_type (res, nunits);\n \t    }\n \t    break;\n+\n+\t  case META_TYPE:\n+\t    if (!get_overrun ())\n+\t      res = meta_info_type_node;\n+\t    break;\n \t  }\n \n \t/* In the exporting TU, a derived type with attributes was built by\ndiff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc\nindex 4c07fd40f64..769228f0aa0 100644\n--- a/gcc/cp/name-lookup.cc\n+++ b/gcc/cp/name-lookup.cc\n@@ -1569,6 +1569,13 @@ name_lookup::adl_type (tree type)\n       adl_type (TYPE_PTRMEM_POINTED_TO_TYPE (type));\n       return;\n     }\n+  else if (REFLECTION_TYPE_P (type))\n+    {\n+      /* The namespace std::meta is an associated namespace of\n+\t std::meta::info.  */\n+      adl_namespace (std_meta_node);\n+      return;\n+    }\n \n   switch (TREE_CODE (type))\n     {\n@@ -2740,7 +2747,10 @@ strip_using_decl (tree decl)\n   if (decl == NULL_TREE)\n     return NULL_TREE;\n \n-  while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))\n+  while (TREE_CODE (decl) == USING_DECL\n+\t && !DECL_DEPENDENT_P (decl)\n+\t && (LIKELY (!cp_preserve_using_decl)\n+\t     || TREE_CODE (USING_DECL_DECLS (decl)) == NAMESPACE_DECL))\n     decl = USING_DECL_DECLS (decl);\n \n   if (TREE_CODE (decl) == USING_DECL && DECL_DEPENDENT_P (decl)\n@@ -6655,6 +6665,15 @@ handle_namespace_attrs (tree ns, tree attributes)\n \t    DECL_ATTRIBUTES (ns) = tree_cons (name, args,\n \t\t\t\t\t      DECL_ATTRIBUTES (ns));\n \t}\n+      else if (annotation_p (d))\n+\t{\n+\t  const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (d));\n+\t  bool no_add_attrs = false;\n+\t  as->handler (&ns, name, args, 0, &no_add_attrs);\n+\t  if (!no_add_attrs)\n+\t    DECL_ATTRIBUTES (ns) = tree_cons (TREE_PURPOSE (d), args,\n+\t\t\t\t\t      DECL_ATTRIBUTES (ns));\n+\t}\n       else if (!attribute_ignored_p (d))\n \t{\n \t  warning (OPT_Wattributes, \"%qD attribute directive ignored\",\n@@ -6692,9 +6711,10 @@ do_namespace_alias (location_t loc, tree alias, tree name_space)\n   if (name_space == error_mark_node)\n     return;\n \n-  gcc_assert (TREE_CODE (name_space) == NAMESPACE_DECL);\n-\n-  name_space = ORIGINAL_NAMESPACE (name_space);\n+  if (TREE_CODE (name_space) == NAMESPACE_DECL)\n+    name_space = ORIGINAL_NAMESPACE (name_space);\n+  else\n+    gcc_assert (TREE_CODE (name_space) == SPLICE_EXPR);\n \n   /* Build the alias.  */\n   alias = build_lang_decl_loc (loc, NAMESPACE_DECL, alias, void_type_node);\n@@ -7504,7 +7524,9 @@ lookup_qualified_name (tree scope, tree name, LOOK_want want, bool complain)\n \n \t  /* If we have a known type overload, pull it out.  This can happen\n \t     for using decls.  */\n-\t  if (TREE_CODE (t) == OVERLOAD && TREE_TYPE (t) != unknown_type_node)\n+\t  if (TREE_CODE (t) == OVERLOAD\n+\t      && TREE_TYPE (t) != unknown_type_node\n+\t      && LIKELY (!cp_preserve_using_decl))\n \t    t = OVL_FUNCTION (t);\n \t}\n     }\n@@ -9126,6 +9148,8 @@ finish_using_directive (tree target, tree attribs)\n \t\tdiagnosed = true;\n \t      }\n \t  }\n+\telse if (annotation_p (a))\n+\t  error (\"annotation on using directive\");\n \telse if (!attribute_ignored_p (a))\n \t  warning (OPT_Wattributes, \"%qD attribute directive ignored\", name);\n       }\ndiff --git a/gcc/cp/operators.def b/gcc/cp/operators.def\nindex 17601d31207..8d72cb49b14 100644\n--- a/gcc/cp/operators.def\n+++ b/gcc/cp/operators.def\n@@ -50,6 +50,12 @@ along with GCC; see the file COPYING3.  If not see\n      ovl_op_flags bits.  Postincrement and postdecrement operators are\n      marked as binary.\n \n+   META_NAME\n+\n+     The name of std::meta::operators enumerator corresponding to the\n+     operator, without the \"op_\" prefix or NULL if there is no\n+     corresponding enumerator.\n+\n    Before including this file, you should define DEF_OPERATOR\n    to take these arguments.\n \n@@ -63,83 +69,88 @@ along with GCC; see the file COPYING3.  If not see\n    FLAGS (OVL_OP_FLAG_BINARY).  */\n \n #ifndef DEF_ASSN_OPERATOR\n-#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING) \\\n-  DEF_OPERATOR(NAME, CODE, MANGLING, OVL_OP_FLAG_BINARY)\n+#define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, META) \\\n+  DEF_OPERATOR(NAME, CODE, MANGLING, OVL_OP_FLAG_BINARY, META)\n #endif\n \n /* Memory allocation operators.  ARITY has special meaning. */\n-DEF_OPERATOR (\"new\", NEW_EXPR, \"nw\", OVL_OP_FLAG_ALLOC)\n+DEF_OPERATOR (\"new\", NEW_EXPR, \"nw\", OVL_OP_FLAG_ALLOC, \"new\")\n DEF_OPERATOR (\"new []\", VEC_NEW_EXPR, \"na\",\n-\t      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC)\n+\t      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_VEC, \"array_new\")\n DEF_OPERATOR (\"delete\", DELETE_EXPR, \"dl\",\n-\t      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE)\n+\t      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE, \"delete\")\n DEF_OPERATOR (\"delete []\", VEC_DELETE_EXPR, \"da\",\n-\t      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE | OVL_OP_FLAG_VEC)\n+\t      OVL_OP_FLAG_ALLOC | OVL_OP_FLAG_DELETE\n+\t      | OVL_OP_FLAG_VEC, \"array_delete\")\n \n /* Unary operators.  */\n-DEF_OPERATOR (\"+\", UNARY_PLUS_EXPR, \"ps\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"-\", NEGATE_EXPR, \"ng\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"&\", ADDR_EXPR, \"ad\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"*\", INDIRECT_REF, \"de\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"~\", BIT_NOT_EXPR, \"co\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"!\", TRUTH_NOT_EXPR, \"nt\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"++\", PREINCREMENT_EXPR, \"pp\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"--\", PREDECREMENT_EXPR, \"mm\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"->\", COMPONENT_REF, \"pt\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"sizeof\", SIZEOF_EXPR, \"sz\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"co_await\", CO_AWAIT_EXPR, \"aw\", OVL_OP_FLAG_UNARY)\n+DEF_OPERATOR (\"+\", UNARY_PLUS_EXPR, \"ps\", OVL_OP_FLAG_UNARY, \"plus\")\n+DEF_OPERATOR (\"-\", NEGATE_EXPR, \"ng\", OVL_OP_FLAG_UNARY, \"minus\")\n+DEF_OPERATOR (\"&\", ADDR_EXPR, \"ad\", OVL_OP_FLAG_UNARY, \"ampersand\")\n+DEF_OPERATOR (\"*\", INDIRECT_REF, \"de\", OVL_OP_FLAG_UNARY, \"star\")\n+DEF_OPERATOR (\"~\", BIT_NOT_EXPR, \"co\", OVL_OP_FLAG_UNARY, \"tilde\")\n+DEF_OPERATOR (\"!\", TRUTH_NOT_EXPR, \"nt\", OVL_OP_FLAG_UNARY, \"exclamation\")\n+DEF_OPERATOR (\"++\", PREINCREMENT_EXPR, \"pp\", OVL_OP_FLAG_UNARY, \"plus_plus\")\n+DEF_OPERATOR (\"--\", PREDECREMENT_EXPR, \"mm\", OVL_OP_FLAG_UNARY, \"minus_minus\")\n+DEF_OPERATOR (\"->\", COMPONENT_REF, \"pt\", OVL_OP_FLAG_UNARY, \"arrow\")\n+DEF_OPERATOR (\"sizeof\", SIZEOF_EXPR, \"sz\", OVL_OP_FLAG_UNARY, NULL)\n+DEF_OPERATOR (\"co_await\", CO_AWAIT_EXPR, \"aw\", OVL_OP_FLAG_UNARY, \"co_await\")\n \n /* These are extensions.  */\n-DEF_OPERATOR (\"alignof\", ALIGNOF_EXPR, \"az\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"__imag__\", IMAGPART_EXPR, \"v18__imag__\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (\"__real__\", REALPART_EXPR, \"v18__real__\", OVL_OP_FLAG_UNARY)\n+DEF_OPERATOR (\"alignof\", ALIGNOF_EXPR, \"az\", OVL_OP_FLAG_UNARY, NULL)\n+DEF_OPERATOR (\"__imag__\", IMAGPART_EXPR, \"v18__imag__\", OVL_OP_FLAG_UNARY,\n+\t      NULL)\n+DEF_OPERATOR (\"__real__\", REALPART_EXPR, \"v18__real__\", OVL_OP_FLAG_UNARY,\n+\t      NULL)\n \n /* Binary operators.  */\n-DEF_OPERATOR (\"+\", PLUS_EXPR, \"pl\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"-\", MINUS_EXPR, \"mi\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"*\", MULT_EXPR, \"ml\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"/\", TRUNC_DIV_EXPR, \"dv\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"%\", TRUNC_MOD_EXPR, \"rm\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"&\", BIT_AND_EXPR, \"an\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"|\", BIT_IOR_EXPR, \"or\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"^\", BIT_XOR_EXPR, \"eo\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"<<\", LSHIFT_EXPR, \"ls\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\">>\", RSHIFT_EXPR, \"rs\", OVL_OP_FLAG_BINARY)\n+DEF_OPERATOR (\"+\", PLUS_EXPR, \"pl\", OVL_OP_FLAG_BINARY, \"plus\")\n+DEF_OPERATOR (\"-\", MINUS_EXPR, \"mi\", OVL_OP_FLAG_BINARY, \"minus\")\n+DEF_OPERATOR (\"*\", MULT_EXPR, \"ml\", OVL_OP_FLAG_BINARY, \"star\")\n+DEF_OPERATOR (\"/\", TRUNC_DIV_EXPR, \"dv\", OVL_OP_FLAG_BINARY, \"slash\")\n+DEF_OPERATOR (\"%\", TRUNC_MOD_EXPR, \"rm\", OVL_OP_FLAG_BINARY, \"percent\")\n+DEF_OPERATOR (\"&\", BIT_AND_EXPR, \"an\", OVL_OP_FLAG_BINARY, \"ampersand\")\n+DEF_OPERATOR (\"|\", BIT_IOR_EXPR, \"or\", OVL_OP_FLAG_BINARY, \"pipe\")\n+DEF_OPERATOR (\"^\", BIT_XOR_EXPR, \"eo\", OVL_OP_FLAG_BINARY, \"caret\")\n+DEF_OPERATOR (\"<<\", LSHIFT_EXPR, \"ls\", OVL_OP_FLAG_BINARY, \"less_less\")\n+DEF_OPERATOR (\">>\", RSHIFT_EXPR, \"rs\", OVL_OP_FLAG_BINARY, \"greater_greater\")\n \n /* defaultable_fn_check relies on the ordering of the comparison operators.  */\n-DEF_OPERATOR (\"==\", EQ_EXPR, \"eq\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"!=\", NE_EXPR, \"ne\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"<\", LT_EXPR, \"lt\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\">\", GT_EXPR, \"gt\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"<=\", LE_EXPR, \"le\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\">=\", GE_EXPR, \"ge\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"<=>\", SPACESHIP_EXPR, \"ss\", OVL_OP_FLAG_BINARY)\n-\n-DEF_OPERATOR (\"&&\", TRUTH_ANDIF_EXPR, \"aa\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"||\", TRUTH_ORIF_EXPR, \"oo\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\",\", COMPOUND_EXPR, \"cm\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"->*\", MEMBER_REF, \"pm\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\".*\", DOTSTAR_EXPR, \"ds\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"[]\", ARRAY_REF, \"ix\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"++\", POSTINCREMENT_EXPR, \"pp\", OVL_OP_FLAG_BINARY)\n-DEF_OPERATOR (\"--\", POSTDECREMENT_EXPR, \"mm\", OVL_OP_FLAG_BINARY)\n+DEF_OPERATOR (\"==\", EQ_EXPR, \"eq\", OVL_OP_FLAG_BINARY, \"equals_equals\")\n+DEF_OPERATOR (\"!=\", NE_EXPR, \"ne\", OVL_OP_FLAG_BINARY, \"exclamation_equals\")\n+DEF_OPERATOR (\"<\", LT_EXPR, \"lt\", OVL_OP_FLAG_BINARY, \"less\")\n+DEF_OPERATOR (\">\", GT_EXPR, \"gt\", OVL_OP_FLAG_BINARY, \"greater\")\n+DEF_OPERATOR (\"<=\", LE_EXPR, \"le\", OVL_OP_FLAG_BINARY, \"less_equals\")\n+DEF_OPERATOR (\">=\", GE_EXPR, \"ge\", OVL_OP_FLAG_BINARY, \"greater_equals\")\n+DEF_OPERATOR (\"<=>\", SPACESHIP_EXPR, \"ss\", OVL_OP_FLAG_BINARY, \"spaceship\")\n+\n+DEF_OPERATOR (\"&&\", TRUTH_ANDIF_EXPR, \"aa\", OVL_OP_FLAG_BINARY,\n+\t      \"ampersand_ampersand\")\n+DEF_OPERATOR (\"||\", TRUTH_ORIF_EXPR, \"oo\", OVL_OP_FLAG_BINARY, \"pipe_pipe\")\n+DEF_OPERATOR (\",\", COMPOUND_EXPR, \"cm\", OVL_OP_FLAG_BINARY, \"comma\")\n+DEF_OPERATOR (\"->*\", MEMBER_REF, \"pm\", OVL_OP_FLAG_BINARY, \"arrow_star\")\n+DEF_OPERATOR (\".*\", DOTSTAR_EXPR, \"ds\", OVL_OP_FLAG_BINARY, NULL)\n+DEF_OPERATOR (\"[]\", ARRAY_REF, \"ix\", OVL_OP_FLAG_BINARY, \"square_brackets\")\n+DEF_OPERATOR (\"++\", POSTINCREMENT_EXPR, \"pp\", OVL_OP_FLAG_BINARY, \"plus_plus\")\n+DEF_OPERATOR (\"--\", POSTDECREMENT_EXPR, \"mm\", OVL_OP_FLAG_BINARY,\n+\t      \"minus_minus\")\n \n /* Miscellaneous.  */\n-DEF_OPERATOR (\"?:\", COND_EXPR, \"qu\", OVL_OP_FLAG_NONE)\n-DEF_OPERATOR (\"()\", CALL_EXPR, \"cl\", OVL_OP_FLAG_NONE)\n+DEF_OPERATOR (\"?:\", COND_EXPR, \"qu\", OVL_OP_FLAG_NONE, NULL)\n+DEF_OPERATOR (\"()\", CALL_EXPR, \"cl\", OVL_OP_FLAG_NONE, \"parentheses\")\n \n /* Operators needed for mangling.  */\n-DEF_OPERATOR (NULL, CAST_EXPR, \"cv\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (NULL, DYNAMIC_CAST_EXPR, \"dc\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (NULL, REINTERPRET_CAST_EXPR, \"rc\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (NULL, CONST_CAST_EXPR, \"cc\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (NULL, STATIC_CAST_EXPR, \"sc\", OVL_OP_FLAG_UNARY)\n-DEF_OPERATOR (NULL, SCOPE_REF, \"sr\", OVL_OP_FLAG_NONE)\n-DEF_OPERATOR (NULL, EXPR_PACK_EXPANSION, \"sp\", OVL_OP_FLAG_NONE)\n-DEF_OPERATOR (NULL, UNARY_LEFT_FOLD_EXPR, \"fl\", OVL_OP_FLAG_NONE)\n-DEF_OPERATOR (NULL, UNARY_RIGHT_FOLD_EXPR, \"fr\", OVL_OP_FLAG_NONE)\n-DEF_OPERATOR (NULL, BINARY_LEFT_FOLD_EXPR, \"fL\", OVL_OP_FLAG_NONE)\n-DEF_OPERATOR (NULL, BINARY_RIGHT_FOLD_EXPR, \"fR\", OVL_OP_FLAG_NONE)\n+DEF_OPERATOR (NULL, CAST_EXPR, \"cv\", OVL_OP_FLAG_UNARY, NULL)\n+DEF_OPERATOR (NULL, DYNAMIC_CAST_EXPR, \"dc\", OVL_OP_FLAG_UNARY, NULL)\n+DEF_OPERATOR (NULL, REINTERPRET_CAST_EXPR, \"rc\", OVL_OP_FLAG_UNARY, NULL)\n+DEF_OPERATOR (NULL, CONST_CAST_EXPR, \"cc\", OVL_OP_FLAG_UNARY, NULL)\n+DEF_OPERATOR (NULL, STATIC_CAST_EXPR, \"sc\", OVL_OP_FLAG_UNARY, NULL)\n+DEF_OPERATOR (NULL, SCOPE_REF, \"sr\", OVL_OP_FLAG_NONE, NULL)\n+DEF_OPERATOR (NULL, EXPR_PACK_EXPANSION, \"sp\", OVL_OP_FLAG_NONE, NULL)\n+DEF_OPERATOR (NULL, UNARY_LEFT_FOLD_EXPR, \"fl\", OVL_OP_FLAG_NONE, NULL)\n+DEF_OPERATOR (NULL, UNARY_RIGHT_FOLD_EXPR, \"fr\", OVL_OP_FLAG_NONE, NULL)\n+DEF_OPERATOR (NULL, BINARY_LEFT_FOLD_EXPR, \"fL\", OVL_OP_FLAG_NONE, NULL)\n+DEF_OPERATOR (NULL, BINARY_RIGHT_FOLD_EXPR, \"fR\", OVL_OP_FLAG_NONE, NULL)\n \n #ifdef OPERATOR_TRANSITION\n OPERATOR_TRANSITION\n@@ -147,17 +158,17 @@ OPERATOR_TRANSITION\n #endif\n \n /* Assignment operators.  */\n-DEF_ASSN_OPERATOR (\"=\", NOP_EXPR, \"aS\")\n-DEF_ASSN_OPERATOR (\"+=\", PLUS_EXPR, \"pL\")\n-DEF_ASSN_OPERATOR (\"-=\", MINUS_EXPR, \"mI\")\n-DEF_ASSN_OPERATOR (\"*=\", MULT_EXPR, \"mL\")\n-DEF_ASSN_OPERATOR (\"/=\", TRUNC_DIV_EXPR, \"dV\")\n-DEF_ASSN_OPERATOR (\"%=\", TRUNC_MOD_EXPR, \"rM\")\n-DEF_ASSN_OPERATOR (\"&=\", BIT_AND_EXPR, \"aN\")\n-DEF_ASSN_OPERATOR (\"|=\", BIT_IOR_EXPR, \"oR\")\n-DEF_ASSN_OPERATOR (\"^=\", BIT_XOR_EXPR, \"eO\")\n-DEF_ASSN_OPERATOR (\"<<=\", LSHIFT_EXPR, \"lS\")\n-DEF_ASSN_OPERATOR (\">>=\", RSHIFT_EXPR, \"rS\")\n+DEF_ASSN_OPERATOR (\"=\", NOP_EXPR, \"aS\", \"equals\")\n+DEF_ASSN_OPERATOR (\"+=\", PLUS_EXPR, \"pL\", \"plus_equals\")\n+DEF_ASSN_OPERATOR (\"-=\", MINUS_EXPR, \"mI\", \"minus_equals\")\n+DEF_ASSN_OPERATOR (\"*=\", MULT_EXPR, \"mL\", \"star_equals\")\n+DEF_ASSN_OPERATOR (\"/=\", TRUNC_DIV_EXPR, \"dV\", \"slash_equals\")\n+DEF_ASSN_OPERATOR (\"%=\", TRUNC_MOD_EXPR, \"rM\", \"percent_equals\")\n+DEF_ASSN_OPERATOR (\"&=\", BIT_AND_EXPR, \"aN\", \"ampersand_equals\")\n+DEF_ASSN_OPERATOR (\"|=\", BIT_IOR_EXPR, \"oR\", \"pipe_equals\")\n+DEF_ASSN_OPERATOR (\"^=\", BIT_XOR_EXPR, \"eO\", \"caret_equals\")\n+DEF_ASSN_OPERATOR (\"<<=\", LSHIFT_EXPR, \"lS\", \"less_less_equals\")\n+DEF_ASSN_OPERATOR (\">>=\", RSHIFT_EXPR, \"rS\", \"greater_greater_equals\")\n \n #undef DEF_ASSN_OPERATOR\n #undef DEF_OPERATOR\ndiff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc\nindex d9c8cfada93..5521de235c2 100644\n--- a/gcc/cp/parser.cc\n+++ b/gcc/cp/parser.cc\n@@ -152,6 +152,7 @@ enum required_token {\n   RT_COMMA_CLOSE_PAREN, /* ',' or ')' */\n   RT_PRAGMA_EOL, /* end of line */\n   RT_NAME, /* identifier */\n+  RT_CLOSE_SPLICE, /* ':]' */\n \n   /* The type is CPP_KEYWORD */\n   RT_NEW, /* new */\n@@ -291,6 +292,10 @@ static FILE *cp_lexer_debug_stream;\n    sizeof, typeof, or alignof.  */\n int cp_unevaluated_operand;\n \n+/* Nonzero if we are parsing a reflect-expression and shouldn't strip\n+   using-declarations.  */\n+bool cp_preserve_using_decl;\n+\n #if ENABLE_ANALYZER\n \n namespace ana {\n@@ -2753,7 +2758,7 @@ static tree cp_parser_template_type_arg\n   (cp_parser *);\n static tree cp_parser_trailing_type_id (cp_parser *);\n static tree cp_parser_type_id_1\n-  (cp_parser *, cp_parser_flags, bool, bool, location_t *);\n+  (cp_parser *, cp_parser_flags, bool, bool, location_t *, bool *);\n static void cp_parser_type_specifier_seq\n   (cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *);\n static tree cp_parser_parameter_declaration_clause\n@@ -2854,7 +2859,7 @@ static tree cp_parser_template_parameter\n static tree cp_parser_type_parameter\n   (cp_parser *, bool *);\n static tree cp_parser_template_id\n-  (cp_parser *, bool, bool, enum tag_types, bool);\n+  (cp_parser *, bool, bool, enum tag_types, bool, tree = NULL_TREE);\n static tree cp_parser_template_id_expr\n   (cp_parser *, bool, bool, bool);\n static tree cp_parser_template_name\n@@ -3345,6 +3350,8 @@ get_required_cpp_ttype (required_token token_desc)\n       return CPP_COLON;\n     case RT_CLOSE_PAREN:\n       return CPP_CLOSE_PAREN;\n+    case RT_CLOSE_SPLICE:\n+      return CPP_CLOSE_SPLICE;\n \n     default:\n       /* Use CPP_EOF as a \"no completions possible\" code.  */\n@@ -6056,6 +6063,454 @@ cp_parser_pack_index (cp_parser *parser, tree pack)\n   return make_pack_index (pack, index);\n }\n \n+/* Return true iff the next tokens start a splice-type-specifier.\n+   If REQUIRE_TYPENAME_P, we only return true if there is a preceding\n+   typename keyword.  */\n+\n+static bool\n+cp_parser_next_tokens_start_splice_type_spec_p (cp_parser *parser,\n+\t\t\t\t\t\tbool require_typename_p)\n+{\n+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SPLICE))\n+    return !require_typename_p;\n+  return (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME)\n+\t  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_SPLICE));\n+}\n+\n+/* Return true iff the next tokens start a splice-scope-specifier.  */\n+\n+static bool\n+cp_parser_next_tokens_can_start_splice_scope_spec_p (cp_parser *parser)\n+{\n+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SPLICE))\n+    return true;\n+  return (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)\n+\t  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_SPLICE));\n+}\n+\n+/* Parse a splice-specifier.\n+\n+   splice-specifier:\n+     [: constant-expression :]\n+\n+    splice-specialization-specifier:\n+      splice-specifier < template-argument-list[opt] >\n+\n+   TEMPLATE_P is true if we've parsed the leading template keyword.\n+   TARGS_P is set to true if there is a splice-specialization-specifier.  */\n+\n+static cp_expr\n+cp_parser_splice_specifier (cp_parser *parser, bool template_p = false,\n+\t\t\t    bool *targs_p = nullptr)\n+{\n+  /* Get the location of the '[:'.  */\n+  location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;\n+\n+  /* Consume the '[:'.  */\n+  cp_lexer_consume_token (parser->lexer);\n+\n+  /* Get the location of the operand.  */\n+  location_t caret_loc = cp_lexer_peek_token (parser->lexer)->location;\n+\n+  if (!flag_reflection)\n+    {\n+      error_at (caret_loc,\n+\t\t\"reflection is only available with %<-freflection%>\");\n+      return error_mark_node;\n+    }\n+\n+  tree object_type = parser->context->object_type;\n+  /* Clear parser->context->object_type.  E.g.,\n+     struct A { static int x; };\n+     int q = A ().[: ^^x :];\n+     should be an error -- x is not a member-qualified name and isn't\n+     in scope.  */\n+  parser->context->object_type = NULL;\n+  tree expr = cp_parser_constant_expression (parser,\n+\t\t\t\t\t     /*allow_non_constant_p=*/false,\n+\t\t\t\t\t     /*non_constant_p=*/nullptr,\n+\t\t\t\t\t     /*strict_p=*/true);\n+\n+  /* Get the location of the ':]'.  */\n+  location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;\n+\n+  /* Consume the ':]'.  */\n+  if (!cp_parser_require (parser, CPP_CLOSE_SPLICE, RT_CLOSE_SPLICE))\n+    return error_mark_node;\n+\n+  /* Get the reflected operand.  */\n+  expr = splice (expr);\n+\n+  /* If the next token is a '<', it's a splice-specialization-specifier.  */\n+  if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))\n+    {\n+      /* For member access splice-specialization-specifier, try to wrap\n+\t non-dependent splice for function template into a BASELINK so\n+\t that cp_parser_template_id can handle it.  */\n+      if (object_type\n+\t  && DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (expr))\n+\t  && !dependent_type_p (object_type))\n+\t{\n+\t  tree scope = DECL_CONTEXT (OVL_FIRST (expr));\n+\t  if (scope && CLASS_TYPE_P (scope))\n+\t    {\n+\t      tree access_path = lookup_base (object_type, scope, ba_unique,\n+\t\t\t\t\t      NULL, tf_warning_or_error);\n+\t      if (access_path == error_mark_node)\n+\t\texpr = error_mark_node;\n+\t      else\n+\t\texpr\n+\t\t  = build_baselink (access_path, TYPE_BINFO (object_type),\n+\t\t\t\t    expr,\n+\t\t\t\t    IDENTIFIER_CONV_OP_P (OVL_NAME (expr))\n+\t\t\t\t    ? TREE_TYPE (OVL_NAME (expr)) : NULL_TREE);\n+\t    }\n+\t}\n+      /* Let cp_parser_template_id parse the template arguments.  */\n+      expr = cp_parser_template_id (parser, template_p,\n+\t\t\t\t    /*check_dependency_p=*/true,\n+\t\t\t\t    /*tag_type=*/none_type,\n+\t\t\t\t    /*is_declaration=*/false,\n+\t\t\t\t    expr);\n+      if (targs_p)\n+\t*targs_p = true;\n+    }\n+\n+  return cp_expr (expr, make_location (caret_loc, start_loc, finish_loc));\n+}\n+\n+/* Parse a splice-type-specifier.\n+\n+   splice-type-specifier:\n+     typename[opt] splice-specifier\n+     typename[opt] splice-specialization-specifier\n+\n+ */\n+\n+static tree\n+cp_parser_splice_type_specifier (cp_parser *parser)\n+{\n+  /* Consume the optional typename.  */\n+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))\n+    cp_lexer_consume_token (parser->lexer);\n+\n+  cp_expr expr = cp_parser_splice_specifier (parser);\n+  const location_t loc = (expr != error_mark_node\n+\t\t\t  ? expr.get_location () : input_location);\n+  tree type = expr.get_value ();\n+\n+  if (TREE_CODE (type) == TYPE_DECL)\n+    type = TREE_TYPE (type);\n+\n+  /* When we see [:T:] or [:T:]<arg> we don't know what it'll turn out\n+     to be.  */\n+  if (dependent_splice_p (type))\n+    return make_splice_scope (type, /*type_p=*/true);\n+\n+  if (!valid_splice_type_p (type))\n+    {\n+      if (!cp_parser_simulate_error (parser))\n+\terror_at (loc, \"reflection %qE not usable in a splice type\", type);\n+      type = NULL_TREE;\n+    }\n+\n+  return type;\n+}\n+\n+/* Parse a splice-expression.\n+\n+   splice-expression:\n+     splice-specifier\n+     template splice-specifier\n+     template splice-specialization-specifier\n+\n+   TEMPLATE_P is true if we've parsed the leading template keyword.\n+   ADDRESS_P is true if we are taking the address of the splice.\n+   TEMPLATE_ARG_P is true iff this splice is a template argument.\n+   MEMBER_ACCESS_P is true if this splice is used in foo.[: bar :] or\n+   foo->[: bar :] context.  */\n+\n+static tree\n+cp_parser_splice_expression (cp_parser *parser, bool template_p,\n+\t\t\t     bool address_p, bool template_arg_p,\n+\t\t\t     bool member_access_p, cp_id_kind *idk)\n+{\n+  bool targs_p = false;\n+\n+  /* E.g., [: X::x :] is a separate lookup and we shouldn't take into\n+     account any previous scopes.  */\n+  parser->scope = NULL_TREE;\n+  parser->object_scope = NULL_TREE;\n+  parser->qualifying_scope = NULL_TREE;\n+\n+  cp_expr expr = cp_parser_splice_specifier (parser, template_p, &targs_p);\n+\n+  /* And don't leave the scopes set, either.  */\n+  parser->scope = NULL_TREE;\n+  parser->object_scope = NULL_TREE;\n+  parser->qualifying_scope = NULL_TREE;\n+\n+  const location_t loc = expr.get_location ();\n+  tree t = expr.get_value ();\n+  STRIP_ANY_LOCATION_WRAPPER (t);\n+  tree unresolved = t;\n+  t = MAYBE_BASELINK_FUNCTIONS (t);\n+  t = resolve_nondeduced_context (t, tf_warning_or_error);\n+\n+  if (dependent_splice_p (t))\n+    {\n+      SET_SPLICE_EXPR_EXPRESSION_P (t);\n+      SET_SPLICE_EXPR_MEMBER_ACCESS_P (t, member_access_p);\n+      SET_SPLICE_EXPR_ADDRESS_P (t, address_p);\n+    }\n+\n+  if (error_operand_p (t))\n+    {\n+      gcc_assert (seen_error ());\n+      return error_mark_node;\n+    }\n+\n+  if (template_p)\n+    {\n+      /* [expr.prim.splice] For a splice-expression of the form template\n+\t splice-specifier, the splice-specifier shall designate a function\n+\t template.  */\n+      if (!targs_p)\n+\t{\n+\t  if (!really_overloaded_fn (t) && !dependent_splice_p (t))\n+\t    {\n+\t      auto_diagnostic_group d;\n+\t      error_at (loc, \"reflection %qE not usable in a template splice\",\n+\t\t\tt);\n+\t      inform (loc, \"only function templates are allowed here\");\n+\t      return error_mark_node;\n+\t    }\n+\t}\n+      /* [expr.prim.splice] For a splice-expression of the form\n+\t template splice-specialization-specifier, the splice-specifier of the\n+\t splice-specialization-specifier shall designate a template.  */\n+      else\n+\t{\n+\t  if (really_overloaded_fn (t)\n+\t      || get_template_info (t)\n+\t      || TREE_CODE (t) == TEMPLATE_ID_EXPR)\n+\t    /* OK */;\n+\t  else\n+\t    {\n+\t      auto_diagnostic_group d;\n+\t      error_at (loc, \"reflection %qE not usable in a template splice\",\n+\t\t\tt);\n+\t      inform (loc, \"only templates are allowed here\");\n+\t      return error_mark_node;\n+\t    }\n+\t}\n+    }\n+  else if (/* No 'template' but there were template arguments?  */\n+\t   targs_p\n+\t   /* No 'template' but the splice-specifier designates a template?  */\n+\t   || really_overloaded_fn (t))\n+    {\n+      auto_diagnostic_group d;\n+      if (targs_p)\n+\terror_at (loc, \"reflection %qE not usable in a splice expression with \"\n+\t\t  \"template arguments\", t);\n+      else\n+\terror_at (loc, \"reflection %qE not usable in a splice expression\", t);\n+      location_t sloc = expr.get_start ();\n+      rich_location richloc (line_table, sloc);\n+      richloc.add_fixit_insert_before (sloc, \"template \");\n+      inform (&richloc, \"add %<template%> to denote a template\");\n+      return error_mark_node;\n+    }\n+\n+  if (parser->in_template_argument_list_p\n+      && !parser->greater_than_is_operator_p)\n+    {\n+      error_at (loc, \"unparenthesized splice expression cannot be used as \"\n+\t\t\"a template argument\");\n+      return error_mark_node;\n+    }\n+\n+  /* Make sure this splice-expression produces an expression.  */\n+  if (!check_splice_expr (loc, expr.get_start (), t, address_p,\n+\t\t\t  member_access_p, /*complain=*/true))\n+    return error_mark_node;\n+\n+  /* When doing foo.[: bar :], cp_parser_postfix_dot_deref_expression wants\n+     to see an identifier or a TEMPLATE_ID_EXPR, if we have something like\n+     s.template [: ^^S::var :]<int> where S::var is a variable template.  */\n+  if (member_access_p)\n+    {\n+      /* Grab the unresolved expression then.  */\n+      t = unresolved;\n+      if (TREE_CODE (t) == FIELD_DECL\n+\t  || VAR_P (t)\n+\t  || TREE_CODE (t) == CONST_DECL\n+\t  || TREE_CODE (t) == FUNCTION_DECL\n+\t  || DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (t)))\n+\t;\n+      else\n+\t{\n+\t  if (DECL_P (t))\n+\t    /* We cannot forget what context we came from, so build up\n+\t       a SCOPE_REF.  */\n+\t    t = build_qualified_name (/*type=*/NULL_TREE, CP_DECL_CONTEXT (t),\n+\t\t\t\t      DECL_NAME (t), /*template_p=*/false);\n+\t  else if (OVL_P (t))\n+\t    t = OVL_NAME (t);\n+\t  gcc_assert (TREE_CODE (t) == SCOPE_REF\n+\t\t      || BASELINK_P (t)\n+\t\t      || TREE_CODE (t) == SPLICE_EXPR\n+\t\t      || TREE_CODE (t) == TEMPLATE_ID_EXPR\n+\t\t      || TREE_CODE (t) == TREE_BINFO);\n+\t}\n+      /* ??? We're not setting *idk here.  */\n+    }\n+  else\n+    {\n+      /* We may have to instantiate; for instance, if we're dealing with\n+\t a variable template.  For &[: ^^S::x :], we have to create an\n+\t OFFSET_REF.  For a VAR_DECL, we need the convert_from_reference.  */\n+      cp_unevaluated u;\n+      /* CWG 3109 adjusted [class.protected] to say that checking access to\n+\t protected non-static members is disabled for members designated by a\n+\t splice-expression.  */\n+      push_deferring_access_checks (dk_no_check);\n+      const char *error_msg;\n+      /* We don't have the parser scope here, so figure out the context.  In\n+\t   struct S { static constexpr int i = 42; };\n+\t   constexpr auto r = ^^S::i;\n+\t   int i = [: r :];\n+\t we need to pass down 'S'.  */\n+      tree ctx = DECL_P (t) ? DECL_CONTEXT (t) : NULL_TREE;\n+      t = finish_id_expression (t, t, ctx, idk,\n+\t\t\t\t/*integral_constant_expression_p=*/false,\n+\t\t\t\t/*allow_non_integral_constant_expr_p=*/true,\n+\t\t\t\t&parser->non_integral_constant_expression_p,\n+\t\t\t\ttemplate_p,\n+\t\t\t\t/*done=*/true,\n+\t\t\t\taddress_p,\n+\t\t\t\ttemplate_arg_p,\n+\t\t\t\t&error_msg,\n+\t\t\t\tloc);\n+      if (error_msg)\n+\tcp_parser_error (parser, error_msg);\n+      pop_deferring_access_checks ();\n+    }\n+\n+  return t;\n+}\n+\n+/* Parse a splice-scope-specifier.\n+\n+   splice-scope-specifier:\n+     splice-specifier\n+     template[opt] splice-specialization-specifier\n+\n+   TYPENAME_P is true if we've seen the typename keyword.\n+   TEMPLATE_P is true if we've seen the leading template keyword.  */\n+\n+static tree\n+cp_parser_splice_scope_specifier (cp_parser *parser, bool typename_p,\n+\t\t\t\t  bool template_p)\n+{\n+  bool targs_p = false;\n+  cp_expr scope = cp_parser_splice_specifier (parser, template_p, &targs_p);\n+  const location_t loc = scope.get_location ();\n+  if (TREE_CODE (scope) == TYPE_DECL)\n+    scope = TREE_TYPE (scope);\n+\n+  if (template_p && !targs_p)\n+    {\n+      error_at (loc, \"extra %<template%> in a scope splice\");\n+      return error_mark_node;\n+    }\n+  /* [expr.prim.id.qual] The template may only be omitted from the\n+     form template(opt) splice-specialization-specifier :: when the\n+     splice-specialization-specifier is preceded by typename.  */\n+  if (targs_p && !typename_p && !template_p)\n+    {\n+      auto_diagnostic_group d;\n+      error_at (loc, \"missing %<template%> in a scope splice with template \"\n+\t\t\"arguments\");\n+      inform (loc, \"%<template%> may only be omitted when the scope splice \"\n+\t      \"is preceded by %<typename%>\");\n+      return error_mark_node;\n+    }\n+\n+  /* A dependent scope.  Turn this into SPLICE_SCOPE which is a type,\n+     so that dependent_scope_p et al can recognize this.  */\n+  if (dependent_splice_p (scope))\n+    return make_splice_scope (scope, /*type_p=*/false);\n+\n+  if (!valid_splice_scope_p (scope))\n+    {\n+      auto_diagnostic_group d;\n+      error_at (loc, \"reflection not usable in a splice scope\");\n+      if (TYPE_P (scope))\n+\tinform (loc, \"%qT is not a class, namespace, or enumeration\",\n+\t\ttree (scope));\n+      else\n+\tinform (loc, \"%qE is not a class, namespace, or enumeration\",\n+\t\ttree (scope));\n+      scope = error_mark_node;\n+    }\n+\n+  return scope;\n+}\n+\n+/* We know the next token is '[:' (optionally preceded by a template or\n+   typename) and we are wondering if a '::' follows right after the\n+   closing ':]', or after the possible '<...>' after the ':]'.  Return\n+   true if yes, false otherwise.  */\n+\n+static bool\n+cp_parser_splice_spec_is_nns_p (cp_parser *parser)\n+{\n+  /* ??? It'd be nice to use saved_token_sentinel, but its rollback\n+     uses cp_lexer_previous_token, but we may be the first token in the\n+     file so there are no previous tokens.  Sigh.  */\n+  cp_lexer_save_tokens (parser->lexer);\n+\n+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME)\n+      || cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))\n+    cp_lexer_consume_token (parser->lexer);\n+\n+  bool ok = false;\n+  size_t n = cp_parser_skip_balanced_tokens (parser, 1);\n+  if (n != 1)\n+    {\n+      ok = true;\n+      /* Consume tokens up to the ':]' (including).  */\n+      for (n = n - 1; n; --n)\n+\tcp_lexer_consume_token (parser->lexer);\n+\n+      /* Consume the whole '<....>', if present.  */\n+      if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)\n+\t  && !cp_parser_skip_entire_template_parameter_list (parser))\n+\tok = false;\n+\n+      ok = ok && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE);\n+    }\n+\n+  /* Roll back the tokens we skipped.  */\n+  cp_lexer_rollback_tokens (parser->lexer);\n+\n+  return ok;\n+}\n+\n+/* Return true if the N-th token is '[:' and its closing ':]' is NOT\n+   followed by a '::'.  For example, we could be checking if what follows\n+   can be a splice-expression or not -- we can tell that '[:R:]::type' is\n+   not a splice-expression.  */\n+\n+static bool\n+cp_parser_nth_token_starts_splice_without_nns_p (cp_parser *parser, size_t n)\n+{\n+  return (cp_lexer_nth_token_is (parser->lexer, n, CPP_OPEN_SPLICE)\n+\t  && !cp_parser_splice_spec_is_nns_p (parser));\n+}\n+\n /* Parse a primary-expression.\n \n    primary-expression:\n@@ -6064,6 +6519,9 @@ cp_parser_pack_index (cp_parser *parser, tree pack)\n      ( expression )\n      id-expression\n      lambda-expression (C++11)\n+     fold-expression\n+     requires-expression\n+     splice-expression\n \n    GNU Extensions:\n \n@@ -6347,6 +6805,11 @@ cp_parser_primary_expression (cp_parser *parser,\n \treturn lam;\n       }\n \n+    case CPP_OPEN_SPLICE:\n+      return cp_parser_splice_expression (parser, /*template_p=*/false,\n+\t\t\t\t\t  address_p, template_arg_p,\n+\t\t\t\t\t  /*member_access_p=*/false, idk);\n+\n     case CPP_OBJC_STRING:\n       if (c_dialect_objc ())\n \t/* We have an Objective-C++ string literal. */\n@@ -6503,13 +6966,23 @@ cp_parser_primary_expression (cp_parser *parser,\n \tcase RID_TEMPLATE:\n \t  if (parser->in_function_body\n \t      && (cp_lexer_peek_nth_token (parser->lexer, 2)->type\n-\t      \t  == CPP_LESS))\n+\t\t  == CPP_LESS))\n \t    {\n \t      error_at (token->location,\n \t\t\t\"a template declaration cannot appear at block scope\");\n \t      cp_parser_skip_to_end_of_block_or_statement (parser);\n \t      return error_mark_node;\n \t    }\n+\t  else if (cp_lexer_peek_nth_token (parser->lexer, 2)->type\n+\t\t   == CPP_OPEN_SPLICE)\n+\t    {\n+\t      cp_lexer_consume_token (parser->lexer);\n+\t      return cp_parser_splice_expression (parser, /*template_p=*/true,\n+\t\t\t\t\t\t  address_p, template_arg_p,\n+\t\t\t\t\t\t  /*member_access_p=*/false,\n+\t\t\t\t\t\t  idk);\n+\t    }\n+\n \t  /* FALLTHRU */\n \tdefault:\n \t  cp_parser_error (parser, \"expected primary-expression\");\n@@ -6699,6 +7172,16 @@ cp_parser_primary_expression (cp_parser *parser,\n \treturn decl;\n       }\n \n+    case CPP_XOR:\n+      if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_XOR)\n+\t{\n+\t  error_at (token->location,\n+\t\t    \"reflection is only available in C++26 with \"\n+\t\t    \"%<-freflection%>\");\n+\t  return error_mark_node;\n+\t}\n+      gcc_fallthrough ();\n+\n       /* Anything else is an error.  */\n     default:\n       cp_parser_error (parser, \"expected primary-expression\");\n@@ -7166,6 +7649,20 @@ cp_parser_unqualified_id (cp_parser* parser,\n \t    if (cp_parser_parse_definitely (parser))\n \t      done = true;\n \t  }\n+\t/* Allow r.~typename [:R:].  */\n+\telse if (!done\n+\t\t && cp_parser_next_tokens_start_splice_type_spec_p\n+\t\t     (parser, /*require_typename_p=*/true))\n+\t  {\n+\t    parser->scope = object_scope;\n+\t    parser->object_scope = NULL_TREE;\n+\t    parser->qualifying_scope = NULL_TREE;\n+\t    type_decl = cp_parser_splice_type_specifier (parser);\n+\t    if (!type_decl)\n+\t      /* We don't have a TYPE_DECL, so return early.  */\n+\t      return error_mark_node;\n+\t    return build_min_nt_loc (loc, BIT_NOT_EXPR, type_decl);\n+\t  }\n \t/* Look in the surrounding context.  */\n \tif (!done)\n \t  {\n@@ -7313,6 +7810,7 @@ check_template_keyword_in_nested_name_spec (tree name)\n      type-name ::\n      namespace-name ::\n      computed-type-specifier ::\n+     splice-scope-specifier ::\n      nested-name-specifier identifier ::\n      nested-name-specifier template [opt] simple-template-id ::\n \n@@ -7400,6 +7898,9 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,\n       /* DR 743: decltype can be used in a nested-name-specifier.  */\n       else if (token_is_decltype (token))\n \t;\n+      /* Could be a splice-scope-specifier.  */\n+      else if (cp_parser_next_tokens_can_start_splice_scope_spec_p (parser))\n+\t;\n       else\n \t{\n \t  /* If the next token is not an identifier, then it is\n@@ -7776,6 +8277,23 @@ cp_parser_qualifying_entity (cp_parser *parser,\n       return scope;\n     }\n \n+  /* In a nested-name-specifier, we can reach a splice-specifier\n+     either via the computed-type-specifier -> splice-type-specifier\n+     production, or via splice-scope-specifier.  But [dcl.type.splice]\n+     says \"A splice-specifier or splice-specialization-specifier immediately\n+     followed by :: is never interpreted as part of a splice-type-specifier\"\n+     so we call only cp_parser_splice_scope_specifier.  */\n+  if (cp_parser_next_tokens_can_start_splice_scope_spec_p (parser)\n+      && cp_parser_splice_spec_is_nns_p (parser))\n+    {\n+      if (cp_parser_optional_template_keyword (parser))\n+\ttemplate_keyword_p = true;\n+      scope = cp_parser_splice_scope_specifier (parser,\n+\t\t\t\t\t\ttypename_keyword_p,\n+\t\t\t\t\t\ttemplate_keyword_p);\n+      return scope;\n+    }\n+\n   /* Before we try to parse the class-name, we must save away the\n      current PARSER->SCOPE since cp_parser_class_name will destroy\n      it.  */\n@@ -7869,6 +8387,8 @@ literal_integer_zerop (const_tree expr)\n      postfix-expression -> template [opt] id-expression\n      postfix-expression . pseudo-destructor-name\n      postfix-expression -> pseudo-destructor-name\n+     postfix-expression . splice-expression\n+     postfix-expression -> splice-expression\n      postfix-expression ++\n      postfix-expression --\n      dynamic_cast < type-id > ( expression )\n@@ -8073,6 +8593,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,\n \n     case RID_TYPENAME:\n       {\n+\t/* Just like cp_parser_type_specifier/RID_TYPENAME: if we see\n+\t   'typename [:', this could be a typename-specifier.  But if\n+\t   there's no '::' after the '[:x:]' then it is not.  */\n+\tif (cp_parser_nth_token_starts_splice_without_nns_p (parser, 2))\n+\t  goto default_;\n+\n \ttree type;\n \t/* The syntax permitted here is the same permitted for an\n \t   elaborated-type-specifier.  */\n@@ -8274,6 +8800,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,\n       }\n \n     default:\n+    default_:\n       {\n \ttree type;\n \n@@ -8621,7 +9148,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,\n \t  /* postfix-expression . template [opt] id-expression\n \t     postfix-expression . pseudo-destructor-name\n \t     postfix-expression -> template [opt] id-expression\n-\t     postfix-expression -> pseudo-destructor-name */\n+\t     postfix-expression -> pseudo-destructor-name\n+\t     postfix-expression . splice-expression\n+\t     postfix-expression -> splice-expression  */\n \n \t  /* Consume the `.' or `->' operator.  */\n \t  cp_lexer_consume_token (parser->lexer);\n@@ -8981,6 +9510,8 @@ cp_parser_dot_deref_incomplete (tree *scope, cp_expr *postfix_expression,\n      postfix-expression . pseudo-destructor-name\n      postfix-expression -> template [opt] id-expression\n      postfix-expression -> pseudo-destructor-name\n+     postfix-expression . splice-expression\n+     postfix-expression -> splice-expression\n \n    FOR_OFFSETOF is set if we're being called in that context.  That sorta\n    limits what of the above we'll actually accept, but nevermind.\n@@ -9105,15 +9636,32 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,\n \t ordinary class member access expression, rather than a\n \t pseudo-destructor-name.  */\n       bool template_p;\n+      bool template_keyword_p = cp_parser_optional_template_keyword (parser);\n       cp_token *token = cp_lexer_peek_token (parser->lexer);\n-      /* Parse the id-expression.  */\n-      name = (cp_parser_id_expression\n-\t      (parser,\n-\t       cp_parser_optional_template_keyword (parser),\n-\t       /*check_dependency_p=*/true,\n-\t       &template_p,\n-\t       /*declarator_p=*/false,\n-\t       /*optional_p=*/false));\n+      /* See if there was this->[:R:].  Note that in this->[: ^^S :]::i;\n+\t the RHS is not a splice-expression.  */\n+      const bool splice_p\n+\t= cp_parser_nth_token_starts_splice_without_nns_p (parser, 1);\n+      if (splice_p)\n+\t{\n+\t  name = cp_parser_splice_expression (parser, template_keyword_p,\n+\t\t\t\t\t      /*address_p=*/false,\n+\t\t\t\t\t      /*template_arg_p=*/false,\n+\t\t\t\t\t      /*member_access_p=*/true, idk);\n+\t  /* This is not the leading 'template' but the one after n-n-s,\n+\t     which we don't have here.  */\n+\t  template_p = false;\n+\t}\n+      else\n+\t/* Parse the id-expression.  */\n+\tname = (cp_parser_id_expression\n+\t\t(parser,\n+\t\t template_keyword_p,\n+\t\t /*check_dependency_p=*/true,\n+\t\t &template_p,\n+\t\t /*declarator_p=*/false,\n+\t\t /*optional_p=*/false));\n+\n       /* In general, build a SCOPE_REF if the member name is qualified.\n \t However, if the name was not dependent and has already been\n \t resolved; there is no need to build the SCOPE_REF.  For example;\n@@ -9122,10 +9670,16 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,\n \t     template <typename T> void f(T* t) { t->X::f(); }\n \n \t Even though \"t\" is dependent, \"X::f\" is not and has been resolved\n-\t to a BASELINK; there is no need to include scope information.  */\n+\t to a BASELINK; there is no need to include scope information.\n \n-      /* But we do need to remember that there was an explicit scope for\n-\t virtual function calls.  */\n+\t But we do need to remember that there was an explicit scope for\n+\t virtual function calls.  If the name was represented by\n+\t a splice-expression, behave like this:\n+\n+\t   [:^^B::fn:]()  // do not disable virtual dispatch\n+\t   [:^^B:]::fn()  // disable virtual dispatch\n+\n+\t In the former, parser->scope has been cleared when we get here.  */\n       if (parser->scope)\n \t*idk = CP_ID_KIND_QUALIFIED;\n \n@@ -9146,6 +9700,14 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,\n \t\t\t    parser->scope, name);\n \t\t  postfix_expression = error_mark_node;\n \t\t}\n+\t      /* cp_parser_splice_expression may have given us a SCOPE_REF.  */\n+\t      else if (TREE_CODE (name) == SCOPE_REF\n+\t\t       || TREE_CODE (name) == FIELD_DECL\n+\t\t       || VAR_P (name)\n+\t\t       || TREE_CODE (name) == CONST_DECL\n+\t\t       || TREE_CODE (name) == FUNCTION_DECL\n+\t\t       || DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (name)))\n+\t\tgcc_checking_assert (splice_p);\n \t      else\n \t\tname = build_qualified_name (/*type=*/NULL_TREE,\n \t\t\t\t\t     parser->scope,\n@@ -9155,13 +9717,19 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,\n \t      parser->qualifying_scope = NULL_TREE;\n \t      parser->object_scope = NULL_TREE;\n \t    }\n-\t  if (parser->scope && name && BASELINK_P (name))\n+\t  if ((parser->scope || splice_p) && name && BASELINK_P (name))\n \t    adjust_result_of_qualified_name_lookup\n-\t      (name, parser->scope, scope);\n+\t      (name,\n+\t       /* For obj->[:^^R:] we won't have parser->scope, but we still\n+\t\t  have to perform this adjustment.  */\n+\t       (splice_p\n+\t\t? BINFO_TYPE (BASELINK_ACCESS_BINFO (name))\n+\t\t: parser->scope),\n+\t       scope);\n \t  postfix_expression\n \t    = finish_class_member_access_expr (postfix_expression, name,\n \t\t\t\t\t       template_p,\n-\t\t\t\t\t       tf_warning_or_error);\n+\t\t\t\t\t       tf_warning_or_error, splice_p);\n \t  /* Build a location e.g.:\n \t       ptr->access_expr\n \t       ~~~^~~~~~~~~~~~~\n@@ -9451,6 +10019,159 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,\n   *type = TREE_TYPE (cp_parser_nonclass_name (parser));\n }\n \n+/* Parse a reflection-name.\n+\n+   reflection-name:\n+    nested-name-specifier[opt] identifier\n+    nested-name-specifier template identifier\n+\n+ */\n+\n+static tree\n+cp_parser_reflection_name (cp_parser *parser)\n+{\n+  auto s = make_temp_override (cp_preserve_using_decl, true);\n+\n+  /* Look for the optional `::' operator.  */\n+  bool global_scope_p\n+    = (cp_parser_global_scope_opt (parser,\n+\t\t\t\t   /*current_scope_valid_p=*/false)\n+       != NULL_TREE);\n+  /* And the optional nested-name-specifier.  */\n+  bool nested_name_specifier_p\n+    = (cp_parser_nested_name_specifier_opt (parser,\n+\t\t\t\t\t    /*typename_keyword_p=*/false,\n+\t\t\t\t\t    /*check_dependency_p=*/true,\n+\t\t\t\t\t    /*type_p=*/false,\n+\t\t\t\t\t    /*is_declaration=*/false,\n+\t\t\t\t\t    /*template_keyword_p=*/false,\n+\t\t\t\t\t    global_scope_p)\n+       != NULL_TREE);\n+  /* Look for the optional `template' keyword.  */\n+  if (cp_parser_optional_template_keyword (parser)\n+      && !global_scope_p\n+      && !nested_name_specifier_p)\n+    cp_parser_error (parser, \"%<template%> must follow a nested-name-\"\n+\t\t     \"specifier\");\n+\n+  /* Look for the identifier.  */\n+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;\n+  tree name = cp_parser_identifier (parser);\n+  tree decl = cp_parser_lookup_name_simple (parser, name, loc);\n+  if (name != error_mark_node && decl == error_mark_node)\n+    cp_parser_name_lookup_error (parser, name, decl, NLE_NULL, loc);\n+\n+  return decl;\n+}\n+\n+/* Parse a reflect-expression.\n+\n+   reflect-expression:\n+     ^^ ::\n+     ^^ reflection-name\n+     ^^ type-id\n+     ^^ id-expression\n+\n+  Returns a representation of the reflection.  */\n+\n+static tree\n+cp_parser_reflect_expression (cp_parser *parser)\n+{\n+  if (!flag_reflection)\n+    {\n+      error_at (cp_lexer_peek_token (parser->lexer)->location,\n+\t\t\"reflection is only available with %<-freflection%>\");\n+      return error_mark_node;\n+    }\n+\n+  /* Consume the '^^'.  */\n+  cp_lexer_consume_token (parser->lexer);\n+\n+  /* Get the location of the operand.  */\n+  const location_t loc = cp_lexer_peek_token (parser->lexer)->location;\n+\n+  /* We don't know what this might be.  Try and see what works.  */\n+  cp_parser_parse_tentatively (parser);\n+  tree t = cp_parser_reflection_name (parser);\n+  if (TREE_CODE (t) == TYPE_DECL && !cp_parser_error_occurred (parser))\n+    /* Need to call cp_parser_type_id, because say\n+\tusing A = int;\n+\t^^A &\n+       should parse the type id rather than reflection-name.  */\n+    cp_parser_simulate_error (parser);\n+  /* For ^^tmpl<args>, looking for a nested-name-specifier in\n+     cp_parser_reflection_name above creates a CPP_TEMPLATE_ID which\n+     makes cp_parser_identifier cause a parser error.  So we don't\n+     return early here.  */\n+  if (cp_parser_parse_definitely (parser))\n+    return get_reflection (loc, t);\n+  /* Nope.  Well then, maybe it's a type-id.  */\n+  cp_parser_parse_tentatively (parser);\n+\n+  bool type_alias_p;\n+  t = cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_NONE, false, false,\n+\t\t\t   nullptr, &type_alias_p);\n+  if (cp_parser_parse_definitely (parser))\n+    {\n+      /* With using A = int; ^^A is a type alias but ^^const A or ^^A & or\n+\t ^^A const is not.  With template<typename T> using B = C <T>;\n+\t ^^B <int> is a type alias though.  */\n+      if (TYPE_P (t) && !type_alias_p)\n+\tt = strip_typedefs (t);\n+      return get_reflection (loc, t);\n+    }\n+  /* Try an id-expression.  */\n+  {\n+    cp_parser_parse_tentatively (parser);\n+    /* [expr.reflect] The id-expression of a reflect-expression is\n+       an unevaluated operand.  */\n+    cp_unevaluated u;\n+    tree id = cp_parser_id_expression (parser,\n+\t\t\t\t       /*template_keyword_p=*/false,\n+\t\t\t\t       /*check_dependency_p=*/true,\n+\t\t\t\t       /*template_p=*/nullptr,\n+\t\t\t\t       /*declarator_p=*/false,\n+\t\t\t\t       /*optional_p=*/false);\n+    /* Lookup the name we got back from the id-expression.  */\n+    if (identifier_p (id))\n+      t = cp_parser_lookup_name_simple (parser, id, loc);\n+    else\n+      t = id;\n+    /* We couldn't look ID up, harrumph.  */\n+    if (id != error_mark_node && t == error_mark_node)\n+      cp_parser_name_lookup_error (parser, id, t, NLE_NULL, loc);\n+    /* We don't finish_id_expression here because we don't know in what\n+       context this reflection will be used (address, class member access,\n+       template argument, ...).  Except go ahead and (try to) resolve the\n+       variable TEMPLATE_ID_EXPR (which is always considered type-dependent\n+       because such TEMPLATE_ID_EXPRs don't have a type) now.  We don't need\n+       to keep these TEMPLATE_ID_EXPRs for a possible class member access,\n+       but most importantly, function templates with ^^vt<int> as one of its\n+       template argument would never be mangled (mangle_decl checks if any\n+       template arguments are dependent).  */\n+    if (TREE_CODE (t) == TEMPLATE_ID_EXPR\n+\t&& variable_template_p (TREE_OPERAND (t, 0))\n+\t&& !concept_check_p (t))\n+      t = finish_template_variable (t);\n+    if (cp_parser_parse_definitely (parser))\n+      return get_reflection (loc, t);\n+  }\n+\n+  /* Last chance, see if there's ^^::.  This must be done only after we've\n+     tried the other options.  */\n+  if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))\n+    {\n+      cp_lexer_consume_token (parser->lexer);\n+      /* A reflect-expression of the form ^^:: represents the global\n+\t namespace.  */\n+      return get_reflection (loc, global_namespace);\n+    }\n+\n+  /* Oy vey, nothing worked.  */\n+  error_at (loc, \"%<^^%> cannot be applied to this operand\");\n+  return error_mark_node;\n+}\n+\n /* Parse a unary-expression.\n \n    unary-expression:\n@@ -9461,9 +10182,10 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,\n      unary-operator cast-expression\n      sizeof unary-expression\n      sizeof ( type-id )\n-     alignof ( type-id )  [C++0x]\n+     alignof ( type-id )  [C++11]\n      new-expression\n      delete-expression\n+     reflect-expression\t[C++26]\n \n    GNU Extensions:\n \n@@ -9727,6 +10449,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,\n       else if (keyword == RID_DELETE)\n \treturn cp_parser_delete_expression (parser);\n     }\n+  else if (cp_lexer_next_token_is (parser->lexer, CPP_REFLECT_OP))\n+    return cp_parser_reflect_expression (parser);\n \n   /* Look for a unary operator.  */\n   unary_operator = cp_parser_unary_operator (token);\n@@ -16787,6 +17511,12 @@ cp_parser_declaration (cp_parser* parser, tree prefix_attrs)\n       /* `template <' indicates a template declaration.  */\n       else if (token2->type == CPP_LESS)\n \tcp_parser_template_declaration (parser, /*member_p=*/false);\n+      /* We can have\n+\t   template [: ^^T :]<3>::type t = 4;\n+\t where the template binds to the splice-scope-specifier.  */\n+      else if (token2->type == CPP_OPEN_SPLICE\n+\t       && cp_parser_splice_spec_is_nns_p (parser))\n+\tcp_parser_block_declaration (parser, /*statement_p=*/false);\n       /* Anything else must be an explicit instantiation.  */\n       else\n \t{\n@@ -17477,6 +18207,8 @@ cp_parser_decomposition_declaration (cp_parser *parser,\n \t      attr = NULL_TREE;\n \t    if (attr && first_attr == -1)\n \t      first_attr = v.length ();\n+\t    if (lookup_attribute (\"internal \", \"annotation \", attr))\n+\t      error (\"annotation on structured binding\");\n \t  }\n \tv.safe_push (e);\n \t++cnt;\n@@ -18555,9 +19287,22 @@ cp_parser_decltype_expr (cp_parser *parser,\n          expression.  */\n       cp_parser_abort_tentative_parse (parser);\n \n-      /* Parse a full expression.  */\n-      expr = cp_parser_expression (parser, /*pidk=*/NULL, /*cast_p=*/false,\n-\t\t\t\t   /*decltype_p=*/true);\n+      /* [dcl.type.decltype] \"if E is an unparenthesized splice-expression,\n+\t decltype(E) is the type of the entity, object, or value designated\n+\t by the splice-specifier of E\"  */\n+      if (cp_parser_nth_token_starts_splice_without_nns_p (parser, 1))\n+\t{\n+\t  cp_id_kind idk;\n+\t  expr = cp_parser_splice_expression (parser, /*template_p=*/false,\n+\t\t\t\t\t      /*address_p=*/false,\n+\t\t\t\t\t      /*template_arg_p=*/false,\n+\t\t\t\t\t      /*member_access_p=*/false, &idk);\n+\t  id_expression_or_member_access_p = true;\n+\t}\n+      else\n+\t/* Parse a full expression.  */\n+\texpr = cp_parser_expression (parser, /*pidk=*/NULL, /*cast_p=*/false,\n+\t\t\t\t     /*decltype_p=*/true);\n     }\n \n   return expr;\n@@ -20229,6 +20974,9 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)\n    of functions, returns a TEMPLATE_ID_EXPR.  If the template-name\n    names a class, returns a TYPE_DECL for the specialization.\n \n+   PARSED_TEMPL, if non-null, is the already parsed template-name.  This\n+   is used when parsing a splice-specialization-specifier.\n+\n    If CHECK_DEPENDENCY_P is FALSE, names are looked up in\n    uninstantiated templates.  */\n \n@@ -20237,7 +20985,8 @@ cp_parser_template_id (cp_parser *parser,\n \t\t       bool template_keyword_p,\n \t\t       bool check_dependency_p,\n \t\t       enum tag_types tag_type,\n-\t\t       bool is_declaration)\n+\t\t       bool is_declaration,\n+\t\t       tree parsed_templ/*=NULL_TREE*/)\n {\n   tree templ;\n   tree arguments;\n@@ -20258,28 +21007,32 @@ cp_parser_template_id (cp_parser *parser,\n \n   /* Avoid performing name lookup if there is no possibility of\n      finding a template-id.  */\n-  if ((token->type != CPP_NAME && token->keyword != RID_OPERATOR)\n-      || (token->type == CPP_NAME\n-\t  && !cp_parser_nth_token_starts_template_argument_list_p\n-\t       (parser, 2)))\n+  if (!parsed_templ\n+      && ((token->type != CPP_NAME && token->keyword != RID_OPERATOR)\n+\t  || (token->type == CPP_NAME\n+\t      && !cp_parser_nth_token_starts_template_argument_list_p\n+\t\t   (parser, 2))))\n     {\n       cp_parser_error (parser, \"expected template-id\");\n       return error_mark_node;\n     }\n \n   /* Remember where the template-id starts.  */\n-  if (cp_parser_uncommitted_to_tentative_parse_p (parser))\n+  if (!parsed_templ && cp_parser_uncommitted_to_tentative_parse_p (parser))\n     start_of_id = cp_lexer_token_position (parser->lexer, false);\n \n   push_deferring_access_checks (dk_deferred);\n \n   /* Parse the template-name.  */\n   is_identifier = false;\n-  templ = cp_parser_template_name (parser, template_keyword_p,\n-\t\t\t\t   check_dependency_p,\n-\t\t\t\t   is_declaration,\n-\t\t\t\t   tag_type,\n-\t\t\t\t   &is_identifier);\n+  if (parsed_templ)\n+    templ = parsed_templ;\n+  else\n+    templ = cp_parser_template_name (parser, template_keyword_p,\n+\t\t\t\t     check_dependency_p,\n+\t\t\t\t     is_declaration,\n+\t\t\t\t     tag_type,\n+\t\t\t\t     &is_identifier);\n \n   /* Push any access checks inside the firewall we're about to create.  */\n   vec<deferred_access_check, va_gc> *checks = get_deferred_access_checks ();\n@@ -20394,7 +21147,9 @@ cp_parser_template_id (cp_parser *parser,\n     = make_location (token->location, token->location, parser->lexer);\n \n   /* Build a representation of the specialization.  */\n-  if (identifier_p (templ))\n+  if (identifier_p (templ)\n+      /* We can't do much with [:T:]<arg> at this point.  */\n+      || TREE_CODE (templ) == SPLICE_EXPR)\n     template_id = build_min_nt_loc (combined_loc,\n \t\t\t\t    TEMPLATE_ID_EXPR,\n \t\t\t\t    templ, arguments);\n@@ -20444,7 +21199,20 @@ cp_parser_template_id (cp_parser *parser,\n     {\n       /* If it's not a class-template or a template-template, it should be\n \t a function-template.  */\n-      gcc_assert (OVL_P (templ) || BASELINK_P (templ));\n+      if (OVL_P (templ) || BASELINK_P (templ))\n+\t/* It is.  */;\n+      else if (parsed_templ)\n+\t{\n+\t  /* This means there was a splice-specifier.  Maybe the user\n+\t     used the wrong reflection, so complain.  */\n+\t  if (TYPE_P (templ))\n+\t    error_at (token->location, \"%qT is not a template\", templ);\n+\t  else\n+\t    error_at (token->location, \"%qE is not a template\", templ);\n+\t  return error_mark_node;\n+\t}\n+      else\n+\tgcc_assert (false);\n \n       template_id = lookup_template_function (templ, arguments);\n       if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR)\n@@ -21475,6 +22243,13 @@ cp_parser_type_specifier (cp_parser* parser,\n \n       /* Fall through.  */\n     case RID_TYPENAME:\n+      /* If we see 'typename [:', this could be a typename-specifier.\n+\t But if there's no '::' after the '[:x:]' then it is probably\n+\t a simple-type-specifier.  */\n+      if (keyword == RID_TYPENAME\n+\t  && cp_parser_nth_token_starts_splice_without_nns_p (parser, 2))\n+\tbreak;\n+\n       /* Look for an elaborated-type-specifier.  */\n       type_spec\n \t= (cp_parser_elaborated_type_specifier\n@@ -21573,6 +22348,15 @@ cp_parser_type_specifier (cp_parser* parser,\n \n      nested-name-specifier(opt) template-name\n \n+   computed-type-specifier:\n+     decltype-specifier\n+     pack-index-specifier\n+     splice-type-specifier\n+\n+   splice-type-specifier:\n+     typename[opt] splice-specifier\n+     typename[opt] splice-specialization-specifier\n+\n    GNU Extension:\n \n    simple-type-specifier:\n@@ -21940,6 +22724,15 @@ cp_parser_simple_type_specifier (cp_parser* parser,\n \t    type = NULL_TREE;\n \t}\n \n+      /* \"[: ... :]\" is a C++26 splice-type-specifier.  The second argument\n+\t decides if we require 'typename' before the splice-type-specifier.\n+\t In a type-only context ([temp.res.general]/4) we shouldn't require\n+\t it.  */\n+      if (!type\n+\t  && cp_parser_next_tokens_start_splice_type_spec_p (parser,\n+\t\t\t\t\t\t\t     !typename_p))\n+\ttype = cp_parser_splice_type_specifier (parser);\n+\n       /* Otherwise, look for a type-name.  */\n       if (!type)\n \t{\n@@ -23116,6 +23909,7 @@ cp_parser_enum_specifier (cp_parser* parser)\n \t{\n \t  new_value_list = true;\n \t  SET_OPAQUE_ENUM_P (type, false);\n+\t  ENUM_BEING_DEFINED_P (type) = 1;\n \t  DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;\n \t}\n       else\n@@ -23524,7 +24318,8 @@ cp_parser_namespace_body (cp_parser* parser)\n /* Parse a namespace-alias-definition.\n \n    namespace-alias-definition:\n-     namespace identifier = qualified-namespace-specifier ;  */\n+     namespace identifier = qualified-namespace-specifier\n+     namespace identifier = splice-specifier  */\n \n static void\n cp_parser_namespace_alias_definition (cp_parser* parser)\n@@ -23553,10 +24348,13 @@ cp_parser_namespace_alias_definition (cp_parser* parser)\n       return;\n     }\n   cp_parser_require (parser, CPP_EQ, RT_EQ);\n-  /* Look for the qualified-namespace-specifier.  */\n-  namespace_specifier\n-    = cp_parser_qualified_namespace_specifier (parser);\n-  cp_warn_deprecated_use_scopes (namespace_specifier);\n+  if (cp_parser_nth_token_starts_splice_without_nns_p (parser, 1))\n+    namespace_specifier = cp_parser_splice_specifier (parser);\n+  else\n+    /* Look for the qualified-namespace-specifier.  */\n+    namespace_specifier = cp_parser_qualified_namespace_specifier (parser);\n+  if (!dependent_namespace_p (namespace_specifier))\n+    cp_warn_deprecated_use_scopes (namespace_specifier);\n   /* Look for the `;' token.  */\n   cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);\n \n@@ -24018,8 +24816,9 @@ cp_parser_alias_declaration (cp_parser* parser)\n /* Parse a using-directive.\n \n    using-directive:\n-     attribute-specifier-seq [opt] using namespace :: [opt]\n-       nested-name-specifier [opt] namespace-name ;  */\n+     attribute-specifier-seq [opt] using namespace nested-name-specifier [opt]\n+       namespace-name ;\n+     attribute-specifier-seq [opt] using namespace splice-specifier ;  */\n \n static void\n cp_parser_using_directive (cp_parser* parser)\n@@ -24038,16 +24837,21 @@ cp_parser_using_directive (cp_parser* parser)\n   cp_parser_require_keyword (parser, RID_USING, RT_USING);\n   /* And the `namespace' keyword.  */\n   cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE);\n-  /* Look for the optional `::' operator.  */\n-  cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);\n-  /* And the optional nested-name-specifier.  */\n-  cp_parser_nested_name_specifier_opt (parser,\n-\t\t\t\t       /*typename_keyword_p=*/false,\n-\t\t\t\t       /*check_dependency_p=*/true,\n-\t\t\t\t       /*type_p=*/false,\n-\t\t\t\t       /*is_declaration=*/true);\n-  /* Get the namespace being used.  */\n-  namespace_decl = cp_parser_namespace_name (parser);\n+  if (cp_parser_nth_token_starts_splice_without_nns_p (parser, 1))\n+    namespace_decl = cp_parser_splice_specifier (parser);\n+  else\n+    {\n+      /* Look for the optional `::' operator.  */\n+      cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);\n+      /* And the optional nested-name-specifier.  */\n+      cp_parser_nested_name_specifier_opt (parser,\n+\t\t\t\t\t   /*typename_keyword_p=*/false,\n+\t\t\t\t\t   /*check_dependency_p=*/true,\n+\t\t\t\t\t   /*type_p=*/false,\n+\t\t\t\t\t   /*is_declaration=*/true);\n+      /* Get the namespace being used.  */\n+      namespace_decl = cp_parser_namespace_name (parser);\n+    }\n   cp_warn_deprecated_use_scopes (namespace_decl);\n   /* And any specified GNU attributes.  */\n   if (cp_next_tokens_can_be_gnu_attribute_p (parser))\n@@ -26806,15 +27610,25 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)\n    If IS_TRAILING_RETURN is true, we are in a trailing-return-type,\n    i.e. we've just seen \"->\".\n \n+   If TYPE_ALIAS_P is non-null, we set it to true or false depending\n+   on if the type-id is a type alias or just a type.  E.g., given\n+\n+     template<typename> struct S {};\n+     template<typename T> using A = const S<T>;\n+\n+   ^^A<int> is a type alias, but ^^const A<int>, ^^A<int> const, or ^^A<int>*\n+   are just types, not type aliases.\n+\n    Returns the TYPE specified.  */\n \n static tree\n cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,\n \t\t     bool is_template_arg, bool is_trailing_return,\n-\t\t     location_t *type_location)\n+\t\t     location_t *type_location, bool *type_alias_p)\n {\n   cp_decl_specifier_seq type_specifier_seq;\n   cp_declarator *abstract_declarator;\n+  cp_token *next = nullptr;\n \n   /* Parse the type-specifier-seq.  */\n   cp_parser_type_specifier_seq (parser, flags,\n@@ -26824,6 +27638,17 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,\n   if (type_location)\n     *type_location = type_specifier_seq.locations[ds_type_spec];\n \n+  /* If there is just ds_type_spec specified, this could be a type alias.  */\n+  if (type_alias_p && is_typedef_decl (type_specifier_seq.type))\n+    {\n+      int i;\n+      for (i = ds_first; i < ds_last; ++i)\n+\tif (i != ds_type_spec && type_specifier_seq.locations[i])\n+\t  break;\n+      if (i == ds_last)\n+\tnext = cp_lexer_peek_token (parser->lexer);\n+    }\n+\n   if (is_template_arg && type_specifier_seq.type\n       && TREE_CODE (type_specifier_seq.type) == TEMPLATE_TYPE_PARM\n       && CLASS_PLACEHOLDER_TEMPLATE (type_specifier_seq.type))\n@@ -26851,6 +27676,11 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,\n   if (!cp_parser_parse_definitely (parser))\n     abstract_declarator = NULL;\n \n+  /* If we found * or & and similar after the type-specifier, it's not\n+     a type alias.  */\n+  if (type_alias_p)\n+    *type_alias_p = cp_lexer_peek_token (parser->lexer) == next;\n+\n   bool auto_typeid_ok = false;\n   /* DR 625 prohibits use of auto as a template-argument.  We allow 'auto'\n      outside the template-argument-list context here only for the sake of\n@@ -26913,7 +27743,8 @@ static tree\n cp_parser_type_id (cp_parser *parser, cp_parser_flags flags,\n \t\t   location_t *type_location)\n {\n-  return cp_parser_type_id_1 (parser, flags, false, false, type_location);\n+  return cp_parser_type_id_1 (parser, flags, false, false, type_location,\n+\t\t\t      nullptr);\n }\n \n /* Wrapper for cp_parser_type_id_1.  */\n@@ -26926,7 +27757,7 @@ cp_parser_template_type_arg (cp_parser *parser)\n     = G_(\"types may not be defined in template arguments\");\n   tree r = cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_NONE,\n \t\t\t\t/*is_template_arg=*/true,\n-\t\t\t\t/*is_trailing_return=*/false, nullptr);\n+\t\t\t\t/*is_trailing_return=*/false, nullptr, nullptr);\n   parser->type_definition_forbidden_message = saved_message;\n   /* cp_parser_type_id_1 checks for auto, but only for\n      ->auto_is_implicit_function_template_parm_p.  */\n@@ -26944,7 +27775,7 @@ static tree\n cp_parser_trailing_type_id (cp_parser *parser)\n {\n   return cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,\n-\t\t\t      false, true, NULL);\n+\t\t\t      false, true, nullptr, nullptr);\n }\n \n /* Parse a type-specifier-seq.\n@@ -30854,14 +31685,17 @@ cp_parser_base_clause (cp_parser* parser)\n      public\n \n    Returns a TREE_LIST.  The TREE_PURPOSE will be one of\n-   ACCESS_{DEFAULT,PUBLIC,PROTECTED,PRIVATE}_[VIRTUAL]_NODE to\n-   indicate the specifiers provided.  The TREE_VALUE will be a TYPE\n+   ACCESS_{DEFAULT,PUBLIC,PROTECTED,PRIVATE}_NODE to\n+   indicate the specifiers provided, or if the base specifier\n+   has any annotations, a TREE_LIST with TREE_PURPOSE the\n+   ACCESS_{DEFAULT,PUBLIC,PROTECTED,PRIVATE}_NODE and\n+   TREE_VALUE the list of annotations.  The TREE_VALUE will be a TYPE\n    (or the ERROR_MARK_NODE) indicating the type that was specified.  */\n \n static tree\n cp_parser_base_specifier (cp_parser* parser)\n {\n-  cp_token *token;\n+  cp_token *token, *typename_token = nullptr, *splice_token = nullptr;\n   bool done = false;\n   bool virtual_p = false;\n   bool duplicate_virtual_error_issued_p = false;\n@@ -30871,10 +31705,28 @@ cp_parser_base_specifier (cp_parser* parser)\n   tree type;\n   location_t attrs_loc = cp_lexer_peek_token (parser->lexer)->location;\n   tree std_attrs = cp_parser_std_attribute_spec_seq (parser);\n+  tree annotations = NULL_TREE;\n \n-  if (std_attrs != NULL_TREE && any_nonignored_attribute_p (std_attrs))\n-    warning_at (attrs_loc, OPT_Wattributes,\n-\t\t\"attributes on base specifiers are ignored\");\n+  if (std_attrs != NULL_TREE)\n+    {\n+      tree *pannotations = &annotations;\n+      for (tree attr = std_attrs; attr; attr = TREE_CHAIN (attr))\n+\t{\n+\t  if (annotation_p (attr))\n+\t    {\n+\t      *pannotations = attr;\n+\t      pannotations = &TREE_CHAIN (attr);\n+\t    }\n+\t  else if (!attribute_ignored_p (attr))\n+\t    {\n+\t      if (std_attrs)\n+\t\twarning_at (attrs_loc, OPT_Wattributes,\n+\t\t\t    \"attributes on base specifiers are ignored\");\n+\t      std_attrs = NULL_TREE;\n+\t    }\n+\t}\n+      *pannotations = NULL_TREE;\n+    }\n \n   /* Process the optional `virtual' and `access-specifier'.  */\n   while (!done)\n@@ -30927,17 +31779,14 @@ cp_parser_base_specifier (cp_parser* parser)\n     }\n   /* It is not uncommon to see programs mechanically, erroneously, use\n      the 'typename' keyword to denote (dependent) qualified types\n-     as base classes.  */\n+     as base classes.  The diagnostic is deferred because if typename is\n+     be followed by [:, it depends on whether it is splice-scope-specifier\n+     or splice-type-specifier.  */\n   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))\n     {\n-      token = cp_lexer_peek_token (parser->lexer);\n-      if (!processing_template_decl)\n-\terror_at (token->location,\n-\t\t  \"keyword %<typename%> not allowed outside of templates\");\n-      else\n-\terror_at (token->location,\n-\t\t  \"keyword %<typename%> not allowed in this context \"\n-\t\t  \"(the base class is implicitly a type)\");\n+      typename_token = cp_lexer_peek_token (parser->lexer);\n+      if (cp_parser_next_tokens_start_splice_type_spec_p (parser, true))\n+\tsplice_token = cp_lexer_peek_nth_token (parser->lexer, 2);\n       cp_lexer_consume_token (parser->lexer);\n     }\n \n@@ -30965,10 +31814,35 @@ cp_parser_base_specifier (cp_parser* parser)\n   class_scope_p = (parser->scope && TYPE_P (parser->scope));\n   template_p = class_scope_p && cp_parser_optional_template_keyword (parser);\n \n+  if (typename_token && cp_lexer_peek_token (parser->lexer) != splice_token)\n+    {\n+      /* Emit deferred diagnostics for invalid typename keyword if\n+\t cp_parser_nested_name_specifier_opt parsed splice-scope-specifier.  */\n+      // TODO This error should be removed:\n+      // struct A { struct B {}; };\n+      // typename A::B b;\n+      // is valid.\n+      if (!processing_template_decl)\n+\terror_at (typename_token->location,\n+\t\t  \"keyword %<typename%> not allowed outside of templates\");\n+      else\n+\terror_at (typename_token->location,\n+\t\t  \"keyword %<typename%> not allowed in this context \"\n+\t\t  \"(the base class is implicitly a type)\");\n+    }\n+\n   if (!parser->scope\n       && cp_lexer_next_token_is_decltype (parser->lexer))\n     /* DR 950 allows decltype as a base-specifier.  */\n     type = cp_parser_decltype (parser);\n+  else if (!parser->scope\n+\t   && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SPLICE))\n+    {\n+      /* Parse C++26 splice-type-specifier.  */\n+      type = cp_parser_splice_type_specifier (parser);\n+      if (type == NULL_TREE)\n+\treturn error_mark_node;\n+    }\n   else\n     {\n       /* Otherwise, look for the class-name.  */\n@@ -30988,7 +31862,7 @@ cp_parser_base_specifier (cp_parser* parser)\n   if (type == error_mark_node)\n     return error_mark_node;\n \n-  return finish_base_specifier (type, access, virtual_p);\n+  return finish_base_specifier (type, access, virtual_p, annotations);\n }\n \n /* Exception handling [gram.exception] */\n@@ -32372,6 +33246,21 @@ cp_parser_check_std_attribute (location_t loc, tree attributes, tree attribute)\n   return true;\n }\n \n+/* Parse a C++-26 annotation.\n+\n+  annotation:\n+    = constant-expression  */\n+\n+static tree\n+cp_parser_annotation (cp_parser *parser)\n+{\n+  cp_parser_require (parser, CPP_EQ, RT_EQ);\n+  auto suppression = make_temp_override (suppress_location_wrappers, 0);\n+  return cp_parser_constant_expression (parser, /*allow_non_constant_p=*/false,\n+\t\t\t\t\t/*non_constant_p=*/nullptr,\n+\t\t\t\t\t/*strict_p=*/true);\n+}\n+\n /* Parse a list of standard C++-11 attributes.\n \n    attribute-list:\n@@ -32389,7 +33278,22 @@ cp_parser_std_attribute_list (cp_parser *parser, tree attr_ns)\n \n   while (true)\n     {\n-      location_t loc = cp_lexer_peek_token (parser->lexer)->location;\n+      token = cp_lexer_peek_token (parser->lexer);\n+      location_t loc = token->location;\n+      if (token->type == CPP_EQ)\n+\t{\n+\t  error_at (loc, \"mixing annotations and attributes in the same list\");\n+\t  tree annotation = cp_parser_annotation (parser);\n+\t  if (annotation == error_mark_node)\n+\t    break;\n+\t  if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))\n+\t    cp_lexer_consume_token (parser->lexer);\n+\t  token = cp_lexer_peek_token (parser->lexer);\n+\t  if (token->type != CPP_COMMA)\n+\t    break;\n+\t  cp_lexer_consume_token (parser->lexer);\n+\t  continue;\n+\t}\n       attribute = cp_parser_std_attribute (parser, attr_ns);\n       if (attribute == error_mark_node)\n \tbreak;\n@@ -32781,10 +33685,70 @@ void cp_parser_late_contract_condition (cp_parser *parser,\n     }\n }\n \n+/* Parse a C++-26 annotation list.\n+\n+   annotation-list:\n+     annotation ... [opt]\n+     annotation-list , annotation ... [opt]\n+\n+   annotation:\n+     = constant-expression  */\n+\n+static tree\n+cp_parser_annotation_list (cp_parser *parser)\n+{\n+  tree attributes = NULL_TREE;\n+\n+  while (true)\n+    {\n+      cp_token *token = cp_lexer_peek_token (parser->lexer);\n+      location_t loc = token->location;\n+      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))\n+\t{\n+\t  tree annotation = cp_parser_annotation (parser);\n+\t  if (annotation == error_mark_node)\n+\t    break;\n+\t  annotation = build_tree_list (NULL_TREE, annotation);\n+\t  if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))\n+\t    {\n+\t      cp_lexer_consume_token (parser->lexer);\n+\t      annotation = make_pack_expansion (annotation);\n+\t      if (annotation == error_mark_node)\n+\t\tbreak;\n+\t    }\n+\t  attributes = tree_cons (build_tree_list (internal_identifier,\n+\t\t\t\t\t\t   annotation_identifier),\n+\t\t\t\t  annotation, attributes);\n+\t}\n+      else if (token->type == CPP_NAME\n+\t       || token->type == CPP_KEYWORD\n+\t       || (token->flags & NAMED_OP))\n+\t{\n+\t  error_at (loc, \"mixing annotations and attributes in the same list\");\n+\t  if (cp_parser_std_attribute (parser, NULL_TREE) == error_mark_node)\n+\t    break;\n+\t  if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))\n+\t    cp_lexer_consume_token (parser->lexer);\n+\t}\n+      else\n+\t{\n+\t  cp_parser_require (parser, CPP_EQ, RT_EQ);\n+\t  break;\n+\t}\n+      token = cp_lexer_peek_token (parser->lexer);\n+      if (token->type != CPP_COMMA)\n+\tbreak;\n+      cp_lexer_consume_token (parser->lexer);\n+    }\n+  attributes = nreverse (attributes);\n+  return attributes;\n+}\n+\n /* Parse a standard C++-11 attribute specifier.\n \n    attribute-specifier:\n      [ [ attribute-using-prefix [opt] attribute-list ] ]\n+     [ [ annotation-list ]]\n      contract-attribute-specifier\n      alignment-specifier\n \n@@ -32823,6 +33787,20 @@ cp_parser_std_attribute_spec (cp_parser *parser)\n       cp_lexer_consume_token (parser->lexer);\n \n       token = cp_lexer_peek_token (parser->lexer);\n+      if (token->type == CPP_EQ)\n+\t{\n+\t  if (cxx_dialect < cxx26)\n+\t    pedwarn (token->location, OPT_Wc__26_extensions,\n+\t\t     \"annotations only available with %<-std=c++2c%> \"\n+\t\t     \"or %<-std=gnu++2c%>\");\n+\t  attributes = cp_parser_annotation_list (parser);\n+\t  if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)\n+\t      || !cp_parser_require (parser, CPP_CLOSE_SQUARE,\n+\t\t\t\t     RT_CLOSE_SQUARE))\n+\t    cp_parser_skip_to_end_of_statement (parser);\n+\t  return attributes;\n+\t}\n+\n       if (token->type == CPP_NAME)\n \t{\n \t  attr_name = token->u.value;\n@@ -32984,7 +33962,7 @@ static size_t\n cp_parser_skip_balanced_tokens (cp_parser *parser, size_t n)\n {\n   size_t orig_n = n;\n-  int nparens = 0, nbraces = 0, nsquares = 0;\n+  int nparens = 0, nbraces = 0, nsquares = 0, nsplices = 0;\n   do\n     switch (cp_lexer_peek_nth_token (parser->lexer, n++)->type)\n       {\n@@ -33004,6 +33982,9 @@ cp_parser_skip_balanced_tokens (cp_parser *parser, size_t n)\n       case CPP_OPEN_SQUARE:\n \t++nsquares;\n \tbreak;\n+      case CPP_OPEN_SPLICE:\n+\t++nsplices;\n+\tbreak;\n       case CPP_CLOSE_PAREN:\n \t--nparens;\n \tbreak;\n@@ -33013,10 +33994,13 @@ cp_parser_skip_balanced_tokens (cp_parser *parser, size_t n)\n       case CPP_CLOSE_SQUARE:\n \t--nsquares;\n \tbreak;\n+      case CPP_CLOSE_SPLICE:\n+\t--nsplices;\n+\tbreak;\n       default:\n \tbreak;\n       }\n-  while (nparens || nbraces || nsquares);\n+  while (nparens || nbraces || nsquares || nsplices);\n   return n;\n }\n \n@@ -33830,12 +34814,10 @@ cp_parser_simple_requirement (cp_parser *parser)\n \n /* Parse a type requirement\n \n-     type-requirement\n-         nested-name-specifier [opt] required-type-name ';'\n-\n-     required-type-name:\n-         type-name\n-         'template' [opt] simple-template-id  */\n+     type-requirement:\n+       typename nested-name-specifier [opt] type-name ';'\n+       typename splice-specifier ';'\n+       typename splice-specialization-specifier ';' */\n \n static tree\n cp_parser_type_requirement (cp_parser *parser)\n@@ -33866,8 +34848,15 @@ cp_parser_type_requirement (cp_parser *parser)\n       type = make_typename_type (parser->scope, type, typename_type,\n                                  /*complain=*/tf_error);\n     }\n+  else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SPLICE))\n+    {\n+      /* tsubst_type_requirement wants this to be a type.  */\n+      type = cp_parser_splice_type_specifier (parser);\n+      if (!type)\n+\ttype = error_mark_node;\n+    }\n   else\n-   type = cp_parser_type_name (parser, /*typename_keyword_p=*/true);\n+    type = cp_parser_type_name (parser, /*typename_keyword_p=*/true);\n \n   if (TREE_CODE (type) == TYPE_DECL)\n     type = TREE_TYPE (type);\n@@ -34139,8 +35128,9 @@ cp_parser_lookup_name (cp_parser *parser, tree name,\n \t looking up names in uninstantiated templates.  Even then, we\n \t cannot look up the name if the scope is not a class type; it\n \t might, for example, be a template type parameter.  */\n-      dependent_p = (TYPE_P (parser->scope)\n-\t\t     && dependent_scope_p (parser->scope));\n+      dependent_p = ((TYPE_P (parser->scope)\n+\t\t      && dependent_scope_p (parser->scope))\n+\t\t     || dependent_namespace_p (parser->scope));\n       if ((check_dependency || !CLASS_TYPE_P (parser->scope))\n \t  && dependent_p)\n \t/* Defer lookup.  */\n@@ -34192,8 +35182,10 @@ cp_parser_lookup_name (cp_parser *parser, tree name,\n \n       /* If the scope is a dependent type and either we deferred lookup or\n \t we did lookup but didn't find the name, rememeber the name.  */\n-      if (decl == error_mark_node && TYPE_P (parser->scope)\n-\t  && dependentish_scope_p (parser->scope))\n+      if (decl == error_mark_node\n+\t  && ((TYPE_P (parser->scope)\n+\t       && dependentish_scope_p (parser->scope))\n+\t      || dependent_namespace_p (parser->scope)))\n \t{\n \t  if (tag_type)\n \t    {\n@@ -34307,7 +35299,10 @@ cp_parser_lookup_name (cp_parser *parser, tree name,\n \n      During an explicit instantiation, access is not checked at all,\n      as per [temp.explicit].  */\n-  if (DECL_P (decl))\n+  if (DECL_P (decl)\n+      /* One cannot take the reflection of a using-declarator.  Skip this\n+\t check because we are going to report an error anyway.  */\n+      && LIKELY (TREE_CODE (decl) != USING_DECL))\n     check_accessibility_of_qualified_id (decl, object_type, parser->scope,\n \t\t\t\t\t tf_warning_or_error);\n \n@@ -36645,6 +37640,9 @@ cp_parser_required_error (cp_parser *parser,\n \t  case RT_CLASS_TYPENAME_TEMPLATE:\n \t    gmsgid = G_(\"expected %<class%>, %<typename%>, or %<template%>\");\n \t    break;\n+\t  case RT_CLOSE_SPLICE:\n+\t    gmsgid = G_(\"expected %<:]%>\");\n+\t    break;\n \t  default:\n \t    gcc_unreachable ();\n \t}\ndiff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc\nindex 20a1177ffab..55b6676f540 100644\n--- a/gcc/cp/pt.cc\n+++ b/gcc/cp/pt.cc\n@@ -277,6 +277,18 @@ pop_access_scope (tree t)\n     pop_from_top_level ();\n }\n \n+/* Return current function, ignoring temporary overrides\n+   of current_function_decl by push_access_scope.  */\n+\n+tree\n+current_function_decl_without_access_scope ()\n+{\n+  if (vec_safe_length (saved_access_scope))\n+    return (*saved_access_scope)[0];\n+  else\n+    return current_function_decl;\n+}\n+\n /* Do any processing required when DECL (a member template\n    declaration) is finished.  Returns the TEMPLATE_DECL corresponding\n    to DECL, unless it is a specialization, in which case the DECL\n@@ -1216,7 +1228,7 @@ verify_unstripped_args_1 (tree inner)\n   for (int i = 0; i < TREE_VEC_LENGTH (inner); ++i)\n     {\n       tree arg = TREE_VEC_ELT (inner, i);\n-      if (TREE_CODE (arg) == TEMPLATE_DECL)\n+      if (TREE_CODE (arg) == TEMPLATE_DECL || REFLECT_EXPR_P (arg))\n \t/* OK */;\n       else if (TYPE_P (arg))\n \tgcc_assert (strip_typedefs (arg, NULL) == arg);\n@@ -1899,6 +1911,22 @@ iterative_hash_template_arg (tree arg, hashval_t val)\n \treturn val;\n       }\n \n+    case REFLECT_EXPR:\n+      val = iterative_hash_hashval_t (REFLECT_EXPR_KIND (arg), val);\n+      if (REFLECT_EXPR_KIND (arg) == REFLECT_BASE)\n+\t{\n+\t  tree binfo = REFLECT_EXPR_HANDLE (arg);\n+\t  val = iterative_hash_template_arg (BINFO_TYPE (binfo), val);\n+\t  tree d = binfo;\n+\t  /* Looping needed for multiple virtual inheritance.  */\n+\t  while (BINFO_INHERITANCE_CHAIN (d))\n+\t    d = BINFO_INHERITANCE_CHAIN (d);\n+\t  val = iterative_hash_template_arg (BINFO_TYPE (d), val);\n+\t  return val;\n+\t}\n+      /* Now hash operands as usual.  */\n+      break;\n+\n     default:\n       break;\n     }\n@@ -1920,7 +1948,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)\n \n       switch (code)\n \t{\n-\tcase  DECLTYPE_TYPE:\n+\tcase DECLTYPE_TYPE:\n \t  val = iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);\n \t  break;\n \n@@ -7980,6 +8008,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)\n       if (expr == error_mark_node)\n \treturn NULL_TREE;\n     }\n+  else if (REFLECTION_TYPE_P (type))\n+    {\n+      if (!REFLECTION_TYPE_P (TREE_TYPE (expr)))\n+\t{\n+\t  if (complain & tf_error)\n+\t    error (\"%qE is not a valid template argument for type %qT \"\n+\t\t   \"because it is of type %qT\", expr, type, TREE_TYPE (expr));\n+\t  return NULL_TREE;\n+\t}\n+      return expr;\n+    }\n   /* A template non-type parameter must be one of the above.  */\n   else\n     gcc_unreachable ();\n@@ -10941,6 +10980,11 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)\n \treturn error_mark_node;\n       break;\n \n+    case SPLICE_SCOPE:\n+      WALK_SUBTREE (SPLICE_SCOPE_EXPR (t));\n+      *walk_subtrees = 0;\n+      break;\n+\n     default:\n       break;\n     }\n@@ -12745,20 +12789,31 @@ instantiate_class_template (tree type)\n \t{\n \t  tree base;\n \t  tree access = BINFO_BASE_ACCESS (pbinfo, i);\n+\t  tree annotations = NULL_TREE;\n           tree expanded_bases = NULL_TREE;\n           int idx, len = 1;\n \n+\t  if (i + BINFO_BASE_BINFOS (pbinfo)->length ()\n+\t      < vec_safe_length (BINFO_BASE_ACCESSES (pbinfo)))\n+\t    annotations\n+\t      = BINFO_BASE_ACCESS (pbinfo,\n+\t\t\t\t   i + BINFO_BASE_BINFOS (pbinfo)->length ());\n+\n           if (PACK_EXPANSION_P (BINFO_TYPE (pbase_binfo)))\n             {\n-              expanded_bases =\n-\t\ttsubst_pack_expansion (BINFO_TYPE (pbase_binfo),\n-\t\t\t\t       args, tf_error, NULL_TREE);\n+\t      expanded_bases\n+\t\t= tsubst_pack_expansion (BINFO_TYPE (pbase_binfo),\n+\t\t\t\t\t args, tf_error, NULL_TREE);\n               if (expanded_bases == error_mark_node)\n                 continue;\n \n               len = TREE_VEC_LENGTH (expanded_bases);\n             }\n \n+\t  if (annotations)\n+\t    annotations = tsubst_attributes (annotations, args,\n+\t\t\t\t\t     tf_warning_or_error, NULL_TREE);\n+\n           for (idx = 0; idx < len; idx++)\n             {\n               if (expanded_bases)\n@@ -12772,7 +12827,13 @@ instantiate_class_template (tree type)\n               if (base == error_mark_node)\n                 continue;\n \n-              base_list = tree_cons (access, base, base_list);\n+\t      tree acc = access;\n+\t      if (annotations)\n+\t\t/* Make sure each direct base from the pack has its unique\n+\t\t   set of annotations.  */\n+\t\tacc = build_tree_list (access, idx == 0 ? annotations\n+\t\t\t\t\t       : copy_list (annotations));\n+\t      base_list = tree_cons (acc, base, base_list);\n               if (BINFO_VIRTUAL_P (pbase_binfo))\n                 TREE_TYPE (base_list) = integer_type_node;\n             }\n@@ -14236,7 +14297,7 @@ tsubst_tree_vec (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n    node if only a partial substitution could be performed, or ERROR_MARK_NODE\n    if there was an error.  */\n \n-tree\n+static tree\n tsubst_pack_index (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n {\n   tree pack = PACK_INDEX_PACK (t);\n@@ -16148,6 +16209,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,\n       }\n       break;\n \n+    case NAMESPACE_DECL:\n+      if (dependent_namespace_p (t))\n+\tr = tsubst_expr (ORIGINAL_NAMESPACE (t), args, complain, in_decl);\n+      else\n+\tr = t;\n+      break;\n+\n     default:\n       gcc_unreachable ();\n     }\n@@ -16587,6 +16655,91 @@ tsubst_tree_list (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n   return chain;\n }\n \n+/* Substitute ARGS into T, which is a splice scope.  */\n+\n+static tree\n+tsubst_splice_scope (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n+{\n+  tree r = tsubst (SPLICE_SCOPE_EXPR (t), args, complain, in_decl);\n+  if (r == error_mark_node)\n+    return r;\n+  if (dependent_splice_p (r))\n+    return make_splice_scope (r, SPLICE_SCOPE_TYPE_P (t));\n+  if (SPLICE_SCOPE_TYPE_P (t)\n+      ? !valid_splice_type_p (r)\n+      : !valid_splice_scope_p (r))\n+    {\n+      if (complain & tf_error)\n+\t{\n+\t  const location_t loc = EXPR_LOCATION (SPLICE_SCOPE_EXPR (t));\n+\t  if (SPLICE_SCOPE_TYPE_P (t))\n+\t    error_at (loc, \"%qE is not usable in a splice type\", r);\n+\t  else\n+\t    error_at (loc, \"%qE is not usable in a splice scope\", r);\n+\t}\n+      return error_mark_node;\n+    }\n+\n+  return r;\n+}\n+\n+/* Substitute ARGS into T, which is a splice expression.  */\n+\n+static tree\n+tsubst_splice_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n+{\n+  tree op = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl);\n+  if (op == error_mark_node)\n+    return error_mark_node;\n+  op = splice (op);\n+  if (dependent_splice_p (op))\n+    {\n+      if (SPLICE_EXPR_EXPRESSION_P (t))\n+\tSET_SPLICE_EXPR_EXPRESSION_P (op);\n+      if (SPLICE_EXPR_MEMBER_ACCESS_P (t))\n+\tSET_SPLICE_EXPR_MEMBER_ACCESS_P (op, true);\n+      if (SPLICE_EXPR_ADDRESS_P (t))\n+\tSET_SPLICE_EXPR_ADDRESS_P (op, true);\n+      return op;\n+    }\n+  if (SPLICE_EXPR_EXPRESSION_P (t)\n+      && !check_splice_expr (input_location, UNKNOWN_LOCATION, op,\n+\t\t\t     SPLICE_EXPR_ADDRESS_P (t),\n+\t\t\t     SPLICE_EXPR_MEMBER_ACCESS_P (t),\n+\t\t\t     (complain & tf_error)))\n+    return error_mark_node;\n+  if (outer_automatic_var_p (op))\n+    op = process_outer_var_ref (op, complain);\n+  /* Like in cp_parser_splice_expression, for foo.[: bar :]\n+     cp_parser_postfix_dot_deref_expression wants to see only\n+     certain kind of entities.  */\n+  if (SPLICE_EXPR_MEMBER_ACCESS_P (t))\n+    {\n+      if (TREE_CODE (op) == FIELD_DECL\n+\t  || VAR_P (op)\n+\t  || TREE_CODE (op) == CONST_DECL\n+\t  || TREE_CODE (op) == FUNCTION_DECL\n+\t  || DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (op))\n+\t  || variable_template_p (op))\n+\t;\n+      else\n+\t{\n+\t  if (DECL_P (op))\n+\t    /* If we are called from tsubst_expr/SCOPE_REF, we'll build\n+\t       the SCOPE_REF there.  */\n+\t    op = DECL_NAME (op);\n+\t  else if (OVL_P (op))\n+\t    op = OVL_NAME (op);\n+\t  gcc_assert (identifier_p (op)\n+\t\t      || BASELINK_P (op)\n+\t\t      || TREE_CODE (op) == TEMPLATE_ID_EXPR\n+\t\t      || TREE_CODE (op) == TREE_BINFO);\n+\t}\n+    }\n+\n+  return op;\n+}\n+\n /* Take the tree structure T and replace template parameters used\n    therein with the argument vector ARGS.  IN_DECL is an associated\n    decl for diagnostics.  If an error occurs, returns ERROR_MARK_NODE.\n@@ -16614,7 +16767,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n       || t == void_type_node\n       || t == char_type_node\n       || t == unknown_type_node\n-      || TREE_CODE (t) == NAMESPACE_DECL\n       || TREE_CODE (t) == TRANSLATION_UNIT_DECL)\n     return t;\n \n@@ -16750,6 +16902,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n     case VECTOR_TYPE:\n     case BOOLEAN_TYPE:\n     case NULLPTR_TYPE:\n+    case META_TYPE:\n     case LANG_TYPE:\n       return t;\n \n@@ -17303,6 +17456,39 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \tif (f == error_mark_node)\n \t  return error_mark_node;\n \n+\t/* We had [:X:]:: which was substituted into a NAMESPACE_DECL and not\n+\t   a type.  */\n+\tif (TREE_CODE (ctx) == NAMESPACE_DECL)\n+\t  {\n+\t    if (TREE_CODE (f) == TEMPLATE_ID_EXPR)\n+\t      {\n+\t\ttree d = TREE_OPERAND (f, 0);\n+\t\ttree n = TREE_OPERAND (f, 1);\n+\t\tf = lookup_template_class (d, n, in_decl, ctx, complain);\n+\t\tif (f == error_mark_node)\n+\t\t  return error_mark_node;\n+\t      }\n+\t    else\n+\t      {\n+\t\tgcc_assert (TREE_CODE (f) == IDENTIFIER_NODE);\n+\t\ttree decl = lookup_qualified_name (ctx, f);\n+\t\tif (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)\n+\t\t  {\n+\t\t    qualified_name_lookup_error (ctx, f, decl, input_location);\n+\t\t    return error_mark_node;\n+\t\t  }\n+\t\tif (TREE_CODE (decl) == NAMESPACE_DECL)\n+\t\t  return decl;\n+\t\telse\n+\t\t  {\n+\t\t    gcc_checking_assert (TREE_CODE (decl) == TYPE_DECL);\n+\t\t    f = TREE_TYPE (decl);\n+\t\t  }\n+\t      }\n+\t    return cp_build_qualified_type\n+\t\t    (f, cp_type_quals (f) | cp_type_quals (t), complain);\n+\t  }\n+\n \tif (!MAYBE_CLASS_TYPE_P (ctx))\n \t  {\n \t    if (complain & tf_error)\n@@ -17468,6 +17654,35 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n     case PACK_INDEX_TYPE:\n       return tsubst_pack_index (t, args, complain, in_decl);\n \n+    case SPLICE_SCOPE:\n+      return tsubst_splice_scope (t, args, complain, in_decl);\n+\n+    case SPLICE_EXPR:\n+      /* We are coming from tsubst_splice_scope for [:R:]\n+\t where R needs to expand to a type or scope.  */\n+      gcc_checking_assert (!SPLICE_EXPR_EXPRESSION_P (t));\n+      return tsubst_splice_expr (t, args, complain, in_decl);\n+\n+    case TEMPLATE_ID_EXPR:\n+      {\n+\t/* We end up here coming from tsubst_splice_scope for\n+\t   [:R:]<int>.  R needs to expand to a type or scope.  */\n+\ttree templ = TREE_OPERAND (t, 0);\n+\tgcc_assert (TREE_CODE (templ) == SPLICE_EXPR);\n+\ttempl = tsubst_splice_expr (templ, args, complain, in_decl);\n+\tif (templ == error_mark_node)\n+\t  return error_mark_node;\n+\ttree targs = TREE_OPERAND (t, 1);\n+\tif (targs)\n+\t  targs = tsubst_template_args (targs, args, complain, in_decl);\n+\tif (targs == error_mark_node)\n+\t  return error_mark_node;\n+\ttree r = finish_template_type (templ, targs, /*entering_scope=*/false);\n+\tif (TREE_CODE (r) == TYPE_DECL)\n+\t  r = TREE_TYPE (r);\n+\treturn r;\n+      }\n+\n     case VOID_CST:\n     case INTEGER_CST:\n     case REAL_CST:\n@@ -17497,7 +17712,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n static tree\n tsubst_scope (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n {\n-  gcc_checking_assert (TYPE_P (t));\n+  gcc_checking_assert (TYPE_P (t) || TREE_CODE (t) == NAMESPACE_DECL);\n   return tsubst (t, args, complain | tf_qualifying_scope, in_decl);\n }\n \n@@ -17790,7 +18005,7 @@ tsubst_qualified_id (tree qualified_id, tree args,\n   else\n     expr = name;\n \n-  if (dependent_scope_p (scope))\n+  if (dependent_scope_p (scope) || dependent_namespace_p (scope))\n     {\n       if (TREE_CODE (expr) == SCOPE_REF)\n \t/* We built one in tsubst_baselink.  */\n@@ -20490,10 +20705,9 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \n   tree r = build_lambda_expr ();\n \n-  LAMBDA_EXPR_LOCATION (r)\n-    = LAMBDA_EXPR_LOCATION (t);\n-  LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)\n-    = LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);\n+  LAMBDA_EXPR_LOCATION (r) = LAMBDA_EXPR_LOCATION (t);\n+  LAMBDA_EXPR_CONSTEVAL_BLOCK_P (r) = LAMBDA_EXPR_CONSTEVAL_BLOCK_P (t);\n+  LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r) = LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);\n   if (tree ti = LAMBDA_EXPR_REGEN_INFO (t))\n     LAMBDA_EXPR_REGEN_INFO (r)\n       = build_template_info (t, add_to_template_args (TI_ARGS (ti),\n@@ -22119,7 +22333,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \t    /* Assume access of this FIELD_DECL has already been checked; we\n \t       don't recheck it to avoid bogus access errors when substituting\n \t       a reduced constant initializer (97740).  */\n-\t    gcc_checking_assert (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL);\n+\t    gcc_checking_assert (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL\n+\t\t\t\t || dependent_splice_p (TREE_OPERAND (t, 1)));\n \t    push_deferring_access_checks (dk_deferred);\n \t    r = finish_non_static_data_member (member, object, NULL_TREE,\n \t\t\t\t\t       complain);\n@@ -22195,7 +22410,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \n \tr = finish_class_member_access_expr (object, member,\n \t\t\t\t\t     /*template_p=*/false,\n-\t\t\t\t\t     complain);\n+\t\t\t\t\t     complain,\n+\t\t\t\t\t     COMPONENT_REF_SPLICE_P (t));\n \tif (REF_PARENTHESIZED_P (t))\n \t  r = force_paren_expr (r);\n \tRETURN (r);\n@@ -22517,9 +22733,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \t}\n       RETURN (t);\n \n-    case NAMESPACE_DECL:\n-      RETURN (t);\n-\n     case OVERLOAD:\n       if (modules_p ())\n \tfor (tree ovl : lkp_range (t))\n@@ -22592,7 +22805,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n       }\n \n     case PACK_INDEX_EXPR:\n-    RETURN (tsubst_pack_index (t, args, complain, in_decl));\n+      RETURN (tsubst_pack_index (t, args, complain, in_decl));\n \n     case EXPR_PACK_EXPANSION:\n       error (\"invalid use of pack expansion expression\");\n@@ -22809,6 +23022,25 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)\n \tRETURN (op);\n       }\n \n+    case REFLECT_EXPR:\n+      {\n+\ttree h = REFLECT_EXPR_HANDLE (t);\n+\treflect_kind kind = REFLECT_EXPR_KIND (t);\n+\tif (TYPE_P (h) || TREE_CODE (h) == NAMESPACE_DECL)\n+\t  h = tsubst (h, args, complain, in_decl);\n+\telse\n+\t  {\n+\t    /* [expr.reflect] The id-expression of a reflect-expression is\n+\t       an unevaluated operand.  */\n+\t    cp_unevaluated u;\n+\t    h = RECUR (h);\n+\t  }\n+\tRETURN (get_reflection (EXPR_LOCATION (t), h, kind));\n+      }\n+\n+    case SPLICE_EXPR:\n+      RETURN (tsubst_splice_expr (t, args, complain, in_decl));\n+\n     default:\n       /* Handle Objective-C++ constructs, if appropriate.  */\n       if (tree subst = objcp_tsubst_expr (t, args, complain, in_decl))\n@@ -26014,6 +26246,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,\n     case VOID_TYPE:\n     case OPAQUE_TYPE:\n     case NULLPTR_TYPE:\n+    case META_TYPE:\n       if (TREE_CODE (arg) != TREE_CODE (parm))\n \treturn unify_type_mismatch (explain_p, parm, arg);\n \n@@ -28139,6 +28372,8 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p)\n       if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))\n \tcp_check_omp_declare_reduction (d);\n \n+      check_consteval_only_fn (d);\n+\n       if (int errs = errorcount + sorrycount)\n \tif (errs > current_tinst_level->errors)\n \t  if (function *f = DECL_STRUCT_FUNCTION (d))\n@@ -28705,6 +28940,8 @@ tsubst_enum (tree tag, tree newtag, tree args)\n   if (SCOPED_ENUM_P (newtag))\n     begin_scope (sk_scoped_enum, newtag);\n \n+  ENUM_BEING_DEFINED_P (newtag) = 1;\n+\n   for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))\n     {\n       tree value;\n@@ -28985,6 +29222,11 @@ dependent_type_p_r (tree type)\n   if (TREE_CODE (type) == DEPENDENT_OPERATOR_TYPE)\n     return true;\n \n+  /* A splice-scope-specifier is dependent if its splice-specifier\n+     or splice-specialization-specifier is dependent.  */\n+  if (TREE_CODE (type) == SPLICE_SCOPE)\n+    return true;\n+\n   if (any_dependent_type_attributes_p (TYPE_ATTRIBUTES (type)))\n     return true;\n \n@@ -29074,6 +29316,17 @@ dependentish_scope_p (tree scope)\n   return dependent_scope_p (scope) || any_dependent_bases_p (scope);\n }\n \n+/* Returns TRUE if NS is a dependent namespace, in which we can't do any\n+   lookup.  */\n+\n+bool\n+dependent_namespace_p (tree ns)\n+{\n+  if (TREE_CODE (ns) == NAMESPACE_DECL)\n+    ns = ORIGINAL_NAMESPACE (ns);\n+  return TREE_CODE (ns) == SPLICE_EXPR;\n+}\n+\n /* T is a SCOPE_REF.  Return whether it represents a non-static member of\n    an unknown base of 'this' (and is therefore instantiation-dependent).  */\n \n@@ -29352,6 +29605,24 @@ value_dependent_expression_p (tree expression)\n \t    if (value_dependent_expression_p (op))\n \t      return true;\n \t  }\n+\tif (flag_reflection && !fn && CALL_EXPR_FN (expression))\n+\t  {\n+\t    fn = MAYBE_BASELINK_FUNCTIONS (CALL_EXPR_FN (expression));\n+\t    if (fn && TREE_CODE (fn) != FUNCTION_DECL)\n+\t      fn = NULL_TREE;\n+\t  }\n+\t/* [meta.reflection.access.context]/8: An invocation of current that\n+\t   appears at a program point P is value-dependent if eval-point(P)\n+\t   is enclosed by a scope corresponding to a templated entity.  */\n+\tif (flag_reflection\n+\t    && fn\n+\t    && metafunction_p (fn)\n+\t    && id_equal (DECL_NAME (fn), \"current\")\n+\t    && DECL_CLASS_SCOPE_P (fn)\n+\t    && id_equal (TYPE_IDENTIFIER (DECL_CONTEXT (fn)),\n+\t\t\t \"access_context\"))\n+\t  return true;\n+\n \treturn false;\n       }\n \n@@ -29384,6 +29655,24 @@ value_dependent_expression_p (tree expression)\n \t      || value_dependent_expression_p (TREE_OPERAND (expression, 2))\n \t      || value_dependent_expression_p (TREE_OPERAND (expression, 3)));\n \n+    case REFLECT_EXPR:\n+      /* [temp.dep.constexpr] A reflect-expression is value-dependent\n+\t if it contains a dependent nested-name-specifier, type-id,\n+\t namespace-name, or template-name, or if it contains\n+\t a value-dependent or type-dependent id-expression.  */\n+      if (REFLECT_EXPR_KIND (expression) == REFLECT_BASE)\n+\t/* Direct base relationship isn't value-dependent and calling\n+\t   uses_template_parms on TREE_BINFO leads to ICEs.  */\n+\treturn false;\n+      if (REFLECT_EXPR_KIND (expression) == REFLECT_DATA_MEMBER_SPEC)\n+\t{\n+\t  /* Data member description is value dependent if the type is\n+\t     dependent, other optional fields shouldn't be ever dependent.  */\n+\t  tree h = REFLECT_EXPR_HANDLE (expression);\n+\t  return dependent_type_p (TREE_VEC_ELT (h, 0));\n+\t}\n+      return uses_template_parms (REFLECT_EXPR_HANDLE (expression));\n+\n     default:\n       /* A constant expression is value-dependent if any subexpression is\n \t value-dependent.  */\n@@ -29473,7 +29762,8 @@ type_dependent_expression_p (tree expression)\n       || TREE_CODE (expression) == DELETE_EXPR\n       || TREE_CODE (expression) == VEC_DELETE_EXPR\n       || TREE_CODE (expression) == THROW_EXPR\n-      || TREE_CODE (expression) == REQUIRES_EXPR)\n+      || TREE_CODE (expression) == REQUIRES_EXPR\n+      || REFLECT_EXPR_P (expression))\n     return false;\n \n   /* The types of these expressions depends only on the type to which\n@@ -33093,6 +33383,24 @@ finish_expansion_stmt (tree expansion_stmt, tree args,\n     }\n }\n \n+/* Perform the appropriate conversion of the argument of\n+   std::meta::reflect_constant.   EXPR is the argument, TYPE is its type.\n+   Mainly, the point is to check that the type is valid in this context\n+   and maybe replace the argument with a reference to the corresponding\n+   template parameter object.  */\n+\n+tree\n+convert_reflect_constant_arg (tree type, tree expr)\n+{\n+  if (invalid_nontype_parm_type_p (type, tf_none))\n+    return error_mark_node;\n+\n+  expr = convert_nontype_argument (type, expr, tf_none);\n+  if (!expr)\n+    return error_mark_node;\n+  return expr;\n+}\n+\n /* Set up the hash tables for template instantiations.  */\n \n void\ndiff --git a/gcc/cp/search.cc b/gcc/cp/search.cc\nindex 77b5b1da527..58182a625df 100644\n--- a/gcc/cp/search.cc\n+++ b/gcc/cp/search.cc\n@@ -2123,11 +2123,15 @@ check_final_overrider (tree overrider, tree basefn)\n       return 0;\n     }\n \n-  /* A consteval virtual function shall not override a virtual function that is\n-     not consteval. A consteval virtual function shall not be overridden by a\n-     virtual function that is not consteval.  */\n-  if (DECL_IMMEDIATE_FUNCTION_P (overrider)\n-      != DECL_IMMEDIATE_FUNCTION_P (basefn))\n+  /* A class with a consteval virtual function that overrides a virtual\n+     function that is not consteval shall have consteval-only type (CWG 3117).\n+     A consteval virtual function shall not be overridden by a virtual\n+     function that is not consteval.  */\n+  if ((DECL_IMMEDIATE_FUNCTION_P (basefn)\n+       && !DECL_IMMEDIATE_FUNCTION_P (overrider))\n+      || (!DECL_IMMEDIATE_FUNCTION_P (basefn)\n+\t  && DECL_IMMEDIATE_FUNCTION_P (overrider)\n+\t  && !consteval_only_p (overrider)))\n     {\n       auto_diagnostic_group d;\n       if (DECL_IMMEDIATE_FUNCTION_P (overrider))\ndiff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc\nindex e420fd4ebaf..5b645aa5568 100644\n--- a/gcc/cp/semantics.cc\n+++ b/gcc/cp/semantics.cc\n@@ -4456,15 +4456,18 @@ finish_template_type (tree name, tree args, int entering_scope)\n     return TYPE_NAME (type);\n }\n \n-/* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.\n-   Return a TREE_LIST containing the ACCESS_SPECIFIER and the\n-   BASE_CLASS, or NULL_TREE if an error occurred.  The\n+/* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER\n+   and ANNOTATIONS.\n+   Return a TREE_LIST containing the ACCESS_SPECIFIER (or if there are\n+   ANNOTATIONS, TREE_LIST containing the ACCESS_SPECIFIER and ANNOTATIONS)\n+   and the BASE_CLASS, or NULL_TREE if an error occurred.  The\n    ACCESS_SPECIFIER is one of\n-   access_{default,public,protected_private}_node.  For a virtual base\n+   access_{default,public,protected,private}_node.  For a virtual base\n    we set TREE_TYPE.  */\n \n tree\n-finish_base_specifier (tree base, tree access, bool virtual_p)\n+finish_base_specifier (tree base, tree access, bool virtual_p,\n+\t\t       tree annotations)\n {\n   tree result;\n \n@@ -4486,6 +4489,8 @@ finish_base_specifier (tree base, tree access, bool virtual_p)\n \t     class type?  */\n \t  base = TYPE_MAIN_VARIANT (base);\n \t}\n+      if (annotations)\n+\taccess = build_tree_list (access, nreverse (annotations));\n       result = build_tree_list (access, base);\n       if (virtual_p)\n \tTREE_TYPE (result) = integer_type_node;\n@@ -4524,7 +4529,7 @@ baselink_for_fns (tree fns)\n \n /* Returns true iff we are currently parsing a lambda-declarator.  */\n \n-static bool\n+bool\n parsing_lambda_declarator ()\n {\n   cp_binding_level *b = current_binding_level;\n@@ -4774,6 +4779,7 @@ finish_id_expression_1 (tree id_expression,\n \t{\n \t  /* Name lookup failed.  */\n \t  if (scope\n+\t      && !dependent_namespace_p (scope)\n \t      && (!TYPE_P (scope)\n \t\t  || (!dependentish_scope_p (scope)\n \t\t      && !(identifier_p (id_expression)\n@@ -13642,6 +13648,57 @@ fold_builtin_is_corresponding_member (location_t loc, int nargs,\n \t\t\t\t   fold_convert (TREE_TYPE (arg1), arg2)));\n }\n \n+/* Fold __builtin_is_string_literal call.  */\n+\n+tree\n+fold_builtin_is_string_literal (location_t loc, int nargs, tree *args)\n+{\n+  /* Unless users call the builtin directly, the following 3 checks should be\n+     ensured from std::is_string_literal overloads.  */\n+  if (nargs != 1)\n+    {\n+      error_at (loc, \"%<__builtin_is_string_literal%> needs a single \"\n+\t\t\"argument\");\n+      return boolean_false_node;\n+    }\n+  tree arg = args[0];\n+  if (error_operand_p (arg))\n+    return boolean_false_node;\n+  if (!TYPE_PTR_P (TREE_TYPE (arg))\n+      || !TYPE_READONLY (TREE_TYPE (TREE_TYPE (arg)))\n+      || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (arg))))\n+    {\n+    arg_invalid:\n+      error_at (loc, \"%<__builtin_is_string_literal%> \"\n+\t\t     \"argument is not %<const char*%>, %<const wchar_t*%>, \"\n+\t\t     \"%<const char8_t*%>, %<const char16_t*%> or \"\n+\t\t     \"%<const char32_t*%>\");\n+      return boolean_false_node;\n+    }\n+  tree chart = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (arg)));\n+  if (chart != char_type_node\n+      && chart != wchar_type_node\n+      && chart != char8_type_node\n+      && chart != char16_type_node\n+      && chart != char32_type_node)\n+    goto arg_invalid;\n+\n+  STRIP_NOPS (arg);\n+  while (TREE_CODE (arg) == POINTER_PLUS_EXPR)\n+    {\n+      arg = TREE_OPERAND (arg, 0);\n+      STRIP_NOPS (arg);\n+    }\n+  if (TREE_CODE (arg) != ADDR_EXPR)\n+    return boolean_false_node;\n+  arg = TREE_OPERAND (arg, 0);\n+  if (TREE_CODE (arg) == ARRAY_REF)\n+    arg = TREE_OPERAND (arg, 0);\n+  if (TREE_CODE (arg) != STRING_CST)\n+    return boolean_false_node;\n+  return boolean_true_node;\n+}\n+\n /* [basic.types] 8.  True iff TYPE is an object type.  */\n \n static bool\n@@ -13901,6 +13958,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)\n     case CPTK_IS_DEDUCIBLE:\n       return type_targs_deducible_from (type1, type2);\n \n+    case CPTK_IS_CONSTEVAL_ONLY:\n+      return consteval_only_p (type1);\n+\n     /* __array_rank, __builtin_type_order and __builtin_structured_binding_size\n        are handled in finish_trait_expr.  */\n     case CPTK_RANK:\n@@ -14081,6 +14141,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)\n     case CPTK_IS_STD_LAYOUT:\n     case CPTK_IS_TRIVIAL:\n     case CPTK_IS_TRIVIALLY_COPYABLE:\n+    case CPTK_IS_CONSTEVAL_ONLY:\n     case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:\n       if (!check_trait_type (type1, /* kind = */ 2))\n \treturn error_mark_node;\ndiff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc\nindex 35abe553a1b..e69b1643777 100644\n--- a/gcc/cp/tree.cc\n+++ b/gcc/cp/tree.cc\n@@ -48,6 +48,7 @@ static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);\n static tree handle_abi_tag_attribute (tree *, tree, tree, int, bool *);\n static tree handle_contract_attribute (tree *, tree, tree, int, bool *);\n static tree handle_no_dangling_attribute (tree *, tree, tree, int, bool *);\n+static tree handle_annotation_attribute (tree *, tree, tree, int, bool *);\n \n /* If REF is an lvalue, returns the kind of lvalue that REF is.\n    Otherwise, returns clk_none.  */\n@@ -489,6 +490,7 @@ builtin_valid_in_constant_expr_p (const_tree decl)\n \t  case CP_BUILT_IN_IS_CORRESPONDING_MEMBER:\n \t  case CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS:\n \t  case CP_BUILT_IN_EH_PTR_ADJUST_REF:\n+\t  case CP_BUILT_IN_IS_STRING_LITERAL:\n \t    return true;\n \t  default:\n \t    break;\n@@ -4428,6 +4430,12 @@ cp_tree_equal (tree t1, tree t2)\n \treturn equivalent_member_references (t1, t2);\n       break;\n \n+    case REFLECT_EXPR:\n+      if (!cp_tree_equal (REFLECT_EXPR_HANDLE (t1), REFLECT_EXPR_HANDLE (t2))\n+\t  || REFLECT_EXPR_KIND (t1) != REFLECT_EXPR_KIND (t2))\n+\treturn false;\n+      return true;\n+\n     default:\n       break;\n     }\n@@ -5517,7 +5525,9 @@ const scoped_attribute_specs std_attribute_table =\n static const attribute_spec internal_attributes[] =\n {\n   { \"aligned\", 0, 1, false, false, false, false,\n-    handle_alignas_attribute, attr_aligned_exclusions }\n+    handle_alignas_attribute, attr_aligned_exclusions },\n+  { \"annotation \", 1, 1, false, false, false, false,\n+    handle_annotation_attribute, NULL }\n };\n \n const scoped_attribute_specs internal_attribute_table =\n@@ -5805,6 +5815,78 @@ handle_no_dangling_attribute (tree *node, tree name, tree args, int,\n   return NULL_TREE;\n }\n \n+/* Perform checking for annotations.  */\n+\n+tree\n+handle_annotation_attribute (tree *node, tree ARG_UNUSED (name),\n+\t\t\t     tree args, int ARG_UNUSED (flags),\n+\t\t\t     bool *no_add_attrs)\n+{\n+  if (TYPE_P (*node)\n+      && TREE_CODE (*node) != ENUMERAL_TYPE\n+      && TREE_CODE (*node) != RECORD_TYPE\n+      && TREE_CODE (*node) != UNION_TYPE)\n+    {\n+      error (\"annotation on a type other than class or enumeration \"\n+\t     \"definition\");\n+      *no_add_attrs = true;\n+      return NULL_TREE;\n+    }\n+  if (TREE_CODE (*node) == LABEL_DECL)\n+    {\n+      error (\"annotation applied to a label\");\n+      *no_add_attrs = true;\n+      return NULL_TREE;\n+    }\n+  if (TREE_CODE (*node) == FIELD_DECL && DECL_UNNAMED_BIT_FIELD (*node))\n+    {\n+      error (\"annotation on unnamed bit-field\");\n+      *no_add_attrs = true;\n+      return NULL_TREE;\n+    }\n+  if (!type_dependent_expression_p (TREE_VALUE (args)))\n+    {\n+      if (!structural_type_p (TREE_TYPE (TREE_VALUE (args))))\n+\t{\n+\t  auto_diagnostic_group d;\n+\t  error (\"annotation does not have structural type\");\n+\t  structural_type_p (TREE_TYPE (TREE_VALUE (args)), true);\n+\t  *no_add_attrs = true;\n+\t  return NULL_TREE;\n+\t}\n+      if (CLASS_TYPE_P (TREE_TYPE (TREE_VALUE (args))))\n+\t{\n+\t  tree arg = make_tree_vec (1);\n+\t  tree type = TREE_TYPE (TREE_VALUE (args));\n+\t  tree ctype\n+\t    = cp_build_qualified_type (type, cp_type_quals (type)\n+\t\t\t\t\t     | TYPE_QUAL_CONST);\n+\t  TREE_VEC_ELT (arg, 0)\n+\t    = cp_build_reference_type (ctype, /*rval=*/false);\n+\t  if (!is_xible (INIT_EXPR, type, arg))\n+\t    {\n+\t      auto_diagnostic_group d;\n+\t      error (\"annotation does not have copy constructible type\");\n+\t      is_xible (INIT_EXPR, type, arg, /*explain=*/true);\n+\t      *no_add_attrs = true;\n+\t      return NULL_TREE;\n+\t    }\n+\t}\n+    }\n+  if (!processing_template_decl)\n+    {\n+      location_t loc = EXPR_LOCATION (TREE_VALUE (args));\n+      TREE_VALUE (args) = cxx_constant_value (TREE_VALUE (args));\n+      if (TREE_VALUE (args) == error_mark_node)\n+        *no_add_attrs = true;\n+      auto suppression\n+\t= make_temp_override (suppress_location_wrappers, 0);\n+      TREE_VALUE (args) = maybe_wrap_with_location (TREE_VALUE (args), loc);\n+    }\n+  ATTR_UNIQUE_VALUE_P (args) = 1;\n+  return NULL_TREE;\n+}\n+\n /* Return a new PTRMEM_CST of the indicated TYPE.  The MEMBER is the\n    thing pointed to by the constant.  */\n \n@@ -6725,6 +6807,14 @@ maybe_adjust_arg_pos_for_attribute (const_tree fndecl)\n   return n > 0 ? n - 1 : 0;\n }\n \n+/* True if ATTR is annotation.  */\n+\n+bool\n+annotation_p (tree attr)\n+{\n+  return is_attribute_p (\"annotation \", get_attribute_name (attr));\n+}\n+\n \f\n /* Release memory we no longer need after parsing.  */\n void\ndiff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc\nindex 65e08eaa645..beee605d0b7 100644\n--- a/gcc/cp/typeck.cc\n+++ b/gcc/cp/typeck.cc\n@@ -3443,16 +3443,18 @@ complain_about_unrecognized_member (tree access_path, tree name,\n \n /* This function is called by the parser to process a class member\n    access expression of the form OBJECT.NAME.  NAME is a node used by\n-   the parser to represent a name; it is not yet a DECL.  It may,\n-   however, be a BASELINK where the BASELINK_FUNCTIONS is a\n-   TEMPLATE_ID_EXPR.  Templates must be looked up by the parser, and\n+   the parser to represent a name; it is not yet a DECL, except when\n+   SPLICE_P.  It may, however, be a BASELINK where the BASELINK_FUNCTIONS\n+   is a TEMPLATE_ID_EXPR.  Templates must be looked up by the parser, and\n    there is no reason to do the lookup twice, so the parser keeps the\n    BASELINK.  TEMPLATE_P is true iff NAME was explicitly declared to\n-   be a template via the use of the \"A::template B\" syntax.  */\n+   be a template via the use of the \"A::template B\" syntax.  SPLICE_P\n+   is true if NAME was designated by a splice-expression.  */\n \n tree\n finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n-\t\t\t\t tsubst_flags_t complain)\n+\t\t\t\t tsubst_flags_t complain,\n+\t\t\t\t bool splice_p/*=false*/)\n {\n   tree expr;\n   tree object_type;\n@@ -3488,11 +3490,18 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n \t     lookup until we instantiate the T.  */\n \t  || (TREE_CODE (name) == IDENTIFIER_NODE\n \t      && IDENTIFIER_CONV_OP_P (name)\n-\t      && dependent_type_p (TREE_TYPE (name))))\n+\t      && dependent_type_p (TREE_TYPE (name)))\n+\t  /* This is OBJECT.[:R:], which is dependent.  */\n+\t  || dependent_splice_p (name)\n+\t  /* This is OBJECT.[:T::R:], which is dependent.  */\n+\t  || (TREE_CODE (name) == SCOPE_REF\n+\t      && dependent_splice_p (TREE_OPERAND (name, 1))))\n \t{\n \tdependent:\n-\t  return build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF,\n+\t  expr = build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF,\n \t\t\t\t   orig_object, orig_name, NULL_TREE);\n+\t  COMPONENT_REF_SPLICE_P (expr) = splice_p;\n+\t  return expr;\n \t}\n     }\n   else if (c_dialect_objc ()\n@@ -3526,6 +3535,16 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n   if (BASELINK_P (name))\n     /* A member function that has already been looked up.  */\n     member = name;\n+  else if (TREE_CODE (name) == TREE_BINFO)\n+    {\n+      /* Splicing a base class subobject.  We can only get here via\n+\t e1.[:e2:].  */\n+      expr = build_base_path (PLUS_EXPR, object, name, /*nonnull=*/true,\n+\t\t\t      complain);\n+      if (expr == error_mark_node && (complain & tf_error))\n+\terror_not_base_type (BINFO_TYPE (name), object_type);\n+      return expr;\n+    }\n   else\n     {\n       bool is_template_id = false;\n@@ -3552,6 +3571,13 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n \t      return error_mark_node;\n \t    }\n \t}\n+      else if (splice_p\n+\t       && (TREE_CODE (name) == FIELD_DECL\n+\t\t   || VAR_P (name)\n+\t\t   || TREE_CODE (name) == CONST_DECL\n+\t\t   || TREE_CODE (name) == FUNCTION_DECL\n+\t\t   || DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (name))))\n+\tscope = DECL_CONTEXT (OVL_FIRST (name));\n \n       if (TREE_CODE (name) == TEMPLATE_ID_EXPR)\n \t{\n@@ -3559,7 +3585,11 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n \t  template_args = TREE_OPERAND (name, 1);\n \t  name = TREE_OPERAND (name, 0);\n \n-\t  if (!identifier_p (name))\n+\t  if (splice_p\n+\t      && (DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (name))\n+\t\t  || variable_template_p (name)))\n+\t    scope = DECL_CONTEXT (OVL_FIRST (name));\n+\t  else if (!identifier_p (name))\n \t    name = OVL_NAME (name);\n \t}\n \n@@ -3577,7 +3607,11 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n \t\t\t   scope, name, object_type);\n \t\t  return error_mark_node;\n \t\t}\n-\t      tree val = lookup_enumerator (scope, name);\n+\t      tree val;\n+\t      if (splice_p && TREE_CODE (name) == CONST_DECL)\n+\t\tval = name;\n+\t      else\n+\t\tval = lookup_enumerator (scope, name);\n \t      if (!val)\n \t\t{\n \t\t  if (complain & tf_error)\n@@ -3592,7 +3626,16 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n \t    }\n \n \t  gcc_assert (CLASS_TYPE_P (scope));\n-\t  gcc_assert (identifier_p (name) || TREE_CODE (name) == BIT_NOT_EXPR);\n+\t  gcc_assert (identifier_p (name)\n+\t\t      || TREE_CODE (name) == BIT_NOT_EXPR\n+\t\t      || (splice_p\n+\t\t\t  && (TREE_CODE (name) == FIELD_DECL\n+\t\t\t      || VAR_P (name)\n+\t\t\t      || TREE_CODE (name) == CONST_DECL\n+\t\t\t      || TREE_CODE (name) == FUNCTION_DECL\n+\t\t\t      || DECL_FUNCTION_TEMPLATE_P\n+\t\t\t\t\t\t(OVL_FIRST (name))\n+\t\t\t      || variable_template_p (name))));\n \n \t  if (constructor_name_p (name, scope))\n \t    {\n@@ -3606,8 +3649,13 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n \t     one copy of the data member that is shared by all the objects of\n \t     the class.  So NAME can be unambiguously referred to even if\n \t     there are multiple indirect base classes containing NAME.  */\n-\t  const base_access ba = [scope, name] ()\n+\t  const base_access ba = [scope, name, splice_p] ()\n \t    {\n+\t      /* [class.access.base]/5: A member m is accessible at the\n+\t\t point R when designated in class N if\n+\t\t -- m is designated by a splice-expression  */\n+\t      if (splice_p)\n+\t\treturn ba_unique;\n \t      if (identifier_p (name))\n \t\t{\n \t\t  tree m = lookup_member (scope, name, /*protect=*/0,\n@@ -3639,6 +3687,25 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n \t    goto dependent;\n \t  member = lookup_destructor (object, scope, name, complain);\n \t}\n+      else if (splice_p && (TREE_CODE (name) == FIELD_DECL\n+\t\t\t    || VAR_P (name)\n+\t\t\t    || TREE_CODE (name) == CONST_DECL\n+\t\t\t    || TREE_CODE (name) == FUNCTION_DECL\n+\t\t\t    || DECL_FUNCTION_TEMPLATE_P (OVL_FIRST (name))\n+\t\t\t    || variable_template_p (name)))\n+\t{\n+\t  member = name;\n+\t  name = OVL_FIRST (name);\n+\t  if (any_dependent_type_attributes_p (DECL_ATTRIBUTES (name)))\n+\t    /* Dependent type attributes on the decl mean that the TREE_TYPE is\n+\t       wrong, so don't use it.  */\n+\t    goto dependent;\n+\t  if (is_overloaded_fn (name))\n+\t    member\n+\t      = build_baselink (access_path, TYPE_BINFO (object_type), member,\n+\t\t\t\tIDENTIFIER_CONV_OP_P (DECL_NAME (name))\n+\t\t\t\t? TREE_TYPE (DECL_NAME (name)) : NULL_TREE);\n+\t}\n       else\n \t{\n \t  /* Look up the member.  */\n@@ -3718,9 +3785,10 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,\n \t    BASELINK_QUALIFIED_P (member) = 1;\n \t  orig_name = member;\n \t}\n-      return build_min_non_dep (COMPONENT_REF, expr,\n+      expr = build_min_non_dep (COMPONENT_REF, expr,\n \t\t\t\torig_object, orig_name,\n \t\t\t\tNULL_TREE);\n+      COMPONENT_REF_SPLICE_P (STRIP_REFERENCE_REF (expr)) = splice_p;\n     }\n \n   return expr;\n@@ -6256,6 +6324,10 @@ cp_build_binary_op (const op_location_t &location,\n \t  return cp_build_binary_op (location,\n \t\t\t\t     EQ_EXPR, e, integer_zero_node, complain);\n \t}\n+      /* [expr.eq]: \"If both operands are of type std::meta::info,\n+\t comparison is defined as follows...\"  */\n+      else if (code0 == META_TYPE && code1 == META_TYPE)\n+\tresult_type = type0;\n       else\n \t{\n \t  gcc_assert (!TYPE_PTRMEMFUNC_P (type0)\n@@ -11691,6 +11763,12 @@ check_return_expr (tree retval, bool *no_warning, bool *dangling)\n \t*dangling = true;\n     }\n \n+  if (check_out_of_consteval_use (retval))\n+    {\n+      current_function_return_value = error_mark_node;\n+      return error_mark_node;\n+    }\n+\n   /* A naive attempt to reduce the number of -Wdangling-reference false\n      positives: if we know that this function can return a variable with\n      static storage duration rather than one of its parameters, suppress\ndiff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi\nindex c54eb758b17..8095d899de0 100644\n--- a/gcc/doc/invoke.texi\n+++ b/gcc/doc/invoke.texi\n@@ -251,7 +251,7 @@ in the following sections.\n -fnew-ttp-matching\n -fno-nonansi-builtins  -fnothrow-opt  -fno-operator-names\n -fno-optional-diags\n--fno-pretty-templates  -frange-for-ext-temps\n+-fno-pretty-templates  -frange-for-ext-temps  -freflection\n -fno-rtti  -fsized-deallocation\n -fstrict-enums  -fstrong-eval-order@r{[}=@var{kind}@r{]}\n -ftemplate-backtrace-limit=@var{n}\n@@ -3675,6 +3675,10 @@ so lifetime of the temporaries is extended until the end of the loop\n by default.  This option allows enabling that behavior also\n in earlier versions of the standard.\n \n+@opindex freflection\n+@item -freflection\n+Enable experimental C++26 Reflection.\n+\n @opindex fno-rtti\n @opindex frtti\n @item -fno-rtti\ndiff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc\nindex c637f9d93f0..baef5e9a974 100644\n--- a/gcc/dwarf2out.cc\n+++ b/gcc/dwarf2out.cc\n@@ -13494,7 +13494,10 @@ is_base_type (tree type)\n       return false;\n \n     default:\n-      if (is_cxx_auto (type))\n+      if (is_cxx ()\n+\t  && TREE_CODE (type) >= LAST_AND_UNUSED_TREE_CODE\n+\t  && TYPE_P (type)\n+\t  && TYPE_IDENTIFIER (type))\n \treturn false;\n       gcc_unreachable ();\n     }\n@@ -26949,6 +26952,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,\n \n     case NULLPTR_TYPE:\n     case LANG_TYPE:\n+    unspecified_type:\n       /* Just use DW_TAG_unspecified_type.  */\n       {\n         dw_die_ref type_die = lookup_type_die (type);\n@@ -26978,6 +26982,11 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,\n \t  equate_type_number_to_die (type, *die);\n \t  break;\n \t}\n+      if (is_cxx ()\n+\t  && TREE_CODE (type) >= LAST_AND_UNUSED_TREE_CODE\n+\t  && TYPE_P (type)\n+\t  && TYPE_IDENTIFIER (type))\n+\tgoto unspecified_type;\n       gcc_unreachable ();\n     }\n \ndiff --git a/gcc/tree-core.h b/gcc/tree-core.h\nindex 7bdb474a253..183d2e4a2f6 100644\n--- a/gcc/tree-core.h\n+++ b/gcc/tree-core.h\n@@ -1183,7 +1183,8 @@ struct GTY(()) tree_base {\n \t present in tree_base instead of tree_type is to save space.  The size\n \t of the field must be large enough to hold addr_space_t values.\n \t For CONSTRUCTOR nodes this holds the clobber_kind enum.\n-\t The C++ front-end uses this in IDENTIFIER_NODE and NAMESPACE_DECL.  */\n+\t The C++ front-end uses this in IDENTIFIER_NODE, REFLECT_EXPR, and\n+\t NAMESPACE_DECL.  */\n       unsigned address_space : 8;\n     } bits;\n \ndiff --git a/gcc/tree.h b/gcc/tree.h\nindex d25fc4316c7..2d9254f99f2 100644\n--- a/gcc/tree.h\n+++ b/gcc/tree.h\n@@ -1240,6 +1240,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,\n #define TREE_PURPOSE(NODE) (TREE_LIST_CHECK (NODE)->list.purpose)\n #define TREE_VALUE(NODE) (TREE_LIST_CHECK (NODE)->list.value)\n \n+/* In TREE_VALUE of an attribute this means the attribute is never equal to\n+   different attribute with the same name and value and that the attribute\n+   is order sensitive, the order of attributes with this flag on their\n+   TREE_VALUE should be preserved.  */\n+#define ATTR_UNIQUE_VALUE_P(NODE) (TREE_LIST_CHECK (NODE)->base.protected_flag)\n+\n /* In a TREE_VEC node.  */\n #define TREE_VEC_LENGTH(NODE) (TREE_VEC_CHECK (NODE)->base.u.length)\n #define TREE_VEC_BEGIN(NODE) (&TREE_VEC_CHECK (NODE)->vec.a[0])\n@@ -2767,9 +2773,14 @@ extern tree vector_element_bits_tree (const_tree);\n    vtable where the offset to the virtual base can be found.  */\n #define BINFO_VPTR_FIELD(NODE) (TREE_BINFO_CHECK (NODE)->binfo.vptr_field)\n \n-/* Indicates the accesses this binfo has to its bases. The values are\n+/* Indicates the accesses this binfo has to its bases.  The values are\n    access_public_node, access_protected_node or access_private_node.\n-   If this array is not present, public access is implied.  */\n+   If this vector is not present, public access is implied.  If present,\n+   the vector should have BINFO_N_BASE_BINFOS or larger length.  Elements\n+   beyond BINFO_N_BASE_BINFOS are base attributes instead of the\n+   access_p*_node values for base with index IDX at IDX + BINFO_N_BASE_BINFOS\n+   index.  If that is beyond the length of the vector, no attributes for\n+   that base is implied.  */\n #define BINFO_BASE_ACCESSES(NODE) \\\n   (TREE_BINFO_CHECK (NODE)->binfo.base_accesses)\n \ndiff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc\nindex 3c5e78bfe87..df20aa49e9d 100644\n--- a/libcc1/libcp1plugin.cc\n+++ b/libcc1/libcp1plugin.cc\n@@ -1568,7 +1568,8 @@ start_class_def (tree type,\n \n \t  tree base = finish_base_specifier\n \t    (convert_in (base_classes->elements[i]), access,\n-\t     (base_classes->flags[i] & GCC_CP_FLAG_BASECLASS_VIRTUAL) != 0);\n+\t     (base_classes->flags[i] & GCC_CP_FLAG_BASECLASS_VIRTUAL) != 0,\n+\t     NULL_TREE);\n \t  TREE_CHAIN (base) = bases;\n \t  bases = base;\n \t}\ndiff --git a/libcpp/charset.cc b/libcpp/charset.cc\nindex 95ba376606e..bea40d7c65b 100644\n--- a/libcpp/charset.cc\n+++ b/libcpp/charset.cc\n@@ -840,6 +840,10 @@ _cpp_destroy_iconv (cpp_reader *pfile)\n \ticonv_close (pfile->char32_cset_desc.cd);\n       if (pfile->wide_cset_desc.func == convert_using_iconv)\n \ticonv_close (pfile->wide_cset_desc.cd);\n+      if (pfile->reverse_narrow_cset_desc.func == convert_using_iconv)\n+\ticonv_close (pfile->narrow_cset_desc.cd);\n+      if (pfile->reverse_utf8_cset_desc.func == convert_using_iconv)\n+\ticonv_close (pfile->utf8_cset_desc.cd);\n     }\n }\n \n@@ -2726,6 +2730,110 @@ cpp_interpret_string_notranslate (cpp_reader *pfile, const cpp_string *from,\n   return retval;\n }\n \n+/* Convert a string FROM to TO, without handling of any UCNs etc., just\n+   pure character set conversion.  If !REVERSE, convert from SOURCE_CHARSET\n+   to execution charset corresponding to TYPE, if REVERSE, convert from the\n+   execution charset corresponding to TYPE to SOURCE_CHARSET.  Return false\n+   on error.  */\n+\n+bool\n+cpp_translate_string (cpp_reader *pfile, const cpp_string *from,\n+\t\t      cpp_string *to, enum cpp_ttype type, bool reverse)\n+{\n+  struct cset_converter cvt = converter_for_type (pfile, type);\n+  struct _cpp_strbuf tbuf;\n+  if (reverse)\n+    {\n+      struct cset_converter *pcvt;\n+      switch (type)\n+\t{\n+\tdefault:\n+\t  pcvt = &pfile->reverse_narrow_cset_desc;\n+\t  break;\n+\tcase CPP_UTF8CHAR:\n+\tcase CPP_UTF8STRING:\n+\t  pcvt = &pfile->reverse_utf8_cset_desc;\n+\t  break;\n+\tcase CPP_CHAR16:\n+\tcase CPP_STRING16:\n+\tcase CPP_CHAR32:\n+\tcase CPP_STRING32:\n+\tcase CPP_WCHAR:\n+\tcase CPP_WSTRING:\n+\t  return false;\n+\t}\n+      if (pcvt->func == NULL)\n+\t{\n+\t  *pcvt = init_iconv_desc (pfile, cvt.from, cvt.to);\n+\t  pcvt->width = cvt.width;\n+\t}\n+      cvt = *pcvt;\n+    }\n+  tbuf.asize = MAX (OUTBUF_BLOCK_SIZE, from->len);\n+  tbuf.text = XNEWVEC (uchar, tbuf.asize);\n+  tbuf.len = 0;\n+  if (!APPLY_CONVERSION (cvt, from->text, from->len, &tbuf))\n+    {\n+      XDELETEVEC (tbuf.text);\n+      return false;\n+    }\n+  tbuf.text = XRESIZEVEC (uchar, tbuf.text, tbuf.len);\n+  to->text = tbuf.text;\n+  to->len = tbuf.len;\n+  return true;\n+}\n+\n+/* Return true if ID is a valid identifier, false otherwise.  Without any\n+   diagnostics.  */\n+\n+bool\n+cpp_valid_identifier (cpp_reader *pfile, const unsigned char *id)\n+{\n+  normalize_state nst = INITIAL_NORMALIZE_STATE;\n+  const unsigned char *p = id;\n+  if (*p == '\\0')\n+    return false;\n+  const unsigned char *limit\n+    = (const unsigned char *) strchr ((const char *) p, '\\0');\n+  static const cppchar_t utf8_signifier = 0xC0;\n+  if (ISIDST (*p))\n+    {\n+      NORMALIZE_STATE_UPDATE_IDNUM (&nst, *p);\n+      ++p;\n+    }\n+  while (*p)\n+    {\n+      if (p != id && ISIDNUM (*p))\n+\t{\n+\t  while (ISIDNUM (*p))\n+\t    ++p;\n+\t  NORMALIZE_STATE_UPDATE_IDNUM (&nst, *(p - 1));\n+\t  continue;\n+\t}\n+      if (CPP_OPTION (pfile, extended_identifiers) && *p >= utf8_signifier)\n+\t{\n+\t  const unsigned char *base = p;\n+\t  size_t inbytesleft = limit - p;\n+\t  cppchar_t c;\n+\t  if (one_utf8_to_cppchar (&p, &inbytesleft, &c))\n+\t    return false;\n+\t  switch (ucn_valid_in_identifier (pfile, c, &nst))\n+\t    {\n+\t    default:\n+\t      return false;\n+\t    case 1:\n+\t      continue;\n+\t    case 2:\n+\t      if (base == id)\n+\t\treturn false;\n+\t      continue;\n+\t    }\n+\t}\n+      return false;\n+    }\n+  return true;\n+}\n+\n \f\n /* Return number of source characters in STR.  */\n static unsigned\ndiff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h\nindex 65e1bc6aae0..bf1c911ec41 100644\n--- a/libcpp/include/cpplib.h\n+++ b/libcpp/include/cpplib.h\n@@ -101,6 +101,8 @@ class rich_location;\n   OP(CLOSE_SQUARE,\t\"]\")\t\t\t\t\t\t\\\n   OP(OPEN_BRACE,\t\"{\")\t\t\t\t\t\t\\\n   OP(CLOSE_BRACE,\t\"}\")\t\t\t\t\t\t\\\n+  OP(OPEN_SPLICE,\t\"[:\")\t\t\t\t\t\t\\\n+  OP(CLOSE_SPLICE,\t\":]\")\t\t\t\t\t\t\\\n   /* The remainder of the punctuation.\tOrder is not significant.  */\t\\\n   OP(SEMICOLON,\t\t\";\")\t/* structure */\t\t\t\t\\\n   OP(ELLIPSIS,\t\t\"...\")\t\t\t\t\t\t\\\n@@ -111,6 +113,7 @@ class rich_location;\n   OP(SCOPE,\t\t\"::\")\t\t\t\t\t\t\\\n   OP(DEREF_STAR,\t\"->*\")\t\t\t\t\t\t\\\n   OP(DOT_STAR,\t\t\".*\")\t\t\t\t\t\t\\\n+  OP(REFLECT_OP,\t\"^^\")\t\t\t\t\t\t\\\n   OP(ATSIGN,\t\t\"@\")  /* used in Objective-C */\t\t\t\\\n \t\t\t\t\t\t\t\t\t\\\n   TK(NAME,\t\tIDENT)\t /* word */\t\t\t\t\\\n@@ -1306,6 +1309,9 @@ extern const char *cpp_interpret_string_ranges (cpp_reader *pfile,\n extern bool cpp_interpret_string_notranslate (cpp_reader *,\n \t\t\t\t\t      const cpp_string *, size_t,\n \t\t\t\t\t      cpp_string *, enum cpp_ttype);\n+extern bool cpp_translate_string (cpp_reader *, const cpp_string *,\n+\t\t\t\t  cpp_string *, enum cpp_ttype, bool);\n+extern bool cpp_valid_identifier (cpp_reader *, const unsigned char *);\n \n /* Convert a host character constant to the execution character set.  */\n extern cppchar_t cpp_host_to_exec_charset (cpp_reader *, cppchar_t);\ndiff --git a/libcpp/internal.h b/libcpp/internal.h\nindex ae985241415..2367a0c0fac 100644\n--- a/libcpp/internal.h\n+++ b/libcpp/internal.h\n@@ -543,6 +543,14 @@ struct cpp_reader\n      wide execution character set.  */\n   struct cset_converter wide_cset_desc;\n \n+  /* Descriptor for converting from the execution character set to the\n+     source character set.  */\n+  struct cset_converter reverse_narrow_cset_desc;\n+\n+  /* Descriptor for converting from the UTF-8 execution character set to the\n+     source character set.  */\n+  struct cset_converter reverse_utf8_cset_desc;\n+\n   /* Date and time text.  Calculated together if either is requested.  */\n   const unsigned char *date;\n   const unsigned char *time;\ndiff --git a/libcpp/lex.cc b/libcpp/lex.cc\nindex 43d369108ab..f94e762c917 100644\n--- a/libcpp/lex.cc\n+++ b/libcpp/lex.cc\n@@ -4312,6 +4312,10 @@ _cpp_lex_direct (cpp_reader *pfile)\n \t  else\n \t    result->flags |= COLON_SCOPE;\n \t}\n+      else if (*buffer->cur == ']'\n+\t       && CPP_OPTION (pfile, cplusplus)\n+\t       && CPP_OPTION (pfile, lang) >= CLK_GNUCXX26)\n+\tbuffer->cur++, result->type = CPP_CLOSE_SPLICE;\n       else if (*buffer->cur == '>' && CPP_OPTION (pfile, digraphs))\n \t{\n \t  buffer->cur++;\n@@ -4323,7 +4327,15 @@ _cpp_lex_direct (cpp_reader *pfile)\n     case '*': IF_NEXT_IS ('=', CPP_MULT_EQ, CPP_MULT); break;\n     case '=': IF_NEXT_IS ('=', CPP_EQ_EQ, CPP_EQ); break;\n     case '!': IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT); break;\n-    case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break;\n+    case '^':\n+      result->type = CPP_XOR;\n+      if (*buffer->cur == '=')\n+\tbuffer->cur++, result->type = CPP_XOR_EQ;\n+      else if (*buffer->cur == '^'\n+\t       && CPP_OPTION (pfile, cplusplus)\n+\t       && CPP_OPTION (pfile, lang) >= CLK_GNUCXX26)\n+\tbuffer->cur++, result->type = CPP_REFLECT_OP;\n+      break;\n     case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); result->val.token_no = 0; break;\n \n     case '?': result->type = CPP_QUERY; break;\n@@ -4331,7 +4343,24 @@ _cpp_lex_direct (cpp_reader *pfile)\n     case ',': result->type = CPP_COMMA; break;\n     case '(': result->type = CPP_OPEN_PAREN; break;\n     case ')': result->type = CPP_CLOSE_PAREN; break;\n-    case '[': result->type = CPP_OPEN_SQUARE; break;\n+    case '[':\n+      result->type = CPP_OPEN_SQUARE;\n+      /* C++ [lex.pptoken]/4.3: \"Otherwise, if the next three characters are\n+\t [:: and the subsequent character is not :, or if the next three\n+\t characters are [:>, the [ is treated as a preprocessing token by\n+\t itself and not as the first character of the preprocessing token [:.\"\n+\t Also, the tokens [: and :] cannot be composed from digraphs.  */\n+      if (*buffer->cur == ':'\n+\t  && CPP_OPTION (pfile, cplusplus)\n+\t  && CPP_OPTION (pfile, lang) >= CLK_GNUCXX26)\n+\t{\n+\t  if ((buffer->cur[1] == ':' && buffer->cur[2] != ':')\n+\t      || buffer->cur[1] == '>')\n+\t    break;\n+\t  else\n+\t    buffer->cur++, result->type = CPP_OPEN_SPLICE;\n+\t}\n+      break;\n     case ']': result->type = CPP_CLOSE_SQUARE; break;\n     case '{': result->type = CPP_OPEN_BRACE; break;\n     case '}': result->type = CPP_CLOSE_BRACE; break;\n","prefixes":["1/9","v2"]}