I've posted this to http://gcc.gnu.org/wiki/Cxx11AbiCompatibility. I
would greatly appreciate any corrections or improvements.

On Tue, May 22, 2012 at 9:04 AM, Jeffrey Yasskin <jyass...@googlers.com> wrote:
> I've put together the following description of C++98/11 ABI
> (in)compatibility, so people can tell which libraries need to be
> recompiled. This is useful when you've bought a library that didn't
> come with source code, and you're trying to figure out if you need to
> buy a new version. I think this belongs on the Wiki somewhere, but I
> wanted to run it by the list first to make sure it's accurate. You can
> probably skip the first section, since it's just a description of how
> to use the subsequent list.
>
>
>
> This page explains how to identify when your pre-compiled library (.a
> or .so) defines a symbol that has a different enough definition in
> C++98 vs C++11 that it could cause runtime problems if it's linked
> into a program compiled for the other version.
>
> First, get a list of demangled symbols from your .a or .so:
>
> $ (find . -name '*.a'|xargs nm -f posix; find . -name '*.so' | xargs
> nm -f posix -D)|cut -f1 -d' '|LANG=C sort -u|c++filt|sort
>
> (There may be better ways to get this list.)
>
> Next, find instances in this list of the ABI changes listed below.
> For example, you might find:
>
>  std::_List_base<FooBar, std::allocator<FooBar> >::_M_clear()
>
> Since std::_List_base::_M_clear() destroys nodes, it's affected by the
> addition of the _M_size field and can't be used by C++11 code if it
> was compiled for C++98, or vice versa.  If it's possible that code
> outside the library would use this instance of _List_base, then you
> have to recompile the library. On the other hand, if FooBar is a type
> used only inside this library, then code using the library is safe.
> If FooBar is defined by the library but exposed in one of the
> library's headers, then the library still needs to be recompiled,
> since code using it could wind up including the other version's
> implementation.
>
>
> === ABI Changes ===
>
> complex::{real,imag}(), std::{real,imag}(complex)
>
> The non-const overloads go from returning _Tp& to _Tp.
> [Since gcc-4.4]
>
>
> std::list, std::_List_impl, and std::_List_base
>
> New _M_size member, meaning any method that adds or removes nodes or
> inspects the size has a new ABI.
> [Since gcc-4.7]
>
>
> std::operator-(reverse_iterator) and std::operator-(__normal_iterator)
> may return a different type if
> reverse_iterator<_IteratorL>::difference_type (respectively,
> __normal_iterator<_IteratorL, _Container>::difference_type) isn't
> accurate.
> [Since gcc-4.4]
>
>
> map::erase(iterator), multimap::erase(iterator),
> set::erase(const_iterator), set::erase(const_iterator,
> const_iterator), multiset::erase(const_iterator),
> multiset::erase(const_iterator, const_iterator):
>
> Return type changes from void to iterator.
> [Since gcc-4.5]
>
>
> _Rb_tree<T, T>::erase(const_iterator), _Rb_tree<T,
> T>::erase(const_iterator, const_iterator), _Rb_tree<T,
> pair>::erase(iterator):
>
> Return type changes from void to iterator. these are instantiated from
> map and set.
> [Since gcc-4.5]
>
>
> vector::data()'s return type changes from pointer to _Tp*
>
> This is a no-op with most allocators, but any allocator that defines a
> non-default pointer typedef will be incompatible.
> [Since gcc-4.6]
>
>
>
> Probably safe: istreambuf_iterator::reference changes from _CharT& to _CharT.
>
> This could affect return types if they mention 'reference', but they
> appear not to mention it when istreambuf_iterator is involved.
> [Since gcc-4.7]
>
>
> Probably safe: map::erase(iterator, iterator),
> multimap::erase(iterator, iterator)
>
> C++11 uses const_iterator, which doesn't collide.  Other versions of
> gcc are unlikely to have defined this overload in C++98 mode, and
> C++11 is unlikely to have defined the iterator version.
>
> [Since gcc-4.5]
>
>
> Probably safe: Types with node allocators, like deque and tree
>
> C++11 uses _M_get_Node_allocator().construct(node, ...), while C++98
> uses get_allocator().construct(node->_M_value_field, ...).  The node's
> constructor forwards to the value_field's constructor, so this works
> by default.  Can this cause problems with some mix of C++98/C++11
> allocator compilations?
>
>
>
>
> I haven't analyzed the debug and profile headers.
>
>
>
>
> I found these differences by grepping for GXX_EXPERIMENTAL_CXX0X
> inside libstdc++, and examining each instance to see if there was an
> #else clause that had different behavior in C++11 vs C++98.
>
>
> === ABI non-changes ===
>
> libstdc++'s binary component is nearly ABI-compatible between C++98
> and C++11.  Most incompatibilities are in the templates defined in
> headers, but the complex<> stream operators call the real() and imag()
> methods that change return type.  If these calls aren't inlined, (and
> they're likely to be inlined), then libstdc++ (which is compiled in
> C++98 mode by default) could cause problems when linked into C++11
> programs.  (http://gcc.gnu.org/PR53429)
>
> There have been some claims that the change in the definition of POD
> types causes an ABI incompatibility, but apparently it doesn't in
> practice: http://gcc.gnu.org/ml/gcc/2012-01/msg00056.html.

Reply via email to