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.
This commit is contained in:
parent
86558afc09
commit
d4fd8638be
2 changed files with 66 additions and 82 deletions
|
@ -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
|
||||
|
|
|
@ -31,8 +31,7 @@
|
|||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <bits/stl_function.h>
|
||||
#include <functional> // for std::_Placeholder, std::_Bind, std::_Bind_result
|
||||
|
||||
#include <typeinfo>
|
||||
#include <new>
|
||||
|
@ -42,18 +41,49 @@
|
|||
#include <tr1/functional_hash.h>
|
||||
#include <ext/type_traits.h>
|
||||
#include <bits/move.h> // for std::__addressof
|
||||
#if __cplusplus >= 201103L
|
||||
# include <type_traits> // for integral_constant, true_type, false_type
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
#if __cplusplus >= 201103L
|
||||
template<int> struct _Placeholder;
|
||||
template<typename> class _Bind;
|
||||
template<typename, typename> class _Bind_result;
|
||||
#endif
|
||||
|
||||
#if __cplusplus < 201103L
|
||||
// In C++98 mode, <functional> doesn't declare std::placeholders::_1 etc.
|
||||
// because they are not reserved names in C++98. However, they are reserved
|
||||
// by <tr1/functional> so we can declare them here, in order to redeclare
|
||||
// them in the std::tr1::placeholders namespace below.
|
||||
namespace placeholders
|
||||
{
|
||||
extern const _Placeholder<1> _1;
|
||||
extern const _Placeholder<2> _2;
|
||||
extern const _Placeholder<3> _3;
|
||||
extern const _Placeholder<4> _4;
|
||||
extern const _Placeholder<5> _5;
|
||||
extern const _Placeholder<6> _6;
|
||||
extern const _Placeholder<7> _7;
|
||||
extern const _Placeholder<8> _8;
|
||||
extern const _Placeholder<9> _9;
|
||||
extern const _Placeholder<10> _10;
|
||||
extern const _Placeholder<11> _11;
|
||||
extern const _Placeholder<12> _12;
|
||||
extern const _Placeholder<13> _13;
|
||||
extern const _Placeholder<14> _14;
|
||||
extern const _Placeholder<15> _15;
|
||||
extern const _Placeholder<16> _16;
|
||||
extern const _Placeholder<17> _17;
|
||||
extern const _Placeholder<18> _18;
|
||||
extern const _Placeholder<19> _19;
|
||||
extern const _Placeholder<20> _20;
|
||||
extern const _Placeholder<21> _21;
|
||||
extern const _Placeholder<22> _22;
|
||||
extern const _Placeholder<23> _23;
|
||||
extern const _Placeholder<24> _24;
|
||||
extern const _Placeholder<25> _25;
|
||||
extern const _Placeholder<26> _26;
|
||||
extern const _Placeholder<27> _27;
|
||||
extern const _Placeholder<28> _28;
|
||||
extern const _Placeholder<29> _29;
|
||||
}
|
||||
#endif // C++98
|
||||
|
||||
namespace tr1
|
||||
{
|
||||
|
@ -850,49 +880,18 @@ namespace tr1
|
|||
const int is_placeholder<_Tp>::value;
|
||||
|
||||
/// The type of placeholder objects defined by libstdc++.
|
||||
template<int _Num> struct _Placeholder { };
|
||||
using ::std::_Placeholder;
|
||||
|
||||
/** @namespace std::tr1::placeholders
|
||||
* @brief Sub-namespace for tr1/functional.
|
||||
*/
|
||||
namespace placeholders
|
||||
{
|
||||
/* Define a large number of placeholders. There is no way to
|
||||
* simplify this with variadic templates, because we're introducing
|
||||
* unique names for each.
|
||||
*/
|
||||
namespace
|
||||
{
|
||||
_Placeholder<1> _1;
|
||||
_Placeholder<2> _2;
|
||||
_Placeholder<3> _3;
|
||||
_Placeholder<4> _4;
|
||||
_Placeholder<5> _5;
|
||||
_Placeholder<6> _6;
|
||||
_Placeholder<7> _7;
|
||||
_Placeholder<8> _8;
|
||||
_Placeholder<9> _9;
|
||||
_Placeholder<10> _10;
|
||||
_Placeholder<11> _11;
|
||||
_Placeholder<12> _12;
|
||||
_Placeholder<13> _13;
|
||||
_Placeholder<14> _14;
|
||||
_Placeholder<15> _15;
|
||||
_Placeholder<16> _16;
|
||||
_Placeholder<17> _17;
|
||||
_Placeholder<18> _18;
|
||||
_Placeholder<19> _19;
|
||||
_Placeholder<20> _20;
|
||||
_Placeholder<21> _21;
|
||||
_Placeholder<22> _22;
|
||||
_Placeholder<23> _23;
|
||||
_Placeholder<24> _24;
|
||||
_Placeholder<25> _25;
|
||||
_Placeholder<26> _26;
|
||||
_Placeholder<27> _27;
|
||||
_Placeholder<28> _28;
|
||||
_Placeholder<29> _29;
|
||||
}
|
||||
namespace placeholders
|
||||
{
|
||||
// The C++11 std::placeholders are already exported from the library.
|
||||
// Reusing them here avoids needing to export additional symbols for
|
||||
// the TR1 placeholders, and avoids ODR violations due to defining
|
||||
// them with internal linkage (as we used to do).
|
||||
using namespace ::std::placeholders;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -901,22 +900,13 @@ namespace tr1
|
|||
*/
|
||||
template<int _Num>
|
||||
struct is_placeholder<_Placeholder<_Num> >
|
||||
{ static const int value = _Num; };
|
||||
|
||||
template<int _Num>
|
||||
const int is_placeholder<_Placeholder<_Num> >::value;
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<int _Num>
|
||||
struct is_placeholder<std::_Placeholder<_Num>>
|
||||
: std::integral_constant<int, _Num>
|
||||
: integral_constant<int, _Num>
|
||||
{ };
|
||||
|
||||
template<int _Num>
|
||||
struct is_placeholder<const std::_Placeholder<_Num>>
|
||||
: std::integral_constant<int, _Num>
|
||||
struct is_placeholder<const _Placeholder<_Num> >
|
||||
: integral_constant<int, _Num>
|
||||
{ };
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Stores a tuple of indices. Used by bind() to extract the elements
|
||||
|
@ -1423,6 +1413,9 @@ namespace tr1
|
|||
_Signature> >::value;
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Specialize tr1::is_bind_expression for std::bind closure types,
|
||||
// so that they can also work with tr1::bind.
|
||||
|
||||
template<typename _Signature>
|
||||
struct is_bind_expression<std::_Bind<_Signature>>
|
||||
: true_type { };
|
||||
|
@ -2242,20 +2235,8 @@ namespace tr1
|
|||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
template<typename> struct is_placeholder;
|
||||
|
||||
template<int _Num>
|
||||
struct is_placeholder<tr1::_Placeholder<_Num>>
|
||||
: integral_constant<int, _Num>
|
||||
{ };
|
||||
|
||||
template<int _Num>
|
||||
struct is_placeholder<const tr1::_Placeholder<_Num>>
|
||||
: integral_constant<int, _Num>
|
||||
{ };
|
||||
|
||||
template<typename> struct is_bind_expression;
|
||||
// Specialize std::is_bind_expression for tr1::bind closure types,
|
||||
// so that they can also work with std::bind.
|
||||
|
||||
template<typename _Signature>
|
||||
struct is_bind_expression<tr1::_Bind<_Signature>>
|
||||
|
|
Loading…
Add table
Reference in a new issue