As mentioned in http://gcc.gnu.org/wiki/Cxx11AbiCompatibility, C++11
changes the return type of complex::real and imag, leading to a binary
incompatibility between C++98 and C++11 code if the functions are used
without inlining. This patch adds an ABI tag to the C++11 variants so
that they have different mangled names. This does not change the
exports from libstdc++.
For the map void->iterator change, I think it would make sense to just
unconditionally return an iterator; there's no binary compatibility
issue with older code that expects it to return void, the problem is
only with C++11 code calling a C++98 instantiation that returns void.
For the other cases mentioned on that page, I think either we want to
unify the two implementations (because we think they're compatible) or
add ABI tags to the C++11 implementations.
Is this patch OK for trunk? Does someone on the library team want to
look at the other cases?
commit be79353c10252bc99cac5f9d9ce045207e665238
Author: Jason Merrill <ja...@redhat.com>
Date: Sat Nov 10 13:10:15 2012 -0500
* include/std/complex (real, imag): Add ABI tag in C++11 mode.
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index f9221a8..24fa414 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -141,9 +141,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 387. std::complex over-encapsulated.
+ __attribute ((abi_tag ("cxx11")))
constexpr _Tp
real() { return _M_real; }
+ __attribute ((abi_tag ("cxx11")))
constexpr _Tp
imag() { return _M_imag; }
#else
@@ -1061,9 +1063,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 387. std::complex over-encapsulated.
+ __attribute ((abi_tag ("cxx11")))
constexpr float
real() { return __real__ _M_value; }
+ __attribute ((abi_tag ("cxx11")))
constexpr float
imag() { return __imag__ _M_value; }
#else
@@ -1210,9 +1214,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 387. std::complex over-encapsulated.
+ __attribute ((abi_tag ("cxx11")))
constexpr double
real() { return __real__ _M_value; }
+ __attribute ((abi_tag ("cxx11")))
constexpr double
imag() { return __imag__ _M_value; }
#else
@@ -1360,9 +1366,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 387. std::complex over-encapsulated.
+ __attribute ((abi_tag ("cxx11")))
constexpr long double
real() { return __real__ _M_value; }
+ __attribute ((abi_tag ("cxx11")))
constexpr long double
imag() { return __imag__ _M_value; }
#else
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc b/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc
new file mode 100644
index 0000000..a845466
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/complex/abi_tag.cc
@@ -0,0 +1,25 @@
+// Test that the C++11 variants of real/imag have an ABI tag
+// { dg-do compile }
+// { dg-options -std=c++11 }
+
+#include <complex>
+
+// { dg-final { scan-assembler "_ZNKSt7complexIfE4realB5cxx11Ev" } }
+float (std::complex<float>::*p1)() const = &std::complex<float>::real;
+// { dg-final { scan-assembler "_ZNKSt7complexIdE4realB5cxx11Ev" } }
+double (std::complex<double>::*p2)() const = &std::complex<double>::real;
+// { dg-final { scan-assembler "_ZNKSt7complexIeE4realB5cxx11Ev" } }
+long double (std::complex<long double>::*p3)() const
+ = &std::complex<long double>::real;
+// { dg-final { scan-assembler "_ZNKSt7complexIiE4realB5cxx11Ev" } }
+int (std::complex<int>::*p4)() const = &std::complex<int>::real;
+
+// { dg-final { scan-assembler "_ZNKSt7complexIfE4imagB5cxx11Ev" } }
+float (std::complex<float>::*p5)() const = &std::complex<float>::imag;
+// { dg-final { scan-assembler "_ZNKSt7complexIdE4imagB5cxx11Ev" } }
+double (std::complex<double>::*p6)() const = &std::complex<double>::imag;
+// { dg-final { scan-assembler "_ZNKSt7complexIeE4imagB5cxx11Ev" } }
+long double (std::complex<long double>::*p7)() const
+ = &std::complex<long double>::imag;
+// { dg-final { scan-assembler "_ZNKSt7complexIiE4imagB5cxx11Ev" } }
+int (std::complex<int>::*p8)() const = &std::complex<int>::imag;