diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2020-10-27 16:32:53 +0000 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-10-27 16:32:53 +0000 |
commit | d4fd8638be8a6f105bfaf1c0e3bcfad36aca03be (patch) | |
tree | ab33757b7854e5f9f5c2e6c804c626bb29bb9e2c /libstdc++-v3/include/std/functional | |
parent | 86558afc09e65b172377d4e759b00094dd985e8a (diff) | |
download | gcc-d4fd8638be8a6f105bfaf1c0e3bcfad36aca03be.tar.gz |
libstdc++: Fix ODR violations caused by <tr1/functional>
The placeholders for std::tr1::bind are defined in an anonymous
namespace, which means they have internal linkage. This will cause ODR
violations when used in function templates (such as std::tr1::bind) from
multiple translation units. Although probably harmless (every definition
will generate identical code, even if technically ill-formed) we can
avoid the ODR violations by reusing the std::placeholder objects as the
std::tr1::placeholder objects.
To make this work, the std::_Placeholder type needs to be defined for
C++98 mode, so that <tr1/functional> can use it. The members of the
std::placeholder namespace must not be defined by <functional> in C++98
mode, because "placeholders", "_1", "_2" etc. are not reserved names in
C++98. Instead they can be declared in <tr1/functional>, because those
names *are* reserved in that header. With the std::placeholders objects
declared, a simple using-directive suffices to redeclare them in
namespace std::tr1::placeholders. This means any use of the TR1
placeholders actually refers to the C++11 placeholders, which are
defined with external linkage and exported from the library, so don't
cause ODR violations.
libstdc++-v3/ChangeLog:
* include/std/functional (std::_Placeholder): Define for C++98
as well as later standards.
* include/tr1/functional (std::placeholders::_1 etc): Declare
for C++98.
(tr1::_Placeholder): Replace with using-declaration for
std::_Placeholder.
(tr1::placeholders::_1 etc.): Replace with using-directive for
std::placeholders.
Diffstat (limited to 'libstdc++-v3/include/std/functional')
-rw-r--r-- | libstdc++-v3/include/std/functional | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 9bad692f2ad..4e2d053f778 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -69,10 +69,19 @@ # include <compare> #endif +#endif // C++11 + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + /** @brief The type of placeholder objects defined by libstdc++. + * @ingroup binders + */ + template<int _Num> struct _Placeholder { }; + +#if __cplusplus >= 201103L + #if __cplusplus >= 201703L # define __cpp_lib_invoke 201411L # if __cplusplus > 201703L @@ -203,11 +212,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = is_placeholder<_Tp>::value; #endif // C++17 - /** @brief The type of placeholder objects defined by libstdc++. - * @ingroup binders - */ - template<int _Num> struct _Placeholder { }; - /** @namespace std::placeholders * @brief ISO C++ 2011 namespace for std::bind placeholders. * @ingroup binders @@ -1271,10 +1275,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // C++17 #endif // C++14 +#endif // C++11 _GLIBCXX_END_NAMESPACE_VERSION } // namespace std -#endif // C++11 - #endif // _GLIBCXX_FUNCTIONAL |