OSDN Git Service

2006-01-06 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index a38ce6c..bda8789 100644 (file)
@@ -1,6 +1,7 @@
 /* Build expressions with type checking for C compiler.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006  
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -617,6 +618,22 @@ c_common_type (tree t1, tree t2)
   if (code2 == REAL_TYPE && code1 != REAL_TYPE)
     return t2;
 
+  /* If both are real and either are decimal floating point types, use
+     the decimal floating point type with the greater precision. */
+
+  if (code1 == REAL_TYPE && code2 == REAL_TYPE)
+    {
+      if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node
+         || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node)
+       return dfloat128_type_node;
+      else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node
+              || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node)
+       return dfloat64_type_node;
+      else if (TYPE_MAIN_VARIANT (t1) == dfloat32_type_node
+              || TYPE_MAIN_VARIANT (t2) == dfloat32_type_node)
+       return dfloat32_type_node;
+    }
+
   /* Both real or both integers; use the one with greater precision.  */
 
   if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
@@ -918,7 +935,7 @@ same_translation_unit_p (tree t1, tree t2)
 static struct tagged_tu_seen_cache *
 alloc_tagged_tu_seen_cache (tree t1, tree t2)
 {
-  struct tagged_tu_seen_cache *tu = xmalloc (sizeof (struct tagged_tu_seen_cache));
+  struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
   tu->next = tagged_tu_seen_base;
   tu->t1 = t1;
   tu->t2 = t2;
@@ -2370,10 +2387,37 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                    {
                      /* Warn if any argument is passed as `float',
                         since without a prototype it would be `double'.  */
-                     if (formal_prec == TYPE_PRECISION (float_type_node))
+                     if (formal_prec == TYPE_PRECISION (float_type_node)
+                         && type != dfloat32_type_node)
                        warning (0, "passing argument %d of %qE as %<float%> "
                                 "rather than %<double%> due to prototype",
                                 argnum, rname);
+
+                     /* Warn if mismatch between argument and prototype
+                        for decimal float types.  Warn of conversions with
+                        binary float types and of precision narrowing due to
+                        prototype. */
+                     else if (type != TREE_TYPE (val)
+                              && (type == dfloat32_type_node
+                                  || type == dfloat64_type_node
+                                  || type == dfloat128_type_node 
+                                  || TREE_TYPE (val) == dfloat32_type_node
+                                  || TREE_TYPE (val) == dfloat64_type_node
+                                  || TREE_TYPE (val) == dfloat128_type_node)
+                              && (formal_prec 
+                                  <= TYPE_PRECISION (TREE_TYPE (val))
+                                  || (type == dfloat128_type_node
+                                      && (TREE_TYPE (val)
+                                          != dfloat64_type_node 
+                                          && (TREE_TYPE (val) 
+                                              != dfloat32_type_node)))
+                                  || (type == dfloat64_type_node
+                                      && (TREE_TYPE (val)
+                                          != dfloat32_type_node))))
+                       warning (0, "passing argument %d of %qE as %qT "
+                                "rather than %qT due to prototype",
+                                argnum, rname, type, TREE_TYPE (val));
+
                    }
                  /* Detect integer changing in width or signedness.
                     These warnings are only activated with
@@ -2436,7 +2480,8 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
        }
       else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
                && (TYPE_PRECISION (TREE_TYPE (val))
-                  < TYPE_PRECISION (double_type_node)))
+                  < TYPE_PRECISION (double_type_node))
+              && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
        /* Convert `float' to `double'.  */
        result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
       else if ((invalid_func_diag = 
@@ -3464,8 +3509,12 @@ build_c_cast (tree type, tree expr)
 
       if (TREE_CODE (type) == INTEGER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
-         && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
-         && !TREE_CONSTANT (value))
+         && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
+      /* Unlike conversion of integers to pointers, where the 
+         warning is disabled for converting constants because 
+         of cases such as SIG_*, warn about converting constant 
+         pointers to integers. In some cases it may cause unwanted 
+         sign extension, and a warning is appropriate.  */
        warning (OPT_Wpointer_to_int_cast,
                 "cast from pointer to integer of different size");
 
@@ -4838,7 +4887,7 @@ void
 start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
 {
   const char *locus;
-  struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack));
+  struct initializer_stack *p = XNEW (struct initializer_stack);
 
   p->decl = constructor_decl;
   p->require_constant_value = require_constant_value;