From 881cdd61eef4cb4e4b907f571c60c41bdb7d43ed Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 22 Dec 2014 11:04:42 +0000 Subject: [PATCH] trans.c (Attribute_to_gnu): If the type is a floating-point type... * gcc-interface/trans.c (Attribute_to_gnu) : 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 | 8 ++++++ gcc/ada/gcc-interface/trans.c | 57 ++++++++++++++++++++++++++++++++++++++---- gcc/ada/gcc-interface/utils2.c | 10 ++++---- gcc/testsuite/ChangeLog | 4 +++ 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 + * gcc-interface/trans.c (Attribute_to_gnu) : 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 + * 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 + * gnat.dg/nan_max.adb: New test. + +2014-12-22 Eric Botcazou + * gnat.dg/specs/volatile1.ads: New test. * gnat.dg/specs/clause_on_volatile.ads: Adjust. * gnat.dg/specs/size_clause3.ads: Likewise. -- 2.7.4