commit cc11073f74626fa0f33b8e1a67a72b3c37ef284d Author: Jason Merrill Date: Sat Mar 2 01:07:41 2019 -0500 PR c++/86485 - -Wmaybe-unused with empty class ?: * cp-gimplify.c (simple_empty_class_p): Also true for MODIFY_EXPR. diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 12c576ca3fd..2d892ca1264 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -571,19 +571,20 @@ gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p) return slot optimization alone because it isn't a copy. */ static bool -simple_empty_class_p (tree type, tree op) +simple_empty_class_p (tree type, tree op, tree_code code) { return ((TREE_CODE (op) == COMPOUND_EXPR - && simple_empty_class_p (type, TREE_OPERAND (op, 1))) + && simple_empty_class_p (type, TREE_OPERAND (op, 1), code)) || TREE_CODE (op) == EMPTY_CLASS_EXPR + || code == MODIFY_EXPR || is_gimple_lvalue (op) || INDIRECT_REF_P (op) || (TREE_CODE (op) == CONSTRUCTOR - && CONSTRUCTOR_NELTS (op) == 0 - && !TREE_CLOBBER_P (op)) + && CONSTRUCTOR_NELTS (op) == 0) || (TREE_CODE (op) == CALL_EXPR && !CALL_EXPR_RETURN_SLOT_OPT (op))) + && !TREE_CLOBBER_P (op) && is_really_empty_class (type, /*ignore_vptr*/true); } @@ -692,7 +693,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op0), op1); - else if (simple_empty_class_p (TREE_TYPE (op0), op1)) + else if (simple_empty_class_p (TREE_TYPE (op0), op1, code)) { /* Remove any copies of empty classes. Also drop volatile variables on the RHS to avoid infinite recursion from commit c84e0e7af74e018aab19e4d0ea5e9f2653934442 Author: Jason Merrill Date: Mon Mar 4 17:33:59 2019 -0500 PR c++/20408 - unnecessary code for empty struct. * call.c (build_call_a): Use simple_empty_class_p. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d5b0560a897..57109f5df33 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7589,6 +7589,7 @@ extern tree cp_fully_fold_init (tree); extern void clear_fold_cache (void); extern tree lookup_hotness_attribute (tree); extern tree process_stmt_hotness_attribute (tree, location_t); +extern bool simple_empty_class_p (tree, tree, tree_code); /* in name-lookup.c */ extern tree strip_using_decl (tree); diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 16676664760..1bd199c53b7 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -394,7 +394,7 @@ build_call_a (tree function, int n, tree *argarray) { tree arg = CALL_EXPR_ARG (function, i); if (is_empty_class (TREE_TYPE (arg)) - && ! TREE_ADDRESSABLE (TREE_TYPE (arg))) + && simple_empty_class_p (TREE_TYPE (arg), arg, INIT_EXPR)) { tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg)); arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t); diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 2d892ca1264..8eecbf3fb19 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -570,7 +570,7 @@ gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p) non-empty CONSTRUCTORs get reduced properly, and we leave the return slot optimization alone because it isn't a copy. */ -static bool +bool simple_empty_class_p (tree type, tree op, tree_code code) { return diff --git a/gcc/testsuite/g++.dg/tree-ssa/empty-3.C b/gcc/testsuite/g++.dg/tree-ssa/empty-3.C new file mode 100644 index 00000000000..f340bd4070b --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/empty-3.C @@ -0,0 +1,16 @@ +// PR c++/20408 +// { dg-additional-options -fdump-tree-gimple } +// { dg-final { scan-tree-dump-times "struct Foo" 2 "gimple" } } + +struct Foo {}; +void foo(const Foo&); +void bar(Foo); + +void fooc(void) +{ + foo(Foo()); +} +void barc(void) +{ + bar(Foo()); +}