PR libstdc++/51333 Define recursive_init_error constructor non-inline

The recursive_init_error class is defined in a header, with an inline
constructor, but the definition of the vtable and destructor are not
exported from the shared library. With -fkeep-inline-functions the
constructor gets emitted in user code, and requires the (non-exported)
vtable. This fails to link.

As far as I can tell, the recursive_init_error class definition was
moved into <cxxabi.h> so it could be documented with Doxygen, not for
any technical reason. But now it's there (and documented), somebody
could be relying on it, by catching that type and possibly performing
derived-to-base conversions to the std::exception base class. So the
conservative fix is to leave the class definition in the header but make
the constructor non-inline. This still allows the type to be caught and
still defines its base class.

Backport from mainline
2019-07-29  Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/51333
	* libsupc++/cxxabi.h (__gnu_cxx::recursive_init_error): Do not define
	constructor inline.
	* libsupc++/guard_error.cc (__gnu_cxx::recursive_init_error): Define
	constructor.
	* testsuite/18_support/51333.cc: New test.

From-SVN: r273946
This commit is contained in:
Jonathan Wakely 2019-07-31 20:56:04 +01:00 committed by Jonathan Wakely
parent 8153c366de
commit 9acd8777c4
4 changed files with 41 additions and 6 deletions

View File

@ -1,3 +1,15 @@
2019-07-31 Jonathan Wakely <jwakely@redhat.com>
Backport from mainline
2019-07-29 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/51333
* libsupc++/cxxabi.h (__gnu_cxx::recursive_init_error): Do not define
constructor inline.
* libsupc++/guard_error.cc (__gnu_cxx::recursive_init_error): Define
constructor.
* testsuite/18_support/51333.cc: New test.
2019-07-26 Jonathan Wakely <jwakely@redhat.com>
Backport from mainline

View File

@ -684,8 +684,9 @@ namespace __gnu_cxx
* @brief Exception thrown by __cxa_guard_acquire.
* @ingroup exceptions
*
* 6.7[stmt.dcl]/4: If control re-enters the declaration (recursively)
* while the object is being initialized, the behavior is undefined.
* C++ 2011 6.7 [stmt.dcl]/4: If control re-enters the declaration
* recursively while the variable is being initialized, the behavior
* is undefined.
*
* Since we already have a library function to handle locking, we might
* as well check for this situation and throw an exception.
@ -695,8 +696,8 @@ namespace __gnu_cxx
class recursive_init_error: public std::exception
{
public:
recursive_init_error() throw() { }
virtual ~recursive_init_error() throw ();
recursive_init_error() _GLIBCXX_NOTHROW;
virtual ~recursive_init_error() _GLIBCXX_NOTHROW;
};
}
#endif // __cplusplus

View File

@ -26,6 +26,6 @@
namespace __gnu_cxx
{
recursive_init_error::~recursive_init_error() throw() { }
recursive_init_error::recursive_init_error() noexcept { }
recursive_init_error::~recursive_init_error() noexcept { }
}

View File

@ -0,0 +1,22 @@
// Copyright (C) 2019 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-fkeep-inline-functions" }
// { dg-do link }
#include <cxxabi.h>
int main() { } // PR libstdc++/51333