[ moving from libtool@ ] > * Bob Friesenhahn wrote on Tue, Jan 05, 2010 at 05:11:56PM CET: > > Using 'llvm-gcc' (GCC frontend to llvm compiler) I find that C++ > > exceptions do not work (are not caught) in the built programs. [ and suspect libtool as culprit ]
We can only find out better if we have small examples to look at. Here is a proposed patch to try exception handling in libraries and modules. Tested with g++ on GNU/Linux; it will certainly need fixes for other systems, and Libtool may as well. I'd appreciate a look over it for any obvious glitches, before I commit it. Thanks, Ralf Testsuite exposure for C++ exception handling. * tests/exceptions.at (C++ exception handling): New file, new test. * Makefile.am (TESTSUITE_AT): Update. Report by Bob Friesenhahn. diff --git a/Makefile.am b/Makefile.am index 31b4275..e9f8566 100644 --- a/Makefile.am +++ b/Makefile.am @@ -496,6 +496,7 @@ TESTSUITE_AT = tests/testsuite.at \ tests/recursive.at \ tests/template.at \ tests/ctor.at \ + tests/exceptions.at \ tests/early-libtool.at \ tests/no-executables.at \ tests/deplibs-ident.at \ diff --git a/tests/exceptions.at b/tests/exceptions.at new file mode 100644 index 0000000..d551cb8 --- /dev/null +++ b/tests/exceptions.at @@ -0,0 +1,231 @@ +# exception.at -- test C++ exception handling with libtool -*- Autotest -*- +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This file is part of GNU Libtool. +# +# GNU Libtool 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 2 of +# the License, or (at your option) any later version. +# +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +#### + +AT_SETUP([C++ exception handling]) +AT_KEYWORDS([libtool]) +AT_KEYWORDS([libltdl]) +: ${LTDLINCL="-I$abs_top_srcdir/libltdl"} +: ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"} +CPPFLAGS="$LTDLINCL $CPPFLAGS" + +AT_DATA([module.h], +[[class modexc { }; +extern "C" int modfoo () throw (modexc); +]]) + +AT_DATA([module.cpp], +[[#include <iostream> +#include "module.h" + +int modbar (void) throw (modexc) +{ + throw modexc (); +} + +extern "C" +int modfoo (void) throw (modexc) +{ + try { + modbar (); + } + catch (modexc) { + std::cerr << "caught inside module\n"; + throw modexc (); + } + return 0; +} +]]) + +AT_DATA([lib.h], +[[class libexc { }; +int libfoo () throw (libexc); +]]) + +AT_DATA([lib.cpp], +[[#include <iostream> +#include "lib.h" + +int libbar (void) throw (libexc) +{ + throw libexc (); +} + +int libfoo (void) throw (libexc) +{ + try { + libbar (); + } + catch (libexc) { + std::cerr << "caught inside lib\n"; + throw libexc (); + } + return 0; +} +]]) + +AT_DATA([main.cpp], +[[#include <ltdl.h> +#include <cstdlib> +#include <iostream> +#include "lib.h" +#include "module.h" + +class exc { }; + +int foo (void) throw (exc) +{ + throw exc (); + return 0; +} + +int exceptions_in_prog (void) +{ + std::cerr << "exceptions_in_prog\n"; + try { + foo (); + } + catch (exc) { + std::cerr << "caught\n"; + return 0; + } + return 1; +} + +int exceptions_in_lib (void) +{ + std::cerr << "exceptions_in_lib\n"; + try { + libfoo (); + } + catch (libexc) { + std::cerr << "caught\n"; + return 0; + } + return 1; +} + +int exceptions_in_module (void) +{ + std::cerr << "exceptions_in_module\n"; + + if (lt_dlinit ()) + { + std::cerr << "init error: " << lt_dlerror () << '\n'; + return 1; + } + + // Some systems need RTLD_GLOBAL for exceptions to work in modules. + lt_dladvise advise; + if (lt_dladvise_init (&advise) || lt_dladvise_global (&advise)) + { + std::cerr << "error setting advise global\n"; + return 1; + } + + lt_dlhandle handle = lt_dlopenadvise ("module.la", advise); + if (handle == NULL) + { + std::cerr << "dlopen failed: " << lt_dlerror () << '\n'; + return 1; + } + lt_dladvise_destroy (&advise); + + typedef int (*pfun) (void); + pfun pf = (pfun) lt_dlsym (handle, "modfoo"); + if (pf == NULL) + { + std::cerr << "dlsym failed: " << lt_dlerror () << '\n'; + return 1; + } + + try { + (*pf) (); + } + catch (modexc) { + if (lt_dlclose (handle)) + { + std::cerr << "dlclose failed: " << lt_dlerror () << '\n'; + return 1; + } + if (lt_dlexit ()) + { + std::cerr << "lt_dlexit failed: " << lt_dlerror () << '\n'; + return 1; + } + return 0; + } + return 1; +} + +int main (void) +{ + if (exceptions_in_prog ()) + return 1; + if (exceptions_in_lib ()) + return 1; + if (exceptions_in_module ()) + return 1; + return 0; +} +]]) + +inst=`pwd`/inst +libdir=$inst/lib +bindir=$inst/bin +moddir=$inst/mod +mkdir l m $inst $libdir $bindir $moddir + +# If the C++ compiler isn't capable, don't bother. +AT_CHECK([$CXX $CPPFLAGS $CXXFLAGS -c main.cpp || exit 77], [], [ignore], [ignore]) + +for file in lib.cpp module.cpp; do + AT_CHECK([$LIBTOOL --mode=compile --tag=CXX $CXX $CPPFLAGS $CXXFLAGS -c $file], + [], [ignore], [ignore]) +done +AT_CHECK([$LIBTOOL --mode=link --tag=CXX $CXX $CXXFLAGS $LDFLAGS -o l/liba.la ]dnl + [lib.lo -no-undefined -version-info 1:0:0 -rpath $libdir], + [], [ignore], [ignore]) +AT_CHECK([$LIBTOOL --mode=link --tag=CXX $CXX $CXXFLAGS $LDFLAGS -o m/module.la ]dnl + [module.lo -module -avoid-version -no-undefined -rpath $moddir], + [], [ignore], [ignore]) + +# We need -export-dynamic for the exception handling in modules to work. +AT_CHECK([$LIBTOOL --mode=link --tag=CXX $CXX $CXXFLAGS $LDFLAGS -o main$EXEEXT ]dnl + [main.$OBJEXT l/liba.la -dlopen m/module.la $LIBLTDL -export-dynamic], + [], [ignore], [ignore]) + +LT_AT_NOINST_EXEC_CHECK([./main], [-dlopen m/module.la], [], [ignore], [ignore]) + +AT_CHECK([$LIBTOOL --mode=install cp l/liba.la $libdir], + [], [ignore], [ignore]) +AT_CHECK([$LIBTOOL --mode=install cp m/module.la $moddir], + [], [ignore], [ignore]) +AT_CHECK([$LIBTOOL --mode=install cp main$EXEEXT $bindir], + [], [ignore], [ignore]) +rm -rf l m main$EXEEXT + +LTDL_LIBRARY_PATH=$moddir +export LTDL_LIBRARY_PATH +LT_AT_EXEC_CHECK([$bindir/main], [], [ignore], [ignore]) + +AT_CLEANUP