Patchwork [c++] fix PR 45332, missing semicolon after member declaration

login
register
mail settings
Submitter Nathan Froyd
Date Nov. 5, 2010, 8:04 p.m.
Message ID <20101105200412.GA26083@nightcrawler>
Download mbox | patch
Permalink /patch/70289/
State New
Headers show

Comments

Nathan Froyd - Nov. 5, 2010, 8:04 p.m.
On Fri, Nov 05, 2010 at 03:39:38PM -0400, Jason Merrill wrote:
> On 11/05/2010 12:13 PM, Nathan Froyd wrote:
> >+	      error_at (token->location,
> >+			"expected %<;%>  at end of member declaration");
> 
> Did you mean for this to use cp_parser_error_at_token?

Er.  I did at one point, then realized c_parse_error is always going to
say "ERROR before TOKEN", which is part of what people were grumbling
about.  So I changed it to use error_at and forgot about deleting
cp_parser_error_at_token.  Sorry about that.

How's this modified patch?  Updated message in new testcase, too.

-Nathan

gcc/cp/
	PR c++/45332
	* parser.c (cp_lexer_previous_token): New function.
	(cp_parser_member_declaration): Use previous token for error
	messages.  Assume semicolon presence rather than grovelling for
	the next one.

gcc/testsuite/
	PR c++/45332
	* g++.dg/parse/semicolon2.C: New testcase.
	* g++.dg/ext/asmspec1.C: Adjust.
	* g++.dg/init/new13.C: Adjust.
	* g++.dg/parse/ctor5.C: Adjust.

	Modified gcc/cp/parser.c
Jason Merrill - Nov. 5, 2010, 9 p.m.
On 11/05/2010 04:04 PM, Nathan Froyd wrote:
> How's this modified patch?  Updated message in new testcase, too.

OK.

Jason

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6302864..6a9e4d7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -502,6 +502,19 @@  cp_lexer_token_at (cp_lexer *lexer ATTRIBUTE_UNUSED, cp_token_position pos)
   return pos;
 }
 
+static inline cp_token *
+cp_lexer_previous_token (cp_lexer *lexer)
+{
+  cp_token_position tp;
+
+  if (lexer->next_token == &eof_token)
+    tp = lexer->last_token - 1;
f+  else
+    tp = cp_lexer_token_position (lexer, true);
+
+  return cp_lexer_token_at (lexer, tp);
+}
+
 /* nonzero if we are presently saving tokens.  */
 
 static inline int
@@ -17627,6 +17640,8 @@  cp_parser_member_declaration (cp_parser* parser)
     }
   else
     {
+      bool assume_semicolon = false;
+
       /* See if these declarations will be friends.  */
       friend_p = cp_parser_friend_p (&decl_specifiers);
 
@@ -17820,11 +17835,18 @@  cp_parser_member_declaration (cp_parser* parser)
 	  else if (cp_lexer_next_token_is_not (parser->lexer,
 					       CPP_SEMICOLON))
 	    {
-	      cp_parser_error (parser, "expected %<;%>");
-	      /* Skip tokens until we find a `;'.  */
-	      cp_parser_skip_to_end_of_statement (parser);
+	      /* The next token might be a ways away from where the
+		 actual semicolon is missing.  Find the previous token
+		 and use that for our error position.  */
+	      cp_token *token = cp_lexer_previous_token (parser->lexer);
+	      error_at (token->location,
+			"expected %<;%> at end of member declaration");
 
-	      break;
+	      /* Assume that the user meant to provide a semicolon.  If
+		 we were to cp_parser_skip_to_end_of_statement, we might
+		 skip to a semicolon inside a member function definition
+		 and issue nonsensical error messages.  */
+	      assume_semicolon = true;
 	    }
 
 	  if (decl)
@@ -17836,6 +17858,9 @@  cp_parser_member_declaration (cp_parser* parser)
 	      if (TREE_CODE (decl) == FUNCTION_DECL)
 		cp_parser_save_default_args (parser, decl);
 	    }
+
+	  if (assume_semicolon)
+	    return;
 	}
     }
 
	Modified gcc/testsuite/g++.dg/ext/asmspec1.C
diff --git a/gcc/testsuite/g++.dg/ext/asmspec1.C b/gcc/testsuite/g++.dg/ext/asmspec1.C
index 3df2483..0661136 100644
--- a/gcc/testsuite/g++.dg/ext/asmspec1.C
+++ b/gcc/testsuite/g++.dg/ext/asmspec1.C
@@ -3,6 +3,6 @@ 
 
 struct A
 {
-  int i __asm__(int);         // { dg-error "before" }
-  static int j __asm__(int);  // { dg-error "before" }
+  int i __asm__(int);         // { dg-error "expected" }
+  static int j __asm__(int);  // { dg-error "expected" }
 };
	Modified gcc/testsuite/g++.dg/init/new13.C
diff --git a/gcc/testsuite/g++.dg/init/new13.C b/gcc/testsuite/g++.dg/init/new13.C
index 3563c48..2ced6e3 100644
--- a/gcc/testsuite/g++.dg/init/new13.C
+++ b/gcc/testsuite/g++.dg/init/new13.C
@@ -5,7 +5,7 @@ 
 
 struct A
 {
-  void* operator new(__SIZE_TYPE__) throw(X);  // { dg-error "" }
+  void* operator new(__SIZE_TYPE__) throw(X);  // { dg-error "expected|type" }
 };
 
-A* p = new A;                                  // { dg-error "no suitable" }
+A* p = new A;
	Modified gcc/testsuite/g++.dg/parse/ctor5.C
diff --git a/gcc/testsuite/g++.dg/parse/ctor5.C b/gcc/testsuite/g++.dg/parse/ctor5.C
index 8194585..3ea2354 100644
--- a/gcc/testsuite/g++.dg/parse/ctor5.C
+++ b/gcc/testsuite/g++.dg/parse/ctor5.C
@@ -2,9 +2,9 @@ 
 
 struct A
 {
-  int i;
-  A() i() {}  // { dg-error "expected" }
-}; // { dg-error "expected" }
+  int i; // { dg-error "conflicts" }
+  A() i() {}  // { dg-error "declaration" }
+};
 
 struct B
 {
	New      gcc/testsuite/g++.dg/parse/semicolon2.C
diff --git a/gcc/testsuite/g++.dg/parse/semicolon2.C b/gcc/testsuite/g++.dg/parse/semicolon2.C
new file mode 100644
index 0000000..50c3ce1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/semicolon2.C
@@ -0,0 +1,9 @@ 
+// PR c++/45332
+// { dg-do compile }
+
+class C
+{
+ int x				// { dg-error "at end of member declaration" }
+
+ const int foo() { return x; }
+};