OSDN Git Service

2007-07-09 Geoffrey Keating <geoffk@apple.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index fd5b065..82e7c73 100644 (file)
@@ -70,6 +70,16 @@ enum decl_context
   FIELD,                       /* Declaration inside struct or union */
   TYPENAME};                   /* Typename (inside cast or sizeof)  */
 
+/* States indicating how grokdeclarator() should handle declspecs marked
+   with __attribute__((deprecated)).  An object declared as
+   __attribute__((deprecated)) suppresses warnings of uses of other
+   deprecated items.  */
+
+enum deprecated_states {
+  DEPRECATED_NORMAL,
+  DEPRECATED_SUPPRESS
+};
+
 \f
 /* Nonzero if we have seen an invalid cross reference
    to a struct, union, or enum, but not yet printed the message.  */
@@ -81,18 +91,6 @@ location_t pending_invalid_xref_location;
 /* True means we've initialized exception handling.  */
 bool c_eh_initialized_p;
 
-/* While defining an enum type, this is 1 plus the last enumerator
-   constant value.  Note that will do not have to save this or `enum_overflow'
-   around nested function definition since such a definition could only
-   occur in an enum value expression and we don't use these variables in
-   that case.  */
-
-static tree enum_next_value;
-
-/* Nonzero means that there was overflow computing enum_next_value.  */
-
-static int enum_overflow;
-
 /* The file and line that the prototype came from if this is an
    old-style definition; used for diagnostics in
    store_parm_decls_oldstyle.  */
@@ -250,7 +248,7 @@ extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
 
 union lang_tree_node
   GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : (GIMPLE_TUPLE_P (&%h.generic) ? (union lang_tree_node *) 0 : (union lang_tree_node *) TREE_CHAIN (&%h.generic))")))
+       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : ((union lang_tree_node *) GENERIC_NEXT (&%h.generic))")))
 {
   union tree_node GTY ((tag ("0"),
                        desc ("tree_node_structure (&%h)")))
@@ -410,7 +408,8 @@ static tree lookup_name_in_scope (tree, struct c_scope *);
 static tree c_make_fname_decl (tree, int);
 static tree grokdeclarator (const struct c_declarator *,
                            struct c_declspecs *,
-                           enum decl_context, bool, tree *);
+                           enum decl_context, bool, tree *,
+                           enum deprecated_states);
 static tree grokparms (struct c_arg_info *, bool);
 static void layout_array_type (tree);
 \f
@@ -439,17 +438,6 @@ add_stmt (tree t)
   return t;
 }
 \f
-/* States indicating how grokdeclarator() should handle declspecs marked
-   with __attribute__((deprecated)).  An object declared as
-   __attribute__((deprecated)) suppresses warnings of uses of other
-   deprecated items.  */
-
-enum deprecated_states {
-  DEPRECATED_NORMAL,
-  DEPRECATED_SUPPRESS
-};
-
-static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
 void
 c_print_identifier (FILE *file, tree node, int indent)
@@ -1676,12 +1664,11 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
       DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
       DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
       DECL_MODE (newdecl) = DECL_MODE (olddecl);
-      if (TREE_CODE (olddecl) != FUNCTION_DECL)
-       if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
-         {
-           DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
-           DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
-         }
+      if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
+       {
+         DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+         DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
+       }
     }
 
 
@@ -3154,7 +3141,7 @@ groktypename (struct c_type_name *type_name)
   type_name->specs->attrs = NULL_TREE;
 
   type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
-                        false, NULL);
+                        false, NULL, DEPRECATED_NORMAL);
 
   /* Apply attributes.  */
   decl_attributes (&type, attrs, 0);
@@ -3183,6 +3170,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
 {
   tree decl;
   tree tem;
+  enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
   /* An object declared as __attribute__((deprecated)) suppresses
      warnings of uses of other deprecated items.  */
@@ -3190,12 +3178,11 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
     deprecated_state = DEPRECATED_SUPPRESS;
 
   decl = grokdeclarator (declarator, declspecs,
-                        NORMAL, initialized, NULL);
+                        NORMAL, initialized, NULL,
+                        deprecated_state);
   if (!decl)
     return 0;
 
-  deprecated_state = DEPRECATED_NORMAL;
-
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
       && MAIN_NAME_P (DECL_NAME (decl)))
     warning (OPT_Wmain, "%q+D is usually a function", decl);
@@ -3383,7 +3370,7 @@ c_maybe_initialize_eh (void)
 void
 finish_decl (tree decl, tree init, tree asmspec_tree)
 {
-  tree type = TREE_TYPE (decl);
+  tree type;
   int was_incomplete = (DECL_SIZE (decl) == 0);
   const char *asmspec = 0;
 
@@ -3410,6 +3397,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
                            || TREE_CODE (decl) == FIELD_DECL))
     objc_check_decl (decl);
 
+  type = TREE_TYPE (decl);
+
   /* Deduce size of array from initialization, if not already known.  */
   if (TREE_CODE (type) == ARRAY_TYPE
       && TYPE_DOMAIN (type) == 0
@@ -3679,7 +3668,7 @@ tree
 grokparm (const struct c_parm *parm)
 {
   tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
-                             NULL);
+                             NULL, DEPRECATED_NORMAL);
 
   decl_attributes (&decl, parm->attrs, 0);
 
@@ -3694,7 +3683,8 @@ push_parm_decl (const struct c_parm *parm)
 {
   tree decl;
 
-  decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
+  decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL,
+                        DEPRECATED_NORMAL);
   decl_attributes (&decl, parm->attrs, 0);
 
   decl = pushdecl (decl);
@@ -3891,6 +3881,61 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
 }
 
 \f
+
+/* Print warning about variable length array if necessary.  */
+
+static void
+warn_variable_length_array (const char *name, tree size)
+{
+  int ped = !flag_isoc99 && pedantic && warn_vla != 0;
+  int const_size = TREE_CONSTANT (size);
+
+  if (ped)
+    {
+      if (const_size)
+       {
+         if (name)
+           pedwarn ("ISO C90 forbids array %qs whose size "
+                    "can%'t be evaluated",
+                    name);
+         else
+           pedwarn ("ISO C90 forbids array whose size "
+                    "can%'t be evaluated");
+       }
+      else
+       {
+         if (name) 
+           pedwarn ("ISO C90 forbids variable length array %qs",
+                    name);
+         else
+           pedwarn ("ISO C90 forbids variable length array");
+       }
+    }
+  else if (warn_vla > 0)
+    {
+      if (const_size)
+        {
+         if (name)
+           warning (OPT_Wvla,
+                    "the size of array %qs can"
+                    "%'t be evaluated", name);
+         else
+           warning (OPT_Wvla,
+                    "the size of array can %'t be evaluated");
+       }
+      else
+       {
+         if (name)
+           warning (OPT_Wvla,
+                    "variable length array %qs is used",
+                    name);
+         else
+           warning (OPT_Wvla,
+                    "variable length array is used");
+       }
+    }
+}
+
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -3912,6 +3957,8 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
    INITIALIZED is true if the decl has an initializer.
    WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
    representing the width of the bit-field.
+   DEPRECATED_STATE is a deprecated_states value indicating whether
+   deprecation warnings should be suppressed.
 
    In the TYPENAME case, DECLARATOR is really an absolute declarator.
    It may also be so in the PARM case, for a prototype where the
@@ -3923,7 +3970,8 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
 static tree
 grokdeclarator (const struct c_declarator *declarator,
                struct c_declspecs *declspecs,
-               enum decl_context decl_context, bool initialized, tree *width)
+               enum decl_context decl_context, bool initialized, tree *width,
+               enum deprecated_states deprecated_state)
 {
   tree type = declspecs->type;
   bool threadp = declspecs->thread_p;
@@ -4289,17 +4337,7 @@ grokdeclarator (const struct c_declarator *declarator,
                       nonconstant even if it is (eg) a const variable
                       with known value.  */
                    size_varies = 1;
-
-                   if (!flag_isoc99 && pedantic)
-                     {
-                       if (TREE_CONSTANT (size))
-                         pedwarn ("ISO C90 forbids array %qs whose size "
-                                  "can%'t be evaluated",
-                                  name);
-                       else
-                         pedwarn ("ISO C90 forbids variable-size array %qs",
-                                  name);
-                     }
+                   warn_variable_length_array (orig_name, size);
                  }
 
                if (integer_zerop (size))
@@ -5410,7 +5448,7 @@ grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
     }
 
   value = grokdeclarator (declarator, declspecs, FIELD, false,
-                         width ? &width : NULL);
+                         width ? &width : NULL, DEPRECATED_NORMAL);
 
   finish_decl (value, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
@@ -5754,7 +5792,7 @@ layout_array_type (tree t)
    may be used to declare the individual values as they are read.  */
 
 tree
-start_enum (tree name)
+start_enum (struct c_enum_contents *the_enum, tree name)
 {
   tree enumtype = 0;
 
@@ -5786,8 +5824,8 @@ start_enum (tree name)
       TYPE_VALUES (enumtype) = 0;
     }
 
-  enum_next_value = integer_zero_node;
-  enum_overflow = 0;
+  the_enum->enum_next_value = integer_zero_node;
+  the_enum->enum_overflow = 0;
 
   if (flag_short_enums)
     TYPE_PACKED (enumtype) = 1;
@@ -5940,7 +5978,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
    Assignment of sequential values by default is handled here.  */
 
 tree
-build_enumerator (tree name, tree value)
+build_enumerator (struct c_enum_contents *the_enum, tree name, tree value)
 {
   tree decl, type;
 
@@ -5970,8 +6008,8 @@ build_enumerator (tree name, tree value)
      in the default.  */
   if (value == 0)
     {
-      value = enum_next_value;
-      if (enum_overflow)
+      value = the_enum->enum_next_value;
+      if (the_enum->enum_overflow)
        error ("overflow in enumeration values");
     }
 
@@ -5984,8 +6022,9 @@ build_enumerator (tree name, tree value)
     }
 
   /* Set basis for default for next value.  */
-  enum_next_value = build_binary_op (PLUS_EXPR, value, integer_one_node, 0);
-  enum_overflow = tree_int_cst_lt (enum_next_value, value);
+  the_enum->enum_next_value = build_binary_op (PLUS_EXPR, value,
+                                              integer_one_node, 0);
+  the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
 
   /* Now create a declaration for the enum value name.  */
 
@@ -6049,7 +6088,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
      error message in c_finish_bc_stmt.  */
   c_break_label = c_cont_label = size_zero_node;
 
-  decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL);
+  decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
+                         DEPRECATED_NORMAL);
 
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
@@ -6229,18 +6269,6 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
   declare_parm_level ();
 
   restype = TREE_TYPE (TREE_TYPE (current_function_decl));
-  /* Promote the value to int before returning it.  */
-  if (c_promoting_integer_type_p (restype))
-    {
-      /* It retains unsignedness if not really getting wider.  */
-      if (TYPE_UNSIGNED (restype)
-         && (TYPE_PRECISION (restype)
-                 == TYPE_PRECISION (integer_type_node)))
-       restype = unsigned_type_node;
-      else
-       restype = integer_type_node;
-    }
-
   resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
   DECL_ARTIFICIAL (resdecl) = 1;
   DECL_IGNORED_P (resdecl) = 1;
@@ -6741,21 +6769,10 @@ finish_function (void)
       TREE_NO_WARNING (fndecl) = 1;
     }
 
-  /* With just -Wextra, complain only if function returns both with
-     and without a value.  */
-  if (extra_warnings
-      && current_function_returns_value
-      && current_function_returns_null)
-    warning (OPT_Wextra, "this function may return with or without a value");
-
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
 
-  /* Keep track of functions declared with the "constructor" and
-     "destructor" attribute.  */
-  c_record_cdtor_fn (fndecl);
-
   /* Finalize the ELF visibility for the function.  */
   c_determine_visibility (fndecl);
 
@@ -7876,10 +7893,6 @@ c_write_global_declarations (void)
     c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
   c_write_global_declarations_1 (BLOCK_VARS (ext_block));
 
-  /* Call functions declared with the "constructor" or "destructor"
-     attribute.  */
-  c_build_cdtor_fns ();
-
   /* We're done parsing; proceed to optimize and emit assembly.
      FIXME: shouldn't be the front end's responsibility to call this.  */
   cgraph_optimize ();