tsubst_flags_t);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
+static bool pass_as_empty_struct (tree type);
+static tree empty_class_arg (tree);
/* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
NAME can take many forms... */
for (i = 0; i < n; i++)
{
tree arg = CALL_EXPR_ARG (function, i);
- if (is_empty_class (TREE_TYPE (arg))
- && ! TREE_ADDRESSABLE (TREE_TYPE (arg)))
+ tree type = TREE_TYPE (arg);
+ if (is_really_empty_class (type)
+ && ! TREE_ADDRESSABLE (type))
{
- tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
- arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
- CALL_EXPR_ARG (function, i) = arg;
+ CALL_EXPR_ARG (function, i) = empty_class_arg (arg);
}
}
expr = build_va_arg (loc, expr, ref);
return convert_from_reference (expr);
}
+ else if (is_really_empty_class (type) && !TREE_ADDRESSABLE (type))
+ {
+ /* Do the reverse of empty_class_arg. */
+ tree etype = pass_as_empty_struct (type) ? empty_struct_type : type;
+ expr = build_va_arg (loc, expr, etype);
+ tree ec = build0 (EMPTY_CLASS_EXPR, type);
+ return build2 (COMPOUND_EXPR, type, expr, ec);
+ }
return build_va_arg (loc, expr, type);
}
return arg;
}
+/* Return true iff TYPE should be passed and returned as a size 0 type rather
+ than its normal size, for compatibility with C. */
+
+static bool
+pass_as_empty_struct (tree type)
+{
+ return (abi_version_at_least (10)
+ && type != error_mark_node
+ && COMPLETE_TYPE_P (type)
+ && !TREE_ADDRESSABLE (type)
+ && is_really_empty_class (type));
+}
+
+/* Adjust the value VAL of empty class type TYPE for argument passing.
+ Keep this synced with build_x_va_arg. */
+
+static tree
+empty_class_arg (tree val)
+{
+ /* Don't pass empty class objects by value. This is useful
+ for tags in STL, which are used to control overload resolution.
+ We don't need to handle other cases of copying empty classes. */
+ tree type = TREE_TYPE (val);
+ tree etype = pass_as_empty_struct (type) ? empty_struct_type : type;
+ tree empty = build0 (EMPTY_CLASS_EXPR, etype);
+ return build2 (COMPOUND_EXPR, etype, val, empty);
+}
+
/* Returns the type which will really be used for passing an argument of
type TYPE. */
&& COMPLETE_TYPE_P (type)
&& tree_int_cst_lt (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
type = integer_type_node;
+ else if (pass_as_empty_struct (type))
+ type = empty_struct_type;
return type;
}