diff options
author | Nathan Froyd <froydnj@codesourcery.com> | 2010-11-06 18:41:57 +0000 |
---|---|---|
committer | Nathan Froyd <froydnj@gcc.gnu.org> | 2010-11-06 18:41:57 +0000 |
commit | 134c192bb33f87fc0b261b32d4e18a497c1e1b1c (patch) | |
tree | 85f85d6ade9121cc2106c12f318d3a31ee0c9783 | |
parent | fbc7f9df71ac3c5dd63e014686ce9b3022f83f82 (diff) | |
download | gcc-134c192bb33f87fc0b261b32d4e18a497c1e1b1c.tar.gz |
re PR c++/45332 (Generate clear diagnostics when a terminating semicolon is missing from a class member declaration.)
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.
From-SVN: r166406
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/parser.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/asmspec1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/new13.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/ctor5.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/semicolon2.C | 9 |
7 files changed, 61 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bfa4af43916..784f3aab15d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2010-11-06 Nathan Froyd <froydnj@codesourcery.com> + + 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. + 2010-11-06 Joern Rennecke <amylaar@spamcop.net> PR middle-end/46314 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6302864fd97..6a9e4d7b981 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; + 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; } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4577eb26dfa..911ba143162 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2010-11-06 Nathan Froyd <froydnj@codesourcery.com> + + 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. + 2010-11-06 Janus Weil <janus@gcc.gnu.org> PR fortran/46330 diff --git a/gcc/testsuite/g++.dg/ext/asmspec1.C b/gcc/testsuite/g++.dg/ext/asmspec1.C index 3df2483ad53..0661136fecc 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" } }; diff --git a/gcc/testsuite/g++.dg/init/new13.C b/gcc/testsuite/g++.dg/init/new13.C index 3563c48808f..2ced6e3fe02 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; diff --git a/gcc/testsuite/g++.dg/parse/ctor5.C b/gcc/testsuite/g++.dg/parse/ctor5.C index 819458598a3..3ea23549c0b 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 { diff --git a/gcc/testsuite/g++.dg/parse/semicolon2.C b/gcc/testsuite/g++.dg/parse/semicolon2.C new file mode 100644 index 00000000000..d14a225a674 --- /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; } +}; |