From ebf0bf7f49c75c98d4c51e8c451eae068a2dd647 Mon Sep 17 00:00:00 2001 From: Janis Johnson Date: Thu, 21 Jan 2010 05:49:35 +0000 Subject: [PATCH] tree.h (TYPE_TRANSPARENT_UNION): Replace with ... * tree.h (TYPE_TRANSPARENT_UNION): Replace with ... (TYPE_TRANSPARENT_AGGR): this, for union and record. * calls.c (initialize argument_information): Handle it. * c-common.c (handle_transparent_union_attribute): Use new name. * c-decl.c (finish_struct): Ditto. * c-typeck.c (type_lists_compatible_p): Ditto. (convert_for_assignment): Use new name and also handle record. * function.c (aggregate_value_p): Handle it. (pass_by_reference): Ditto. (assign_parm_data_types): Ditto. * print-tree.c (print_node): Ditto. * lto-streamer-in.c (unpack_ts_type_value_fields): Ditto. * lto-streamer-out.c (pack_ts_type_value_fields): Ditto. * tree.c (first_field): New fn. gcc/cp/ * mangle.c (write_type): Mangle transparent record as member type. * semantics.c (begin_class_definition): Recognize decimal classes and set TYPE_TRANSPARENT_AGGR. Co-Authored-By: Jason Merrill From-SVN: r156106 --- gcc/ChangeLog | 18 +++ gcc/c-common.c | 2 +- gcc/c-decl.c | 4 +- gcc/c-typeck.c | 9 +- gcc/calls.c | 11 +- gcc/cp/ChangeLog | 7 + gcc/cp/mangle.c | 6 + gcc/cp/semantics.c | 12 ++ gcc/function.c | 26 ++- gcc/lto-streamer-in.c | 4 +- gcc/lto-streamer-out.c | 4 +- gcc/print-tree.c | 5 +- gcc/testsuite/ChangeLog | 45 ++++++ .../g++.dg/compat/decimal/compat-common.h | 55 +++++++ .../g++.dg/compat/decimal/decimal-dummy.h | 67 ++++++++ .../g++.dg/compat/decimal/pass-1_main.C | 13 ++ .../g++.dg/compat/decimal/pass-1_x.C | 30 ++++ .../g++.dg/compat/decimal/pass-1_y.C | 5 + .../g++.dg/compat/decimal/pass-2_main.C | 13 ++ .../g++.dg/compat/decimal/pass-2_x.C | 32 ++++ .../g++.dg/compat/decimal/pass-2_y.C | 7 + .../g++.dg/compat/decimal/pass-3_main.C | 13 ++ .../g++.dg/compat/decimal/pass-3_x.C | 30 ++++ .../g++.dg/compat/decimal/pass-3_y.C | 7 + .../g++.dg/compat/decimal/pass-4_main.C | 13 ++ .../g++.dg/compat/decimal/pass-4_x.C | 32 ++++ .../g++.dg/compat/decimal/pass-4_y.C | 5 + .../g++.dg/compat/decimal/pass-5_main.C | 13 ++ .../g++.dg/compat/decimal/pass-5_x.C | 30 ++++ .../g++.dg/compat/decimal/pass-5_y.C | 7 + .../g++.dg/compat/decimal/pass-6_main.C | 13 ++ .../g++.dg/compat/decimal/pass-6_x.C | 32 ++++ .../g++.dg/compat/decimal/pass-6_y.C | 5 + gcc/testsuite/g++.dg/compat/decimal/pass_x.h | 151 ++++++++++++++++++ gcc/testsuite/g++.dg/compat/decimal/pass_y.h | 89 +++++++++++ .../g++.dg/compat/decimal/return-1_main.C | 13 ++ .../g++.dg/compat/decimal/return-1_x.C | 24 +++ .../g++.dg/compat/decimal/return-1_y.C | 5 + .../g++.dg/compat/decimal/return-2_main.C | 13 ++ .../g++.dg/compat/decimal/return-2_x.C | 26 +++ .../g++.dg/compat/decimal/return-2_y.C | 7 + .../g++.dg/compat/decimal/return-3_main.C | 13 ++ .../g++.dg/compat/decimal/return-3_x.C | 24 +++ .../g++.dg/compat/decimal/return-3_y.C | 7 + .../g++.dg/compat/decimal/return-4_main.C | 13 ++ .../g++.dg/compat/decimal/return-4_x.C | 26 +++ .../g++.dg/compat/decimal/return-4_y.C | 5 + .../g++.dg/compat/decimal/return-5_main.C | 14 ++ .../g++.dg/compat/decimal/return-5_x.C | 24 +++ .../g++.dg/compat/decimal/return-5_y.C | 7 + .../g++.dg/compat/decimal/return-6_main.C | 14 ++ .../g++.dg/compat/decimal/return-6_x.C | 26 +++ .../g++.dg/compat/decimal/return-6_y.C | 5 + .../g++.dg/compat/decimal/return_x.h | 90 +++++++++++ .../g++.dg/compat/decimal/return_y.h | 67 ++++++++ gcc/tree.c | 12 ++ gcc/tree.h | 18 ++- 57 files changed, 1238 insertions(+), 30 deletions(-) create mode 100644 gcc/testsuite/g++.dg/compat/decimal/compat-common.h create mode 100644 gcc/testsuite/g++.dg/compat/decimal/decimal-dummy.h create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-1_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-1_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-1_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-2_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-2_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-2_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-3_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-3_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-3_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-4_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-4_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-4_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-5_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-5_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-5_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-6_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-6_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass-6_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass_x.h create mode 100644 gcc/testsuite/g++.dg/compat/decimal/pass_y.h create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-1_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-1_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-1_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-2_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-2_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-2_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-3_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-3_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-3_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-4_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-4_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-4_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-5_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-5_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-5_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-6_main.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-6_x.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return-6_y.C create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return_x.h create mode 100644 gcc/testsuite/g++.dg/compat/decimal/return_y.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8b18dbd4c32e..90061ec7f5a8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2010-01-20 Janis Johnson + Jason Merrill + + * tree.h (TYPE_TRANSPARENT_UNION): Replace with ... + (TYPE_TRANSPARENT_AGGR): this, for union and record. + * calls.c (initialize argument_information): Handle it. + * c-common.c (handle_transparent_union_attribute): Use new name. + * c-decl.c (finish_struct): Ditto. + * c-typeck.c (type_lists_compatible_p): Ditto. + (convert_for_assignment): Use new name and also handle record. + * function.c (aggregate_value_p): Handle it. + (pass_by_reference): Ditto. + (assign_parm_data_types): Ditto. + * print-tree.c (print_node): Ditto. + * lto-streamer-in.c (unpack_ts_type_value_fields): Ditto. + * lto-streamer-out.c (pack_ts_type_value_fields): Ditto. + * tree.c (first_field): New fn. + 2010-01-21 Dave Korn PR target/42818 diff --git a/gcc/c-common.c b/gcc/c-common.c index 7552077d280f..f9bdf38f2d2b 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -6247,7 +6247,7 @@ handle_transparent_union_attribute (tree *node, tree name, *node = type = build_duplicate_type (type); } - TYPE_TRANSPARENT_UNION (type) = 1; + TYPE_TRANSPARENT_AGGR (type) = 1; return NULL_TREE; } diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 91d588445508..e48cdc88e4e9 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -6953,10 +6953,10 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, /* If this was supposed to be a transparent union, but we can't make it one, warn and turn off the flag. */ if (TREE_CODE (t) == UNION_TYPE - && TYPE_TRANSPARENT_UNION (t) + && TYPE_TRANSPARENT_AGGR (t) && (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t)))) { - TYPE_TRANSPARENT_UNION (t) = 0; + TYPE_TRANSPARENT_AGGR (t) = 0; warning_at (loc, 0, "union cannot be made transparent"); } diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 17bdbf92b3b1..567c2a512826 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1622,7 +1622,7 @@ type_lists_compatible_p (const_tree args1, const_tree args2, and wait (union wait *) to be compatible. */ if (TREE_CODE (a1) == UNION_TYPE && (TYPE_NAME (a1) == 0 - || TYPE_TRANSPARENT_UNION (a1)) + || TYPE_TRANSPARENT_AGGR (a1)) && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST && tree_int_cst_equal (TYPE_SIZE (a1), TYPE_SIZE (a2))) @@ -1643,7 +1643,7 @@ type_lists_compatible_p (const_tree args1, const_tree args2, } else if (TREE_CODE (a2) == UNION_TYPE && (TYPE_NAME (a2) == 0 - || TYPE_TRANSPARENT_UNION (a2)) + || TYPE_TRANSPARENT_AGGR (a2)) && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST && tree_int_cst_equal (TYPE_SIZE (a2), TYPE_SIZE (a1))) @@ -5014,9 +5014,10 @@ convert_for_assignment (location_t location, tree type, tree rhs, && comptypes (type, rhstype)) return convert_and_check (type, rhs); - /* Conversion to a transparent union from its member types. + /* Conversion to a transparent union or record from its member types. This applies only to function arguments. */ - if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type) + if (((codel == UNION_TYPE || codel == RECORD_TYPE) + && TYPE_TRANSPARENT_AGGR (type)) && errtype == ic_argpass) { tree memb, marginal_memb = NULL_TREE; diff --git a/gcc/calls.c b/gcc/calls.c index fe4bf0dbce55..ce54bbea8460 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1010,11 +1010,12 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, if (type == error_mark_node || !COMPLETE_TYPE_P (type)) args[i].tree_value = integer_zero_node, type = integer_type_node; - /* If TYPE is a transparent union, pass things the way we would - pass the first field of the union. We have already verified that - the modes are the same. */ - if (TREE_CODE (type) == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)) - type = TREE_TYPE (TYPE_FIELDS (type)); + /* If TYPE is a transparent union or record, pass things the way + we would pass the first field of the union or record. We have + already verified that the modes are the same. */ + if ((TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == RECORD_TYPE) + && TYPE_TRANSPARENT_AGGR (type)) + type = TREE_TYPE (first_field (type)); /* Decide where to pass this arg. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a6a3eb215d82..43da561ffd23 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2010-01-20 Janis Johnson + Jason Merrill + + * mangle.c (write_type): Mangle transparent record as member type. + * semantics.c (begin_class_definition): Recognize decimal classes + and set TYPE_TRANSPARENT_AGGR. + 2010-01-20 Jason Merrill PR c++/42338 diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 7e4cf668e9c4..c14f5b7d844e 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1732,6 +1732,12 @@ write_type (tree type) if (find_substitution (type)) return; + /* According to the C++ ABI, some library classes are passed the + same as the scalar type of their single member and use the same + mangling. */ + if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type)) + type = TREE_TYPE (first_field (type)); + if (write_CV_qualifiers_for_type (type) > 0) /* If TYPE was CV-qualified, we just wrote the qualifiers; now mangle the unqualified type. The recursive call is needed here diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 1545443c8cf4..d9ba591b3f58 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2368,6 +2368,18 @@ begin_class_definition (tree t, tree attributes) error ("definition of %q#T inside template parameter list", t); return error_mark_node; } + + /* According to the C++ ABI, decimal classes defined in ISO/IEC TR 24733 + are passed the same as decimal scalar types. */ + if (TREE_CODE (t) == RECORD_TYPE) + { + const char *n = type_as_string (t, TFF_CLASS_KEY_OR_ENUM); + if ((strcmp (n, "class std::decimal::decimal32") == 0) + || (strcmp (n, "class std::decimal::decimal64") == 0) + || (strcmp (n, "class std::decimal::decimal128") == 0)) + TYPE_TRANSPARENT_AGGR (t) = 1; + } + /* A non-implicit typename comes from code like: template struct A { diff --git a/gcc/function.c b/gcc/function.c index 6314ae01a6c7..f85f780e9164 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -1890,6 +1890,11 @@ aggregate_value_p (const_tree exp, const_tree fntype) if (TREE_CODE (type) == VOID_TYPE) return 0; + /* If a record should be passed the same as its first (and only) member + don't pass it as an aggregate. */ + if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type)) + return aggregate_value_p (first_field (type), fntype); + /* If the front end has decided that this needs to be passed by reference, do so. */ if ((TREE_CODE (exp) == PARM_DECL || TREE_CODE (exp) == RESULT_DECL) @@ -2004,6 +2009,14 @@ pass_by_reference (CUMULATIVE_ARGS *ca, enum machine_mode mode, /* GCC post 3.4 passes *all* variable sized types by reference. */ if (!TYPE_SIZE (type) || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) return true; + + /* If a record type should be passed the same as its first (and only) + member, use the type and mode of that member. */ + if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type)) + { + type = TREE_TYPE (first_field (type)); + mode = TYPE_MODE (type); + } } return targetm.calls.pass_by_reference (ca, mode, type, named_arg); @@ -2218,12 +2231,13 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, passed_mode = TYPE_MODE (passed_type); nominal_mode = TYPE_MODE (nominal_type); - /* If the parm is to be passed as a transparent union, use the type of - the first field for the tests below. We have already verified that - the modes are the same. */ - if (TREE_CODE (passed_type) == UNION_TYPE - && TYPE_TRANSPARENT_UNION (passed_type)) - passed_type = TREE_TYPE (TYPE_FIELDS (passed_type)); + /* If the parm is to be passed as a transparent union or record, use the + type of the first field for the tests below. We have already verified + that the modes are the same. */ + if ((TREE_CODE (passed_type) == UNION_TYPE + || TREE_CODE (passed_type) == RECORD_TYPE) + && TYPE_TRANSPARENT_AGGR (passed_type)) + passed_type = TREE_TYPE (first_field (passed_type)); /* See if this arg was passed by invisible reference. */ if (pass_by_reference (&all->args_so_far, passed_mode, diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index f316459e083a..e41917702f1c 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -1742,8 +1742,8 @@ unpack_ts_type_value_fields (struct bitpack_d *bp, tree expr) TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_NO_FORCE_BLK (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_NEEDS_CONSTRUCTING(expr) = (unsigned) bp_unpack_value (bp, 1); - if (TREE_CODE (expr) == UNION_TYPE) - TYPE_TRANSPARENT_UNION (expr) = (unsigned) bp_unpack_value (bp, 1); + if (TREE_CODE (expr) == UNION_TYPE || TREE_CODE (expr) == RECORD_TYPE) + TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr) diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index d5431ba5a6e9..b5fc3e26c207 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -518,8 +518,8 @@ pack_ts_type_value_fields (struct bitpack_d *bp, tree expr) bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1); bp_pack_value (bp, TYPE_NO_FORCE_BLK (expr), 1); bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING(expr), 1); - if (TREE_CODE (expr) == UNION_TYPE) - bp_pack_value (bp, TYPE_TRANSPARENT_UNION (expr), 1); + if (TREE_CODE (expr) == UNION_TYPE || TREE_CODE (expr) == RECORD_TYPE) + bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1); bp_pack_value (bp, TYPE_PACKED (expr), 1); bp_pack_value (bp, TYPE_RESTRICT (expr), 1); bp_pack_value (bp, TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr), 2); diff --git a/gcc/print-tree.c b/gcc/print-tree.c index eebd1c35ba12..b5656adcaa38 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -605,8 +605,9 @@ print_node (FILE *file, const char *prefix, tree node, int indent) /* The transparent-union flag is used for different things in different nodes. */ - if (code == UNION_TYPE && TYPE_TRANSPARENT_UNION (node)) - fputs (" transparent-union", file); + if ((code == UNION_TYPE || code == RECORD_TYPE) + && TYPE_TRANSPARENT_AGGR (node)) + fputs (" transparent-aggr", file); else if (code == ARRAY_TYPE && TYPE_NONALIASED_COMPONENT (node)) fputs (" nonaliased-component", file); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0fac516223ef..9c89203d503b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,48 @@ +2010-01-20 Janis Johnson + + * g++.dg/compat/decimal/compat-common.h: New file. + * g++.dg/compat/decimal/decimal-dummy.h: New file. + * g++.dg/compat/decimal/pass_x.h: New file. + * g++.dg/compat/decimal/pass_y.h: New file. + * g++.dg/compat/decimal/pass-1_main.C: New file. + * g++.dg/compat/decimal/pass-1_x.C: New file. + * g++.dg/compat/decimal/pass-1_y.C: New file. + * g++.dg/compat/decimal/pass-2_main.C: New file. + * g++.dg/compat/decimal/pass-2_x.C: New file. + * g++.dg/compat/decimal/pass-2_y.C: New file. + * g++.dg/compat/decimal/pass-3_main.C: New file. + * g++.dg/compat/decimal/pass-3_x.C: New file. + * g++.dg/compat/decimal/pass-3_y.C: New file. + * g++.dg/compat/decimal/pass-4_main.C: New file. + * g++.dg/compat/decimal/pass-4_x.C: New file. + * g++.dg/compat/decimal/pass-4_y.C: New file. + * g++.dg/compat/decimal/pass-5_main.C: New file. + * g++.dg/compat/decimal/pass-5_x.C: New file. + * g++.dg/compat/decimal/pass-5_y.C: New file. + * g++.dg/compat/decimal/pass-6_main.C: New file. + * g++.dg/compat/decimal/pass-6_x.C: New file. + * g++.dg/compat/decimal/pass-6_y.C: New file. + * g++.dg/compat/decimal/return_x.h: New file. + * g++.dg/compat/decimal/return_y.h: New file. + * g++.dg/compat/decimal/return-1_main.C: New file. + * g++.dg/compat/decimal/return-1_x.C: New file. + * g++.dg/compat/decimal/return-1_y.C: New file. + * g++.dg/compat/decimal/return-2_main.C: New file. + * g++.dg/compat/decimal/return-2_x.C: New file. + * g++.dg/compat/decimal/return-2_y.C: New file. + * g++.dg/compat/decimal/return-3_main.C: New file. + * g++.dg/compat/decimal/return-3_x.C: New file. + * g++.dg/compat/decimal/return-3_y.C: New file. + * g++.dg/compat/decimal/return-4_main.C: New file. + * g++.dg/compat/decimal/return-4_x.C: New file. + * g++.dg/compat/decimal/return-4_y.C: New file. + * g++.dg/compat/decimal/return-5_main.C: New file. + * g++.dg/compat/decimal/return-5_x.C: New file. + * g++.dg/compat/decimal/return-5_y.C: New file. + * g++.dg/compat/decimal/return-6_main.C: New file. + * g++.dg/compat/decimal/return-6_x.C: New file. + * g++.dg/compat/decimal/return-6_y.C: New file. + 2010-01-20 Alexandre Oliva PR debug/42715 diff --git a/gcc/testsuite/g++.dg/compat/decimal/compat-common.h b/gcc/testsuite/g++.dg/compat/decimal/compat-common.h new file mode 100644 index 000000000000..43c22d722f76 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/compat-common.h @@ -0,0 +1,55 @@ +/* Several of the binary compatibility tests use these macros to + allow debugging the test or tracking down a failure by getting an + indication of whether each individual check passed or failed. + When DBG is defined, each check is shown by a dot (pass) or 'F' + (fail) rather than aborting as soon as a failure is detected. */ + +#ifdef DBG +#include +#define DEBUG_INIT setbuf (stdout, NULL); +#define DEBUG_FPUTS(x) fputs (x, stdout); +#define DEBUG_DOT putc ('.', stdout); +#define DEBUG_NL putc ('\n', stdout); +#define DEBUG_FAIL putc ('F', stdout); fails++; +#define DEBUG_CHECK { DEBUG_FAIL } else { DEBUG_DOT } +#define DEBUG_FINI if (fails) DEBUG_FPUTS ("failed\n") \ + else DEBUG_FPUTS ("passed\n") +#else +#define DEBUG_INIT +#define DEBUG_FPUTS(x) +#define DEBUG_DOT +#define DEBUG_NL +#define DEBUG_FAIL abort (); +#define DEBUG_CHECK abort (); +#define DEBUG_FINI +#endif + +#ifdef SKIP_COMPLEX +#ifndef SKIP_COMPLEX_INT +#define SKIP_COMPLEX_INT +#endif +#endif + +#ifndef SKIP_COMPLEX +#ifdef __GNUC__ +#define CINT(x, y) (x + y * __extension__ 1i) +#define CDBL(x, y) (x + y * __extension__ 1i) +#else +#ifdef __SUNPRO_C +/* ??? Complex support without . */ +#else +#include +#endif +#ifndef SKIP_COMPLEX_INT +#define CINT(x, y) ((_Complex int) (x + y * _Complex_I)) +#endif +#define CDBL(x, y) (x + y * _Complex_I) +#endif +#endif + +#ifdef __cplusplus +extern "C" void abort (void); +#else +extern void abort (void); +#endif +extern int fails; diff --git a/gcc/testsuite/g++.dg/compat/decimal/decimal-dummy.h b/gcc/testsuite/g++.dg/compat/decimal/decimal-dummy.h new file mode 100644 index 000000000000..ec347f9b7ebd --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/decimal-dummy.h @@ -0,0 +1,67 @@ +namespace std { +namespace decimal { + + class decimal32 + { + public: + typedef float __dec32 __attribute__((mode(SD))); + decimal32 () : __val(0.e-101DF) {} + decimal32 (__dec32 x) : __val(x) {} + __dec32 __val; + }; + + class decimal64 + { + public: + typedef float __dec64 __attribute__((mode(DD))); + decimal64 () : __val(0.e-398dd) {} + decimal64 (__dec64 x) : __val(x) {} + __dec64 __val; + }; + + class decimal128 + { + public: + typedef float __dec128 __attribute__((mode(TD))); + decimal128 () : __val(0.e-6176DL) {} + decimal128 (__dec128 x) : __val(x) {} + __dec128 __val; + }; + + inline decimal32 operator+ (decimal32 lhs, decimal32 rhs) + { + decimal32 tmp; + tmp.__val = lhs.__val + rhs.__val; + return tmp; + } + + inline decimal64 operator+ (decimal64 lhs, decimal64 rhs) + { + decimal64 tmp; + tmp.__val = lhs.__val + rhs.__val; + return tmp; + } + + inline decimal128 operator+ (decimal128 lhs, decimal128 rhs) + { + decimal128 tmp; + tmp.__val = lhs.__val + rhs.__val; + return tmp; + } + + inline bool operator!= (decimal32 lhs, decimal32 rhs) + { + return lhs.__val != rhs.__val; + } + + inline bool operator!= (decimal64 lhs, decimal64 rhs) + { + return lhs.__val != rhs.__val; + } + + inline bool operator!= (decimal128 lhs, decimal128 rhs) + { + return lhs.__val != rhs.__val; + } +} +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-1_main.C b/gcc/testsuite/g++.dg/compat/decimal/pass-1_main.C new file mode 100644 index 000000000000..963dc3bbfabf --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-1_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test passing decimal scalars by value. */ + +extern void pass_1_x (void); +int fails; + +int +main () +{ + pass_1_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-1_x.C b/gcc/testsuite/g++.dg/compat/decimal/pass-1_x.C new file mode 100644 index 000000000000..265a1317b008 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-1_x.C @@ -0,0 +1,30 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "pass_x.h" + +void +pass_1_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +#ifndef SKIP_DECIMAL32 +T(d32) +#endif +#ifndef SKIP_DECIMAL64 +T(d64) +#endif +#ifndef SKIP_DECIMAL128 +T(d128) +#endif + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-1_y.C b/gcc/testsuite/g++.dg/compat/decimal/pass-1_y.C new file mode 100644 index 000000000000..5da7f87d51e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-1_y.C @@ -0,0 +1,5 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "pass_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-2_main.C b/gcc/testsuite/g++.dg/compat/decimal/pass-2_main.C new file mode 100644 index 000000000000..533e4b276dc7 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-2_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test passing decimal classes by value. */ + +extern void pass_2_x (void); +int fails; + +int +main () +{ + pass_2_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-2_x.C b/gcc/testsuite/g++.dg/compat/decimal/pass-2_x.C new file mode 100644 index 000000000000..8a67bda0ed8a --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-2_x.C @@ -0,0 +1,32 @@ +#include "decimal-dummy.h" + +#define dec32 std::decimal::decimal32 +#define dec64 std::decimal::decimal64 +#define dec128 std::decimal::decimal128 + +#include "pass_x.h" + +void +pass_2_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +#ifndef SKIP_DECIMAL32 +T(d32) +#endif +#ifndef SKIP_DECIMAL64 +T(d64) +#endif +#ifndef SKIP_DECIMAL128 +T(d128) +#endif + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-2_y.C b/gcc/testsuite/g++.dg/compat/decimal/pass-2_y.C new file mode 100644 index 000000000000..97471457dbe2 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-2_y.C @@ -0,0 +1,7 @@ +#include "decimal-dummy.h" + +#define dec32 std::decimal::decimal32 +#define dec64 std::decimal::decimal64 +#define dec128 std::decimal::decimal128 + +#include "pass_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-3_main.C b/gcc/testsuite/g++.dg/compat/decimal/pass-3_main.C new file mode 100644 index 000000000000..de09992c2246 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-3_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test passing decimal scalars and classes by value. */ + +extern void pass_3_x (void); +int fails; + +int +main () +{ + pass_3_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-3_x.C b/gcc/testsuite/g++.dg/compat/decimal/pass-3_x.C new file mode 100644 index 000000000000..17e4d1c8b5a3 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-3_x.C @@ -0,0 +1,30 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "pass_x.h" + +void +pass_3_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +#ifndef SKIP_DECIMAL32 +T(d32) +#endif +#ifndef SKIP_DECIMAL64 +T(d64) +#endif +#ifndef SKIP_DECIMAL128 +T(d128) +#endif + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-3_y.C b/gcc/testsuite/g++.dg/compat/decimal/pass-3_y.C new file mode 100644 index 000000000000..97471457dbe2 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-3_y.C @@ -0,0 +1,7 @@ +#include "decimal-dummy.h" + +#define dec32 std::decimal::decimal32 +#define dec64 std::decimal::decimal64 +#define dec128 std::decimal::decimal128 + +#include "pass_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-4_main.C b/gcc/testsuite/g++.dg/compat/decimal/pass-4_main.C new file mode 100644 index 000000000000..d5a0a47d478b --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-4_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test passing decimal classes and scalars by value. */ + +extern void pass_4_x (void); +int fails; + +int +main () +{ + pass_4_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-4_x.C b/gcc/testsuite/g++.dg/compat/decimal/pass-4_x.C new file mode 100644 index 000000000000..b0483ac278fc --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-4_x.C @@ -0,0 +1,32 @@ +#include "decimal-dummy.h" + +#define dec32 std::decimal::decimal32 +#define dec64 std::decimal::decimal64 +#define dec128 std::decimal::decimal128 + +#include "pass_x.h" + +void +pass_4_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +#ifndef SKIP_DECIMAL32 +T(d32) +#endif +#ifndef SKIP_DECIMAL64 +T(d64) +#endif +#ifndef SKIP_DECIMAL128 +T(d128) +#endif + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-4_y.C b/gcc/testsuite/g++.dg/compat/decimal/pass-4_y.C new file mode 100644 index 000000000000..5da7f87d51e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-4_y.C @@ -0,0 +1,5 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "pass_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-5_main.C b/gcc/testsuite/g++.dg/compat/decimal/pass-5_main.C new file mode 100644 index 000000000000..9b25a49c72e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-5_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test passing decimal scalars and typedef'd classes by value. */ + +extern void pass_5_x (void); +int fails; + +int +main () +{ + pass_5_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-5_x.C b/gcc/testsuite/g++.dg/compat/decimal/pass-5_x.C new file mode 100644 index 000000000000..11c4d96c9cd9 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-5_x.C @@ -0,0 +1,30 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "pass_x.h" + +void +pass_5_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +#ifndef SKIP_DECIMAL32 +T(d32) +#endif +#ifndef SKIP_DECIMAL64 +T(d64) +#endif +#ifndef SKIP_DECIMAL128 +T(d128) +#endif + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-5_y.C b/gcc/testsuite/g++.dg/compat/decimal/pass-5_y.C new file mode 100644 index 000000000000..5a2c1fba01b0 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-5_y.C @@ -0,0 +1,7 @@ +#include "decimal-dummy.h" + +typedef std::decimal::decimal32 dec32; +typedef std::decimal::decimal64 dec64; +typedef std::decimal::decimal128 dec128; + +#include "pass_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-6_main.C b/gcc/testsuite/g++.dg/compat/decimal/pass-6_main.C new file mode 100644 index 000000000000..1b686a21dd02 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-6_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test passing typedef'd decimal classes and scalars by value. */ + +extern void pass_6_x (void); +int fails; + +int +main () +{ + pass_6_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-6_x.C b/gcc/testsuite/g++.dg/compat/decimal/pass-6_x.C new file mode 100644 index 000000000000..e59ca7f722d5 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-6_x.C @@ -0,0 +1,32 @@ +#include "decimal-dummy.h" + +typedef std::decimal::decimal32 dec32; +typedef std::decimal::decimal64 dec64; +typedef std::decimal::decimal128 dec128; + +#include "pass_x.h" + +void +pass_6_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +#ifndef SKIP_DECIMAL32 +T(d32) +#endif +#ifndef SKIP_DECIMAL64 +T(d64) +#endif +#ifndef SKIP_DECIMAL128 +T(d128) +#endif + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass-6_y.C b/gcc/testsuite/g++.dg/compat/decimal/pass-6_y.C new file mode 100644 index 000000000000..5da7f87d51e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass-6_y.C @@ -0,0 +1,5 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "pass_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass_x.h b/gcc/testsuite/g++.dg/compat/decimal/pass_x.h new file mode 100644 index 000000000000..5b25dc9bf1a6 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass_x.h @@ -0,0 +1,151 @@ +#include "compat-common.h" + +#define T(NAME, TYPE, INITVAL) \ +TYPE g01##NAME, g02##NAME, g03##NAME, g04##NAME; \ +TYPE g05##NAME, g06##NAME, g07##NAME, g08##NAME; \ +TYPE g09##NAME, g10##NAME, g11##NAME, g12##NAME; \ +TYPE g13##NAME, g14##NAME, g15##NAME, g16##NAME; \ + \ +extern void init##NAME (TYPE *p, TYPE v); \ +extern void checkg##NAME (void); \ +extern void \ +test##NAME (TYPE x01, TYPE x02, TYPE x03, TYPE x04, \ + TYPE x05, TYPE x06, TYPE x07, TYPE x08, \ + TYPE x09, TYPE x10, TYPE x11, TYPE x12, \ + TYPE x13, TYPE x14, TYPE x15, TYPE x16); \ +extern void testva##NAME (int n, ...); \ + \ +extern void \ +check##NAME (TYPE x, TYPE v) \ +{ \ + if (x != v + INITVAL) \ + DEBUG_CHECK \ +} \ + \ +extern void \ +test2_##NAME (TYPE x01, TYPE x02, TYPE x03, TYPE x04, \ + TYPE x05, TYPE x06, TYPE x07, TYPE x08) \ +{ \ + test##NAME (x01, g02##NAME, x02, g04##NAME, \ + x03, g06##NAME, x04, g08##NAME, \ + x05, g10##NAME, x06, g12##NAME, \ + x07, g14##NAME, x08, g16##NAME); \ +} \ + \ +extern void \ +testit##NAME (void) \ +{ \ + DEBUG_FPUTS (#NAME) \ + DEBUG_FPUTS (" init: ") \ + init##NAME (&g01##NAME, 1); \ + init##NAME (&g02##NAME, 2); \ + init##NAME (&g03##NAME, 3); \ + init##NAME (&g04##NAME, 4); \ + init##NAME (&g05##NAME, 5); \ + init##NAME (&g06##NAME, 6); \ + init##NAME (&g07##NAME, 7); \ + init##NAME (&g08##NAME, 8); \ + init##NAME (&g09##NAME, 9); \ + init##NAME (&g10##NAME, 10); \ + init##NAME (&g11##NAME, 11); \ + init##NAME (&g12##NAME, 12); \ + init##NAME (&g13##NAME, 13); \ + init##NAME (&g14##NAME, 14); \ + init##NAME (&g15##NAME, 15); \ + init##NAME (&g16##NAME, 16); \ + checkg##NAME (); \ + DEBUG_NL \ + DEBUG_FPUTS (#NAME) \ + DEBUG_FPUTS (" test: ") \ + test##NAME (g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME, g10##NAME, g11##NAME, g12##NAME, \ + g13##NAME, g14##NAME, g15##NAME, g16##NAME); \ + DEBUG_NL \ + DEBUG_FPUTS (#NAME) \ + DEBUG_FPUTS (" testva: ") \ + DEBUG_NL \ + testva##NAME (1, \ + g01##NAME); \ + DEBUG_NL \ + testva##NAME (2, \ + g01##NAME, g02##NAME); \ + DEBUG_NL \ + testva##NAME (3, \ + g01##NAME, g02##NAME, g03##NAME); \ + DEBUG_NL \ + testva##NAME (4, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME); \ + DEBUG_NL \ + testva##NAME (5, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME); \ + DEBUG_NL \ + testva##NAME (6, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME); \ + DEBUG_NL \ + testva##NAME (7, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME); \ + DEBUG_NL \ + testva##NAME (8, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME); \ + DEBUG_NL \ + testva##NAME (9, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME); \ + DEBUG_NL \ + testva##NAME (10, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME, g10##NAME); \ + DEBUG_NL \ + testva##NAME (11, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME, g10##NAME, g11##NAME); \ + DEBUG_NL \ + testva##NAME (12, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME, g10##NAME, g11##NAME, g12##NAME); \ + DEBUG_NL \ + testva##NAME (13, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME, g10##NAME, g11##NAME, g12##NAME, \ + g13##NAME); \ + DEBUG_NL \ + testva##NAME (14, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME, g10##NAME, g11##NAME, g12##NAME, \ + g13##NAME, g14##NAME); \ + DEBUG_NL \ + testva##NAME (15, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME, g10##NAME, g11##NAME, g12##NAME, \ + g13##NAME, g14##NAME, g15##NAME); \ + DEBUG_NL \ + testva##NAME (16, \ + g01##NAME, g02##NAME, g03##NAME, g04##NAME, \ + g05##NAME, g06##NAME, g07##NAME, g08##NAME, \ + g09##NAME, g10##NAME, g11##NAME, g12##NAME, \ + g13##NAME, g14##NAME, g15##NAME, g16##NAME); \ + DEBUG_NL \ + DEBUG_FPUTS (#NAME) \ + DEBUG_FPUTS (" test2: ") \ + test2_##NAME (g01##NAME, g03##NAME, g05##NAME, g07##NAME, \ + g09##NAME, g11##NAME, g13##NAME, g15##NAME); \ + DEBUG_NL \ +} + +T(d32, dec32, (dec32)1.5DF) +T(d64, dec64, (dec64)2.5DD) +T(d128, dec128, (dec128)3.5DL) + +#undef T diff --git a/gcc/testsuite/g++.dg/compat/decimal/pass_y.h b/gcc/testsuite/g++.dg/compat/decimal/pass_y.h new file mode 100644 index 000000000000..f835b1983523 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/pass_y.h @@ -0,0 +1,89 @@ +#include + +#include "compat-common.h" + +#ifdef SKIP_VA +const int test_va = 0; +#else +const int test_va = 1; +#endif + +#define T(NAME, TYPE, INITVAL) \ +extern TYPE g01##NAME, g02##NAME, g03##NAME, g04##NAME; \ +extern TYPE g05##NAME, g06##NAME, g07##NAME, g08##NAME; \ +extern TYPE g09##NAME, g10##NAME, g11##NAME, g12##NAME; \ +extern TYPE g13##NAME, g14##NAME, g15##NAME, g16##NAME; \ + \ +extern void check##NAME (TYPE x, TYPE v); \ + \ +extern void \ +init##NAME (TYPE *p, TYPE v) \ +{ \ + *p = v + INITVAL; \ +} \ + \ +extern void \ +checkg##NAME (void) \ +{ \ + check##NAME (g01##NAME, 1); \ + check##NAME (g02##NAME, 2); \ + check##NAME (g03##NAME, 3); \ + check##NAME (g04##NAME, 4); \ + check##NAME (g05##NAME, 5); \ + check##NAME (g06##NAME, 6); \ + check##NAME (g07##NAME, 7); \ + check##NAME (g08##NAME, 8); \ + check##NAME (g09##NAME, 9); \ + check##NAME (g10##NAME, 10); \ + check##NAME (g11##NAME, 11); \ + check##NAME (g12##NAME, 12); \ + check##NAME (g13##NAME, 13); \ + check##NAME (g14##NAME, 14); \ + check##NAME (g15##NAME, 15); \ + check##NAME (g16##NAME, 16); \ +} \ + \ +extern void \ +test##NAME (TYPE x01, TYPE x02, TYPE x03, TYPE x04, \ + TYPE x05, TYPE x06, TYPE x07, TYPE x08, \ + TYPE x09, TYPE x10, TYPE x11, TYPE x12, \ + TYPE x13, TYPE x14, TYPE x15, TYPE x16) \ +{ \ + check##NAME (x01, 1); \ + check##NAME (x02, 2); \ + check##NAME (x03, 3); \ + check##NAME (x04, 4); \ + check##NAME (x05, 5); \ + check##NAME (x06, 6); \ + check##NAME (x07, 7); \ + check##NAME (x08, 8); \ + check##NAME (x09, 9); \ + check##NAME (x10, 10); \ + check##NAME (x11, 11); \ + check##NAME (x12, 12); \ + check##NAME (x13, 13); \ + check##NAME (x14, 14); \ + check##NAME (x15, 15); \ + check##NAME (x16, 16); \ +} \ + \ +extern void \ +testva##NAME (int n, ...) \ +{ \ + int i; \ + va_list ap; \ + if (test_va) \ + { \ + va_start (ap, n); \ + for (i = 0; i < n; i++) \ + { \ + TYPE t = va_arg (ap, TYPE); \ + check##NAME (t, i+1); \ + } \ + va_end (ap); \ + } \ +} + +T(d32, dec32, (dec32)1.5DF) +T(d64, dec64, (dec64)2.5DD) +T(d128, dec128, (dec128)3.5DL) diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-1_main.C b/gcc/testsuite/g++.dg/compat/decimal/return-1_main.C new file mode 100644 index 000000000000..c663bb01cf3c --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-1_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test function return values for decimal float scalars. */ + +extern void return_1_x (void); +int fails; + +int +main () +{ + return_1_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-1_x.C b/gcc/testsuite/g++.dg/compat/decimal/return-1_x.C new file mode 100644 index 000000000000..e391bd1f1f3b --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-1_x.C @@ -0,0 +1,24 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "return_x.h" + +void +return_1_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +T(d32) +T(d64) +T(d128) + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-1_y.C b/gcc/testsuite/g++.dg/compat/decimal/return-1_y.C new file mode 100644 index 000000000000..0b4d4bf38c6f --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-1_y.C @@ -0,0 +1,5 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "return_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-2_main.C b/gcc/testsuite/g++.dg/compat/decimal/return-2_main.C new file mode 100644 index 000000000000..afa27f269dfb --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-2_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test function return values for decimal classes. */ + +extern void return_2_x (void); +int fails; + +int +main () +{ + return_2_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-2_x.C b/gcc/testsuite/g++.dg/compat/decimal/return-2_x.C new file mode 100644 index 000000000000..d96c01479c25 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-2_x.C @@ -0,0 +1,26 @@ +#include "decimal-dummy.h" + +#define dec32 std::decimal::decimal32 +#define dec64 std::decimal::decimal64 +#define dec128 std::decimal::decimal128 + +#include "return_x.h" + +void +return_2_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +T(d32) +T(d64) +T(d128) + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-2_y.C b/gcc/testsuite/g++.dg/compat/decimal/return-2_y.C new file mode 100644 index 000000000000..c68088b30cf9 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-2_y.C @@ -0,0 +1,7 @@ +#include "decimal-dummy.h" + +#define dec32 std::decimal::decimal32 +#define dec64 std::decimal::decimal64 +#define dec128 std::decimal::decimal128 + +#include "return_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-3_main.C b/gcc/testsuite/g++.dg/compat/decimal/return-3_main.C new file mode 100644 index 000000000000..468f3fc0c347 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-3_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test function return values for decimal float scalars and classes. */ + +extern void return_3_x (void); +int fails; + +int +main () +{ + return_3_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-3_x.C b/gcc/testsuite/g++.dg/compat/decimal/return-3_x.C new file mode 100644 index 000000000000..52e599c76310 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-3_x.C @@ -0,0 +1,24 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "return_x.h" + +void +return_3_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +T(d32) +T(d64) +T(d128) + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-3_y.C b/gcc/testsuite/g++.dg/compat/decimal/return-3_y.C new file mode 100644 index 000000000000..c68088b30cf9 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-3_y.C @@ -0,0 +1,7 @@ +#include "decimal-dummy.h" + +#define dec32 std::decimal::decimal32 +#define dec64 std::decimal::decimal64 +#define dec128 std::decimal::decimal128 + +#include "return_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-4_main.C b/gcc/testsuite/g++.dg/compat/decimal/return-4_main.C new file mode 100644 index 000000000000..365d8becd598 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-4_main.C @@ -0,0 +1,13 @@ +/* { dg-require-effective-target dfp } */ + +/* Test function return values for decimal float classes and scalars. */ + +extern void return_4_x (void); +int fails; + +int +main () +{ + return_4_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-4_x.C b/gcc/testsuite/g++.dg/compat/decimal/return-4_x.C new file mode 100644 index 000000000000..b9d28fa5b9a2 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-4_x.C @@ -0,0 +1,26 @@ +#include "decimal-dummy.h" + +#define dec32 std::decimal::decimal32 +#define dec64 std::decimal::decimal64 +#define dec128 std::decimal::decimal128 + +#include "return_x.h" + +void +return_4_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +T(d32) +T(d64) +T(d128) + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-4_y.C b/gcc/testsuite/g++.dg/compat/decimal/return-4_y.C new file mode 100644 index 000000000000..0b4d4bf38c6f --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-4_y.C @@ -0,0 +1,5 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "return_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-5_main.C b/gcc/testsuite/g++.dg/compat/decimal/return-5_main.C new file mode 100644 index 000000000000..2c334832797f --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-5_main.C @@ -0,0 +1,14 @@ +/* { dg-require-effective-target dfp } */ + +/* Test function return values for decimal float scalars and typedef'd + classes. */ + +extern void return_5_x (void); +int fails; + +int +main () +{ + return_5_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-5_x.C b/gcc/testsuite/g++.dg/compat/decimal/return-5_x.C new file mode 100644 index 000000000000..a2bb6173b2f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-5_x.C @@ -0,0 +1,24 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "return_x.h" + +void +return_5_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +T(d32) +T(d64) +T(d128) + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-5_y.C b/gcc/testsuite/g++.dg/compat/decimal/return-5_y.C new file mode 100644 index 000000000000..0f780167a4e4 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-5_y.C @@ -0,0 +1,7 @@ +#include "decimal-dummy.h" + +typedef std::decimal::decimal32 dec32; +typedef std::decimal::decimal64 dec64; +typedef std::decimal::decimal128 dec128; + +#include "return_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-6_main.C b/gcc/testsuite/g++.dg/compat/decimal/return-6_main.C new file mode 100644 index 000000000000..94526bdcb815 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-6_main.C @@ -0,0 +1,14 @@ +/* { dg-require-effective-target dfp } */ + +/* Test function return values for typedef'd decimal float classes + and scalars. */ + +extern void return_6_x (void); +int fails; + +int +main () +{ + return_6_x (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-6_x.C b/gcc/testsuite/g++.dg/compat/decimal/return-6_x.C new file mode 100644 index 000000000000..e0a487dbe3bd --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-6_x.C @@ -0,0 +1,26 @@ +#include "decimal-dummy.h" + +typedef std::decimal::decimal32 dec32; +typedef std::decimal::decimal64 dec64; +typedef std::decimal::decimal128 dec128; + +#include "return_x.h" + +void +return_6_x (void) +{ +DEBUG_INIT + +#define T(NAME) testit##NAME (); + +T(d32) +T(d64) +T(d128) + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/g++.dg/compat/decimal/return-6_y.C b/gcc/testsuite/g++.dg/compat/decimal/return-6_y.C new file mode 100644 index 000000000000..0b4d4bf38c6f --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return-6_y.C @@ -0,0 +1,5 @@ +typedef float dec32 __attribute__((mode(SD))); +typedef float dec64 __attribute__((mode(DD))); +typedef float dec128 __attribute__((mode(TD))); + +#include "return_y.h" diff --git a/gcc/testsuite/g++.dg/compat/decimal/return_x.h b/gcc/testsuite/g++.dg/compat/decimal/return_x.h new file mode 100644 index 000000000000..401adfb5c937 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return_x.h @@ -0,0 +1,90 @@ +#include "compat-common.h" + +#ifdef SKIP_VA +const int test_va = 0; +#else +const int test_va = 1; +#endif + +#define T(NAME, TYPE, INITVAL) \ +TYPE g01##NAME, g02##NAME, g03##NAME, g04##NAME; \ +TYPE g05##NAME, g06##NAME, g07##NAME, g08##NAME; \ +TYPE g09##NAME, g10##NAME, g11##NAME, g12##NAME; \ +TYPE g13##NAME, g14##NAME, g15##NAME, g16##NAME; \ + \ +extern void init##NAME (TYPE *p, TYPE v); \ +extern void checkg##NAME (void); \ +extern TYPE test0##NAME (void); \ +extern TYPE test1##NAME (TYPE); \ +extern TYPE testva##NAME (int n, ...); \ + \ +extern void \ +check##NAME (TYPE x, TYPE v) \ +{ \ + if (x != v) \ + DEBUG_CHECK \ +} \ + \ +extern void \ +testit##NAME (void) \ +{ \ + TYPE rslt; \ + DEBUG_FPUTS (#NAME) \ + DEBUG_FPUTS (" init: ") \ + init##NAME (&g01##NAME, 1); \ + init##NAME (&g02##NAME, 2); \ + init##NAME (&g03##NAME, 3); \ + init##NAME (&g04##NAME, 4); \ + init##NAME (&g05##NAME, 5); \ + init##NAME (&g06##NAME, 6); \ + init##NAME (&g07##NAME, 7); \ + init##NAME (&g08##NAME, 8); \ + init##NAME (&g09##NAME, 9); \ + init##NAME (&g10##NAME, 10); \ + init##NAME (&g11##NAME, 11); \ + init##NAME (&g12##NAME, 12); \ + init##NAME (&g13##NAME, 13); \ + init##NAME (&g14##NAME, 14); \ + init##NAME (&g15##NAME, 15); \ + init##NAME (&g16##NAME, 16); \ + checkg##NAME (); \ + DEBUG_NL \ + DEBUG_FPUTS (#NAME) \ + DEBUG_FPUTS (" test0: ") \ + rslt = test0##NAME (); \ + check##NAME (rslt, g01##NAME); \ + DEBUG_NL \ + DEBUG_FPUTS (#NAME) \ + DEBUG_FPUTS (" test1: ") \ + rslt = test1##NAME (g01##NAME); \ + check##NAME (rslt, g01##NAME); \ + if (test_va) \ + { \ + DEBUG_NL \ + DEBUG_FPUTS (#NAME) \ + DEBUG_FPUTS (" testva: ") \ + rslt = testva##NAME (1, g01##NAME); \ + check##NAME (rslt, g01##NAME); \ + rslt = testva##NAME (5, g01##NAME, g02##NAME, g03##NAME, \ + g04##NAME, g05##NAME); \ + check##NAME (rslt, g05##NAME); \ + rslt = testva##NAME (9, g01##NAME, g02##NAME, g03##NAME, \ + g04##NAME, g05##NAME, g06##NAME, \ + g07##NAME, g08##NAME, g09##NAME); \ + check##NAME (rslt, g09##NAME); \ + rslt = testva##NAME (16, g01##NAME, g02##NAME, g03##NAME, \ + g04##NAME, g05##NAME, g06##NAME, \ + g07##NAME, g08##NAME, g09##NAME, \ + g10##NAME, g11##NAME, g12##NAME, \ + g13##NAME, g14##NAME, g15##NAME, \ + g16##NAME); \ + check##NAME (rslt, g16##NAME); \ + } \ + DEBUG_NL \ +} + +T(d32, dec32, (dec32)1.5DF); +T(d64, dec64, (dec64)2.5DD); +T(d128, dec128, (dec128)3.5DL); + +#undef T diff --git a/gcc/testsuite/g++.dg/compat/decimal/return_y.h b/gcc/testsuite/g++.dg/compat/decimal/return_y.h new file mode 100644 index 000000000000..285526e2e369 --- /dev/null +++ b/gcc/testsuite/g++.dg/compat/decimal/return_y.h @@ -0,0 +1,67 @@ +#include + +#include "compat-common.h" + +#define T(NAME, TYPE, INITVAL) \ +extern TYPE g01##NAME, g02##NAME, g03##NAME, g04##NAME; \ +extern TYPE g05##NAME, g06##NAME, g07##NAME, g08##NAME; \ +extern TYPE g09##NAME, g10##NAME, g11##NAME, g12##NAME; \ +extern TYPE g13##NAME, g14##NAME, g15##NAME, g16##NAME; \ + \ +extern void check##NAME (TYPE x, TYPE v); \ + \ +extern void \ +init##NAME (TYPE *p, TYPE v) \ +{ \ + *p = v + INITVAL; \ +} \ + \ +extern void \ +checkg##NAME (void) \ +{ \ + check##NAME (g01##NAME, 1+INITVAL); \ + check##NAME (g02##NAME, 2+INITVAL); \ + check##NAME (g03##NAME, 3+INITVAL); \ + check##NAME (g04##NAME, 4+INITVAL); \ + check##NAME (g05##NAME, 5+INITVAL); \ + check##NAME (g06##NAME, 6+INITVAL); \ + check##NAME (g07##NAME, 7+INITVAL); \ + check##NAME (g08##NAME, 8+INITVAL); \ + check##NAME (g09##NAME, 9+INITVAL); \ + check##NAME (g10##NAME, 10+INITVAL); \ + check##NAME (g11##NAME, 11+INITVAL); \ + check##NAME (g12##NAME, 12+INITVAL); \ + check##NAME (g13##NAME, 13+INITVAL); \ + check##NAME (g14##NAME, 14+INITVAL); \ + check##NAME (g15##NAME, 15+INITVAL); \ + check##NAME (g16##NAME, 16+INITVAL); \ +} \ + \ +extern TYPE \ +test0##NAME (void) \ +{ \ + return g01##NAME; \ +} \ + \ +extern TYPE \ +test1##NAME (TYPE x01) \ +{ \ + return x01; \ +} \ + \ +extern TYPE \ +testva##NAME (int n, ...) \ +{ \ + int i; \ + TYPE rslt; \ + va_list ap; \ + va_start (ap, n); \ + for (i = 0; i < n; i++) \ + rslt = va_arg (ap, TYPE); \ + va_end (ap); \ + return rslt; \ +} + +T(d32, dec32, (dec32)1.5) +T(d64, dec64, (dec64)2.5) +T(d128, dec128, (dec128)3.5) diff --git a/gcc/tree.c b/gcc/tree.c index 7fa7649d2f91..5d44841769fd 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1983,6 +1983,18 @@ fields_length (const_tree type) return count; } +/* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or + UNION_TYPE TYPE, or NULL_TREE if none. */ + +tree +first_field (const_tree type) +{ + tree t = TYPE_FIELDS (type); + while (t && TREE_CODE (t) != FIELD_DECL) + t = TREE_CHAIN (t); + return t; +} + /* Concatenate two chains of nodes (chained through TREE_CHAIN) by modifying the last node in chain 1 to point to chain 2. This is the Lisp primitive `nconc'. */ diff --git a/gcc/tree.h b/gcc/tree.h index a0e1f6777610..f5827d59f893 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2251,16 +2251,18 @@ extern enum machine_mode vector_type_mode (const_tree); #define TYPE_NEEDS_CONSTRUCTING(NODE) \ (TYPE_CHECK (NODE)->type.needs_constructing_flag) -/* Indicates that objects of this type (a UNION_TYPE), should be passed - the same way that the first union alternative would be passed. */ -#define TYPE_TRANSPARENT_UNION(NODE) \ - (UNION_TYPE_CHECK (NODE)->type.transparent_union_flag) +/* Indicates that a UNION_TYPE object should be passed the same way that + the first union alternative would be passed, or that a RECORD_TYPE + object should be passed the same way that the first (and only) member + would be passed. */ +#define TYPE_TRANSPARENT_AGGR(NODE) \ + (RECORD_OR_UNION_CHECK (NODE)->type.transparent_aggr_flag) /* For an ARRAY_TYPE, indicates that it is not permitted to take the address of a component of the type. This is the counterpart of DECL_NONADDRESSABLE_P for arrays, see the definition of this flag. */ #define TYPE_NONALIASED_COMPONENT(NODE) \ - (ARRAY_TYPE_CHECK (NODE)->type.transparent_union_flag) + (ARRAY_TYPE_CHECK (NODE)->type.transparent_aggr_flag) /* Indicated that objects of this type should be laid out in as compact a way as possible. */ @@ -2285,7 +2287,7 @@ struct GTY(()) tree_type { unsigned int precision : 10; unsigned no_force_blk_flag : 1; unsigned needs_constructing_flag : 1; - unsigned transparent_union_flag : 1; + unsigned transparent_aggr_flag : 1; unsigned restrict_flag : 1; unsigned contains_placeholder_bits : 2; @@ -4360,6 +4362,10 @@ extern int list_length (const_tree); extern int fields_length (const_tree); +/* Returns the first FIELD_DECL in a type. */ + +extern tree first_field (const_tree); + /* Given an initializer INIT, return TRUE if INIT is zero or some aggregate of zeros. Otherwise return FALSE. */ -- 2.43.5