We could go further and remove the ABI difference in regex_compiler when using _GLIBCXX_DEBUG, as in the attached patch.
The trick is that for the char specialization we have padding bytes between _M_is_non_matching (a bool) and _M_cache (a std::bitset), so we can reuse one of those padding bytes for the _M_is_ready flag. For the non-char specializations the _Dummy struct takes up one byte, so we could reuse that for the _M_is_ready flag. To be safe we should probably check that alignof(std::bitset<8> > 2) so we know there really is a padding byte that can be re-used, and place the _M_is_ready flag afterwards if there is no padding.
diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h index 07a9ed3..9616d4e 100644 --- a/libstdc++-v3/include/bits/regex_compiler.h +++ b/libstdc++-v3/include/bits/regex_compiler.h @@ -369,13 +369,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _BracketMatcher(bool __is_non_matching, const _TraitsT& __traits) : _M_class_set(0), _M_translator(__traits), _M_traits(__traits), - _M_is_non_matching(__is_non_matching) + _M_extra_members(__is_non_matching) { } bool operator()(_CharT __ch) const { - _GLIBCXX_DEBUG_ASSERT(_M_is_ready); + _GLIBCXX_DEBUG_ASSERT(_M_extra._M_is_ready); return _M_apply(__ch, _UseCache()); } @@ -383,7 +383,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_add_char(_CharT __c) { _M_char_set.push_back(_M_translator._M_translate(__c)); - _GLIBCXX_DEBUG_ONLY(_M_is_ready = false); + _GLIBCXX_DEBUG_ONLY(_M_extra._M_is_ready = false); } _StringT @@ -394,7 +394,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__st.empty()) __throw_regex_error(regex_constants::error_collate); _M_char_set.push_back(_M_translator._M_translate(__st[0])); - _GLIBCXX_DEBUG_ONLY(_M_is_ready = false); + _GLIBCXX_DEBUG_ONLY(_M_extra._M_is_ready = false); return __st; } @@ -408,7 +408,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __st = _M_traits.transform_primary(__st.data(), __st.data() + __st.size()); _M_equiv_set.push_back(__st); - _GLIBCXX_DEBUG_ONLY(_M_is_ready = false); + _GLIBCXX_DEBUG_ONLY(_M_extra._M_is_ready = false); } // __neg should be true for \D, \S and \W only. @@ -424,7 +424,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_class_set |= __mask; else _M_neg_class_set.push_back(__mask); - _GLIBCXX_DEBUG_ONLY(_M_is_ready = false); + _GLIBCXX_DEBUG_ONLY(_M_extra._M_is_ready = false); } void @@ -434,7 +434,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __throw_regex_error(regex_constants::error_range); _M_range_set.push_back(make_pair(_M_translator._M_transform(__l), _M_translator._M_transform(__r))); - _GLIBCXX_DEBUG_ONLY(_M_is_ready = false); + _GLIBCXX_DEBUG_ONLY(_M_extra._M_is_ready = false); } void @@ -444,7 +444,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto __end = std::unique(_M_char_set.begin(), _M_char_set.end()); _M_char_set.erase(__end, _M_char_set.end()); _M_make_cache(_UseCache()); - _GLIBCXX_DEBUG_ONLY(_M_is_ready = true); + _GLIBCXX_DEBUG_ONLY(_M_extra._M_is_ready = true); } private: @@ -457,10 +457,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return 1ul << (sizeof(_CharT) * __CHAR_BIT__ * int(_UseCache::value)); } - struct _Dummy { }; - typedef typename std::conditional<_UseCache::value, - std::bitset<_S_cache_size()>, - _Dummy>::type _CacheT; + struct _Flags + { + bool _M_is_non_matching; + bool _M_is_ready; + }; + + struct _Empty { }; + + struct _ExtraMembers + : _Flags, + conditional<_UseCache::value, bitset<_S_cache_size()>, _Empty>::type + { + explicit + _ExtraMembers(bool __is_non_matching) + : _Flags{__is_non_matching, false} + { } + }; + typedef typename std::make_unsigned<_CharT>::type _UnsignedCharT; bool @@ -468,13 +482,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool _M_apply(_CharT __ch, true_type) const - { return _M_cache[static_cast<_UnsignedCharT>(__ch)]; } + { return _M_extra._M_cache[static_cast<_UnsignedCharT>(__ch)]; } void _M_make_cache(true_type) { - for (unsigned __i = 0; __i < _M_cache.size(); __i++) - _M_cache[__i] = _M_apply(static_cast<_CharT>(__i), false_type()); + auto& __cache = _M_extra._M_cache; + for (unsigned __i = 0; __i < __cache.size(); __i++) + __cache[__i] = _M_apply(static_cast<_CharT>(__i), false_type()); } void @@ -489,11 +504,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _CharClassT _M_class_set; _TransT _M_translator; const _TraitsT& _M_traits; - bool _M_is_non_matching; - _CacheT _M_cache; -#ifdef _GLIBCXX_DEBUG - bool _M_is_ready = false; -#endif + _ExtraMembers _M_extra; }; //@} regex-detail