Hey Egas, thanks for the patch!

On Fri, 28 Nov 2025, Egas Ribeiro wrote:

> Lambdas used as non-type template arguments to concepts are wrapped
> in TARGET_EXPR nodes. After r16-5115 changed convert_template_argument
> to call instantiate_non_dependent_expr_internal on non-dependent
> expressions, these TARGET_EXPRs began hitting the default case in
> tsubst_expr, causing an ICE. Add proper TARGET_EXPR handling.

TARGET_EXPR is deliberately not handled by the tsubst routines because
it is considered a non-templated tree (and the tsubst routines naturally
expect to see only templated trees).  TARGET_EXPR represents temporary
objects, but we want the templated representation of expressions to
mirror their syntactic, written form, not their underlying semantic
representation in terms of temporary objects etc.

The problem here seems to be that when parsing A<[]{}>, we haven't yet
seen the 'auto' that indicates an abbreviated function template, so we
haven't switched to being in a template context yet, and we therefore
represent the []{} template argument as a non-templated tree.  Once
we see the auto we switch to a template context but we still build up
the type-constraint using the non-templated []{} tree.  Later when
checking the type-constraint via tsubst, it sees this non-template []{}
tree, which contains a TARGET_EXPR, and we ICE.

We somehow need to switch to being in a template context _before_
parsing the A<[]{}> type-constraint so that it's represented as
a templated tree.  In order to do that I guess we need to do some
sort of lookahead of to detect an abbreviated funciton template (
indicated by an 'auto' function parameter), which admittedly seems
quite tricky :/

In the meantime I think it'd be good to document in tsubst_expr that
TARGET_EXPR is deliberately not handled since it's not a valid templated
tree.

Wonder what Jason thinks

> 
>       PR c++/117034
> 
> gcc/cp/ChangeLog:
> 
>       * pt.cc (tsubst_expr): Add case TARGET_EXPR.
> 
> gcc/testsuite/ChangeLog:
> 
>       * g++.dg/cpp2a/lambda-template-pr117034.C: New test.
> ---
> Bootstrapped and regtested on x86_64-pc-linux-gnu with no new regressions.
> 
>  gcc/cp/pt.cc                                          | 7 +++++++
>  gcc/testsuite/g++.dg/cpp2a/lambda-template-pr117034.C | 7 +++++++
>  2 files changed, 14 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-template-pr117034.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 4dc8f980d0d..9dd218ffe37 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -22300,6 +22300,13 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
> complain, tree in_decl)
>           RETURN (build_typeid (operand_0, complain));
>         }
>        }
> +    case TARGET_EXPR:
> +      {
> +     tree init = RECUR (TREE_OPERAND (t, 1));
> +     if (init == TREE_OPERAND (t, 1))
> +       RETURN (t);
> +     RETURN (get_target_expr (init, complain));
> +      }
>  
>      case FUNCTION_DECL:
>      case PARM_DECL:
> diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-template-pr117034.C 
> b/gcc/testsuite/g++.dg/cpp2a/lambda-template-pr117034.C
> new file mode 100644
> index 00000000000..b9b2773b923
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-template-pr117034.C
> @@ -0,0 +1,7 @@
> +// { dg-do compile { target c++20 } }
> +// PR c++/117034
> +
> +template<typename, auto>
> +concept A = true;
> +
> +void f(A<[] {}> auto) {}
> -- 
> 2.52.0
> 
> 

Reply via email to