Line
Link Here
|
|
94e2418780f1d13235f3e2e6e5c09dbe821c1ce3 c++: Avoid unnecessary empty class copy [94175]. |
|
94e2418780f1d13235f3e2e6e5c09dbe821c1ce3 c++: Avoid unnecessary empty class copy [94175]. |
1 |
"GOT IT GUYS!!!! Doing a handstand and singing the Italian national anthem |
1 |
"GOT IT GUYS!!!! Doing a handstand and singing the Italian national anthem |
2 |
during the compile fixes it." |
2 |
during the compile fixes it." |
3 |
-- not a real example, |
3 |
-- not a real example, |
4 |
gmt |
4 |
++ b/gcc/cp/call.cc |
5 |
-- a/gcc/cp/call.cc |
|
|
Lines 398-407
Link Here
|
398 |
if (is_empty_class (TREE_TYPE (arg)) |
398 |
if (is_empty_class (TREE_TYPE (arg)) |
399 |
&& simple_empty_class_p (TREE_TYPE (arg), arg, INIT_EXPR)) |
399 |
&& simple_empty_class_p (TREE_TYPE (arg), arg, INIT_EXPR)) |
400 |
{ |
400 |
{ |
401 |
while (TREE_CODE (arg) == TARGET_EXPR) |
|
|
402 |
/* We're disconnecting the initializer from its target, |
403 |
don't create a temporary. */ |
404 |
arg = TARGET_EXPR_INITIAL (arg); |
405 |
tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg)); |
401 |
tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg)); |
406 |
arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t); |
402 |
arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t); |
407 |
CALL_EXPR_ARG (function, i) = arg; |
403 |
CALL_EXPR_ARG (function, i) = arg; |
408 |
-- a/gcc/cp/cp-gimplify.cc |
404 |
++ b/gcc/cp/cp-gimplify.cc |
Lines 339-348
Link Here
|
339 |
{ |
339 |
{ |
340 |
if (TREE_CODE (op) == COMPOUND_EXPR) |
340 |
if (TREE_CODE (op) == COMPOUND_EXPR) |
341 |
return simple_empty_class_p (type, TREE_OPERAND (op, 1), code); |
341 |
return simple_empty_class_p (type, TREE_OPERAND (op, 1), code); |
342 |
if (SIMPLE_TARGET_EXPR_P (op) |
|
|
343 |
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) |
344 |
/* The TARGET_EXPR is itself a simple copy, look through it. */ |
345 |
return simple_empty_class_p (type, TARGET_EXPR_INITIAL (op), code); |
346 |
|
342 |
|
347 |
if (TREE_CODE (op) == PARM_DECL |
343 |
if (TREE_CODE (op) == PARM_DECL |
348 |
&& TREE_ADDRESSABLE (TREE_TYPE (op))) |
344 |
&& TREE_ADDRESSABLE (TREE_TYPE (op))) |
Lines 526-536
Link Here
|
526 |
|
522 |
|
527 |
else if (simple_empty_class_p (TREE_TYPE (op0), op1, code)) |
523 |
else if (simple_empty_class_p (TREE_TYPE (op0), op1, code)) |
528 |
{ |
524 |
{ |
529 |
while (TREE_CODE (op1) == TARGET_EXPR) |
|
|
530 |
/* We're disconnecting the initializer from its target, |
531 |
don't create a temporary. */ |
532 |
op1 = TARGET_EXPR_INITIAL (op1); |
533 |
|
534 |
/* Remove any copies of empty classes. Also drop volatile |
525 |
/* Remove any copies of empty classes. Also drop volatile |
535 |
variables on the RHS to avoid infinite recursion from |
526 |
variables on the RHS to avoid infinite recursion from |
536 |
gimplify_expr trying to load the value. */ |
527 |
gimplify_expr trying to load the value. */ |
Lines 545-553
Link Here
|
545 |
gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, |
536 |
gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, |
546 |
is_gimple_lvalue, fb_lvalue); |
537 |
is_gimple_lvalue, fb_lvalue); |
547 |
*expr_p = TREE_OPERAND (*expr_p, 0); |
538 |
*expr_p = TREE_OPERAND (*expr_p, 0); |
548 |
if (code == RETURN_EXPR && REFERENCE_CLASS_P (*expr_p)) |
|
|
549 |
/* Avoid 'return *<retval>;' */ |
550 |
*expr_p = TREE_OPERAND (*expr_p, 0); |
551 |
} |
539 |
} |
552 |
/* P0145 says that the RHS is sequenced before the LHS. |
540 |
/* P0145 says that the RHS is sequenced before the LHS. |
553 |
gimplify_modify_expr gimplifies the RHS before the LHS, but that |
541 |
gimplify_modify_expr gimplifies the RHS before the LHS, but that |
Lines 762-767
Link Here
|
762 |
|| TREE_CODE (TREE_OPERAND (*expr_p, 0)) == MODIFY_EXPR)) |
750 |
|| TREE_CODE (TREE_OPERAND (*expr_p, 0)) == MODIFY_EXPR)) |
763 |
{ |
751 |
{ |
764 |
expr_p = &TREE_OPERAND (*expr_p, 0); |
752 |
expr_p = &TREE_OPERAND (*expr_p, 0); |
|
|
753 |
code = TREE_CODE (*expr_p); |
765 |
/* Avoid going through the INIT_EXPR case, which can |
754 |
/* Avoid going through the INIT_EXPR case, which can |
766 |
degrade INIT_EXPRs into AGGR_INIT_EXPRs. */ |
755 |
degrade INIT_EXPRs into AGGR_INIT_EXPRs. */ |
767 |
goto modify_expr_case; |
756 |
goto modify_expr_case; |
768 |
-- a/gcc/cp/cp-tree.h |
757 |
++ b/gcc/cp/cp-tree.h |
Lines 5384-5390
Link Here
|
5384 |
the initializer has void type, it's doing something more complicated. */ |
5384 |
the initializer has void type, it's doing something more complicated. */ |
5385 |
#define SIMPLE_TARGET_EXPR_P(NODE) \ |
5385 |
#define SIMPLE_TARGET_EXPR_P(NODE) \ |
5386 |
(TREE_CODE (NODE) == TARGET_EXPR \ |
5386 |
(TREE_CODE (NODE) == TARGET_EXPR \ |
5387 |
&& TARGET_EXPR_INITIAL (NODE) \ |
|
|
5388 |
&& !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (NODE)))) |
5387 |
&& !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (NODE)))) |
5389 |
|
5388 |
|
5390 |
/* True if T is a TARGET_EXPR for which we'll need to replace_decl to use it as |
5389 |
/* True if T is a TARGET_EXPR for which we'll need to replace_decl to use it as |
5391 |
-- a/gcc/testsuite/g++.dg/abi/empty30.C |
5390 |
++ b/gcc/testsuite/g++.dg/abi/empty30.C |
Lines 1-14
Link Here
|
1 |
// PR c++/94175 |
|
|
2 |
// { dg-do link } |
3 |
|
4 |
struct A {}; |
5 |
extern A a; |
6 |
|
7 |
int i; |
8 |
__attribute ((noinline, noclone)) |
9 |
void f(A) { ++i; } |
10 |
|
11 |
int main() |
12 |
{ |
13 |
f(a); |
14 |
} |