https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118856
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Comparing the gimple dumps before/after r15-7481 and latest trunk, before that change I see it first constructs one allocator, then the inner vector, then another allocator, then another vector, everything with try ... finally so that stuff is destructed if the ctors throw or when section is left. But with latest trunk I see D.56403[0] = "aaa"; D.57007 = 0; D.56400 = {}; D.56400._M_len = 1; D.57002 = &D.56401; D.57003 = D.57002; _1 = &D.56403 + 8; std::vector<std::__cxx11::basic_string<char> >::vector<const char* const*> (&D.56402, &D.56403, _1, &D.56404); *D.57003 = D.56402; D.57003 = D.57003 + 24; D.57007 = D.57007 + -1; retval.0 = D.57002; D.57007 = 0; D.56400._M_array = &D.56401; std::vector<std::vector<std::__cxx11::basic_string<char> > >::vector (&D.56399, D.56400, &D.57008); __for_range = &D.56399; all in one STATEMENT_LIST, the two allocators (D.56404 and D.57008 are never constructed and have dtors in try / finally only later on, and even if those would be constructed, if e.g. the second vector ctor throws, nothing will destruct the first vector.