(truthvalue_conversion): Turn off Apr 29 change.
[platform/upstream/gcc.git] / gcc / c-common.c
index 7ccad64..ec5f8ad 100644 (file)
@@ -22,18 +22,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "c-lex.h"
 #include "c-tree.h"
 #include "flags.h"
+#include "obstack.h"
 #include <stdio.h>
 
-#undef NULL
-#define NULL 0
+extern struct obstack permanent_obstack;
 
 /* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */
 
 void
 declare_function_name ()
 {
-  tree decl, init;
+  tree decl, type, init;
   char *name, *printable_name;
+  int len;
 
   if (current_function_decl == NULL)
     {
@@ -45,31 +46,51 @@ declare_function_name ()
       char *kind = "function";
       if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)
        kind = "method";
-      name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
+      /* Allow functions to be nameless (such as artificial ones).  */
+      if (DECL_NAME (current_function_decl))
+        name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
+      else
+       name = "";
       printable_name = (*decl_printable_name) (current_function_decl, &kind);
     }
 
+  /* If the default size of char arrays isn't big enough for the name,
+     make a bigger one.  */
+  len = strlen (name) + 1;
+  type = char_array_type_node;
+  if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (char_array_type_node)))
+      < len)
+    type = build_array_type (char_type_node,
+                            build_index_type (build_int_2 (len, 0)));
+
   push_obstacks_nochange ();
-  decl = build_decl (VAR_DECL, get_identifier ("__FUNCTION__"),
-                    char_array_type_node);
+  decl = build_decl (VAR_DECL, get_identifier ("__FUNCTION__"), type);
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
+  DECL_SOURCE_LINE (decl) = 0;
   DECL_IN_SYSTEM_HEADER (decl) = 1;
   DECL_IGNORED_P (decl) = 1;
-  init = build_string (strlen (name) + 1, name);
-  TREE_TYPE (init) = char_array_type_node;
+  init = build_string (len, name);
+  TREE_TYPE (init) = type;
   DECL_INITIAL (decl) = init;
   finish_decl (pushdecl (decl), init, NULL_TREE);
 
+  len = strlen (printable_name) + 1;
+  type = char_array_type_node;
+  if (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TREE_TYPE (char_array_type_node)))
+      < len)
+    type = build_array_type (char_type_node,
+                            build_index_type (build_int_2 (len, 0)));
+
   push_obstacks_nochange ();
-  decl = build_decl (VAR_DECL, get_identifier ("__PRETTY_FUNCTION__"),
-                    char_array_type_node);
+  decl = build_decl (VAR_DECL, get_identifier ("__PRETTY_FUNCTION__"), type);
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
+  DECL_SOURCE_LINE (decl) = 0;
   DECL_IN_SYSTEM_HEADER (decl) = 1;
   DECL_IGNORED_P (decl) = 1;
-  init = build_string (strlen (printable_name) + 1, printable_name);
-  TREE_TYPE (init) = char_array_type_node;
+  init = build_string (len, printable_name);
+  TREE_TYPE (init) = type;
   DECL_INITIAL (decl) = init;
   finish_decl (pushdecl (decl), init, NULL_TREE);
 }
@@ -199,7 +220,7 @@ decl_attributes (decl, attributes)
        if (TREE_CODE (decl) == FIELD_DECL)
          DECL_PACKED (decl) = 1;
        /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
-          used for TREE_REGDECL.  It wouldn't mean anything anyway.  */
+          used for DECL_REGISTER.  It wouldn't mean anything anyway.  */
       }
     else if (TREE_VALUE (a) != 0
             && TREE_CODE (TREE_VALUE (a)) == TREE_LIST
@@ -219,7 +240,7 @@ decl_attributes (decl, attributes)
                {
                  TREE_TYPE (decl) = type;
                  DECL_SIZE (decl) = 0;
-                 layout_decl (decl);
+                 layout_decl (decl, 0);
                }
              else
                error ("no data type for mode `%s'", specified_name);
@@ -254,6 +275,8 @@ decl_attributes (decl, attributes)
        int format_num = TREE_INT_CST_LOW (TREE_PURPOSE (TREE_VALUE (list)));
        int first_arg_num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list)));
        int is_scan;
+       tree argument;
+       int arg_num;
        
        if (TREE_CODE (decl) != FUNCTION_DECL)
          {
@@ -278,12 +301,126 @@ decl_attributes (decl, attributes)
                "format string arg follows the args to be formatted, for `%s'");
            return;
          }
+
+       /* Verify that the format_num argument is actually a string, in case
+          the format attribute is in error.  */
+       argument = TYPE_ARG_TYPES (TREE_TYPE (decl));
+       for (arg_num = 1; ; ++arg_num)
+         {
+           if (argument == 0 || arg_num == format_num)
+             break;
+           argument = TREE_CHAIN (argument);
+         }
+       if (! argument
+           || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE
+           || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
+               != char_type_node))
+         {
+           error_with_decl (decl,
+                            "format string arg not a string type, for `%s'");
+           return;
+         }
+       /* Verify that first_arg_num points to the last argument, the ... */
+       while (argument)
+         arg_num++, argument = TREE_CHAIN (argument);
+       if (arg_num != first_arg_num)
+         {
+           error_with_decl (decl,
+                            "args to be formatted is not ..., for `%s'");
+           return;
+         }
        
        record_format_info (DECL_NAME (decl), is_scan, format_num,
                            first_arg_num);
       }
 }
 \f
+/* Print a warning if a constant expression had overflow in folding.
+   Invoke this function on every expression that the language
+   requires to be a constant expression.
+   Note the ANSI C standard says it is erroneous for a
+   constant expression to overflow.  */
+
+void
+constant_expression_warning (value)
+     tree value;
+{
+  if (TREE_CODE (value) == INTEGER_CST && TREE_CONSTANT_OVERFLOW (value))
+    {
+      pedwarn ("overflow in constant expression");
+      /* Suppress duplicate warnings.  */
+      TREE_CONSTANT_OVERFLOW (value) = 0;
+    }
+}
+
+/* Print a warning if an expression had overflow in folding.
+   Invoke this function on every expression that
+   (1) appears in the source code, and
+   (2) might be a constant expression that overflowed, and
+   (3) is not already checked by convert_and_check;
+   however, do not invoke this function on operands of explicit casts.  */
+
+void
+overflow_warning (value)
+     tree value;
+{
+  if (TREE_CODE (value) == INTEGER_CST && TREE_CONSTANT_OVERFLOW (value))
+    {
+      pedwarn ("integer overflow in expression");
+      TREE_CONSTANT_OVERFLOW (value) = 0;
+    }
+}
+
+/* Print a warning if a large constant is truncated to unsigned,
+   or if -Wconversion is used and a constant < 0 is converted to unsigned.
+   Invoke this function on every expression that might be implicitly
+   converted to an unsigned type.  */
+
+void
+unsigned_conversion_warning (result, operand)
+     tree result, operand;
+{
+  if (TREE_CODE (operand) == INTEGER_CST
+      && TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
+      && TREE_UNSIGNED (TREE_TYPE (result))
+      && !int_fits_type_p (operand, TREE_TYPE (result)))
+    {
+      if (!int_fits_type_p (operand, signed_type (TREE_TYPE (result))))
+       /* This detects cases like converting -129 or 256 to unsigned char.  */
+       pedwarn ("large integer implicitly truncated to unsigned type");
+      else if (warn_conversion)
+       pedwarn ("negative integer implicitly converted to unsigned type");
+    }
+}
+
+/* Convert EXPR to TYPE, warning about conversion problems with constants.
+   Invoke this function on every expression that is converted implicitly,
+   i.e. because of language rules and not because of an explicit cast.  */
+
+tree
+convert_and_check (type, expr)
+     tree type, expr;
+{
+  tree t = convert (type, expr);
+  if (TREE_CODE (t) == INTEGER_CST)
+    {
+      if (TREE_UNSIGNED (TREE_TYPE (expr))
+         && !TREE_UNSIGNED (type)
+         && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+         && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr)))
+       /* No warning for converting 0x80000000 to int.  */
+       TREE_CONSTANT_OVERFLOW (t) = 0;
+      else if (TREE_CONSTANT_OVERFLOW (t))
+       {
+         pedwarn ("overflow in implicit constant conversion");
+         TREE_CONSTANT_OVERFLOW (t) = 0;
+       }
+      else
+       unsigned_conversion_warning (t, expr);
+    }
+  return t;
+}
+\f
 void
 c_expand_expr_stmt (expr)
      tree expr;
@@ -312,8 +449,7 @@ check_case_value (value)
     return value;
 
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
-  if (TREE_CODE (value) == NON_LVALUE_EXPR)
-    value = TREE_OPERAND (value, 0);
+  STRIP_TYPE_NOPS (value);
 
   if (TREE_CODE (value) != INTEGER_CST
       && value != error_mark_node)
@@ -325,6 +461,8 @@ check_case_value (value)
     /* Promote char or short to int.  */
     value = default_conversion (value);
 
+  constant_expression_warning (value);
+
   return value;
 }
 \f
@@ -728,7 +866,8 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
         TYPE is already properly set.  */
     }
   else if (real1 && real2
-          && TYPE_PRECISION (TREE_TYPE (primop0)) == TYPE_PRECISION (TREE_TYPE (primop1)))
+          && (TYPE_PRECISION (TREE_TYPE (primop0))
+              == TYPE_PRECISION (TREE_TYPE (primop1))))
     type = TREE_TYPE (primop0);
 
   /* If args' natural types are both narrower than nominal type
@@ -816,6 +955,31 @@ truthvalue_conversion (expr)
 {
   register enum tree_code code;
 
+  if (TREE_CODE (expr) == ERROR_MARK)
+    return expr;
+
+#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 integer_zero_node;
+
+    case UNION_TYPE:
+      error ("union type value used where scalar is required");
+      return integer_zero_node;
+
+    case ARRAY_TYPE:
+      error ("array type value used where scalar is required");
+      return integer_zero_node;
+
+    default:
+      break;
+    }
+#endif /* 0 */
+
   switch (TREE_CODE (expr))
     {
       /* It is simpler and generates better code to have only TRUTH_*_EXPR
@@ -841,6 +1005,7 @@ truthvalue_conversion (expr)
     case TRUTH_ORIF_EXPR:
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
     case ERROR_MARK:
       return expr;
 
@@ -857,6 +1022,13 @@ truthvalue_conversion (expr)
       else
        return integer_one_node;
 
+    case COMPLEX_EXPR:
+      return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
+                              ? TRUTH_AND_EXPR : TRUTH_ANDIF_EXPR),
+                             truthvalue_conversion (TREE_OPERAND (expr, 0)),
+                             truthvalue_conversion (TREE_OPERAND (expr, 1)),
+                             0);
+
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
@@ -894,9 +1066,16 @@ truthvalue_conversion (expr)
        return truthvalue_conversion (TREE_OPERAND (expr, 0));
       break;
 
-    case BIT_XOR_EXPR:
     case MINUS_EXPR:
-      /* These can be changed into a comparison of the two objects.  */
+      /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
+        this case.  */
+      if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+         && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
+       break;
+      /* fall through... */
+    case BIT_XOR_EXPR:
+      /* This and MINUS_EXPR can be changed into a comparison of the
+        two objects.  */
       if (TREE_TYPE (TREE_OPERAND (expr, 0))
          == TREE_TYPE (TREE_OPERAND (expr, 1)))
        return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),
@@ -905,8 +1084,21 @@ truthvalue_conversion (expr)
                              fold (build1 (NOP_EXPR,
                                            TREE_TYPE (TREE_OPERAND (expr, 0)),
                                            TREE_OPERAND (expr, 1))), 1);
+
+    case MODIFY_EXPR:
+      if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
+       warning ("suggest parentheses around assignment used as truth value");
+      break;
     }
 
+  if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
+    return (build_binary_op
+           ((TREE_SIDE_EFFECTS (expr)
+             ? TRUTH_AND_EXPR : TRUTH_ANDIF_EXPR),
+            truthvalue_conversion (build_unary_op (REALPART_EXPR, expr, 0)),
+            truthvalue_conversion (build_unary_op (IMAGPART_EXPR, expr, 0)),
+            0));
+
   return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
 }
 \f
@@ -988,3 +1180,28 @@ get_directive_line (finput)
       char_escaped = (c == '\\' && ! char_escaped);
     }
 }
+\f
+/* Make a variant type in the proper way for C/C++, propagating qualifiers
+   down to the element type of an array.  */
+
+tree
+c_build_type_variant (type, constp, volatilep)
+     tree type;
+     int constp, volatilep;
+{
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      tree real_main_variant = TYPE_MAIN_VARIANT (type);
+      int permanent = TREE_PERMANENT (type);
+
+      if (permanent)
+       push_obstacks (&permanent_obstack, &permanent_obstack);
+      type = build_array_type (c_build_type_variant (TREE_TYPE (type),
+                                                    constp, volatilep),
+                              TYPE_DOMAIN (type));
+      TYPE_MAIN_VARIANT (type) = real_main_variant;
+      if (permanent)
+       pop_obstacks ();
+    }
+  return build_type_variant (type, constp, volatilep);
+}