https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80331
--- Comment #14 from Jan Hubicka <hubicka at gcc dot gnu.org> --- Declaring _S_create and _M_create inline indeed helps a little: diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 17b973c8b45..d73a61abe5b 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -278,7 +278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } // Create & Destroy - _GLIBCXX20_CONSTEXPR + _GLIBCXX20_CONSTEXPR inline pointer _M_create(size_type&, size_type); diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index 087ddf81dd8..0bd75f0fcb1 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -259,7 +259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Create & Destroy - static _Rep* + static inline _Rep* _S_create(size_type, size_type, const _Alloc&); void Now I get: int sain () { struct allocator_type D.27707; char * _45; _Atomic_word * _49; char __libc_single_threaded.12_50; unsigned int _53; int _54; <bb 2> [local count: 1073741824]: _45 = operator new (26); MEM[(struct _Rep *)_45].D.24285._M_capacity = 1; MEM[(struct _Rep *)_45].D.24285._M_refcount = 0; MEM[(char_type &)_45 + 24] = 97; if (_45 != &_S_empty_rep_storage) goto <bb 4>; [10.00%] else goto <bb 3>; [90.00%] <bb 3> [local count: 999008065]: goto <bb 8>; [100.00%] <bb 4> [local count: 107374184]: MEM[(struct _Rep *)_45].D.24285._M_length = 1; MEM[(char_type &)_45 + 25] = 0; __libc_single_threaded.12_50 = __libc_single_threaded; if (__libc_single_threaded.12_50 != 0) goto <bb 5>; [67.00%] else goto <bb 6>; [33.00%] <bb 5> [local count: 71940704]: MEM[(_Atomic_word *)_45 + 16B] = -1; goto <bb 7>; [100.00%] <bb 6> [local count: 35433481]: _49 = &MEM[(struct _Rep *)_45].D.24285._M_refcount; _53 = __atomic_fetch_add_4 (_49, 4294967295, 4); _54 = (int) _53; if (_54 <= 0) goto <bb 7>; [7.88%] else goto <bb 3>; [92.12%] <bb 7> [local count: 27380417]: std::basic_string<char>::_Rep::_M_destroy (_45, &D.27707); <bb 8> [local count: 1073741824]: D.27707 ={v} {CLOBBER(eos)}; return 0; } New memory is kept alive by: _45 = operator new (26); ... if (_45 != &_S_empty_rep_storage) goto <bb 4>; [10.00%] else goto <bb 3>; [90.00%] I think we ought to be able to deduce from malloc attribute that _45 is different from address of a decl.