OSDN Git Service

[gcc/ChangeLog]
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 9cdd144..4c0ce27 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines shared by all languages that are variants of C.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -599,23 +599,6 @@ int flag_permissive;
 
 int flag_enforce_eh_specs = 1;
 
-/*  The version of the C++ ABI in use.  The following values are
-    allowed:
-
-    0: The version of the ABI believed most conformant with the
-       C++ ABI specification.  This ABI may change as bugs are
-       discovered and fixed.  Therefore, 0 will not necessarily
-       indicate the same ABI in different versions of G++.
-
-    1: The version of the ABI first used in G++ 3.2.
-
-    2: The version of the ABI first used in G++ 3.4.
-
-    Additional positive integers will be assigned as new versions of
-    the ABI become the default version of the ABI.  */
-
-int flag_abi_version = 2;
-
 /* Nonzero means warn about things that will change when compiling
    with an ABI-compliant compiler.  */
 
@@ -784,7 +767,6 @@ static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
 static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
                                                 bool *);
-static tree vector_size_helper (tree, tree);
 
 static void check_function_nonnull (tree, tree);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -1053,7 +1035,13 @@ finish_fname_decls (void)
       tree *p = &DECL_SAVED_TREE (current_function_decl);
       /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK.  */
       while (TREE_CODE (*p) != COMPOUND_STMT)
-       p = &TREE_CHAIN (*p);
+       {
+         if (TREE_CODE (*p) == EXPR_STMT)
+           p = &TREE_CHAIN (*p);
+         else
+           p = &TREE_OPERAND(*p, 0);
+       }
+
       p = &COMPOUND_BODY (*p);
       if (TREE_CODE (*p) == SCOPE_STMT)
        p = &TREE_CHAIN (*p);
@@ -1176,7 +1164,7 @@ fix_string_type (tree value)
      -Wwrite-strings says make the string constant an array of const char
      so that copying it to a non-const pointer will get a warning.
      For C++, this is the standard behavior.  */
-  if (flag_const_strings && ! flag_writable_strings)
+  if (flag_const_strings)
     {
       tree elements
        = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
@@ -1191,7 +1179,7 @@ fix_string_type (tree value)
                          build_index_type (build_int_2 (nchars - 1, 0)));
 
   TREE_CONSTANT (value) = 1;
-  TREE_READONLY (value) = ! flag_writable_strings;
+  TREE_READONLY (value) = 1;
   TREE_STATIC (value) = 1;
   return value;
 }
@@ -2608,28 +2596,6 @@ c_common_truthvalue_conversion (tree expr)
   if (TREE_CODE (expr) == FUNCTION_DECL)
     expr = build_unary_op (ADDR_EXPR, expr, 0);
 
-#if 0 /* This appears to be wrong for C++.  */
-  /* These really should return error_mark_node after 2.4 is stable.
-     But not all callers handle ERROR_MARK properly.  */
-  switch (TREE_CODE (TREE_TYPE (expr)))
-    {
-    case RECORD_TYPE:
-      error ("struct type value used where scalar is required");
-      return truthvalue_false_node;
-
-    case UNION_TYPE:
-      error ("union type value used where scalar is required");
-      return truthvalue_false_node;
-
-    case ARRAY_TYPE:
-      error ("array type value used where scalar is required");
-      return truthvalue_false_node;
-
-    default:
-      break;
-    }
-#endif /* 0 */
-
   switch (TREE_CODE (expr))
     {
     case EQ_EXPR:
@@ -2680,15 +2646,15 @@ c_common_truthvalue_conversion (tree expr)
     case COMPLEX_EXPR:
       return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
                               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+               (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)),
+               (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 1)),
                              0);
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
-      return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+      return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
@@ -2696,15 +2662,15 @@ c_common_truthvalue_conversion (tree expr)
         we can't ignore them if their second arg has side-effects.  */
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
        return build (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1),
-                     c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+                     (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)));
       else
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
       /* Distribute the conversion into the arms of a COND_EXPR.  */
       return fold (build (COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
+               (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 1)),
+               (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 2))));
 
     case CONVERT_EXPR:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
@@ -2717,7 +2683,7 @@ c_common_truthvalue_conversion (tree expr)
       /* If this is widening the argument, we can ignore it.  */
       if (TYPE_PRECISION (TREE_TYPE (expr))
          >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
       break;
 
     case MINUS_EXPR:
@@ -2766,8 +2732,8 @@ c_common_truthvalue_conversion (tree expr)
       return (build_binary_op
              ((TREE_SIDE_EFFECTS (expr)
                ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-       c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
-       c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
+       (*lang_hooks.truthvalue_conversion) (build_unary_op (REALPART_EXPR, t, 0)),
+       (*lang_hooks.truthvalue_conversion) (build_unary_op (IMAGPART_EXPR, t, 0)),
               0));
     }
 
@@ -2784,6 +2750,9 @@ static tree builtin_function_2 (const char *, const char *, tree, tree,
 tree
 c_build_qualified_type (tree type, int type_quals)
 {
+  if (type == error_mark_node)
+    return type;
+  
   if (TREE_CODE (type) == ARRAY_TYPE)
     return build_array_type (c_build_qualified_type (TREE_TYPE (type),
                                                     type_quals),
@@ -2809,6 +2778,9 @@ void
 c_apply_type_quals_to_decl (int type_quals, tree decl)
 {
   tree type = TREE_TYPE (decl);
+  
+  if (type == error_mark_node)
+    return;
 
   if (((type_quals & TYPE_QUAL_CONST)
        || (type && TREE_CODE (type) == REFERENCE_TYPE))
@@ -2910,7 +2882,7 @@ c_common_get_alias_set (tree t)
 
             int *ip;
             int **ipp = &ip;
-            const int* const* cipp = &ipp;
+            const int* const* cipp = ipp;
 
          And, it doesn't make sense for that to be legal unless you
         can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
@@ -4048,8 +4020,9 @@ finish_label_address_expr (tree label)
 /* Hook used by expand_expr to expand language-specific tree codes.  */
 
 rtx
-c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
-     /* Actually enum_modifier.  */
+c_expand_expr (tree exp, rtx target, enum machine_mode tmode, 
+              int modifier /* Actually enum_modifier.  */,
+              rtx *alt_rtl)
 {
   switch (TREE_CODE (exp))
     {
@@ -4058,7 +4031,6 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
        tree rtl_expr;
        rtx result;
        bool preserve_result = false;
-       bool return_target = false;
 
        if (STMT_EXPR_WARN_UNUSED_RESULT (exp) && target == const0_rtx)
          {
@@ -4106,30 +4078,18 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
            if (TREE_CODE (last) == SCOPE_STMT
                && TREE_CODE (expr) == EXPR_STMT)
              {
-               if (target && TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL
-                   && DECL_RTL_IF_SET (EXPR_STMT_EXPR (expr)) == target)
-                 /* If the last expression is a variable whose RTL is the
-                    same as our target, just return the target; if it
-                    isn't valid expanding the decl would produce different
-                    RTL, and store_expr would try to do a copy.  */
-                 return_target = true;
-               else
-                 {
-                   /* Otherwise, note that we want the value from the last
-                      expression.  */
-                   TREE_ADDRESSABLE (expr) = 1;
-                   preserve_result = true;
-                 }
+               /* Otherwise, note that we want the value from the last
+                  expression.  */
+               TREE_ADDRESSABLE (expr) = 1;
+               preserve_result = true;
              }
          }
 
        expand_stmt (STMT_EXPR_STMT (exp));
        expand_end_stmt_expr (rtl_expr);
 
-       result = expand_expr (rtl_expr, target, tmode, modifier);
-       if (return_target)
-         result = target;
-       else if (preserve_result && GET_CODE (result) == MEM)
+       result = expand_expr_real (rtl_expr, target, tmode, modifier, alt_rtl);
+       if (preserve_result && GET_CODE (result) == MEM)
          {
            if (GET_MODE (result) != BLKmode)
              result = copy_to_reg (result);
@@ -4154,7 +4114,7 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
           literal, then return the variable.  */
        tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
        emit_local_var (decl);
-       return expand_expr (decl, target, tmode, modifier);
+       return expand_expr_real (decl, target, tmode, modifier, alt_rtl);
       }
 
     default:
@@ -4288,21 +4248,6 @@ c_init_attributes (void)
 #undef DEF_ATTR_TREE_LIST
 }
 
-/* Output a -Wshadow warning MSGCODE about NAME, and give the location
-   of the previous declaration DECL.  */
-void
-shadow_warning (enum sw_kind msgcode, const char *name, tree decl)
-{
-  static const char *const msgs[] = {
-    /* SW_PARAM  */ N_("declaration of \"%s\" shadows a parameter"),
-    /* SW_LOCAL  */ N_("declaration of \"%s\" shadows a previous local"),
-    /* SW_GLOBAL */ N_("declaration of \"%s\" shadows a global declaration")
-  };
-
-  warning (msgs[msgcode], name);
-  warning ("%Jshadowed declaration is here", decl);
-}
-
 /* Attribute handlers common to C front ends.  */
 
 /* Handle a "packed" attribute; arguments as in
@@ -4882,7 +4827,13 @@ handle_alias_attribute (tree *node, tree name, tree args,
       error ("%J'%D' defined both normally and as an alias", decl, decl);
       *no_add_attrs = true;
     }
-  else if (decl_function_context (decl) == 0)
+
+  /* Note that the very first time we process a nested declaration,
+     decl_function_context will not be set.  Indeed, *would* never
+     be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
+     we do below.  After such frobbery, pushdecl would set the context.
+     In any case, this is never what we want.  */
+  else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
     {
       tree id;
 
@@ -5283,57 +5234,11 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
     }
 
   /* Build back pointers if needed.  */
-  *node = vector_size_helper (*node, new_type);
+  *node = reconstruct_complex_type (*node, new_type);
 
   return NULL_TREE;
 }
 
-/* HACK.  GROSS.  This is absolutely disgusting.  I wish there was a
-   better way.
-
-   If we requested a pointer to a vector, build up the pointers that
-   we stripped off while looking for the inner type.  Similarly for
-   return values from functions.
-
-   The argument "type" is the top of the chain, and "bottom" is the
-   new type which we will point to.  */
-
-static tree
-vector_size_helper (tree type, tree bottom)
-{
-  tree inner, outer;
-
-  if (POINTER_TYPE_P (type))
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_pointer_type (inner);
-    }
-  else if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_array_type (inner, TYPE_DOMAIN (type));
-    }
-  else if (TREE_CODE (type) == FUNCTION_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_function_type (inner, TYPE_ARG_TYPES (type));
-    }
-  else if (TREE_CODE (type) == METHOD_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
-                                         inner, 
-                                         TYPE_ARG_TYPES (type));
-    }
-  else
-    return bottom;
-
-  TREE_READONLY (outer) = TREE_READONLY (type);
-  TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
-
-  return outer;
-}
-
 /* Handle the "nonnull" attribute.  */
 static tree
 handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
@@ -5770,16 +5675,35 @@ c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case MODIFY_EXPR:
     case CONSTRUCTOR:
       {
-       int size = int_size_in_bytes (TREE_TYPE (x));
+       HOST_WIDE_INT size;
+
+       size = int_size_in_bytes (TREE_TYPE (x));
 
-       if (!size || size > MOVE_MAX_PIECES)
+       if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO)
          *count += 10;
        else
-         *count += 2 * (size + MOVE_MAX - 1) / MOVE_MAX;
-       return NULL;
+         *count += ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES);
       }
       break;
-    /* Few special cases of expensive operations.  This is usefull
+    case CALL_EXPR:
+      {
+       tree decl = get_callee_fndecl (x);
+
+       if (decl && DECL_BUILT_IN (decl))
+         switch (DECL_FUNCTION_CODE (decl))
+           {
+           case BUILT_IN_CONSTANT_P:
+             *walk_subtrees = 0;
+             return NULL_TREE;
+           case BUILT_IN_EXPECT:
+             return NULL_TREE;
+           default:
+             break;
+           }
+       *count += 10;
+       break;
+      }
+    /* Few special cases of expensive operations.  This is useful
        to avoid inlining on functions having too many of these.  */
     case TRUNC_DIV_EXPR:
     case CEIL_DIV_EXPR:
@@ -5790,7 +5714,6 @@ c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
     case RDIV_EXPR:
-    case CALL_EXPR:
       *count += 10;
       break;
     /* Various containers that will produce no code themselves.  */