From 9e5b21156632fd14bfaeea24919c614e56645989 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 13 Nov 2010 09:52:00 +0000 Subject: [PATCH] c-tree.h (enum c_typespec_kind): Add ctsk_none. 2010-11-13 Paolo Bonzini * c-tree.h (enum c_typespec_kind): Add ctsk_none. (struct c_declspecs): Replace tagdef_seen_p and type_seen_p with typespec_kind. * c-decl.c (build_null_declspecs): Initialize typespec_kind. (shadow_tag_warned, check_compound_literal_type): Adjust uses of tag_defined_p. (declspecs_add_type): Set typespec_kind. * c-parser.c (c_parser_declaration_or_fndef, c_parser_declspecs, c_parser_struct_declaration, c_parser_parameter_declaration, c_parser_type_name, c_parser_objc_diagnose_bad_element_prefix): Adjust uses of type_seen_p. * c-typeck.c (c_cast_expr): Use typespec_kind instead of tag_defined_p, pass ctsk_firstref through. testsuite: 2010-11-13 Paolo Bonzini * gcc.dg/Wcxx-compat-8.c: Add testcases involving incomplete types. From-SVN: r166699 --- gcc/ChangeLog | 17 +++++++++++++++++ gcc/c-decl.c | 17 +++++++++-------- gcc/c-parser.c | 19 ++++++++++++------- gcc/c-tree.h | 11 +++++------ gcc/c-typeck.c | 5 +++-- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/Wcxx-compat-8.c | 26 ++++++++++++++++++++++++-- 7 files changed, 74 insertions(+), 25 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 44035e34037..af43e31b134 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2010-11-13 Paolo Bonzini + * c-tree.h (enum c_typespec_kind): Add ctsk_none. + (struct c_declspecs): Replace tagdef_seen_p and type_seen_p + with typespec_kind. + * c-decl.c (build_null_declspecs): Initialize typespec_kind. + (shadow_tag_warned, check_compound_literal_type): Adjust + uses of tag_defined_p. + (declspecs_add_type): Set typespec_kind. + * c-parser.c (c_parser_declaration_or_fndef, + c_parser_declspecs, c_parser_struct_declaration, + c_parser_parameter_declaration, c_parser_type_name, + c_parser_objc_diagnose_bad_element_prefix): Adjust uses + of type_seen_p. + * c-typeck.c (c_cast_expr): Use typespec_kind instead of + tag_defined_p, pass ctsk_firstref through. + +2010-11-13 Paolo Bonzini + * c-format.c (enum format_specifier_kind, kind_descriptions): New. (struct format_wanted_type): Replace field "name" with "kind", add "format_start" and "format_length". diff --git a/gcc/c-decl.c b/gcc/c-decl.c index e1f14029b80..c0d5a4922c3 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -3634,7 +3634,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) warned = 1; } } - else if (!declspecs->tag_defined_p + else if (declspecs->typespec_kind != ctsk_tagdef + && declspecs->typespec_kind != ctsk_tagfirstref && declspecs->storage_class != csc_none) { if (warned != 1) @@ -3644,7 +3645,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) warned = 1; pending_xref_error (); } - else if (!declspecs->tag_defined_p + else if (declspecs->typespec_kind != ctsk_tagdef + && declspecs->typespec_kind != ctsk_tagfirstref && (declspecs->const_p || declspecs->volatile_p || declspecs->restrict_p @@ -4580,7 +4582,9 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const) void check_compound_literal_type (location_t loc, struct c_type_name *type_name) { - if (warn_cxx_compat && type_name->specs->tag_defined_p) + if (warn_cxx_compat + && (type_name->specs->typespec_kind == ctsk_tagdef + || type_name->specs->typespec_kind == ctsk_tagfirstref)) warning_at (loc, OPT_Wc___compat, "defining a type in a compound literal is invalid in C++"); } @@ -8616,10 +8620,9 @@ build_null_declspecs (void) ret->storage_class = csc_none; ret->expr_const_operands = true; ret->declspecs_seen_p = false; - ret->type_seen_p = false; + ret->typespec_kind = ctsk_none; ret->non_sc_seen_p = false; ret->typedef_p = false; - ret->tag_defined_p = false; ret->explicit_signed_p = false; ret->deprecated_p = false; ret->default_int_p = false; @@ -8703,7 +8706,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, tree type = spec.spec; specs->non_sc_seen_p = true; specs->declspecs_seen_p = true; - specs->type_seen_p = true; + specs->typespec_kind = spec.kind; if (TREE_DEPRECATED (type)) specs->deprecated_p = true; @@ -9306,8 +9309,6 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, } else if (TREE_CODE (type) != ERROR_MARK) { - if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref) - specs->tag_defined_p = true; if (spec.kind == ctsk_typeof) { specs->typedef_p = true; diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 484dab27f1b..9761e4e0843 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -1462,7 +1462,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, should diagnose if there were no declaration specifiers) or a function definition (in which case the diagnostic for implicit int suffices). */ - declarator = c_parser_declarator (parser, specs->type_seen_p, + declarator = c_parser_declarator (parser, + specs->typespec_kind != ctsk_none, C_DTR_NORMAL, &dummy); if (declarator == NULL) { @@ -1831,7 +1832,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, bool scspec_ok, bool typespec_ok, bool start_attr_ok) { bool attrs_ok = start_attr_ok; - bool seen_type = specs->type_seen_p; + bool seen_type = specs->typespec_kind != ctsk_none; while (c_parser_next_token_is (parser, CPP_NAME) || c_parser_next_token_is (parser, CPP_KEYWORD) || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS))) @@ -2399,7 +2400,7 @@ c_parser_struct_declaration (c_parser *parser) || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { tree ret; - if (!specs->type_seen_p) + if (specs->typespec_kind == ctsk_none) { pedwarn (decl_loc, OPT_pedantic, "ISO C forbids member declarations with no members"); @@ -2434,7 +2435,8 @@ c_parser_struct_declaration (c_parser *parser) if (c_parser_next_token_is (parser, CPP_COLON)) declarator = build_id_declarator (NULL_TREE); else - declarator = c_parser_declarator (parser, specs->type_seen_p, + declarator = c_parser_declarator (parser, + specs->typespec_kind != ctsk_none, C_DTR_NORMAL, &dummy); if (declarator == NULL) { @@ -3078,7 +3080,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs) pending_xref_error (); prefix_attrs = specs->attrs; specs->attrs = NULL_TREE; - declarator = c_parser_declarator (parser, specs->type_seen_p, + declarator = c_parser_declarator (parser, + specs->typespec_kind != ctsk_none, C_DTR_PARM, &dummy); if (declarator == NULL) { @@ -3370,7 +3373,8 @@ c_parser_type_name (c_parser *parser) } pending_xref_error (); finish_declspecs (specs); - declarator = c_parser_declarator (parser, specs->type_seen_p, + declarator = c_parser_declarator (parser, + specs->typespec_kind != ctsk_none, C_DTR_ABSTRACT, &dummy); if (declarator == NULL) return NULL; @@ -7618,7 +7622,8 @@ static bool c_parser_objc_diagnose_bad_element_prefix (c_parser *parser, struct c_declspecs *specs) { - if (!specs->declspecs_seen_p || specs->type_seen_p || specs->non_sc_seen_p) + if (!specs->declspecs_seen_p || specs->non_sc_seen_p + || specs->typespec_kind != ctsk_none) { c_parser_error (parser, "no type or storage class may be specified here,"); diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 0d94cebd84d..0581b38da1f 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -134,6 +134,8 @@ struct c_expr only used to distinguish tag definitions, tag references and typeof uses. */ enum c_typespec_kind { + /* No typespec. This appears only in struct c_declspec. */ + ctsk_none, /* A reserved keyword type specifier. */ ctsk_resword, /* A reference to a tag, previously declared, such as "struct foo". @@ -225,13 +227,14 @@ struct c_declspecs { /* Any type specifier keyword used such as "int", not reflecting modifiers such as "short", or cts_none if none. */ ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8; + /* The kind of type specifier if one has been seen, ctsk_none + otherwise. */ + ENUM_BITFIELD (c_typespec_kind) typespec_kind : 3; /* Whether any expressions in typeof specifiers may appear in constant expressions. */ BOOL_BITFIELD expr_const_operands : 1; /* Whether any declaration specifiers have been seen at all. */ BOOL_BITFIELD declspecs_seen_p : 1; - /* Whether a type specifier has been seen. */ - BOOL_BITFIELD type_seen_p : 1; /* Whether something other than a storage class specifier or attribute has been seen. This is used to warn for the obsolescent usage of storage class specifiers other than at the @@ -241,10 +244,6 @@ struct c_declspecs { BOOL_BITFIELD non_sc_seen_p : 1; /* Whether the type is specified by a typedef or typeof name. */ BOOL_BITFIELD typedef_p : 1; - /* Whether a struct, union or enum type either had its content - defined by a type specifier in the list or was the first visible - declaration of its tag. */ - BOOL_BITFIELD tag_defined_p : 1; /* Whether the type is explicitly "signed" or specified by a typedef whose type is explicitly "signed". */ BOOL_BITFIELD explicit_signed_p : 1; diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 7f448ddf2ba..9018c4e933c 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -4831,8 +4831,9 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr) if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret)) SET_EXPR_LOCATION (ret, loc); - /* C++ does not permits types to be defined in a cast. */ - if (warn_cxx_compat && type_name->specs->tag_defined_p) + /* C++ does not permits types to be defined in a cast, but it + allows references to incomplete types. */ + if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef) warning_at (loc, OPT_Wc___compat, "defining a type in a cast is invalid in C++"); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ee05b7b80f2..f878023b362 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2010-11-13 Paolo Bonzini + * gcc.dg/Wcxx-compat-8.c: Add testcases involving incomplete types. + +2010-11-13 Paolo Bonzini + * gcc.dg/format/few-1.c: New test. * gcc.dg/format/asm_fprintf-1.c: Adjust. * gcc.dg/format/c90-scanf-1.c: Adjust. diff --git a/gcc/testsuite/gcc.dg/Wcxx-compat-8.c b/gcc/testsuite/gcc.dg/Wcxx-compat-8.c index a7343ba91e6..7dad7a48dd4 100644 --- a/gcc/testsuite/gcc.dg/Wcxx-compat-8.c +++ b/gcc/testsuite/gcc.dg/Wcxx-compat-8.c @@ -22,7 +22,17 @@ enum e2 struct s3 v3; int v4 = C; +enum e3 +{ + F = sizeof (struct t3), /* { dg-bogus "invalid in C\[+\]\[+\]" } */ + /* { dg-error "invalid application of 'sizeof'" "" { target *-*-* } 27 } */ + G = __alignof__ (struct t4), /* { dg-bogus "invalid in C\[+\]\[+\]" } */ + /* { dg-error "invalid application of '__alignof__'" "" { target *-*-* } 29 } */ + H +}; + __typeof__ (struct s5 { int i; }) v5; /* { dg-warning "invalid in C\[+\]\[+\]" } */ +__typeof__ (struct t5) w5; /* { dg-bogus "invalid in C\[+\]\[+\]" } */ int f1 (struct s1 *p) @@ -30,14 +40,26 @@ f1 (struct s1 *p) return ((struct s6 { int j; } *) p)->j; /* { dg-warning "invalid in C\[+\]\[+\]" } */ } -int +void * f2 (struct s1 *p) { + return ((struct t6 *) p); /* { dg-bogus "invalid in C\[+\]\[+\]" } */ +} + +int +f3 (struct s1 *p) +{ return (__extension__ (struct s7 { int j; } *)p)->j; } int -f3 () +f4 () { return (struct s8 { int i; }) { 0 }.i; /* { dg-warning "invalid in C\[+\]\[+\]" } */ } + +void * +f5 () +{ + return &((struct t8) { }); /* { dg-warning "invalid in C\[+\]\[+\]" } */ +} -- 2.11.4.GIT