Hi,
thus I had to revert my first try, when it caused c++/85713. I added two
testcases for the latter (the second one covering what I learned from
yet another defective try which I attached to the trail of c++/84588
yesterday) and finally figured out that the problem was that I was
incorrectly calling abort_fully_implicit_template while tentatively
parsing (if you look at the new lambda-generic-85713.C, that made
impossible correctly parsing 'auto (&array) [5]' as second lambda
parameter).
Anyway, a few days ago, while looking for a completely different
solution and comparing to other compilers too, I noticed that, more
generally, we were missing a check in cp_parser_condition that we aren't
declaring a function type when we are sure that we are handling a
declaration: simply adding such a check covers as a special case
c++/84588 too, and, being the check in cp_parser_condition, it
automatically covers variants for conditions elsewhere, eg, for, while
loops: with the patchlet below we handle all of them very similarly to
clang and icc.
Tested x86_64-linux.
Thanks, Paolo.
//////////////////////////////
/cp
2018-05-17 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/84588
* parser.c (cp_parser_condition): Reject a declaration of
a function type.
/testsuite
2018-05-17 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/84588
* g++.dg/cpp1y/pr84588.C: New.
* g++.old-deja/g++.jason/cond.C: Adjust.
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 260308)
+++ cp/parser.c (working copy)
@@ -11571,6 +11571,7 @@ cp_parser_condition (cp_parser* parser)
tree attributes;
cp_declarator *declarator;
tree initializer = NULL_TREE;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
/* Parse the declarator. */
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
@@ -11597,15 +11598,23 @@ cp_parser_condition (cp_parser* parser)
for sure. */
if (cp_parser_parse_definitely (parser))
{
- tree pushed_scope;
+ tree pushed_scope = NULL_TREE;
bool non_constant_p;
int flags = LOOKUP_ONLYCONVERTING;
/* Create the declaration. */
- decl = start_decl (declarator, &type_specifiers,
- /*initialized_p=*/true,
- attributes, /*prefix_attributes=*/NULL_TREE,
- &pushed_scope);
+ if (declarator->kind == cdk_function)
+ {
+ error_at (loc, "a function type is not allowed here");
+ if (parser->fully_implicit_function_template_p)
+ abort_fully_implicit_template (parser);
+ decl = error_mark_node;
+ }
+ else
+ decl = start_decl (declarator, &type_specifiers,
+ /*initialized_p=*/true,
+ attributes, /*prefix_attributes=*/NULL_TREE,
+ &pushed_scope);
/* Parse the initializer. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
Index: testsuite/g++.dg/cpp1y/pr84588.C
===================================================================
--- testsuite/g++.dg/cpp1y/pr84588.C (nonexistent)
+++ testsuite/g++.dg/cpp1y/pr84588.C (working copy)
@@ -0,0 +1,25 @@
+// { dg-do compile { target c++14 } }
+
+struct a {
+ void b() {}
+ void c(void (*) () = [] {
+ if (a a(int auto) {}) // { dg-error "two or more data types|function
type" }
+ ;
+ }) {}
+};
+
+struct d {
+ void e() {}
+ void f(void (*) () = [] {
+ for (;d d(int auto) {};) // { dg-error "two or more data types|function
type" }
+ ;
+ }) {}
+};
+
+struct g {
+ void h() {}
+ void i(void (*) () = [] {
+ while (g g(int auto) {}) // { dg-error "two or more data types|function
type" }
+ ;
+ }) {}
+};
Index: testsuite/g++.old-deja/g++.jason/cond.C
===================================================================
--- testsuite/g++.old-deja/g++.jason/cond.C (revision 260308)
+++ testsuite/g++.old-deja/g++.jason/cond.C (working copy)
@@ -47,8 +47,7 @@ int main()
if (struct B * foo = new B)
;
- if (int f () = 1) // { dg-warning "extern" "extern" }
- // { dg-error "is initialized like a variable" "var" { target *-*-* } .-1 }
+ if (int f () = 1) // { dg-error "function type" }
;
if (int a[2] = {1, 2}) // { dg-error "extended init" "" { target { !
c++11 } } }