Home > Enterprise >  When GCC does not provide __cpp_lib_uncaught_exceptions feature?
When GCC does not provide __cpp_lib_uncaught_exceptions feature?

Time:06-17

Following piece of code does not work right on Alpine Linux:

#ifndef __cpp_lib_uncaught_exceptions
namespace std {
    int uncaught_exceptions() noexcept {
        return std::uncaught_exception();
    }
}
#endif

Source

Error:

[ 89%] Linking CXX executable AdsLibTest.bin
/usr/lib/gcc/x86_64-alpine-linux-musl/11.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: /usr/lib/gcc/x86_64-alpine-linux-musl/11.2.1/../../../../lib/libstdc  .a(eh_catch.o): in function `std::uncaught_exceptions()':
/home/buildozer/aports/main/gcc/src/gcc-11.2.1_git20220219/libstdc  -v3/libsupc  /eh_catch.cc:149: multiple definition of `std::uncaught_exceptions()'; CMakeFiles/AdsLibTest.bin.dir/main.cpp.o:main.cpp:(.text 0x8d0): first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [_deps/ads-build/AdsLibTest/CMakeFiles/AdsLibTest.bin.dir/build.make:98: _deps/ads-build/AdsLibTest/AdsLibTest.bin] Error 1

It looks like GCC does not provide __cpp_lib_uncaught_exceptions feature. Why this could happen?

CodePudding user response:

I see a few issues with your code:

  1. __cpp_lib_uncaught_exceptions is only documented to be defined (when applicable) if you've #include-ed <version> or <exception>; you've included neither. Add #include <exceptions> above that feature test somewhere, and it should work.

  2. Your code as written will redefine uncaught_exceptions() in every compilation unit that includes it when the macro is not defined, because you made the definition in a header and did not make it inline, static or both, so every .cpp file including your header ends up getting its own exportable definition. Without the necessary headers included in your header, whether that feature test macro is defined will depend on whether each .cpp file includes <exception>/<version>, and whether it does so before or after including your header. If they aren't uniform, some files could get your header's definition, while others get the built-in definition.

CodePudding user response:

Adding declarations to namespace std causes (with a few specific exceptions) undefined behavior. There is no reason that this should work, even if the compiler does correctly report that it doesn't provide std::uncaught_exceptions.

In particular, if the standard library implementation supported std::uncaught_exceptions and the file was compiled with language standard set to below C 17, then the feature test will claim that std::uncaught_exceptions is unsupported, but the standard library .a/.so may still provide the definition for it. This would cause a duplicate definition error.

As @ShadowRanger notes, there is also likely an inline missing on the function definition, because it may be included in multiple in multiple translation units.

Also, in order to use a feature test macro, it is necessary to include <version> (since C 20) or the header file corresponding to that features, e.g. in this case <exception>. Otherwise the macro is not defined and the feature check will always fail. It seems that the header is not including <exception>, but is including <stdexcept> though, which technically is not sufficient. However, practically, <stdexcept> is likely going to include <exception> and hence that would likely still work. For current libstdc this seems to be the case at least.

So, I would assume that your issue lies in the chosen compiler options, e.g. the language standard to compile for.

  • Related