On Mon, 6 Oct 2025, Egas Ribeiro wrote: > Regtested on x86_64-pc-linux-gnu. OK for trunk? > > As suggested by Patrick Palka in the bug report, the diagnostic check > for concept_check_p(fn) was being done too late in finish_call_expr(), > which led to an early return inside if (processing_template_decl), which > meant that the error wouldn't be triggered when we are in a type > dependence early exit. This fix makes sure that this error is handled in > the semantic analysis phase, and avoids the failed assertion later in > tsubst_expr().
Some context: GCC represents templated and non-templated expressions differently, and the processing_template_decl flag controls whether our assorted semantic analysis and AST building functions should produce a templated vs non-templated tree. And we naturally want to produce templated trees when parsing a template, hence the flag's name -- although there's other non-parsing situations where we want to produce templated trees such as during partial instantiation, so the flag's name is imprecise nowadays. An alternative fix would be to make tsubst_expr (our main expression instantiation routine) diagnose such calls at instantiation time, but it's sufficient and better to diagnose errors inside templates sooner if possible, i.e. at parse time vs at instantiation time (this is allowed by https://eel.is/c++draft/temp.res.general#6) > > PR c++/116477 > > gcc/cp/ChangeLog: > > * semantics.cc (finish_call_expr): Move concept_check_p diagnostic > before processing_template_decl check to catch errors earlier. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp2a/concepts-pr116477.C: New test. > > Signed-off-by: Egas Ribeiro <[email protected]> > --- > gcc/cp/semantics.cc | 13 +++++++------ > gcc/testsuite/g++.dg/cpp2a/concepts-pr116477.C | 11 +++++++++++ > 2 files changed, 18 insertions(+), 6 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr116477.C > > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc > index 8d0210ef3b6..c818b739539 100644 > --- a/gcc/cp/semantics.cc > +++ b/gcc/cp/semantics.cc > @@ -3327,6 +3327,13 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, > bool disallow_virtual, > > orig_fn = fn; > > + if (concept_check_p (fn)) > + { > + error_at (EXPR_LOC_OR_LOC (fn, input_location), > + "cannot call a concept as a function"); > + return error_mark_node; > + } > + > if (processing_template_decl) > { > /* If FN is a local extern declaration (or set thereof) in a template, > @@ -3456,12 +3463,6 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, > bool disallow_virtual, > /*fn_p=*/NULL, > complain); > } > - else if (concept_check_p (fn)) > - { > - error_at (EXPR_LOC_OR_LOC (fn, input_location), > - "cannot call a concept as a function"); > - return error_mark_node; > - } > else if (is_overloaded_fn (fn)) > { > /* If the function is an overloaded builtin, resolve it. */ The code changes LGTM > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr116477.C > b/gcc/testsuite/g++.dg/cpp2a/concepts-pr116477.C > new file mode 100644 > index 00000000000..b6d75593fd0 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr116477.C > @@ -0,0 +1,11 @@ > +// { dg-do compile { target c++20 } } > +#include <concepts> > + > +template <typename G> > +bool run () { > + return std::regular<G> (G{}); // { dg-error "cannot call a concept as a > function" } > +} > + > +int main () { > + run<int>(); > +} Can you strengthen this testcase by not instantiating/using the function template (ensuring we diagnose the error at parse time)? Also, can you further minimize the size of the testcase by defining a dummy concept instead of including <concepts>? > -- > 2.51.0 > >
