This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH,c++] fix PR 45332, missing semicolon after member declaration
- From: Nathan Froyd <froydnj at codesourcery dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 5 Nov 2010 16:04:14 -0400
- Subject: Re: [PATCH,c++] fix PR 45332, missing semicolon after member declaration
- References: <20101105161332.GY26083@nightcrawler> <4CD45D7A.1000908@redhat.com>
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
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; }
+};