Here when tentatively parsing the if condition as a declaration, we try to treat C<1> as the start of a constrained placeholder type, which we quickly reject because C doesn't accept a type as its first argument. But since we're parsing tentatively, we shouldn't emit an error in this case.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/11? PR c++/98394 gcc/cp/ChangeLog: * parser.c (cp_parser_placeholder_type_specifier): Don't emit a "does not constrain a type" error when parsing tentatively. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-pr98394.C: New test. --- gcc/cp/parser.c | 7 +++++-- gcc/testsuite/g++.dg/cpp2a/concepts-pr98394.C | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr98394.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4c2075742d6..f1498e28da4 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -19909,8 +19909,11 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, if (!flag_concepts_ts || !processing_template_parmlist) { - error_at (loc, "%qE does not constrain a type", DECL_NAME (con)); - inform (DECL_SOURCE_LOCATION (con), "concept defined here"); + if (!tentative) + { + error_at (loc, "%qE does not constrain a type", DECL_NAME (con)); + inform (DECL_SOURCE_LOCATION (con), "concept defined here"); + } return error_mark_node; } } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr98394.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr98394.C new file mode 100644 index 00000000000..c8407cdf7cd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr98394.C @@ -0,0 +1,14 @@ +// PR c++/98394 +// { dg-do compile { target c++20 } } + +template<int...> +concept C = true; + +template<int, int> +concept D = true; + +int main() { + if (C<1>); // { dg-bogus "does not constrain a type" } + if (D<1>); // { dg-error "wrong number of template arguments" } + // { dg-bogus "does not constrain a type" "" { target *-*-* } .-1 } +} -- 2.34.0.rc1.14.g88d915a634