Commit 1a59ccf2 by David Malcolm Committed by David Malcolm

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
parent 0b661358
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
......
......@@ -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;
......
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...
......
/* { 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 "" } */
/* { 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" } */
......
/* { 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;
}
/* { 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 "" } */
......@@ -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 "" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment