OSDN Git Service

2009-02-20 Mark Mitchell <mark@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 7026555..491e7bb 100644 (file)
@@ -781,14 +781,18 @@ pop_scope (void)
              error ("nested function %q+D declared but never defined", p);
              undef_nested_function = true;
            }
-         /* C99 6.7.4p6: "a function with external linkage... declared
-            with an inline function specifier ... shall also be defined in the
-            same translation unit."  */
          else if (DECL_DECLARED_INLINE_P (p)
                   && TREE_PUBLIC (p)
-                  && !DECL_INITIAL (p)
-                  && !flag_gnu89_inline)
-           pedwarn (input_location, 0, "inline function %q+D declared but never defined", p);
+                  && !DECL_INITIAL (p))
+           {
+             /* C99 6.7.4p6: "a function with external linkage... declared
+                with an inline function specifier ... shall also be defined
+                in the same translation unit."  */
+             if (!flag_gnu89_inline)
+               pedwarn (input_location, 0,
+                        "inline function %q+D declared but never defined", p);
+             DECL_EXTERNAL (p) = 1;
+           }
 
          goto common_symbol;
 
@@ -1775,17 +1779,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
         throw it away, in case it was inlined into a function that
         hasn't been written out yet.  */
       if (new_is_definition && DECL_INITIAL (olddecl))
-       {
-         if (TREE_USED (olddecl)
-             /* We never inline re-defined extern inline functions.
-                FIXME: This would be better handled by keeping both functions
-                as separate declarations.  */
-             && cgraph_function_possibly_inlined_p (olddecl))
-           (*debug_hooks->outlining_inline_function) (olddecl);
-
-         /* The new defn must not be inline.  */
-         DECL_UNINLINABLE (newdecl) = 1;
-       }
+       /* The new defn must not be inline.  */
+       DECL_UNINLINABLE (newdecl) = 1;
       else
        {
          /* If either decl says `inline', this fn is inline, unless
@@ -3650,7 +3645,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
          tree cleanup;
 
          /* Build "cleanup(&decl)" for the destructor.  */
-         cleanup = build_unary_op (ADDR_EXPR, decl, 0);
+         cleanup = build_unary_op (input_location, ADDR_EXPR, decl, 0);
          cleanup = build_tree_list (NULL_TREE, cleanup);
          cleanup = build_function_call (cleanup_decl, cleanup);
 
@@ -3878,8 +3873,8 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
     {
       struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
       if (!lt
-         || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
-         || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
+         || w < tree_int_cst_min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
+         || w < tree_int_cst_min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
        warning (0, "%qs is narrower than values of its type", name);
     }
 }
@@ -4394,24 +4389,36 @@ grokdeclarator (const struct c_declarator *declarator,
              }
            else if (decl_context == FIELD)
              {
-               if (pedantic && !flag_isoc99 && !in_system_header)
+               bool flexible_array_member = false;
+               if (array_parm_vla_unspec_p)
+                 /* Field names can in fact have function prototype
+                    scope so [*] is disallowed here through making
+                    the field variably modified, not through being
+                    something other than a declaration with function
+                    prototype scope.  */
+                 size_varies = 1;
+               else
+                 {
+                   const struct c_declarator *t = declarator;
+                   while (t->kind == cdk_attrs)
+                     t = t->declarator;
+                   flexible_array_member = (t->kind == cdk_id);
+                 }
+               if (flexible_array_member
+                   && pedantic && !flag_isoc99 && !in_system_header)
                  pedwarn (input_location, OPT_pedantic,
                           "ISO C90 does not support flexible array members");
 
                /* ISO C99 Flexible array members are effectively
                   identical to GCC's zero-length array extension.  */
-               itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+               if (flexible_array_member || array_parm_vla_unspec_p)
+                 itype = build_range_type (sizetype, size_zero_node,
+                                           NULL_TREE);
              }
            else if (decl_context == PARM)
              {
                if (array_parm_vla_unspec_p)
                  {
-                   if (! orig_name)
-                     {
-                       /* C99 6.7.5.2p4 */
-                       error ("%<[*]%> not allowed in other than a declaration");
-                     }
-
                    itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
                    size_varies = 1;
                  }
@@ -4420,12 +4427,14 @@ grokdeclarator (const struct c_declarator *declarator,
              {
                if (array_parm_vla_unspec_p)
                  {
-                   /* The error is printed elsewhere.  We use this to
-                      avoid messing up with incomplete array types of
-                      the same type, that would otherwise be modified
-                      below.  */
+                   /* C99 6.7.5.2p4 */
+                   warning (0, "%<[*]%> not in a declaration");
+                   /* We use this to avoid messing up with incomplete
+                      array types of the same type, that would
+                      otherwise be modified below.  */
                    itype = build_range_type (sizetype, size_zero_node,
                                              NULL_TREE);
+                   size_varies = 1;
                  }
              }
 
@@ -5311,7 +5320,7 @@ parser_xref_tag (enum tree_code code, tree name)
     {
       /* Give the type a default layout like unsigned int
         to avoid crashing if it does not get defined.  */
-      TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
+      SET_TYPE_MODE (ref, TYPE_MODE (unsigned_type_node));
       TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
       TYPE_USER_ALIGN (ref) = 0;
       TYPE_UNSIGNED (ref) = 1;
@@ -5358,6 +5367,8 @@ start_struct (enum tree_code code, tree name)
            error ("redefinition of %<union %E%>", name);
          else
            error ("redefinition of %<struct %E%>", name);
+         /* Don't create structures using a name already in use.  */
+         ref = NULL_TREE;
        }
       else if (C_TYPE_BEING_DEFINED (ref))
        {
@@ -5573,9 +5584,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
 
       DECL_CONTEXT (x) = t;
 
-      if (TYPE_PACKED (t) && TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT)
-       DECL_PACKED (x) = 1;
-
       /* If any field is const, the structure type is pseudo-const.  */
       if (TREE_READONLY (x))
        C_TYPE_FIELDS_READONLY (t) = 1;
@@ -5607,6 +5615,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          SET_DECL_C_BIT_FIELD (x);
        }
 
+      if (TYPE_PACKED (t)
+         && (DECL_BIT_FIELD (x)
+             || TYPE_ALIGN (TREE_TYPE (x)) > BITS_PER_UNIT))
+       DECL_PACKED (x) = 1;
+
       /* Detect flexible array member in an invalid context.  */
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
          && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
@@ -5875,8 +5888,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
      that normally we only go as narrow as int - and signed iff any of
      the values are negative.  */
   unsign = (tree_int_cst_sgn (minnode) >= 0);
-  precision = MAX (min_precision (minnode, unsign),
-                  min_precision (maxnode, unsign));
+  precision = MAX (tree_int_cst_min_precision (minnode, unsign),
+                  tree_int_cst_min_precision (maxnode, unsign));
 
   if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
@@ -5926,17 +5939,15 @@ finish_enum (tree enumtype, tree values, tree attributes)
          /* The ISO C Standard mandates enumerators to have type int,
             even though the underlying type of an enum type is
             unspecified.  However, GCC allows enumerators of any
-            integer type as an extensions.  Here we convert any
-            enumerators that fit in an int to type int, to avoid
-            promotions to unsigned types when comparing integers with
-            enumerators that fit in the int range.  When -pedantic is
-            given, build_enumerator() would have already warned about
-            those that don't fit.  */
-         if (int_fits_type_p (ini, integer_type_node))
-           tem = integer_type_node;
-         else
-           tem = enumtype;
-         ini = convert (tem, ini);
+            integer type as an extensions.  build_enumerator()
+            converts any enumerators that fit in an int to type int,
+            to avoid promotions to unsigned types when comparing
+            integers with enumerators that fit in the int range.
+            When -pedantic is given, build_enumerator() would have
+            already warned about those that don't fit. Here we
+            convert the rest to the enumerator type. */
+         if (TREE_TYPE (ini) != integer_type_node)
+           ini = convert (enumtype, ini);
 
          DECL_INITIAL (enu) = ini;
          TREE_PURPOSE (pair) = DECL_NAME (enu);
@@ -5963,7 +5974,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
       TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
       TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
       TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
-      TYPE_MODE (tem) = TYPE_MODE (enumtype);
+      SET_TYPE_MODE (tem, TYPE_MODE (enumtype));
       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
       TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
@@ -6026,6 +6037,18 @@ build_enumerator (struct c_enum_contents *the_enum, tree name, tree value,
     pedwarn (value_loc, OPT_pedantic, 
             "ISO C restricts enumerator values to range of %<int%>");
 
+  /* The ISO C Standard mandates enumerators to have type int, even
+     though the underlying type of an enum type is unspecified.
+     However, GCC allows enumerators of any integer type as an
+     extensions.  Here we convert any enumerators that fit in an int
+     to type int, to avoid promotions to unsigned types when comparing
+     integers with enumerators that fit in the int range.  When
+     -pedantic is given, we would have already warned about those that
+     don't fit. We have to do this here rather than in finish_enum
+     because this value may be used to define more enumerators.  */
+  if (int_fits_type_p (value, integer_type_node))
+    value = convert (integer_type_node, value);
+
   /* Set basis for default for next value.  */
   the_enum->enum_next_value
     = build_binary_op
@@ -7765,6 +7788,8 @@ finish_declspecs (struct c_declspecs *specs)
       if (specs->saturating_p)
        {
          error ("%<_Sat%> is used without %<_Fract%> or %<_Accum%>");
+         if (!targetm.fixed_point_supported_p ())
+           error ("fixed-point types not supported for this target");
          specs->typespec_word = cts_fract;
        }
       else if (specs->long_p || specs->short_p
@@ -7887,8 +7912,10 @@ finish_declspecs (struct c_declspecs *specs)
        specs->type = dfloat128_type_node;
       break;
     case cts_fract:
-       gcc_assert (!specs->complex_p);
-       if (specs->saturating_p)
+      gcc_assert (!specs->complex_p);
+      if (!targetm.fixed_point_supported_p ())
+       specs->type = integer_type_node;
+      else if (specs->saturating_p)
        {
          if (specs->long_long_p)
            specs->type = specs->unsigned_p
@@ -7906,7 +7933,7 @@ finish_declspecs (struct c_declspecs *specs)
            specs->type = specs->unsigned_p
                          ? sat_unsigned_fract_type_node
                          : sat_fract_type_node;
-          }
+       }
       else
        {
          if (specs->long_long_p)
@@ -7925,11 +7952,13 @@ finish_declspecs (struct c_declspecs *specs)
            specs->type = specs->unsigned_p
                          ? unsigned_fract_type_node
                          : fract_type_node;
-          }
+       }
       break;
     case cts_accum:
-       gcc_assert (!specs->complex_p);
-       if (specs->saturating_p)
+      gcc_assert (!specs->complex_p);
+      if (!targetm.fixed_point_supported_p ())
+       specs->type = integer_type_node;
+      else if (specs->saturating_p)
        {
          if (specs->long_long_p)
            specs->type = specs->unsigned_p
@@ -7947,7 +7976,7 @@ finish_declspecs (struct c_declspecs *specs)
            specs->type = specs->unsigned_p
                          ? sat_unsigned_accum_type_node
                          : sat_accum_type_node;
-          }
+       }
       else
        {
          if (specs->long_long_p)
@@ -7966,7 +7995,7 @@ finish_declspecs (struct c_declspecs *specs)
            specs->type = specs->unsigned_p
                          ? unsigned_accum_type_node
                          : accum_type_node;
-          }
+       }
       break;
     default:
       gcc_unreachable ();