https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103984
--- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> --- What the C++ FE emits looks just weird to me. In the gimple dump: [pr103984.C:35:1] D.31524.name = string_piece::str ([pr103984.C:35:1] &arg); [return slot optimization] [pr103984.C:35:1] D.31544 = 1; [pr103984.C:29:27] try { [pr103984.C:31:15] string_piece::string_piece ([pr103984.C:31:15] &D.31523, [pr103984.C:31:16] &arg); try { [pr103984.C:31:15] _2 = to_stage ([pr103984.C:31:15] &D.31523); [pr103984.C:35:1] D.31524.stage = _2; [pr103984.C:35:1] D.31544 = 0; try { try { [pr103984.C:29:27] std::vector<Z>::emplace_back<Z> ([pr103984.C:29:27] &input_files, [pr103984.C:29:28] &D.31524); } finally { [pr103984.C:29:28] Z::~Z ([pr103984.C:29:28] &D.31524); } } finally { [pr103984.C:29:28] D.31524 = {CLOBBER(eol)}; } } finally { [pr103984.C:31:15] D.31523 = {CLOBBER(eol)}; } } catch { [pr103984.C:35:1] if (D.31544 != 0) goto <D.35853>; else goto <D.35854>; <D.35853>: [pr103984.C:35:1] std::__cxx11::basic_string<char>::~basic_string ([pr103984.C:35:1] &D.31524.name); goto <D.35855>; <D.35854>: <D.35855>: } Note the D.31524 CLOBBER being added only conditionally (if string_piece ctor doesn't throw), while if it throws, there is a dtor on its element after that and no CLOBBER. The first spot that initializes part of the D.31524 temporary is the above first line, so it would make more sense to me to wrap this whole sequence above into try { ... } finally { [pr103984.C:29:28] D.31524 = {CLOBBER(eol)}; } and remove the inner try finally that does that.