+2002-12-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/8461, c++/8625
+ * integrate.c (copy_decl_for_inlining): Handle explicit invisible
+ references.
+ * tree-inline.c (initialize_inlined_parameters): Likewise.
+
+ * tree.c (variably_modified_type_p): Just return an error_mark_node.
+
2002-12-04 Chris Demetriou <cgd@broadcom.com>
* config/mips/mips.md (get_fnaddr): Avoid placing an "la"
2002-12-03 Jason Merrill <jason@redhat.com>
+ PR c++/8674
+ * call.c (build_over_call): Check specifically for TARGET_EXPR
+ when eliding.
+
+ PR c++/8461, c++/8625
+ * call.c (convert_for_arg_passing): Don't mess with error_mark_node.
+ (cp_convert_parm_for_inlining): Remove.
+ * cp-lang.c (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
+ Remove.
+ * cp-tree.h (ADDR_IS_INVISIREF): Remove.
+ * except.c (stabilize_throw_expr): Remove ADDR_IS_INVISIREF code.
+
* call.c (build_user_type_conversion_1): Don't set ICS_BAD_FLAG on
an ambiguous conversion.
convert_for_arg_passing (type, val)
tree type, val;
{
+ if (val == error_mark_node)
+ ;
/* Pass classes with copy ctors by invisible reference. */
- if (TREE_ADDRESSABLE (type))
- {
- val = build1 (ADDR_EXPR, build_reference_type (type), val);
- ADDR_IS_INVISIREF (val) = 1;
- }
+ else if (TREE_ADDRESSABLE (type))
+ val = build1 (ADDR_EXPR, build_reference_type (type), val);
else if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
return val;
}
-/* Convert VALUE for assignment into inlined parameter PARM. */
-
-tree
-cp_convert_parm_for_inlining (parm, value, fn)
- tree parm, value;
- tree fn ATTRIBUTE_UNUSED;
-{
- /* When inlining, we don't need to mess with invisible references, so
- undo the ADDR_EXPR. */
- if (TREE_ADDRESSABLE (TREE_TYPE (parm)))
- {
- value = TREE_OPERAND (value, 0);
- if (TREE_CODE (value) != TARGET_EXPR)
- abort ();
- }
- return value;
-}
-
/* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
temp or an INIT_EXPR otherwise. */
if (integer_zerop (TREE_VALUE (args)))
{
- if (! real_lvalue_p (arg))
+ if (TREE_CODE (arg) == TARGET_EXPR)
return arg;
else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
}
- else if (!real_lvalue_p (arg)
+ else if (TREE_CODE (arg) == TARGET_EXPR
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
tree address;
#undef LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING
#define LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING \
cp_copy_res_decl_for_inlining
-#undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
-#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
- cp_convert_parm_for_inlining
#undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
BINFO_LOST_PRIMARY_P (in BINFO)
TREE_PARMLIST (in TREE_LIST)
- ADDR_IS_INVISIREF (in ADDR_EXPR)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
BINFO_VTABLE_PATH_MARKED.
BINFO_PUSHDECLS_MARKED.
/* Nonzero for a parmlist means that this parmlist ended in ... */
#define PARMLIST_ELLIPSIS_P(NODE) TREE_LANG_FLAG_0 (NODE)
-/* Nonzero if this ADDR_EXPR is used to implement the pass by invisible
- reference calling convention. */
-#define ADDR_IS_INVISIREF(NODE) TREE_LANG_FLAG_2 (NODE)
-
/* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE
will be NULL_TREE to indicate a throw specification of `()', or
{
tree arg = TREE_VALUE (args);
tree arg_init_expr;
- if (TREE_CODE (arg) == ADDR_EXPR
- && ADDR_IS_INVISIREF (arg))
- {
- /* A sub-TARGET_EXPR. Recurse; we can't wrap the actual call
- without introducing an extra copy. */
- tree sub = TREE_OPERAND (arg, 0);
- if (TREE_CODE (sub) != TARGET_EXPR)
- abort ();
- sub = stabilize_throw_expr (sub, &arg_init_expr);
- TREE_OPERAND (arg, 0) = sub;
- if (TREE_SIDE_EFFECTS (arg_init_expr))
- init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
- arg_init_expr);
- }
- else
- {
- arg = stabilize_expr (arg, &arg_init_expr);
- if (TREE_SIDE_EFFECTS (arg_init_expr))
- init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
- arg_init_expr);
- }
+ arg = stabilize_expr (arg, &arg_init_expr);
+
+ if (TREE_SIDE_EFFECTS (arg_init_expr))
+ init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
+ arg_init_expr);
*p = tree_cons (NULL_TREE, arg, NULL_TREE);
p = &TREE_CHAIN (*p);
}
/* Copy the declaration. */
if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL)
{
+ tree type;
+ int invisiref = 0;
+
+ /* See if the frontend wants to pass this by invisible reference. */
+ if (TREE_CODE (decl) == PARM_DECL
+ && DECL_ARG_TYPE (decl) != TREE_TYPE (decl)
+ && POINTER_TYPE_P (DECL_ARG_TYPE (decl))
+ && TREE_TYPE (DECL_ARG_TYPE (decl)) == TREE_TYPE (decl))
+ {
+ invisiref = 1;
+ type = DECL_ARG_TYPE (decl);
+ }
+ else
+ type = TREE_TYPE (decl);
+
/* For a parameter, we must make an equivalent VAR_DECL, not a
new PARM_DECL. */
- copy = build_decl (VAR_DECL, DECL_NAME (decl), TREE_TYPE (decl));
- TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
- TREE_READONLY (copy) = TREE_READONLY (decl);
- TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
+ copy = build_decl (VAR_DECL, DECL_NAME (decl), type);
+ if (!invisiref)
+ {
+ TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
+ TREE_READONLY (copy) = TREE_READONLY (decl);
+ TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
+ }
+ else
+ {
+ TREE_ADDRESSABLE (copy) = 0;
+ TREE_READONLY (copy) = 1;
+ TREE_THIS_VOLATILE (copy) = 0;
+ }
}
else
{
--- /dev/null
+// PR c++/8674
+
+// Bug: Since B().a is an rvalue, we tried to treat it like a TARGET_EXPR
+// and elide the copy. But that produces a bitwise copy, which causes us
+// to abort in cp_expr_size.
+
+// Test that we actually run the A copy constructor when calling f().
+
+// { dg-do run }
+
+int c;
+
+struct A
+{
+ A () { ++c; }
+ A (const A&) { ++c; }
+};
+
+struct B
+{
+ A a;
+};
+
+void f (A) { }
+
+int main ()
+{
+ f (B().a);
+ return c < 2;
+}
#endif /* not INLINER_FOR_JAVA */
tree var;
tree value;
+ tree var_sub;
/* Find the initializer. */
value = (*lang_hooks.tree_inlining.convert_parm_for_inlining)
/* Make an equivalent VAR_DECL. */
var = copy_decl_for_inlining (p, fn, VARRAY_TREE (id->fns, 0));
+
+ /* See if the frontend wants to pass this by invisible reference. If
+ so, our new VAR_DECL will have REFERENCE_TYPE, and we need to
+ replace uses of the PARM_DECL with dereferences. */
+ if (TREE_TYPE (var) != TREE_TYPE (p)
+ && POINTER_TYPE_P (TREE_TYPE (var))
+ && TREE_TYPE (TREE_TYPE (var)) == TREE_TYPE (p))
+ var_sub = build1 (INDIRECT_REF, TREE_TYPE (p), var);
+ else
+ var_sub = var;
+
/* Register the VAR_DECL as the equivalent for the PARM_DECL;
that way, when the PARM_DECL is encountered, it will be
automatically replaced by the VAR_DECL. */
splay_tree_insert (id->decl_map,
(splay_tree_key) p,
- (splay_tree_value) var);
+ (splay_tree_value) var_sub);
/* Declare this new variable. */
#ifndef INLINER_FOR_JAVA
variably_modified_type_p (type)
tree type;
{
+ if (type == error_mark_node)
+ return false;
+
/* If TYPE itself has variable size, it is variably modified.
We do not yet have a representation of the C99 '[*]' syntax.