2010-11-13 Paolo Bonzini <bonzini@gnu.org>
authorbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 13 Nov 2010 09:52:00 +0000 (09:52 +0000)
committerbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 13 Nov 2010 09:52:00 +0000 (09:52 +0000)
* 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  <bonzini@gnu.org>

* gcc.dg/Wcxx-compat-8.c: Add testcases involving incomplete types.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166699 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-decl.c
gcc/c-parser.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wcxx-compat-8.c

index 44035e3..af43e31 100644 (file)
@@ -1,5 +1,22 @@
 2010-11-13  Paolo Bonzini  <bonzini@gnu.org>
 
+       * 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  <bonzini@gnu.org>
+
        * 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".
index e1f1402..c0d5a49 100644 (file)
@@ -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;
index 484dab2..9761e4e 100644 (file)
@@ -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,");
index 0d94ceb..0581b38 100644 (file)
@@ -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;
index 7f448dd..9018c4e 100644 (file)
@@ -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++");
 
index ee05b7b..f878023 100644 (file)
@@ -1,5 +1,9 @@
 2010-11-13  Paolo Bonzini  <bonzini@gnu.org>
 
+       * gcc.dg/Wcxx-compat-8.c: Add testcases involving incomplete types.
+
+2010-11-13  Paolo Bonzini  <bonzini@gnu.org>
+
        * gcc.dg/format/few-1.c: New test.
        * gcc.dg/format/asm_fprintf-1.c: Adjust.
        * gcc.dg/format/c90-scanf-1.c: Adjust.
index a7343ba..7dad7a4 100644 (file)
@@ -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\[+\]\[+\]" } */
+}