On 10/23/26 9:27 AM, Marek Polacek wrote:
On Tue, Oct 20, 2026 at 06:08:54PM -0400, Jason Merrill wrote:
On 10/8/26 5:26 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
[expr.prim.splice]/2 doesn't actually allow templates in
a splice-expression of the form splice-specifier, but we are not
currently detecting that in check_splice_expr, which can mean
that we crash if the user attempts to use such a splice.

As an extension, we allow function templates, and assume that the
user forgot to type 'template'.

Do we still give a diagnostic by default in that case?

No, the missing "expected template keyword" is subject of PR127802.

We could give that diagnostic here?

mangle3.C was testing invalid cases so remove that.

        PR c++/125631

gcc/cp/ChangeLog:

        * reflect.cc (check_splice_expr): Reject (non-function) templates.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/crash6.C: Adjust dg-error.
        * g++.dg/reflect/mangle3.C: Remove some invalid tests.
        * g++.dg/reflect/error15.C: New test.
---
   gcc/cp/reflect.cc                      | 15 +++++
   gcc/testsuite/g++.dg/reflect/crash6.C  |  4 +-
   gcc/testsuite/g++.dg/reflect/error15.C | 84 ++++++++++++++++++++++++++
   gcc/testsuite/g++.dg/reflect/mangle3.C |  9 ---
   4 files changed, 101 insertions(+), 11 deletions(-)
   create mode 100644 gcc/testsuite/g++.dg/reflect/error15.C

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 8bf518df64f..62c4e168108 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -9362,6 +9362,21 @@ check_splice_expr (location_t loc, location_t start_loc, 
tree t,
         return false;
       }
+  /* [expr.prim.splice]/2 doesn't allow for the splice-expression of the form
+     splice-specifier to designate a template.  But we accept a function
+     template here as an extension, because it would be valid if the 'template'
+     keyword were present.  */
+  if (!template_p
+      && !targs_p
+      && !member_access_p
+      && TREE_CODE (t) == TEMPLATE_DECL
+      && !DECL_FUNCTION_TEMPLATE_P (t))
+    {
+      if (complain_p)
+       error_at (loc, "cannot use template %qE in a splice expression", t);
+      return false;
+    }
+
     /* [expr.prim.splice]/2: "The expression is ill-formed if S [the construct
        designated by splice-specifier] is
        -- a local entity such that there is a lambda scope that intervenes
diff --git a/gcc/testsuite/g++.dg/reflect/crash6.C 
b/gcc/testsuite/g++.dg/reflect/crash6.C
index a455a61cd65..4dd2f5fc7b8 100644
--- a/gcc/testsuite/g++.dg/reflect/crash6.C
+++ b/gcc/testsuite/g++.dg/reflect/crash6.C
@@ -10,8 +10,8 @@ template<info R>
   void
   f ()
   {
-  [:R:] r; // { dg-error "expected" }
-  [:R:]<int> r; // { dg-error "expected" }
+  [:R:] r; // { dg-error "expected|cannot use template" }
+  [:R:]<int> r; // { dg-error "expected|cannot use template" }
   }
   void
diff --git a/gcc/testsuite/g++.dg/reflect/error15.C 
b/gcc/testsuite/g++.dg/reflect/error15.C
new file mode 100644
index 00000000000..a2fdf4a52ed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/error15.C
@@ -0,0 +1,84 @@
+// PR c++/125631
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <tuple>
+
+template<auto Templ, class Tuple>
+const auto
+make_from_tuple (Tuple&& t)
+{
+  return [:Templ:]{}; // { dg-error "expected|cannot use template .std::tuple. in a 
splice expression" }
+}
+auto p = make_from_tuple<^^std::tuple>(std::tuple());
+
+template<auto N> int tv;
+template<auto N> concept C = requires { true; };
+template<typename T> struct S { };
+template<typename T>
+using A = S<T>;
+template<typename> using I = int;
+
+template<auto R>
+void
+g1 ()
+{
+  auto a = [:R:];  // { dg-error "cannot use template .tv<N>. in a splice 
expression" }
+}
+
+template<auto R>
+void
+g2 ()
+{
+  auto a = [:R:];  // { dg-error "cannot use template .C. in a splice 
expression" }
+}
+
+template<auto R>
+void
+g3 ()
+{
+  auto a = [:R:];  // { dg-error "cannot use template .S. in a splice 
expression" }
+}
+
+template<auto R>
+void
+g4 ()
+{
+  auto a = [:R:];  // { dg-error "cannot use template .A. in a splice 
expression" }
+}
+
+template<auto R>
+void
+g5 ()
+{
+  auto a = [:R:];  // { dg-error "cannot use template .I. in a splice 
expression" }
+}
+
+template<template<class> class TT>
+void
+g6 ()
+{
+  auto x = [:^^TT:];  // { dg-error "cannot use template .S. in a splice 
expression" }
+}
+
+template<auto R>
+void
+g7 ()
+{
+  &[:R:];  // { dg-error "cannot use template .S. in a splice expression" }
+}
+
+template<auto R> auto g8 () -> decltype([:R:]);       // { dg-error "cannot use template 
.tv<N>. in a splice expression" }
+
+void
+h ()
+{
+  g1<^^tv>();
+  g2<^^C>();
+  g3<^^S>();
+  g4<^^A>();
+  g5<^^I>();
+  g6<S>();
+  g7<^^S>();
+  g8<^^tv>(); // { dg-error "no matching function" }
+}
diff --git a/gcc/testsuite/g++.dg/reflect/mangle3.C 
b/gcc/testsuite/g++.dg/reflect/mangle3.C
index 390f249fb0c..1e1302d1377 100644
--- a/gcc/testsuite/g++.dg/reflect/mangle3.C
+++ b/gcc/testsuite/g++.dg/reflect/mangle3.C
@@ -15,8 +15,6 @@ using Alias = int;
   template<auto>
   struct TCls { };
-template <auto> int TVar;
-
   template<typename T>
   struct B {
     T t;
@@ -41,7 +39,6 @@ namespace N {
   }
   namespace NSAlias = N;
-template <auto> concept Concept = requires { true; };
   constexpr auto ctx = std::meta::access_context::current ();
   template<typename T>
@@ -160,18 +157,12 @@ g (int p)
   // { dg-final { scan-assembler "_Z2f4ILDmsb2a1EE4TClsIXszDST_EEEv" } }
     f4<^^A>();
   // { dg-final { scan-assembler "_Z2f4ILDmen4Enum1AEE4TClsIXszDST_EEEv" } }
-  f4<^^TVar>();
-// { dg-final { scan-assembler "_Z2f4ILDmvt4TVarEE4TClsIXszDST_EEEv" } }
     f5<^^i>();
   // { dg-final { scan-assembler "_Z2f5ILDmvr1iEEDtDST_EEv" } }
     f5<^^a1>();
   // { dg-final { scan-assembler "_Z2f5ILDmsb2a1EEDtDST_EEv" } }
     f5<^^A>();
   // { dg-final { scan-assembler "_Z2f5ILDmen4Enum1AEEDtDST_EEv" } }
-  f5<^^TVar>();
-// { dg-final { scan-assembler "_Z2f5ILDmvt4TVarEEDtDST_EEv" } }
-  f5<^^Concept>();
-// { dg-final { scan-assembler "_Z2f5ILDmco7ConceptEEDtDST_EEv" } }
     f5<^^p>();
   // { dg-final { scan-assembler "_Z2f5ILDmvrZ1giE1pEEDtDST_EEv" } }
     f5<std::meta::reflect_constant (42)>();

base-commit: 9b2bbe9104aef2e6bd9e8d7ace5fed3e2726f4d3


Marek


Reply via email to