summaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>1999-01-19 11:55:37 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>1999-01-19 11:55:37 +0000
commit417defa436653a97504ee91a2faf383b434a2330 (patch)
treee91ca19634322bc4574280c639a5bc44de7f104c /gcc/calls.c
parent6e087f880769019062d3f0cd0fad990c04a45588 (diff)
downloadgcc-417defa436653a97504ee91a2faf383b434a2330.tar.gz
* calls.c (expand_call): Strip a TARGET_EXPR if we're passing by
invisible reference. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@24763 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index 751e9a5b8a0..8ce140aeebc 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1345,6 +1345,22 @@ expand_call (exp, target, ignore)
#endif
)
{
+ /* C++ uses a TARGET_EXPR to indicate that we want to make a
+ new object from the argument. If we are passing by
+ invisible reference, the callee will do that for us, so we
+ can strip off the TARGET_EXPR. This is not always safe,
+ but it is safe in the only case where this is a useful
+ optimization; namely, when the argument is a plain object.
+ In that case, the frontend is just asking the backend to
+ make a bitwise copy of the argument. */
+
+ if (TREE_CODE (args[i].tree_value) == TARGET_EXPR
+ && (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND
+ (args[i].tree_value, 1)))
+ == 'd')
+ && ! REG_P (DECL_RTL (TREE_OPERAND (args[i].tree_value, 1))))
+ args[i].tree_value = TREE_OPERAND (args[i].tree_value, 1);
+
args[i].tree_value = build1 (ADDR_EXPR,
build_pointer_type (type),
args[i].tree_value);