bug#70935: Support C++17 compilers in the C++ tests

Bruno Haible <[email protected]> Tue, 14 May 2024 14:05:25 +0200
Newsgroups gmane.comp.gnu.libtool.bugs
Message-ID <22577161.hxa6pUQ8Du@nimes>
Hi,

Running the libtool tests on Ubuntu 22.04, I saw this test output:

  Constructors.

  142: C++ static constructors                         ok
  143: C++ exception handling                          skipped (exceptions.at:361)

It sounds odd that a C++ test gets skipped when a perfectly fine C++ compiler
is present. So I investigated...

The log file of the respective test is:

--------------------------------------------------------------------------------
#                             -*- compilation -*-
143. exceptions.at:24: testing C++ exception handling ...
./exceptions.at:33: case $LIBLTDL in #(
 */_inst/lib/*) test -f "$LIBLTDL" || (exit 77) ;;
esac
stdout:
./exceptions.at:361: $CXX $CPPFLAGS $CXXFLAGS -DUSING_COMMON_DLL -DUSING_MODULE_DLL -DUSING_LIB_DLL -c main.cpp || exit 77
stderr:
In file included from main.cpp:7:
lib.h:30:26: error: ISO C++17 does not allow dynamic exception specifications
   30 | int LIB_IMPEXP libfoo () throw (libexc);
      |                          ^~~~~
In file included from main.cpp:8:
module.h:17:40: error: ISO C++17 does not allow dynamic exception specifications
   17 | extern "C" int MODULE_IMPEXP modfoo () throw (modexc);
      |                                        ^~~~~
main.cpp:22:16: error: ISO C++17 does not allow dynamic exception specifications
   22 | int foo (void) throw (exc)
      |                ^~~~~
stdout:
143. exceptions.at:24: 143. C++ exception handling (exceptions.at:24): skipped (exceptions.at:361)
--------------------------------------------------------------------------------

The problem is apparently that the test uses old syntax that was deprecated
in C++11 and removed in C++17 [1]. The new syntax is described in [2].

The attached patch fixes it.

[1] https://en.cppreference.com/w/cpp/language/except_spec
[2] https://en.cppreference.com/w/cpp/language/noexcept_spec
0001-Support-C-17-compilers-in-the-C-tests.patch (text/x-patch, 3.3 KB)
From b6cf9c4650262d810f9ed451a90dfe990151382e Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Tue, 14 May 2024 13:51:39 +0200
Subject: [PATCH] Support C++17 compilers in the C++ tests.

* tests/exceptions.at: For C++11 and newer, use the keyword 'noexcept'
instead of the keyword 'throw'.
---
 tests/exceptions.at | 42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/tests/exceptions.at b/tests/exceptions.at
index 845ccff2..b18dd875 100644
--- a/tests/exceptions.at
+++ b/tests/exceptions.at
@@ -94,11 +94,19 @@ AT_DATA([common.h],
 # define COMMON_IMPEXP
 #endif
 
+#if __cplusplus >= 201103L
+# define ATTRIBUTE_THROW(type) noexcept (false)
+# define ATTRIBUTE_NOTHROW noexcept (true)
+#else
+# define ATTRIBUTE_THROW(type) throw (type)
+# define ATTRIBUTE_NOTHROW throw ()
+#endif
+
 class COMMON_IMPEXP modexc : public std::exception {
 public:
   modexc (std::string str) : message (str) { }
-  ~modexc () throw () { }
-  virtual const char *what () const throw ()
+  ~modexc () ATTRIBUTE_NOTHROW { }
+  virtual const char *what () const ATTRIBUTE_NOTHROW
   {
     return message.c_str ();
   }
@@ -138,7 +146,7 @@ AT_DATA([module.h],
 # define MODULE_IMPEXP
 #endif
 
-extern "C" int MODULE_IMPEXP modfoo () throw (modexc);
+extern "C" int MODULE_IMPEXP modfoo () ATTRIBUTE_THROW (modexc);
 ]])
 
 AT_DATA([module.cpp],
@@ -146,13 +154,13 @@ AT_DATA([module.cpp],
 #define LIBTOOL_TEST_IN_MODULE
 #include "module.h"
 
-int modbar (void) throw (modexc)
+int modbar (void) ATTRIBUTE_THROW (modexc)
 {
   throw modexc ("exception in module");
 }
 
 extern "C"
-int modfoo (void) throw (modexc)
+int modfoo (void) ATTRIBUTE_THROW (modexc)
 {
   try {
     modbar ();
@@ -184,18 +192,26 @@ AT_DATA([lib.h],
 # define LIB_IMPEXP
 #endif
 
+#if __cplusplus >= 201103L
+# define ATTRIBUTE_THROW(type) noexcept (false)
+# define ATTRIBUTE_NOTHROW noexcept (true)
+#else
+# define ATTRIBUTE_THROW(type) throw (type)
+# define ATTRIBUTE_NOTHROW throw ()
+#endif
+
 class LIB_IMPEXP libexc : public std::exception {
 public:
   libexc (std::string str) : message (str) { }
-  ~libexc () throw () { }
-  virtual const char *what () const throw ()
+  ~libexc () ATTRIBUTE_NOTHROW { }
+  virtual const char *what () const ATTRIBUTE_NOTHROW
   {
     return message.c_str ();
   }
 private:
   std::string message;
 };
-int LIB_IMPEXP libfoo () throw (libexc);
+int LIB_IMPEXP libfoo () ATTRIBUTE_THROW (libexc);
 ]])
 
 AT_DATA([lib.cpp],
@@ -203,12 +219,12 @@ AT_DATA([lib.cpp],
 #define LIBTOOL_TEST_IN_LIB
 #include "lib.h"
 
-int libbar (void) throw (libexc)
+int libbar (void) ATTRIBUTE_THROW (libexc)
 {
   throw libexc ("exception in library");
 }
 
-int libfoo (void) throw (libexc)
+int libfoo (void) ATTRIBUTE_THROW (libexc)
 {
   try {
     libbar ();
@@ -234,8 +250,8 @@ AT_DATA([main.cpp],
 class exc : public std::exception {
 public:
   exc (std::string str) : message (str) { }
-  ~exc () throw () { }
-  virtual const char *what () const throw ()
+  ~exc () ATTRIBUTE_NOTHROW { }
+  virtual const char *what () const ATTRIBUTE_NOTHROW
   {
     return message.c_str ();
   }
@@ -243,7 +259,7 @@ private:
   std::string message;
 };
 
-int foo (void) throw (exc)
+int foo (void) ATTRIBUTE_THROW (exc)
 {
   throw exc ("exception in program");
   return 0;
-- 
2.34.1