From: Jonathan Wakely <jwakely@redhat.com>
To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: [committed 1/2] libstdc++: Fix multiple definitions of std::exception_ptr functions [PR 97729]
Date: Thu, 5 Nov 2020 18:03:11 +0000 [thread overview]
Message-ID: <20201105180311.GH503596@redhat.com> (raw)
In-Reply-To: <20201105180152.GA3511218@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1083 bytes --]
This fixes some multiple definition errors caused by the changes for
PR libstdc++/90295. The previous solution for inlining the members of
std::exception_ptr but still exporting them from the library was to
suppress the 'inline' keyword on those functions when compiling
libsupc++/eh_ptr.cc, so they get defined in that file. That produces ODR
violations though, because there are now both inline and non-inline
definitions in the library, due to the use of std::exception_ptr in
other files sucg as src/c++11/future.cc.
The new solution is to define all the relevant members as 'inline'
unconditionally, but use __attribute__((used)) to cause definitions to
be emitted in libsupc++/eh_ptr.cc as before. This doesn't quite work
however, because PR c++/67453 means the attribute is ignored on
constructors and destructors. As a workaround, the old solution
(conditionally inline) is still used for those members, but they are
given the always_inline attribute so that they aren't emitted in
src/c++11/future.o as inline definitions.
Tested powerpc64le-linux. Committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 7677 bytes --]
commit 710508c7b1a2c8e1d75d4c4f1ac79473dbf2b2bb
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Thu Nov 5 16:19:15 2020
libstdc++: Fix multiple definitions of std::exception_ptr functions [PR 97729]
This fixes some multiple definition errors caused by the changes for
PR libstdc++/90295. The previous solution for inlining the members of
std::exception_ptr but still exporting them from the library was to
suppress the 'inline' keyword on those functions when compiling
libsupc++/eh_ptr.cc, so they get defined in that file. That produces ODR
violations though, because there are now both inline and non-inline
definitions in the library, due to the use of std::exception_ptr in
other files sucg as src/c++11/future.cc.
The new solution is to define all the relevant members as 'inline'
unconditionally, but use __attribute__((used)) to cause definitions to
be emitted in libsupc++/eh_ptr.cc as before. This doesn't quite work
however, because PR c++/67453 means the attribute is ignored on
constructors and destructors. As a workaround, the old solution
(conditionally inline) is still used for those members, but they are
given the always_inline attribute so that they aren't emitted in
src/c++11/future.o as inline definitions.
libstdc++-v3/ChangeLog:
PR libstdc++/97729
* include/std/future (__basic_future::_M_get_result): Use
nullptr for null pointer constant.
* libsupc++/eh_ptr.cc (operator==, operator!=): Remove
definitions.
* libsupc++/exception_ptr.h (_GLIBCXX_EH_PTR_USED): Define
macro to conditionally add __attribute__((__used__)).
(operator==, operator!=, exception_ptr::exception_ptr())
(exception_ptr::exception_ptr(const exception_ptr&))
(exception_ptr::~exception_ptr())
(exception_ptr::operator=(const exception_ptr&))
(exception_ptr::swap(exception_ptr&)): Always define as
inline. Add macro to be conditionally "used".
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index 3c2aaa1fab19..5d948018c75c 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -709,7 +709,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
_State_base::_S_check(_M_state);
_Result_base& __res = _M_state->wait();
- if (!(__res._M_error == 0))
+ if (!(__res._M_error == nullptr))
rethrow_exception(__res._M_error);
return static_cast<__result_type>(__res);
}
diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc
index c41bdca234c7..7e6863550ce4 100644
--- a/libstdc++-v3/libsupc++/eh_ptr.cc
+++ b/libstdc++-v3/libsupc++/eh_ptr.cc
@@ -25,7 +25,12 @@
#include <bits/c++config.h>
#include "eh_atomics.h"
+#if ! _GLIBCXX_INLINE_VERSION
+// This macro causes exception_ptr to declare an older API (with corresponding
+// definitions in this file) and to mark some inline functions as "used" so
+// that definitions will be emitted in this translation unit.
#define _GLIBCXX_EH_PTR_COMPAT
+#endif
#include <exception>
#include <bits/exception_ptr.h>
@@ -61,6 +66,8 @@ static_assert( adjptr<__cxa_exception>()
#endif
}
+// Define non-inline functions.
+
std::__exception_ptr::exception_ptr::exception_ptr(void* obj) noexcept
: _M_exception_object(obj) { _M_addref(); }
@@ -130,19 +137,6 @@ std::__exception_ptr::exception_ptr::__cxa_exception_type() const noexcept
return eh->exceptionType;
}
-// Retained for compatibility with CXXABI_1.3.12.
-bool
-std::__exception_ptr::operator==(const exception_ptr& lhs,
- const exception_ptr& rhs) noexcept
-{ return lhs._M_exception_object == rhs._M_exception_object; }
-
-// Retained for compatibility with CXXABI_1.3.12.
-bool
-std::__exception_ptr::operator!=(const exception_ptr& lhs,
- const exception_ptr& rhs) noexcept
-{ return !(lhs == rhs); }
-
-
std::exception_ptr
std::current_exception() noexcept
{
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
index 4497d0e8581b..001343ac0498 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -39,6 +39,12 @@
#include <typeinfo>
#include <new>
+#ifdef _GLIBCXX_EH_PTR_COMPAT
+# define _GLIBCXX_EH_PTR_USED __attribute__((__used__))
+#else
+# define _GLIBCXX_EH_PTR_USED
+#endif
+
extern "C++" {
namespace std
@@ -146,20 +152,17 @@ namespace std
{ return _M_exception_object; }
#endif
-#ifdef _GLIBCXX_EH_PTR_COMPAT
- friend bool
- operator==(const exception_ptr&, const exception_ptr&)
- _GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__));
-#elif __cpp_impl_three_way_comparison >= 201907L
+#if __cpp_impl_three_way_comparison >= 201907L \
+ && ! defined _GLIBCXX_EH_PTR_COMPAT
friend bool
operator==(const exception_ptr&, const exception_ptr&) noexcept = default;
#else
- friend bool
+ friend _GLIBCXX_EH_PTR_USED bool
operator==(const exception_ptr& __x, const exception_ptr& __y)
_GLIBCXX_USE_NOEXCEPT
{ return __x._M_exception_object == __y._M_exception_object; }
- friend bool
+ friend _GLIBCXX_EH_PTR_USED bool
operator!=(const exception_ptr& __x, const exception_ptr& __y)
_GLIBCXX_USE_NOEXCEPT
{ return __x._M_exception_object != __y._M_exception_object; }
@@ -170,25 +173,30 @@ namespace std
__attribute__ ((__pure__));
};
-#ifndef _GLIBCXX_EH_PTR_COMPAT
+ _GLIBCXX_EH_PTR_USED
+#ifndef _GLIBCXX_EH_PTR_COMPAT
+ __attribute__((__always_inline__)) // XXX see PR 97729
inline
#endif
exception_ptr::exception_ptr() _GLIBCXX_NOEXCEPT
: _M_exception_object(0)
{ }
-#ifndef _GLIBCXX_EH_PTR_COMPAT
+ _GLIBCXX_EH_PTR_USED
+#ifndef _GLIBCXX_EH_PTR_COMPAT
+ __attribute__((__always_inline__))
inline
#endif
- exception_ptr::exception_ptr(const exception_ptr& __other)
- _GLIBCXX_NOEXCEPT
+ exception_ptr::exception_ptr(const exception_ptr& __other) _GLIBCXX_NOEXCEPT
: _M_exception_object(__other._M_exception_object)
{
if (_M_exception_object)
_M_addref();
}
-#ifndef _GLIBCXX_EH_PTR_COMPAT
+ _GLIBCXX_EH_PTR_USED
+#ifndef _GLIBCXX_EH_PTR_COMPAT
+ __attribute__((__always_inline__))
inline
#endif
exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
@@ -197,20 +205,16 @@ namespace std
_M_release();
}
-#ifndef _GLIBCXX_EH_PTR_COMPAT
- inline
-#endif
- exception_ptr&
+ _GLIBCXX_EH_PTR_USED
+ inline exception_ptr&
exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT
{
exception_ptr(__other).swap(*this);
return *this;
}
-#ifndef _GLIBCXX_EH_PTR_COMPAT
- inline
-#endif
- void
+ _GLIBCXX_EH_PTR_USED
+ inline void
exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT
{
void *__tmp = _M_exception_object;
@@ -218,16 +222,6 @@ namespace std
__other._M_exception_object = __tmp;
}
-#ifdef _GLIBCXX_EH_PTR_COMPAT
- bool
- operator==(const exception_ptr&, const exception_ptr&)
- _GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__));
-
- bool
- operator!=(const exception_ptr&, const exception_ptr&)
- _GLIBCXX_USE_NOEXCEPT __attribute__ ((__pure__));
-#endif
-
/// @relates exception_ptr
inline void
swap(exception_ptr& __lhs, exception_ptr& __rhs)
@@ -276,6 +270,8 @@ namespace std
#endif
}
+#undef _GLIBCXX_EH_PTR_USED
+
// @} group exceptions
} // namespace std
next prev parent reply other threads:[~2020-11-05 18:03 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-05 18:01 [committed 1/2] libstdc++: Export basic_stringbuf constructor " Jonathan Wakely
2020-11-05 18:03 ` Jonathan Wakely [this message]
2020-11-09 14:31 ` [committed 1/2] libstdc++: Fix multiple definitions of std::exception_ptr functions " Jonathan Wakely
2020-11-06 10:56 ` [committed 1/2] libstdc++: Export basic_stringbuf constructor " Rainer Orth
2020-11-06 20:15 ` Jonathan Wakely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201105180311.GH503596@redhat.com \
--to=jwakely@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).