trans.c (Attribute_to_gnu): If the type is a floating-point type...
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 22 Dec 2014 11:04:42 +0000 (11:04 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 22 Dec 2014 11:04:42 +0000 (11:04 +0000)
* gcc-interface/trans.c (Attribute_to_gnu) <Attr_{Min,Max}>: If the
type is a floating-point type, implement the semantics of the C99
f{min,max} routines with regard to NaNs.
(gnat_to_gnu): Call builtin_decl_implicit.
* gcc-interface/utils2.c (compare_arrays): Adjust comments.

From-SVN: r219010

gcc/ada/ChangeLog
gcc/ada/gcc-interface/trans.c
gcc/ada/gcc-interface/utils2.c
gcc/testsuite/ChangeLog

index c6364eb22d15b13ed89766646882d3f52be13c15..a8eba2941f2951e04cb5defcd6a0fc7ae220e79e 100644 (file)
@@ -1,3 +1,11 @@
+2014-12-22  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/trans.c (Attribute_to_gnu) <Attr_{Min,Max}>: If the
+       type is a floating-point type, implement the semantics of the C99
+       f{min,max} routines with regard to NaNs.
+       (gnat_to_gnu): Call builtin_decl_implicit.
+       * gcc-interface/utils2.c (compare_arrays): Adjust comments.
+
 2014-12-22  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc-interface/decl.c (gnat_to_gnu_field): Post the error message
index d4c9c85a9894797317cbbd54f534c19e6c2af181..a91c0c84433ebbd6abe4c378c746f4c2e7f02d37 100644 (file)
@@ -2268,9 +2268,56 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
        tree gnu_rhs = gnat_to_gnu (Next (First (Expressions (gnat_node))));
 
        gnu_result_type = get_unpadded_type (Etype (gnat_node));
-       gnu_result = build_binary_op (attribute == Attr_Min
-                                     ? MIN_EXPR : MAX_EXPR,
-                                     gnu_result_type, gnu_lhs, gnu_rhs);
+
+       /* The result of {MIN,MAX}_EXPR is unspecified if either operand is
+          a NaN so we implement the semantics of C99 f{min,max} to make it
+          predictable in this case: if either operand is a NaN, the other
+          is returned; if both operands are NaN's, a NaN is returned.  */
+       if (SCALAR_FLOAT_TYPE_P (gnu_result_type))
+         {
+           const bool lhs_side_effects_p = TREE_SIDE_EFFECTS (gnu_lhs);
+           const bool rhs_side_effects_p = TREE_SIDE_EFFECTS (gnu_rhs);
+           tree t = builtin_decl_explicit (BUILT_IN_ISNAN);
+           tree lhs_is_nan, rhs_is_nan;
+
+           /* If the operands have side-effects, they need to be evaluated
+              only once in spite of the multiple references in the result.  */
+           if (lhs_side_effects_p)
+             gnu_lhs = gnat_protect_expr (gnu_lhs);
+           if (rhs_side_effects_p)
+             gnu_rhs = gnat_protect_expr (gnu_rhs);
+
+           lhs_is_nan = fold_build2 (NE_EXPR, boolean_type_node,
+                                     build_call_expr (t, 1, gnu_lhs),
+                                     integer_zero_node);
+
+           rhs_is_nan = fold_build2 (NE_EXPR, boolean_type_node,
+                                     build_call_expr (t, 1, gnu_rhs),
+                                     integer_zero_node);
+
+           gnu_result = build_binary_op (attribute == Attr_Min
+                                         ? MIN_EXPR : MAX_EXPR,
+                                         gnu_result_type, gnu_lhs, gnu_rhs);
+           gnu_result = fold_build3 (COND_EXPR, gnu_result_type,
+                                     rhs_is_nan, gnu_lhs, gnu_result);
+           gnu_result = fold_build3 (COND_EXPR, gnu_result_type,
+                                     lhs_is_nan, gnu_rhs, gnu_result);
+
+           /* If the operands have side-effects, they need to be evaluated
+              before doing the tests above since the place they otherwise
+              would end up being evaluated at run time could be wrong.  */
+           if (lhs_side_effects_p)
+             gnu_result
+               = build2 (COMPOUND_EXPR, gnu_result_type, gnu_lhs, gnu_result);
+
+           if (rhs_side_effects_p)
+             gnu_result
+               = build2 (COMPOUND_EXPR, gnu_result_type, gnu_rhs, gnu_result);
+         }
+       else
+         gnu_result = build_binary_op (attribute == Attr_Min
+                                       ? MIN_EXPR : MAX_EXPR,
+                                       gnu_result_type, gnu_lhs, gnu_rhs);
       }
       break;
 
@@ -6458,7 +6505,7 @@ gnat_to_gnu (Node_Id gnat_node)
              tree size
                = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (type), to);
              tree to_ptr = build_fold_addr_expr (to);
-             tree t = builtin_decl_implicit (BUILT_IN_MEMSET);
+             tree t = builtin_decl_explicit (BUILT_IN_MEMSET);
              if (TREE_CODE (value) == INTEGER_CST)
                {
                  tree mask
@@ -6488,7 +6535,7 @@ gnat_to_gnu (Node_Id gnat_node)
                = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (type), from);
              tree to_ptr = build_fold_addr_expr (to);
              tree from_ptr = build_fold_addr_expr (from);
-             tree t = builtin_decl_implicit (BUILT_IN_MEMMOVE);
+             tree t = builtin_decl_explicit (BUILT_IN_MEMMOVE);
              gnu_result = build_call_expr (t, 3, to_ptr, from_ptr, size);
           }
        }
index 1296a4996119801f11518dc333b4ece126369769..43e8a635611d01bb54961071874f8275325f7577 100644 (file)
@@ -255,8 +255,8 @@ compare_arrays (location_t loc, tree result_type, tree a1, tree a2)
   bool a2_side_effects_p = TREE_SIDE_EFFECTS (a2);
   bool length_zero_p = false;
 
-  /* If either operand has side-effects, they have to be evaluated only once
-     in spite of the multiple references to the operand in the comparison.  */
+  /* If the operands have side-effects, they need to be evaluated only once
+     in spite of the multiple references in the comparison.  */
   if (a1_side_effects_p)
     a1 = gnat_protect_expr (a1);
 
@@ -419,9 +419,9 @@ compare_arrays (location_t loc, tree result_type, tree a1, tree a2)
                                             a1_is_null, a2_is_null),
                            result);
 
-  /* If either operand has side-effects, they have to be evaluated before
-     starting the comparison above since the place they would be otherwise
-     evaluated could be wrong.  */
+  /* If the operands have side-effects, they need to be evaluated before
+     doing the tests above since the place they otherwise would end up
+     being evaluated at run time could be wrong.  */
   if (a1_side_effects_p)
     result = build2 (COMPOUND_EXPR, result_type, a1, result);
 
index 9e17c5cd3fc73e3a7d5b3ccbc2b0fc4d627b2338..4da1c1955912f15375cc655b13d8e58f04eb848c 100644 (file)
@@ -1,3 +1,7 @@
+2014-12-22  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/nan_max.adb: New test.
+
 2014-12-22  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/volatile1.ads: New test.