From 0e36f5c7c103e2d897fcbc9728fa98768b386f9a Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Tue, 15 Sep 2015 17:19:11 +0000 Subject: [PATCH] re PR c/67580 (Improve error message on missing "struct" tag) PR c/67580 * c-decl.c (tag_exists_p): New function. * c-parser.c (c_parser_declaration_or_fndef): Give a hint when struct/union/enum keywords are missing. * c-tree.h (tag_exists_p): Declare. * gcc.dg/pr67580.c: New test. From-SVN: r227803 --- gcc/c/ChangeLog | 8 ++++++++ gcc/c/c-decl.c | 12 ++++++++++++ gcc/c/c-parser.c | 12 ++++++++++-- gcc/c/c-tree.h | 1 + gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.dg/pr67580.c | 31 +++++++++++++++++++++++++++++++ 6 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr67580.c diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 37124b3f587..27659e231c3 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,11 @@ +2015-09-15 Marek Polacek + + PR c/67580 + * c-decl.c (tag_exists_p): New function. + * c-parser.c (c_parser_declaration_or_fndef): Give a hint when + struct/union/enum keywords are missing. + * c-tree.h (tag_exists_p): Declare. + 2015-09-15 Marek Polacek * c-decl.c (lookup_label): Return NULL_TREE instead of 0. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 989ff993223..a110226d01f 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -3856,6 +3856,18 @@ lookup_tag (enum tree_code code, tree name, bool thislevel_only, return b->decl; } +/* Return true if a definition exists for NAME with code CODE. */ + +bool +tag_exists_p (enum tree_code code, tree name) +{ + struct c_binding *b = I_TAG_BINDING (name); + + if (b == NULL || b->decl == NULL_TREE) + return false; + return TREE_CODE (b->decl) == code; +} + /* Print an error message now for a recent invalid struct, union or enum cross reference. We don't print them immediately because they are not invalid diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 4d9cbe05027..d5de1028ddc 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1539,8 +1539,16 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, || c_parser_peek_2nd_token (parser)->type == CPP_MULT) && (!nested || !lookup_name (c_parser_peek_token (parser)->value))) { - error_at (here, "unknown type name %qE", - c_parser_peek_token (parser)->value); + tree name = c_parser_peek_token (parser)->value; + error_at (here, "unknown type name %qE", name); + /* Give a hint to the user. This is not C++ with its implicit + typedef. */ + if (tag_exists_p (RECORD_TYPE, name)) + inform (here, "use % keyword to refer to the type"); + else if (tag_exists_p (UNION_TYPE, name)) + inform (here, "use % keyword to refer to the type"); + else if (tag_exists_p (ENUMERAL_TYPE, name)) + inform (here, "use % keyword to refer to the type"); /* Parse declspecs normally to get a correct pointer type, but avoid a further "fails to be a type name" error. Refuse nested functions diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index a3979dd9f37..667529a68c6 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -701,6 +701,7 @@ extern tree c_omp_reduction_lookup (tree, tree); extern tree c_check_omp_declare_reduction_r (tree *, int *, void *); extern void c_pushtag (location_t, tree, tree); extern void c_bind (location_t, tree, bool); +extern bool tag_exists_p (enum tree_code, tree); /* In c-errors.c */ extern void pedwarn_c90 (location_t, int opt, const char *, ...) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c8aa20a73a1..f8593b346fc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-09-15 Marek Polacek + + PR c/67580 + * gcc.dg/pr67580.c: New test. + 2015-09-15 Richard Biener PR tree-optimization/67470 diff --git a/gcc/testsuite/gcc.dg/pr67580.c b/gcc/testsuite/gcc.dg/pr67580.c new file mode 100644 index 00000000000..90e4b1b113f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr67580.c @@ -0,0 +1,31 @@ +/* PR c/67580 */ +/* { dg-do compile } */ + +struct S { int s; }; +union U { int s; }; +enum E { A }; + +void +f (void) +{ + S s; /* { dg-error "unknown type name" } */ +/* { dg-message "use .struct. keyword to refer to the type" "" { target *-*-* } 11 } */ + U u; /* { dg-error "unknown type name" } */ +/* { dg-message "use .union. keyword to refer to the type" "" { target *-*-* } 13 } */ + E e; /* { dg-error "unknown type name" } */ +/* { dg-message "use .enum. keyword to refer to the type" "" { target *-*-* } 15 } */ +} + +void +g (void) +{ + struct T { int i; }; + union V { int i; }; + enum F { J }; + T t; /* { dg-error "unknown type name" } */ +/* { dg-message "use .struct. keyword to refer to the type" "" { target *-*-* } 25 } */ + V v; /* { dg-error "unknown type name" } */ +/* { dg-message "use .union. keyword to refer to the type" "" { target *-*-* } 27 } */ + F f; /* { dg-error "unknown type name" } */ +/* { dg-message "use .enum. keyword to refer to the type" "" { target *-*-* } 29 } */ +} -- 2.30.2