diff options
author | David Malcolm <dmalcolm@redhat.com> | 2017-10-25 23:53:41 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2017-10-25 23:53:41 +0000 |
commit | 1a59ccf25df49415490423382d31db15fa9c7796 (patch) | |
tree | 26de80d706d83e84643afb24d388f3b4e9e65252 /gcc | |
parent | 0b661358bcd72a70bbf4b903db1f0f8de98a6bbd (diff) | |
download | gcc-1a59ccf25df49415490423382d31db15fa9c7796.zip gcc-1a59ccf25df49415490423382d31db15fa9c7796.tar.gz gcc-1a59ccf25df49415490423382d31db15fa9c7796.tar.bz2 |
C: detect more missing semicolons (PR c/7356)
c_parser_declaration_or_fndef has logic for parsing what might be
either a declaration or a function definition.
This patch adds a test to detect cases where a semicolon would have
terminated the decls as a declaration, where the token that follows
would start a new declaration specifier, and updates the error message
accordingly, with a fix-it hint.
This addresses PR c/7356, fixing the case of a stray token before a
#include that previously gave inscrutable output, and improving e.g.:
int i
int j;
from:
t.c:2:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
int j;
^~~
to:
t.c:1:6: error: expected ';' before 'int'
int i
^
;
int j;
~~~
gcc.dg/noncompile/920923-1.c needs a slight update, as the output for
the first line changes from:
920923-1.c:2:14: error: expected '=', ',', ';', 'asm' or
'__attribute__' before 'unsigned'
typedef BYTE unsigned char; /* { dg-error "expected" } */
^~~~~~~~
to:
920923-1.c:2:13: error: expected ';' before 'unsigned'
typedef BYTE unsigned char; /* { dg-error "expected" } */
^~~~~~~~~
;
920923-1.c:2:1: warning: useless type name in empty declaration
typedef BYTE unsigned char; /* { dg-error "expected" } */
^~~~~~~
The patch also adds a test for PR c/44515 as a baseline.
gcc/c/ChangeLog:
PR c/7356
* c-parser.c (c_parser_declaration_or_fndef): Detect missing
semicolons.
gcc/testsuite/ChangeLog:
PR c/7356
PR c/44515
* c-c++-common/pr44515.c: New test case.
* gcc.dg/pr7356-2.c: New test case.
* gcc.dg/pr7356.c: New test case.
* gcc.dg/spellcheck-typenames.c: Update the "singed" char "TODO"
case to reflect changes to output.
* gcc.dg/noncompile/920923-1.c: Add dg-warning to reflect changes
to output.
From-SVN: r254093
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr44515.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/noncompile/920923-1.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr7356-2.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr7356.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/spellcheck-typenames.c | 5 |
8 files changed, 117 insertions, 7 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index b4fde0d..5d028b4 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2017-10-25 David Malcolm <dmalcolm@redhat.com> + + PR c/7356 + * c-parser.c (c_parser_declaration_or_fndef): Detect missing + semicolons. + 2017-10-25 Jakub Jelinek <jakub@redhat.com> PR libstdc++/81706 diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 6b84324..68c45fd 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -2241,11 +2241,37 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, } if (!start_function (specs, declarator, all_prefix_attrs)) { - /* This can appear in many cases looking nothing like a - function definition, so we don't give a more specific - error suggesting there was one. */ - c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> " - "or %<__attribute__%>"); + /* At this point we've consumed: + declaration-specifiers declarator + and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON, + RID_ASM, RID_ATTRIBUTE, or RID_IN, + but the + declaration-specifiers declarator + aren't grokkable as a function definition, so we have + an error. */ + gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON)); + if (c_parser_next_token_starts_declspecs (parser)) + { + /* If we have + declaration-specifiers declarator decl-specs + then assume we have a missing semicolon, which would + give us: + declaration-specifiers declarator decl-specs + ^ + ; + <~~~~~~~~~ declaration ~~~~~~~~~~> + Use c_parser_require to get an error with a fix-it hint. */ + c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"); + parser->error = false; + } + else + { + /* This can appear in many cases looking nothing like a + function definition, so we don't give a more specific + error suggesting there was one. */ + c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> " + "or %<__attribute__%>"); + } if (nested) c_pop_function_context (); break; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 443e7c7..e2f7e4d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2017-10-25 David Malcolm <dmalcolm@redhat.com> + + PR c/7356 + PR c/44515 + * c-c++-common/pr44515.c: New test case. + * gcc.dg/pr7356-2.c: New test case. + * gcc.dg/pr7356.c: New test case. + * gcc.dg/spellcheck-typenames.c: Update the "singed" char "TODO" + case to reflect changes to output. + * gcc.dg/noncompile/920923-1.c: Add dg-warning to reflect changes + to output. + 2017-10-25 Eric Botcazou <ebotcazou@adacore.com> * gcc.dg/fold-cond_expr-1.c: Rename to... diff --git a/gcc/testsuite/c-c++-common/pr44515.c b/gcc/testsuite/c-c++-common/pr44515.c new file mode 100644 index 0000000..dbb77509 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr44515.c @@ -0,0 +1,14 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +void bar(void); +void foo(void) +{ + bar() /* { dg-error "expected ';' before '.' token" } */ +} +/* { dg-begin-multiline-output "" } + bar() + ^ + ; + } + ~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/noncompile/920923-1.c b/gcc/testsuite/gcc.dg/noncompile/920923-1.c index 1cb140e..006a071 100644 --- a/gcc/testsuite/gcc.dg/noncompile/920923-1.c +++ b/gcc/testsuite/gcc.dg/noncompile/920923-1.c @@ -1,5 +1,6 @@ /* { dg-message "undeclared identifier is reported only once" "reminder for mmu_base" { target *-*-* } 0 } */ typedef BYTE unsigned char; /* { dg-error "expected" } */ +/* { dg-warning "useless type name in empty declaration" "" { target *-*-* } .-1 } */ typedef int item_n; typedef int perm_set; struct PENT { caddr_t v_addr; };/* { dg-error "unknown type name" } */ diff --git a/gcc/testsuite/gcc.dg/pr7356-2.c b/gcc/testsuite/gcc.dg/pr7356-2.c new file mode 100644 index 0000000..ad67975 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr7356-2.c @@ -0,0 +1,33 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +int i /* { dg-error "6: expected ';' before 'int'" } */ +int j; +/* { dg-begin-multiline-output "" } + int i + ^ + ; + int j; + ~~~ + { dg-end-multiline-output "" } */ + + +void test (void) +{ + int i /* { dg-error "8: expected ';' before 'int'" } */ + int j; + + /* { dg-begin-multiline-output "" } + int i + ^ + ; + int j; + ~~~ + { dg-end-multiline-output "" } */ +} + +int old_style_params (first, second) + int first; + int second; +{ + return first + second; +} diff --git a/gcc/testsuite/gcc.dg/pr7356.c b/gcc/testsuite/gcc.dg/pr7356.c new file mode 100644 index 0000000..84baf07 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr7356.c @@ -0,0 +1,17 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +a /* { dg-line stray_token } */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +int main(int argc, char** argv) +{ + return 0; +} + +/* { dg-error "expected ';' before '.*'" "" { target *-*-* } stray_token } */ +/* { dg-begin-multiline-output "" } + a + ^ + ; + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/spellcheck-typenames.c b/gcc/testsuite/gcc.dg/spellcheck-typenames.c index f3b8102..3717ad8 100644 --- a/gcc/testsuite/gcc.dg/spellcheck-typenames.c +++ b/gcc/testsuite/gcc.dg/spellcheck-typenames.c @@ -100,8 +100,9 @@ baz value; /* { dg-error "1: unknown type name .baz.; use .enum. keyword to refe { dg-end-multiline-output "" } */ /* TODO: it would be better to detect the "singed" vs "signed" typo here. */ -singed char ch; /* { dg-error "8: before .char." } */ +singed char ch; /* { dg-error "7: before .char." } */ /* { dg-begin-multiline-output "" } singed char ch; - ^~~~ + ^~~~~ + ; { dg-end-multiline-output "" } */ |