summaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/std/functional
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2020-10-27 16:32:53 +0000
committerJonathan Wakely <jwakely@redhat.com>2020-10-27 16:32:53 +0000
commitd4fd8638be8a6f105bfaf1c0e3bcfad36aca03be (patch)
treeab33757b7854e5f9f5c2e6c804c626bb29bb9e2c /libstdc++-v3/include/std/functional
parent86558afc09e65b172377d4e759b00094dd985e8a (diff)
downloadgcc-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/functional17
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