OSDN Git Service

* builtins.c, c-common.c, c-decl.c, c-format.c: Say "argument"
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
index dc2297e..5b476ca 100644 (file)
@@ -107,12 +107,12 @@ static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
 static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
-static rtx expand_builtin_strcat (tree, rtx, enum machine_mode);
+static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
 static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
 static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
-static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode, int);
+static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
 static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode);
 static rtx expand_builtin_bcopy (tree, tree);
 static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
@@ -162,7 +162,7 @@ static tree fold_builtin_ceil (tree);
 static tree fold_builtin_round (tree);
 static tree fold_builtin_bitop (tree);
 static tree fold_builtin_memcpy (tree);
-static tree fold_builtin_mempcpy (tree);
+static tree fold_builtin_mempcpy (tree, tree, int);
 static tree fold_builtin_memmove (tree, tree);
 static tree fold_builtin_strchr (tree);
 static tree fold_builtin_memcmp (tree);
@@ -452,7 +452,7 @@ builtin_save_expr (tree exp)
    times to get the address of either a higher stack frame, or a return
    address located within it (depending on FNDECL_CODE).  */
 
-rtx
+static rtx
 expand_builtin_return_addr (enum built_in_function fndecl_code, int count,
                            rtx tem)
 {
@@ -688,7 +688,7 @@ expand_builtin_setjmp (tree arglist, rtx target)
    scheme in the compiler and will only work in the method used by
    them.  */
 
-void
+static void
 expand_builtin_longjmp (rtx buf_addr, rtx value)
 {
   rtx fp, lab, stack, insn, last;
@@ -922,28 +922,29 @@ expand_builtin_prefetch (tree arglist)
   /* Argument 1 (read/write flag) must be a compile-time constant int.  */
   if (TREE_CODE (arg1) != INTEGER_CST)
     {
-      error ("second arg to %<__builtin_prefetch%> must be a constant");
+      error ("second argument to %<__builtin_prefetch%> must be a constant");
       arg1 = integer_zero_node;
     }
   op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
   /* Argument 1 must be either zero or one.  */
   if (INTVAL (op1) != 0 && INTVAL (op1) != 1)
     {
-      warning ("invalid second arg to __builtin_prefetch; using zero");
+      warning ("invalid second argument to %<__builtin_prefetch%>;"
+              " using zero");
       op1 = const0_rtx;
     }
 
   /* Argument 2 (locality) must be a compile-time constant int.  */
   if (TREE_CODE (arg2) != INTEGER_CST)
     {
-      error ("third arg to %<__builtin_prefetch%> must be a constant");
+      error ("third argument to %<__builtin_prefetch%> must be a constant");
       arg2 = integer_zero_node;
     }
   op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
   /* Argument 2 must be 0, 1, 2, or 3.  */
   if (INTVAL (op2) < 0 || INTVAL (op2) > 3)
     {
-      warning ("invalid third arg to __builtin_prefetch; using zero");
+      warning ("invalid third argument to %<__builtin_prefetch%>; using zero");
       op2 = const0_rtx;
     }
 
@@ -2621,7 +2622,7 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
    stpcpy.  */
 
 static rtx
-expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
+expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
                        int endp)
 {
   if (!validate_arglist (arglist,
@@ -2648,48 +2649,20 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
       unsigned int dest_align
        = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
       rtx dest_mem, src_mem, len_rtx;
+      tree result = fold_builtin_mempcpy (arglist, type, endp);
 
-      /* If DEST is not a pointer type, call the normal function.  */
-      if (dest_align == 0)
+      if (result)
+       return expand_expr (result, target, mode, EXPAND_NORMAL);
+      
+      /* If either SRC or DEST is not a pointer type, don't do this
+         operation in-line.  */
+      if (dest_align == 0 || src_align == 0)
        return 0;
 
-      /* If SRC and DEST are the same (and not volatile), do nothing.  */
-      if (operand_equal_p (src, dest, 0))
-       {
-         tree expr;
-
-         if (endp == 0)
-           {
-             /* Evaluate and ignore LEN in case it has side-effects.  */
-             expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
-             return expand_expr (dest, target, mode, EXPAND_NORMAL);
-           }
-
-         if (endp == 2)
-           len = fold (build2 (MINUS_EXPR, TREE_TYPE (len), len,
-                               integer_one_node));
-         len = fold_convert (TREE_TYPE (dest), len);
-         expr = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len));
-         return expand_expr (expr, target, mode, EXPAND_NORMAL);
-       }
-
       /* If LEN is not constant, call the normal function.  */
       if (! host_integerp (len, 1))
        return 0;
 
-      /* If the LEN parameter is zero, return DEST.  */
-      if (tree_low_cst (len, 1) == 0)
-       {
-         /* Evaluate and ignore SRC in case it has side-effects.  */
-         expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
-         return expand_expr (dest, target, mode, EXPAND_NORMAL);
-       }
-
-      /* If either SRC is not a pointer type, don't do this
-         operation in-line.  */
-      if (src_align == 0)
-       return 0;
-
       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
       src_str = c_getstr (src);
 
@@ -2753,7 +2726,7 @@ expand_builtin_memmove (tree arglist, tree type, rtx target,
       tree result = fold_builtin_memmove (arglist, type);
 
       if (result)
-       expand_expr (result, target, mode, EXPAND_NORMAL);
+       return expand_expr (result, target, mode, EXPAND_NORMAL);
 
       /* If DEST is not a pointer type, call the normal function.  */
       if (dest_align == 0)
@@ -2779,7 +2752,7 @@ expand_builtin_memmove (tree arglist, tree type, rtx target,
         it is ok to use memcpy as well.  */
       if (integer_onep (len))
         {
-         rtx ret = expand_builtin_mempcpy (arglist, target, mode,
+         rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
                                            /*endp=*/0);
          if (ret)
            return ret;
@@ -2950,7 +2923,8 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
       narglist = build_tree_list (NULL_TREE, lenp1);
       narglist = tree_cons (NULL_TREE, src, narglist);
       narglist = tree_cons (NULL_TREE, dst, narglist);
-      ret = expand_builtin_mempcpy (narglist, target, mode, /*endp=*/2);
+      ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
+                                   target, mode, /*endp=*/2);
 
       if (ret)
        return ret;
@@ -3590,7 +3564,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
    otherwise try to get the result in TARGET, if convenient.  */
 
 static rtx
-expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strcat (tree arglist, tree type, rtx target, enum machine_mode mode)
 {
   if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
     return 0;
@@ -3640,7 +3614,7 @@ expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
                  pass in a target of zero, it should never actually be
                  used.  If this was successful return the original
                  dst, not the result of mempcpy.  */
-             if (expand_builtin_mempcpy (arglist, /*target=*/0, mode, /*endp=*/0))
+             if (expand_builtin_mempcpy (arglist, type, /*target=*/0, mode, /*endp=*/0))
                return expand_expr (dst, target, mode, EXPAND_NORMAL);
              else
                return 0;
@@ -3888,6 +3862,11 @@ expand_builtin_va_start (tree arglist)
 
   chain = TREE_CHAIN (arglist);
 
+  if (!chain)
+    {
+      error ("too few arguments to function %<va_start%>");
+      return const0_rtx;
+    }
   if (TREE_CHAIN (chain))
     error ("too many arguments to function %<va_start%>");
 
@@ -4180,9 +4159,9 @@ expand_builtin_frame_address (tree fndecl, tree arglist)
   else if (! host_integerp (TREE_VALUE (arglist), 1))
     {
       if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
-       error ("invalid arg to %<__builtin_frame_address%>");
+       error ("invalid argument to %<__builtin_frame_address%>");
       else
-       error ("invalid arg to %<__builtin_return_address%>");
+       error ("invalid argument to %<__builtin_return_address%>");
       return const0_rtx;
     }
   else
@@ -4196,9 +4175,9 @@ expand_builtin_frame_address (tree fndecl, tree arglist)
       if (tem == NULL)
        {
          if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
-           warning ("unsupported arg to %<__builtin_frame_address%>");
+           warning ("unsupported argument to %<__builtin_frame_address%>");
          else
-           warning ("unsupported arg to %<__builtin_return_address%>");
+           warning ("unsupported argument to %<__builtin_return_address%>");
          return const0_rtx;
        }
 
@@ -4301,7 +4280,7 @@ expand_builtin_expect (tree arglist, rtx target)
 
   if (TREE_CODE (c) != INTEGER_CST)
     {
-      error ("second arg to %<__builtin_expect%> must be a constant");
+      error ("second argument to %<__builtin_expect%> must be a constant");
       c = integer_zero_node;
     }
 
@@ -4442,7 +4421,7 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
   return ret;
 }
 
-void
+static void
 expand_builtin_trap (void)
 {
 #ifdef HAVE_trap
@@ -5383,7 +5362,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       break;
 
     case BUILT_IN_STRCAT:
-      target = expand_builtin_strcat (arglist, target, mode);
+      target = expand_builtin_strcat (arglist, TREE_TYPE (exp), target, mode);
       if (target)
        return target;
       break;
@@ -5439,7 +5418,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       break;
 
     case BUILT_IN_MEMPCPY:
-      target = expand_builtin_mempcpy (arglist, target, mode, /*endp=*/ 1);
+      target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
       if (target)
        return target;
       break;
@@ -5508,7 +5487,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
 
          if (value != const1_rtx)
            {
-             error ("__builtin_longjmp second argument must be 1");
+             error ("%<__builtin_longjmp%> second argument must be 1");
              return const0_rtx;
            }
 
@@ -5852,8 +5831,15 @@ fold_builtin_inf (tree type, int warn)
 {
   REAL_VALUE_TYPE real;
 
+  /* __builtin_inff is intended to be usable to define INFINITY on all
+     targets.  If an infinity is not available, INFINITY expands "to a
+     positive constant of type float that overflows at translation
+     time", footnote "In this case, using INFINITY will violate the
+     constraint in 6.4.4 and thus require a diagnostic." (C99 7.12#4).
+     Thus we pedwarn to ensure this constraint violation is
+     diagnosed.  */
   if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
-    warning ("target format does not support infinity");
+    pedwarn ("target format does not support infinity");
 
   real_inf (&real);
   return build_real (type, real);
@@ -6971,31 +6957,34 @@ fold_builtin_memcpy (tree exp)
    NULL_TREE if no simplification can be made.  */
 
 static tree
-fold_builtin_mempcpy (tree exp)
+fold_builtin_mempcpy (tree arglist, tree type, int endp)
 {
-  tree arglist = TREE_OPERAND (exp, 1);
-  tree dest, src, len;
-
-  if (!validate_arglist (arglist,
-                        POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
-    return 0;
+  if (validate_arglist (arglist,
+                       POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+    {
+      tree dest = TREE_VALUE (arglist);
+      tree src = TREE_VALUE (TREE_CHAIN (arglist));
+      tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
 
-  dest = TREE_VALUE (arglist);
-  src = TREE_VALUE (TREE_CHAIN (arglist));
-  len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+      /* If the LEN parameter is zero, return DEST.  */
+      if (integer_zerop (len))
+       return omit_one_operand (type, dest, src);
 
-  /* If the LEN parameter is zero, return DEST.  */
-  if (integer_zerop (len))
-    return omit_one_operand (TREE_TYPE (exp), dest, src);
+      /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
+      if (operand_equal_p (src, dest, 0))
+        {
+         if (endp == 0)
+           return omit_one_operand (type, dest, len);
 
-  /* If SRC and DEST are the same (and not volatile), return DEST+LEN.  */
-  if (operand_equal_p (src, dest, 0))
-    {
-      tree temp = fold_convert (TREE_TYPE (dest), len);
-      temp = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp));
-      return fold_convert (TREE_TYPE (exp), temp);
+         if (endp == 2)
+           len = fold (build2 (MINUS_EXPR, TREE_TYPE (len), len,
+                               ssize_int (1)));
+      
+         len = fold_convert (TREE_TYPE (dest), len);
+         len = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len));
+         return fold_convert (type, len);
+       }
     }
-
   return 0;
 }
 
@@ -7614,13 +7603,12 @@ fold_builtin_unordered_cmp (tree exp,
   tree type = TREE_TYPE (TREE_TYPE (fndecl));
   enum tree_code code;
   tree arg0, arg1;
+  tree type0, type1;
+  enum tree_code code0, code1;
+  tree cmp_type = NULL_TREE;
 
   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
     {
-      enum tree_code code0, code1;
-      tree type0, type1;
-      tree cmp_type = 0;
-
       /* Check that we have exactly two arguments.  */
       if (arglist == 0 || TREE_CHAIN (arglist) == 0)
        {
@@ -7634,39 +7622,34 @@ fold_builtin_unordered_cmp (tree exp,
                 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
          return error_mark_node;
        }
-
-      arg0 = TREE_VALUE (arglist);
-      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
-
-      type0 = TREE_TYPE (arg0);
-      type1 = TREE_TYPE (arg1);
-
-      code0 = TREE_CODE (type0);
-      code1 = TREE_CODE (type1);
-
-      if (code0 == REAL_TYPE && code1 == REAL_TYPE)
-       /* Choose the wider of two real types.  */
-        cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
-                  ? type0 : type1;
-      else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
-       cmp_type = type0;
-      else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
-       cmp_type = type1;
-      else
-       {
-         error ("non-floating-point argument to function %qs",
-                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
-         return error_mark_node;
-       }
-
-      arg0 = fold_convert (cmp_type, arg0);
-      arg1 = fold_convert (cmp_type, arg1);
     }
+
+  arg0 = TREE_VALUE (arglist);
+  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+  
+  type0 = TREE_TYPE (arg0);
+  type1 = TREE_TYPE (arg1);
+  
+  code0 = TREE_CODE (type0);
+  code1 = TREE_CODE (type1);
+  
+  if (code0 == REAL_TYPE && code1 == REAL_TYPE)
+    /* Choose the wider of two real types.  */
+    cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
+      ? type0 : type1;
+  else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
+    cmp_type = type0;
+  else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
+    cmp_type = type1;
   else
     {
-      arg0 = TREE_VALUE (arglist);
-      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+      error ("non-floating-point argument to function %qs",
+                IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+      return error_mark_node;
     }
+  
+  arg0 = fold_convert (cmp_type, arg0);
+  arg1 = fold_convert (cmp_type, arg1);
 
   if (unordered_code == UNORDERED_EXPR)
     {
@@ -7964,7 +7947,7 @@ fold_builtin_1 (tree exp, bool ignore)
       return fold_builtin_memcpy (exp);
 
     case BUILT_IN_MEMPCPY:
-      return fold_builtin_mempcpy (exp);
+      return fold_builtin_mempcpy (arglist, type, /*endp=*/1);
 
     case BUILT_IN_MEMMOVE:
       return fold_builtin_memmove (arglist, type);