aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2014-12-22 11:04:42 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2014-12-22 11:04:42 +0000
commit881cdd61eef4cb4e4b907f571c60c41bdb7d43ed (patch)
tree1aa02b64dae0f5cc24ee6f05fb898f03783b7087
parent35786aad0c7e0ea1987b370a3e69d8730c11ae38 (diff)
downloadgcc-881cdd61eef4cb4e4b907f571c60c41bdb7d43ed.zip
gcc-881cdd61eef4cb4e4b907f571c60c41bdb7d43ed.tar.gz
gcc-881cdd61eef4cb4e4b907f571c60c41bdb7d43ed.tar.bz2
trans.c (Attribute_to_gnu): If the type is a floating-point type...
* 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
-rw-r--r--gcc/ada/ChangeLog8
-rw-r--r--gcc/ada/gcc-interface/trans.c57
-rw-r--r--gcc/ada/gcc-interface/utils2.c10
-rw-r--r--gcc/testsuite/ChangeLog4
4 files changed, 69 insertions, 10 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index c6364eb..a8eba29 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,5 +1,13 @@
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
for parent overlapping on the position instead of on the first bit.
For a field that needs strict alignment, issue the error for the
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index d4c9c85..a91c0c8 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -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);
}
}
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 1296a49..43e8a63 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9e17c5c..4da1c19 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
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.
* gnat.dg/specs/clause_on_volatile.ads: Adjust.
* gnat.dg/specs/size_clause3.ads: Likewise.