aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2017-11-22 16:06:18 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2017-11-22 16:06:18 +0000
commit974aedcce8d3eb6d46493c1e597b75743cb4c3db (patch)
tree76a622fb22ebe257b9dfc386c92eb31cc07221bc /gcc/tree.c
parentfc7160b2c718d7974aee97ca9b8448ec760bbfb7 (diff)
downloadgcc-974aedcce8d3eb6d46493c1e597b75743cb4c3db.zip
gcc-974aedcce8d3eb6d46493c1e597b75743cb4c3db.tar.gz
gcc-974aedcce8d3eb6d46493c1e597b75743cb4c3db.tar.bz2
re PR c++/60336 (empty struct value is passed differently in C and C++)
PR c++/60336 PR middle-end/67239 PR target/68355 * c-decl.c (grokdeclarator): Set DECL_PADDING_P on unnamed bit-fields. * class.c (layout_class_type): Set DECL_PADDING_P on padding. * decl.c (cxx_init_decl_processing): Set TRANSLATION_UNIT_WARN_EMPTY_P. (grokdeclarator): Set DECL_PADDING_P on unnamed bit-fields. * lto.c (compare_tree_sccs_1): Compare TYPE_EMPTY_P and DECL_PADDING_P. * calls.c (initialize_argument_information): Call warn_parameter_passing_abi target hook. (store_one_arg): Use 0 for empty record size. Don't push 0 size argument onto stack. (must_pass_in_stack_var_size_or_pad): Return false for empty types. * common.opt: Update -fabi-version description. * config/i386/i386.c (init_cumulative_args): Set cum->warn_empty. (ix86_gimplify_va_arg): Call arg_int_size_in_bytes instead of int_size_in_bytes. (ix86_is_empty_record): New function. (ix86_warn_parameter_passing_abi): New function. (TARGET_EMPTY_RECORD_P): Redefine. (TARGET_WARN_PARAMETER_PASSING_ABI): Redefine. * config/i386/i386.h (CUMULATIVE_ARGS): Add warn_empty. * doc/tm.texi: Regenerated. * doc/tm.texi.in (TARGET_EMPTY_RECORD_P, TARGET_WARN_PARAMETER_PASSING_ABI): Add. * dwarf2out.c (get_ultimate_context): Move to tree.c. * explow.c (hard_function_value): Call arg_int_size_in_bytes instead of int_size_in_bytes. * expr.c (copy_blkmode_to_reg): Likewise. * function.c (aggregate_value_p): Return 0 for empty types. (assign_parm_find_entry_rtl): Call warn_parameter_passing_abi target hook. (locate_and_pad_parm): Call arg size_in_bytes instead size_in_bytes. * lto-streamer-out.c (hash_tree): Hash TYPE_EMPTY_P and DECL_PADDING_P. * stor-layout.c (finalize_type_size): Set TYPE_EMPTY_P. * target.def (empty_record_p, warn_parameter_passing_abi): New target hooks. * targhooks.c (hook_void_CUMULATIVE_ARGS_tree): New hook. (std_gimplify_va_arg_expr): Skip empty records. Call arg_size_in_bytes instead size_in_bytes. * targhooks.h (hook_void_CUMULATIVE_ARGS_tree): Declare. * tree-core.h (tree_type_common): Add empty_flag. (tree_decl_common): Update comments. * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Stream DECL_PADDING_P. (unpack_ts_type_common_value_fields): Stream TYPE_EMPTY_P. * tree-streamer-out.c (pack_ts_decl_common_value_fields): Stream DECL_PADDING_P. (pack_ts_type_common_value_fields): Stream TYPE_EMPTY_P. * tree.c (default_is_empty_type): New function. (default_is_empty_record): New function. (arg_int_size_in_bytes): New function. (arg_size_in_bytes): New function. (get_ultimate_context): New function. * tree.h: Define TYPE_EMPTY_P, DECL_PADDING_P and TRANSLATION_UNIT_WARN_EMPTY_P. (default_is_empty_record, arg_int_size_in_bytes, arg_size_in_bytes, get_ultimate_context): Declare. * g++.dg/abi/empty12.C: New test. * g++.dg/abi/empty12.h: New test. * g++.dg/abi/empty12a.c: New test. * g++.dg/abi/empty13.C: New test. * g++.dg/abi/empty13.h: New test. * g++.dg/abi/empty13a.c: New test. * g++.dg/abi/empty14.C: New test. * g++.dg/abi/empty14.h: New test. * g++.dg/abi/empty14a.c: New test. * g++.dg/abi/empty15.C: New test. * g++.dg/abi/empty15.h: New test. * g++.dg/abi/empty15a.c: New test. * g++.dg/abi/empty16.C: New test. * g++.dg/abi/empty16.h: New test. * g++.dg/abi/empty16a.c: New test. * g++.dg/abi/empty17.C: New test. * g++.dg/abi/empty17.h: New test. * g++.dg/abi/empty17a.c: New test. * g++.dg/abi/empty18.C: New test. * g++.dg/abi/empty18.h: New test. * g++.dg/abi/empty18a.c: New test. * g++.dg/abi/empty19.C: New test. * g++.dg/abi/empty19.h: New test. * g++.dg/abi/empty19a.c: New test. * g++.dg/abi/empty20.C: New test. * g++.dg/abi/empty21.C: New test. * g++.dg/abi/empty22.C: New test. * g++.dg/abi/empty22.h: New test. * g++.dg/abi/empty22a.c: New test. * g++.dg/abi/empty23.C: New test. * g++.dg/abi/empty24.C: New test. * g++.dg/abi/empty25.C: New test. * g++.dg/abi/empty25.h: New test. * g++.dg/abi/empty25a.c: New test. * g++.dg/abi/empty26.C: New test. * g++.dg/abi/empty26.h: New test. * g++.dg/abi/empty26a.c: New test. * g++.dg/abi/empty27.C: New test. * g++.dg/abi/empty28.C: New test. * g++.dg/abi/pr60336-1.C: New test. * g++.dg/abi/pr60336-10.C: New test. * g++.dg/abi/pr60336-11.C: New test. * g++.dg/abi/pr60336-12.C: New test. * g++.dg/abi/pr60336-2.C: New test. * g++.dg/abi/pr60336-3.C: New test. * g++.dg/abi/pr60336-4.C: New test. * g++.dg/abi/pr60336-5.C: New test. * g++.dg/abi/pr60336-6.C: New test. * g++.dg/abi/pr60336-7.C: New test. * g++.dg/abi/pr60336-8.C: New test. * g++.dg/abi/pr60336-9.C: New test. * g++.dg/abi/pr68355.C: New test. * g++.dg/lto/pr60336_0.C: New test. Co-Authored-By: H.J. Lu <hongjiu.lu@intel.com> Co-Authored-By: Jason Merrill <jason@redhat.com> From-SVN: r255066
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 72da683..7efd644 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -8712,6 +8712,21 @@ get_containing_scope (const_tree t)
return (TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t));
}
+/* Returns the ultimate TRANSLATION_UNIT_DECL context of DECL or NULL. */
+
+const_tree
+get_ultimate_context (const_tree decl)
+{
+ while (decl && TREE_CODE (decl) != TRANSLATION_UNIT_DECL)
+ {
+ if (TREE_CODE (decl) == BLOCK)
+ decl = BLOCK_SUPERCONTEXT (decl);
+ else
+ decl = get_containing_scope (decl);
+ }
+ return decl;
+}
+
/* Return the innermost context enclosing DECL that is
a FUNCTION_DECL, or zero if none. */
@@ -13822,6 +13837,62 @@ get_nonnull_args (const_tree fntype)
return argmap;
}
+/* Returns true if TYPE is a type where it and all of its subobjects
+ (recursively) are of structure, union, or array type. */
+
+static bool
+default_is_empty_type (tree type)
+{
+ if (RECORD_OR_UNION_TYPE_P (type))
+ {
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && !DECL_PADDING_P (field)
+ && !default_is_empty_type (TREE_TYPE (field)))
+ return false;
+ return true;
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ return (integer_minus_onep (array_type_nelts (type))
+ || TYPE_DOMAIN (type) == NULL_TREE
+ || default_is_empty_type (TREE_TYPE (type)));
+ return false;
+}
+
+/* Implement TARGET_EMPTY_RECORD_P. Return true if TYPE is an empty type
+ that shouldn't be passed via stack. */
+
+bool
+default_is_empty_record (const_tree type)
+{
+ if (!abi_version_at_least (12))
+ return false;
+
+ if (type == error_mark_node)
+ return false;
+
+ if (TREE_ADDRESSABLE (type))
+ return false;
+
+ return default_is_empty_type (TYPE_MAIN_VARIANT (type));
+}
+
+/* Like int_size_in_bytes, but handle empty records specially. */
+
+HOST_WIDE_INT
+arg_int_size_in_bytes (const_tree type)
+{
+ return TYPE_EMPTY_P (type) ? 0 : int_size_in_bytes (type);
+}
+
+/* Like size_in_bytes, but handle empty records specially. */
+
+tree
+arg_size_in_bytes (const_tree type)
+{
+ return TYPE_EMPTY_P (type) ? size_zero_node : size_in_bytes (type);
+}
+
/* List of pointer types used to declare builtins before we have seen their
real declaration.