We need to mask off tf_cleanup when we're dealing with argument conversions; it should only apply to the top level call.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 833d39a7919caa021848861e2035c8a1ac3e3b51 Author: Jason Merrill <ja...@redhat.com> Date: Wed Feb 22 16:55:24 2017 -0800 PR c++/79679 - missing destructor for argument * call.c (build_over_call): Don't pass tf_no_cleanup to argument conversions. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 93fae0d..f7924f0 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7838,12 +7838,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) if (flags & LOOKUP_NO_CONVERSION) conv->user_conv_p = true; + tsubst_flags_t arg_complain = complain & (~tf_no_cleanup); + if (!conversion_warning) + arg_complain &= ~tf_warning; + val = convert_like_with_context (conv, arg, fn, i - is_method, - conversion_warning - ? complain - : complain & (~tf_warning)); - - val = convert_for_arg_passing (type, val, complain); + arg_complain); + val = convert_for_arg_passing (type, val, arg_complain); if (val == error_mark_node) return error_mark_node; diff --git a/gcc/testsuite/g++.dg/init/cleanup4.C b/gcc/testsuite/g++.dg/init/cleanup4.C new file mode 100644 index 0000000..b9769e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/cleanup4.C @@ -0,0 +1,22 @@ +// PR c++/79679 +// { dg-do run } + +int count; +struct S { + S() { ++count; } + S(const S&) { ++count; } + ~S() { --count; } +}; + +struct T { + T(S) {} +}; + +int main() { + { + S s; + T u(s); + } + if (count) + __builtin_abort(); +}