[PATCH] PR libstdc++/51333 Define recursive_init_error constructor non-inline

Jonathan Wakely jwakely@redhat.com
Mon Jul 29 14:39:00 GMT 2019


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. User code can no longer construct objects
of that type, but that's not something we need to support.

	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.

Tested x86_64-linux, committed to trunk.

-------------- next part --------------
commit 853fb49def8642dd687cd053dda5b8167082934f
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Mon Jul 29 14:27:19 2019 +0000

    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. User code can no longer construct objects
    of that type, but that's not something we need to support.
    
            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.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@273878 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/libstdc++-v3/libsupc++/cxxabi.h b/libstdc++-v3/libsupc++/cxxabi.h
index 3562d4c2271..4d9f829ffed 100644
--- a/libstdc++-v3/libsupc++/cxxabi.h
+++ b/libstdc++-v3/libsupc++/cxxabi.h
@@ -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
diff --git a/libstdc++-v3/libsupc++/guard_error.cc b/libstdc++-v3/libsupc++/guard_error.cc
index 7595c67872a..d7625af4d54 100644
--- a/libstdc++-v3/libsupc++/guard_error.cc
+++ b/libstdc++-v3/libsupc++/guard_error.cc
@@ -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 { }
 }
-
diff --git a/libstdc++-v3/testsuite/18_support/51333.cc b/libstdc++-v3/testsuite/18_support/51333.cc
new file mode 100644
index 00000000000..0fb7c338f8b
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/51333.cc
@@ -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


More information about the Gcc-patches mailing list