OSDN Git Service

* loop-unroll.c (analyze_insns_in_loop): Remove preheader.
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index c82a8a4..d26c8b1 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, 2004 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -46,6 +46,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "hashtab.h"
 #include "tree-mudflap.h"
 #include "opts.h"
+#include "real.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -268,7 +269,6 @@ int flag_const_strings;
 /* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
 
 int flag_signed_bitfields = 1;
-int explicit_flag_signed_bitfields;
 
 /* Nonzero means warn about deprecated conversion from string constant to
    `char *'.  */
@@ -482,14 +482,6 @@ tree *ridpointers;
 
 tree (*make_fname_decl) (tree, int);
 
-/* If non-NULL, the address of a language-specific function that
-   returns 1 for language-specific statement codes.  */
-int (*lang_statement_code_p) (enum tree_code);
-
-/* If non-NULL, the address of a language-specific function that takes
-   any action required right before expand_function_end is called.  */
-void (*lang_expand_function_end) (void);
-
 /* Nonzero means the expression being parsed will never be evaluated.
    This is a count, since unevaluated expressions can nest.  */
 int skip_evaluation;
@@ -545,6 +537,7 @@ static tree handle_tls_model_attribute (tree *, tree, tree, int,
 static tree handle_no_instrument_function_attribute (tree *, tree,
                                                     tree, int, bool *);
 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
                                             bool *);
 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
@@ -615,6 +608,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_no_instrument_function_attribute },
   { "malloc",                 0, 0, true,  false, false,
                              handle_malloc_attribute },
+  { "returns_twice",          0, 0, true,  false, false,
+                             handle_returns_twice_attribute },
   { "no_stack_limit",         0, 0, true,  false, false,
                              handle_no_limit_stack_attribute },
   { "pure",                   0, 0, true,  false, false,
@@ -755,7 +750,10 @@ fname_as_string (int pretty_p)
       strname.len = len - 1;
 
       if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false))
-       return (char *) cstr.text;
+       {
+         XDELETEVEC (namep);
+         return (char *) cstr.text;
+       }
     }
   else
     namep = xstrdup (name);
@@ -867,12 +865,7 @@ fix_string_type (tree value)
   i_type = build_index_type (build_int_cst (NULL_TREE, nchars - 1));
   a_type = build_array_type (e_type, i_type);
   if (flag_const_strings)
-    {
-      /* bleah, c_build_qualified_type should set TYPE_MAIN_VARIANT.  */
-      tree qa_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
-      TYPE_MAIN_VARIANT (qa_type) = a_type;
-      a_type = qa_type;
-    }
+    a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
 
   TREE_TYPE (value) = a_type;
   TREE_CONSTANT (value) = 1;
@@ -1365,8 +1358,6 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
         Other non-expressions need not be processed.  */
       if (cl == tcc_unary)
        {
-         if (first_rtl_op (code) == 0)
-           return;
          x = TREE_OPERAND (x, 0);
          writer = 0;
          goto restart;
@@ -1374,7 +1365,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
       else if (IS_EXPR_CODE_CLASS (cl))
        {
          int lp;
-         int max = first_rtl_op (TREE_CODE (x));
+         int max = TREE_CODE_LENGTH (TREE_CODE (x));
          for (lp = 0; lp < max; lp++)
            {
              tmp_before = tmp_nosp = 0;
@@ -1618,12 +1609,36 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
     return void_type_node;
 
   if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
-    return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
+    return (unsignedp
+           ? make_unsigned_type (GET_MODE_PRECISION (mode))
+           : make_signed_type (GET_MODE_PRECISION (mode)));
 
   if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
-    return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
+    return (unsignedp
+           ? make_unsigned_type (GET_MODE_PRECISION (mode))
+           : make_signed_type (GET_MODE_PRECISION (mode)));
+
+  if (COMPLEX_MODE_P (mode))
+    {
+      enum machine_mode inner_mode;
+      tree inner_type;
+
+      if (mode == TYPE_MODE (complex_float_type_node))
+       return complex_float_type_node;
+      if (mode == TYPE_MODE (complex_double_type_node))
+       return complex_double_type_node;
+      if (mode == TYPE_MODE (complex_long_double_type_node))
+       return complex_long_double_type_node;
+
+      if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
+       return complex_integer_type_node;
 
-  if (VECTOR_MODE_P (mode))
+      inner_mode = GET_MODE_INNER (mode);
+      inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+      if (inner_type != NULL_TREE)
+       return build_complex_type (inner_type);
+    }
+  else if (VECTOR_MODE_P (mode))
     {
       enum machine_mode inner_mode = GET_MODE_INNER (mode);
       tree inner_type = c_common_type_for_mode (inner_mode, unsignedp);
@@ -1863,11 +1878,8 @@ binary_op_error (enum tree_code code)
       opname = "||"; break;
     case BIT_XOR_EXPR:
       opname = "^"; break;
-    case LROTATE_EXPR:
-    case RROTATE_EXPR:
-      opname = "rotate"; break;
     default:
-      opname = "unknown"; break;
+      gcc_unreachable ();
     }
   error ("invalid operands to binary %s", opname);
 }
@@ -1988,14 +2000,6 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       type = c_common_signed_or_unsigned_type (unsignedp0,
                                               TREE_TYPE (primop0));
 
-      /* In C, if TYPE is an enumeration, then we need to get its
-        min/max values from its underlying integral type, not the
-        enumerated type itself.  In C++, TYPE_MAX_VALUE and
-        TYPE_MIN_VALUE have already been set correctly on the
-        enumeration type.  */
-      if (!c_dialect_cxx () && TREE_CODE (type) == ENUMERAL_TYPE)
-       type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0);
-
       maxval = TYPE_MAX_VALUE (type);
       minval = TYPE_MIN_VALUE (type);
 
@@ -2335,18 +2339,30 @@ c_common_truthvalue_conversion (tree expr)
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
+      if (TREE_TYPE (expr) != truthvalue_type_node)
+       return build2 (TREE_CODE (expr), truthvalue_type_node,
+                      TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
+      return expr;
+
     case TRUTH_NOT_EXPR:
-      TREE_TYPE (expr) = truthvalue_type_node;
+      if (TREE_TYPE (expr) != truthvalue_type_node)
+       return build1 (TREE_CODE (expr), truthvalue_type_node,
+                      TREE_OPERAND (expr, 0));
       return expr;
 
     case ERROR_MARK:
       return expr;
 
     case INTEGER_CST:
-      return integer_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
+      /* Avoid integer_zerop to ignore TREE_CONSTANT_OVERFLOW.  */
+      return (TREE_INT_CST_LOW (expr) != 0 || TREE_INT_CST_HIGH (expr) != 0)
+            ? truthvalue_true_node
+            : truthvalue_false_node;
 
     case REAL_CST:
-      return real_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
+      return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0)
+            ? truthvalue_true_node
+            : truthvalue_false_node;
 
     case ADDR_EXPR:
       {
@@ -2489,9 +2505,28 @@ c_build_qualified_type (tree type, int type_quals)
     return type;
 
   if (TREE_CODE (type) == ARRAY_TYPE)
-    return build_array_type (c_build_qualified_type (TREE_TYPE (type),
-                                                    type_quals),
-                            TYPE_DOMAIN (type));
+    {
+      tree t;
+      tree element_type = c_build_qualified_type (TREE_TYPE (type),
+                                                 type_quals);
+
+      /* See if we already have an identically qualified type.  */
+      for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       {
+         if (TYPE_QUALS (strip_array_types (t)) == type_quals
+             && TYPE_NAME (t) == TYPE_NAME (type)
+             && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+             && attribute_list_equal (TYPE_ATTRIBUTES (t),
+                                      TYPE_ATTRIBUTES (type)))
+           break;
+       }
+      if (!t)
+       {
+         t = build_variant_type_copy (type);
+         TREE_TYPE (t) = element_type;
+       }
+      return t;
+    }
 
   /* A restrict-qualified pointer type must be a pointer to object or
      incomplete type.  Note that the use of POINTER_TYPE_P also allows
@@ -2950,9 +2985,10 @@ c_common_nodes_and_builtins (void)
   lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
                                         intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
-                                        get_identifier ("__int128_t"),
-                                        intTI_type_node));
+  if (targetm.scalar_mode_supported_p (TImode))
+    lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                          get_identifier ("__int128_t"),
+                                          intTI_type_node));
 #endif
   lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
                                         unsigned_intQI_type_node));
@@ -2963,9 +2999,10 @@ c_common_nodes_and_builtins (void)
   lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
                                         unsigned_intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
-                                        get_identifier ("__uint128_t"),
-                                        unsigned_intTI_type_node));
+  if (targetm.scalar_mode_supported_p (TImode))
+    lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                          get_identifier ("__uint128_t"),
+                                          unsigned_intTI_type_node));
 #endif
 
   /* Create the widest literal types.  */
@@ -3189,9 +3226,9 @@ c_common_nodes_and_builtins (void)
 
   c_init_attributes ();
 
-#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE,                  \
-                   BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT)     \
-  if (NAME)                                                            \
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
+                   NONANSI_P, ATTRS, IMPLICIT, COND)                   \
+  if (NAME && COND)                                                    \
     {                                                                  \
       tree decl;                                                       \
                                                                        \
@@ -3224,6 +3261,8 @@ c_common_nodes_and_builtins (void)
 #include "builtins.def"
 #undef DEF_BUILTIN
 
+  build_common_builtin_nodes ();
+
   targetm.init_builtins ();
   if (flag_mudflap)
     mudflap_init ();
@@ -3231,6 +3270,26 @@ c_common_nodes_and_builtins (void)
   main_identifier_node = get_identifier ("main");
 }
 
+/* Look up the function in built_in_decls that corresponds to DECL
+   and set ASMSPEC as its user assembler name.  DECL must be a
+   function decl that declares a builtin.  */
+
+void
+set_builtin_user_assembler_name (tree decl, const char *asmspec)
+{
+  tree builtin;
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+             && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+             && asmspec != 0);
+
+  builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
+  set_user_assembler_name (builtin, asmspec);
+  if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
+    init_block_move_fn (asmspec);
+  else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
+    init_block_clear_fn (asmspec);
+}
+
 tree
 build_va_arg (tree expr, tree type)
 {
@@ -3639,7 +3698,7 @@ match_case_to_enum (splay_tree_node node, void *data)
 /* Handle -Wswitch*.  Called from the front end after parsing the switch
    construct.  */
 /* ??? Should probably be somewhere generic, since other languages besides
-   C and C++ would want this.  We'd want to agree on the datastructure,
+   C and C++ would want this.  We'd want to agree on the data structure,
    however, which is a problem.  Alternately, we operate on gimplified
    switch_exprs, which I don't especially like.  At the moment, however,
    C/C++ are the only tree-ssa languages that support enumerations at all,
@@ -3660,7 +3719,7 @@ c_do_switch_warnings (splay_tree cases, tree switch_stmt)
   else
     switch_location = input_location;
 
-  type = SWITCH_TYPE (switch_stmt);
+  type = SWITCH_STMT_TYPE (switch_stmt);
 
   default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
   if (warn_switch_default && !default_node)
@@ -3672,7 +3731,7 @@ c_do_switch_warnings (splay_tree cases, tree switch_stmt)
      default case, or when -Wswitch-enum was specified.  */
   if (((warn_switch && !default_node) || warn_switch_enum)
       && type && TREE_CODE (type) == ENUMERAL_TYPE
-      && TREE_CODE (SWITCH_COND (switch_stmt)) != INTEGER_CST)
+      && TREE_CODE (SWITCH_STMT_COND (switch_stmt)) != INTEGER_CST)
     {
       tree chain;
 
@@ -4313,7 +4372,18 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
          if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
            type = build_variant_type_copy (type);
+
+         /* We cannot use layout_type here, because that will attempt
+            to re-layout all variants, corrupting our original.  */
          TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
+         TYPE_MIN_VALUE (type) = TYPE_MIN_VALUE (typefm);
+         TYPE_MAX_VALUE (type) = TYPE_MAX_VALUE (typefm);
+         TYPE_SIZE (type) = TYPE_SIZE (typefm);
+         TYPE_SIZE_UNIT (type) = TYPE_SIZE_UNIT (typefm);
+         TYPE_MODE (type) = TYPE_MODE (typefm);
+         if (!TYPE_USER_ALIGN (type))
+           TYPE_ALIGN (type) = TYPE_ALIGN (typefm);
+
          typefm = type;
        }
       else if (VECTOR_MODE_P (mode)
@@ -4325,8 +4395,6 @@ handle_mode_attribute (tree *node, tree name, tree args,
        }
 
       *node = typefm;
-
-      /* No need to layout the type here.  The caller should do this.  */
     }
 
   return NULL_TREE;
@@ -4572,6 +4640,12 @@ handle_visibility_attribute (tree *node, tree name, tree args,
       decl = TYPE_NAME (decl);
       if (!decl)
         return NULL_TREE;
+      if (TREE_CODE (decl) == IDENTIFIER_NODE)
+       {
+          warning ("%qE attribute ignored on types",
+                   name);
+          return NULL_TREE;
+       }
     }
 
   if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
@@ -4716,6 +4790,24 @@ handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   return NULL_TREE;
 }
 
+/* Handle a "returns_twice" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+                        int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    DECL_IS_RETURNS_TWICE (*node) = 1;
+  else
+    {
+      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "no_limit_stack" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -5553,6 +5645,27 @@ c_warn_unused_result (tree *top_p)
     }
 }
 
+/* Convert a character from the host to the target execution character
+   set.  cpplib handles this, mostly.  */
+
+HOST_WIDE_INT
+c_common_to_target_charset (HOST_WIDE_INT c)
+{
+  /* Character constants in GCC proper are sign-extended under -fsigned-char,
+     zero-extended under -fno-signed-char.  cpplib insists that characters
+     and character constants are always unsigned.  Hence we must convert
+     back and forth.  */
+  cppchar_t uc = ((cppchar_t)c) & ((((cppchar_t)1) << CHAR_BIT)-1);
+
+  uc = cpp_host_to_exec_charset (parse_in, uc);
+
+  if (flag_signed_char)
+    return ((HOST_WIDE_INT)uc) << (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE)
+                              >> (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE);
+  else
+    return uc;
+}
+
 /* Build the result of __builtin_offsetof.  EXPR is a nested sequence of
    component references, with an INDIRECT_REF at the bottom; much like
    the traditional rendering of offsetof as a macro.  Returns the folded
@@ -5618,4 +5731,40 @@ fold_offsetof (tree expr)
   return convert (size_type_node, fold_offsetof_1 (expr));
 }
 
+/* Return nonzero if REF is an lvalue valid for this language;
+   otherwise, print an error message and return zero.  USE says
+   how the lvalue is being used and so selects the error message.  */
+
+int
+lvalue_or_else (tree ref, enum lvalue_use use)
+{
+  int win = lvalue_p (ref);
+
+  if (!win)
+    {
+      switch (use)
+       {
+       case lv_assign:
+         error ("invalid lvalue in assignment");
+         break;
+       case lv_increment:
+         error ("invalid lvalue in increment");
+         break;
+       case lv_decrement:
+         error ("invalid lvalue in decrement");
+         break;
+       case lv_addressof:
+         error ("invalid lvalue in unary %<&%>");
+         break;
+       case lv_asm:
+         error ("invalid lvalue in asm statement");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+    }
+
+  return win;
+}
+
 #include "gt-c-common.h"