3

I'm testing for a problem that surfaced recently during testing under C++17. Here is the source file:

$ cat test.cxx
#if __EXCEPTIONS && __has_feature(cxx_exceptions)
# include <exception>
# define CXX17_EXCEPTIONS 1
#endif

void Foo()
{
#if defined(CXX17_EXCEPTIONS)
    if (std::uncaught_exceptions() == 0)
#endif
    {
        int x = 0;
    }
}

And compiling it using Macports compiler on OS X 10.8 or 10.9:

$ /opt/local/bin/clang++-mp-5.0 -std=gnu++17 test.cxx -c
test.cxx:9:14: error: 'uncaught_exceptions' is unavailable: introduced in macOS 10.12
    if (std::uncaught_exceptions() == 0)
             ^
/opt/local/libexec/llvm-5.0/include/c++/v1/exception:130:63: note:
      'uncaught_exceptions' has been explicitly marked unavailable here
_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_e...
                                                              ^
1 error generated.

/opt/local/bin/clang++-mp-5.0 also experiences the issue. It does not appear to be a one-off problem. 4.0 rejects -std=gnu++17 so I can't test back further.

According to Clang 3.6 Release Notes, I believe I am using the correct test for std::uncaught_exceptions():

To reliably test if C++ exceptions are enabled, use __EXCEPTIONS && __has_feature(cxx_exceptions), else things won’t work in all versions of Clang in Objective-C++ files.

I probably won't be able to include an Apple specific header file, so I won't be able to test for OS X 10.12. Others have experienced the issue but I have not found a proper solution. For example, this bug report has the same unresolved issue.

Is there a way to work around the issue on Apple platforms that includes standard C++ preprocessor macros and feature testing? If so, what is the method or tests?


$ /opt/local/bin/clang++-mp-6.0 --version
clang version 6.0.1 (tags/RELEASE_601/final)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
InstalledDir: /opt/local/libexec/llvm-6.0/bin

$ /opt/local/bin/clang++-mp-5.0 --version
clang version 5.0.2 (tags/RELEASE_502/final)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
InstalledDir: /opt/local/libexec/llvm-5.0/bin
jww
  • 97,681
  • 90
  • 411
  • 885

3 Answers3

3

The problem here is that the runtime library (libc++.dylib) shipped on Mac OS before 10.12 does not contain a definition for std::uncaught_exceptions(). If you were to try using it on those platforms, it would result on a linker error. So instead, we're warning you at compile-time that this would fail. This has nothing to do with exceptions being available/unavailable: it's about the specific function not being available.

Louis Dionne
  • 3,104
  • 1
  • 15
  • 35
1

__EXCEPTIONS && __has_feature(cxx_exceptions) tests if exceptions are available. Exceptions are a language feature that has been in C++ since about 1990 (they weren't introduced in C++17!), so unless you explicitly disable exceptions they should always be available.

__cpp_lib_uncaught_exceptions alone is the correct test.

MerryMage
  • 11
  • 1
0

I'm not sure if this is the correct way to handle the situation, but it may help others.

$ cat test.cxx
#if __EXCEPTIONS && __has_feature(cxx_exceptions)
# if __cpp_lib_uncaught_exceptions
#  include <exception>
#  define CXX17_EXCEPTIONS 1
# endif
#endif

void Foo()
{
#if defined(CXX17_EXCEPTIONS)
    if (std::uncaught_exceptions() == 0)
#endif
    {
        int x = 0;
    }
}

__EXCEPTIONS && __has_feature(cxx_exceptions) is specific to Clang and detects if C++17 exceptions are available (including ObjectiveC++). __cpp_lib_uncaught_exceptions is a C++ language feature and detects if C++17 exceptions are available.

It is not clear to me how __has_feature(cxx_exceptions) returns true when C++17 exceptions are not available. It seems obvious (to me) the feature is not available.

Also see LLVM Issue 39631, __has_feature(cxx_exceptions) returns true but fails to compile std::uncaught_exceptions().

jww
  • 97,681
  • 90
  • 411
  • 885