aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c31
-rw-r--r--gcc/cp/cp-lang.c3
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/except.c26
-rw-r--r--gcc/integrate.c32
-rw-r--r--gcc/testsuite/g++.dg/init/elide2.C30
-rw-r--r--gcc/tree-inline.c14
-rw-r--r--gcc/tree.c3
10 files changed, 106 insertions, 59 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 579d884..76609c3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+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"
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5da6ebc..60789ee 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -6,6 +6,18 @@
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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 1678ed2..072fbe6 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4276,12 +4276,11 @@ tree
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))
@@ -4289,24 +4288,6 @@ convert_for_arg_passing (type, val)
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
@@ -4477,12 +4458,12 @@ build_over_call (cand, args, flags)
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;
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index d89fb63..a7f2d85 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -122,9 +122,6 @@ static bool cp_var_mod_type_p PARAMS ((tree));
#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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0c8c37a..4c0efd2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -65,7 +65,6 @@ struct diagnostic_context;
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.
@@ -1687,10 +1686,6 @@ struct lang_type GTY(())
/* 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
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 848ef51..747cc1a 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -601,28 +601,12 @@ stabilize_throw_expr (exp, initp)
{
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);
}
diff --git a/gcc/integrate.c b/gcc/integrate.c
index 0e54e48..7752d66 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -344,12 +344,36 @@ copy_decl_for_inlining (decl, from_fn, to_fn)
/* 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
{
diff --git a/gcc/testsuite/g++.dg/init/elide2.C b/gcc/testsuite/g++.dg/init/elide2.C
new file mode 100644
index 0000000..e6d3300
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/elide2.C
@@ -0,0 +1,30 @@
+// 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;
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 6dea353..0f5ab59 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -632,6 +632,7 @@ initialize_inlined_parameters (id, args, fn, block)
#endif /* not INLINER_FOR_JAVA */
tree var;
tree value;
+ tree var_sub;
/* Find the initializer. */
value = (*lang_hooks.tree_inlining.convert_parm_for_inlining)
@@ -669,12 +670,23 @@ initialize_inlined_parameters (id, args, fn, block)
/* 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
diff --git a/gcc/tree.c b/gcc/tree.c
index c926b31..dfac289 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4118,6 +4118,9 @@ bool
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.