diff mbox

[C++] Reject invalid auto foo (), a = 5;

Message ID 20170103223930.GA21933@tucnak
State New
Headers show

Commit Message

Jakub Jelinek Jan. 3, 2017, 10:39 p.m. UTC
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  <jakub@redhat.com>

	* 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.


	Jakub

Comments

Jason Merrill Jan. 4, 2017, 7:48 p.m. UTC | #1
On Tue, Jan 3, 2017 at 5:39 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> +         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;

I might reorder the then/else clauses so you don't need to duplicate
the test whether auto_function_declaration is null, but OK either way.

Jason
diff mbox

Patch

--- 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; }