Hi!
C++14 and above says that for auto specifier in [dcl.spec.auto]/7:
"If the init-declarator-list contains more than one
init-declarator, they shall all form declarations of variables."
The following patch attempts to reject this. Bootstrapped/regtested
on x86_64-linux and i686-linux, ok for trunk?
struct A
{
auto foo(), bar();
};
auto A::foo() { return 1; }
auto A::bar() { return 2; }
isn't rejected though, is that invalid too?
2017-01-03 Jakub Jelinek <[email protected]>
* parser.c (cp_parser_simple_declaration): Diagnose function
declaration among more than one init-declarators with auto
specifier.
* g++.dg/cpp1y/auto-fn34.C: New test.
--- gcc/cp/parser.c.jj 2017-01-03 08:12:27.000000000 +0100
+++ gcc/cp/parser.c 2017-01-03 09:58:13.336703629 +0100
@@ -12723,8 +12723,17 @@ cp_parser_simple_declaration (cp_parser*
break;
tree last_type;
+ bool auto_specifier_p;
+ /* NULL_TREE if both variable and function declaration are allowed,
+ error_mark_node if function declaration are not allowed and
+ a FUNCTION_DECL that should be diagnosed if it is followed by
+ variable declarations. */
+ tree auto_function_declaration;
last_type = NULL_TREE;
+ auto_specifier_p
+ = decl_specifiers.type && type_uses_auto (decl_specifiers.type);
+ auto_function_declaration = NULL_TREE;
/* Keep going until we hit the `;' at the end of the simple
declaration. */
@@ -12770,6 +12779,27 @@ cp_parser_simple_declaration (cp_parser*
if (cp_parser_error_occurred (parser))
goto done;
+ if (auto_specifier_p && cxx_dialect >= cxx14)
+ {
+ /* If the init-declarator-list contains more than one
+ init-declarator, they shall all form declarations of
+ variables. */
+ if (auto_function_declaration
+ && (TREE_CODE (decl) == FUNCTION_DECL
+ || auto_function_declaration != error_mark_node))
+ {
+ error_at (decl_specifiers.locations[ds_type_spec],
+ "non-variable %qD in declaration with more than one "
+ "declarator with placeholder type",
+ TREE_CODE (decl) == FUNCTION_DECL
+ ? decl : auto_function_declaration);
+ auto_function_declaration = error_mark_node;
+ }
+ else if (auto_function_declaration == NULL_TREE)
+ auto_function_declaration
+ = TREE_CODE (decl) == FUNCTION_DECL ? decl : error_mark_node;
+ }
+
if (auto_result)
{
if (last_type && last_type != error_mark_node
--- gcc/testsuite/g++.dg/cpp1y/auto-fn34.C.jj 2017-01-03 09:51:21.208086328
+0100
+++ gcc/testsuite/g++.dg/cpp1y/auto-fn34.C 2017-01-03 09:48:06.000000000
+0100
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++14 } }
+
+auto f1 ();
+auto a = 5, f2 (); // { dg-error "in declaration with more than
one declarator" }
+auto f3 (), b = 6; // { dg-error "in declaration with more than
one declarator" }
+auto f4 (), f5 (), f6 (); // { dg-error "in declaration with more than
one declarator" }
+auto f1 () { return 3; }
+auto f2 () { return 4; }
+auto f3 () { return 5; }
+auto f4 () { return 6; }
+auto f5 () { return 7; }
+auto f6 () { return 8; }
Jakub