Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to catch exceptions with clang++ 18.1.5 on macos ARM (try-catch does nothing) #92121

Open
themightyoarfish opened this issue May 14, 2024 · 8 comments

Comments

@themightyoarfish
Copy link

System Info

  • OS: macos 12.6.5
  • arch: Apple silicon

Compiler info

  • Homebrew clang version 18.1.5
  • Target: arm64-apple-darwin21.6.0
  • Thread model: posix
  • InstalledDir: /opt/homebrew/Cellar/llvm/18.1.5/bin

Problem description

When an exception of custom type is thrown in the constructor for a class, and that constuctor gets invoked in the return statement of a function, this exception cannot be caught in the calling code.

So far the exact circumstances under which this happens or does not happen are unknown to me, but I have attached a small CMake project to demonstrate.

The problem does not occur with std::runtime_error, only with a subclass.

How to run

  • export CC=/opt/homebrew/Cellar/llvm/18.1.5/bin/clang CXX=/opt/homebrew/Cellar/llvm/18.1.5/bin/clang++
  • cmake ..
  • make && ./test

Result

ld: warning: dylib (/opt/homebrew/opt/llvm/lib/c++/libc++.dylib) was built for newer macOS version (12.7) than being linked (12.6)
[100%] Built target test
Throwing
libc++abi: terminating due to uncaught exception of type Error: hallo
Abort trap: 6

Minimal reproducible project

Here is a minimal cmake project (with build artifacts on my machine, in case that is relevant)

clang-wtf.zip

@github-actions github-actions bot added the clang Clang issues not falling into any other category label May 14, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented May 14, 2024

@llvm/issue-subscribers-clang-codegen

Author: Rasmus (themightyoarfish)

# System Info
  • OS: macos 12.6.5
  • arch: Apple silicon

Compiler info

  • Homebrew clang version 18.1.5
  • Target: arm64-apple-darwin21.6.0
  • Thread model: posix
  • InstalledDir: /opt/homebrew/Cellar/llvm/18.1.5/bin

Problem description

When an exception of custom type is thrown in the constructor for a class, and that constuctor gets invoked in the return statement of a function, this exception cannot be caught in the calling code.

So far the exact circumstances under which this happens or does not happen are unknown to me, but I have attached a small CMake project to demonstrate.

The problem does not occur with std::runtime_error, only with a subclass.

How to run

  • export CC=/opt/homebrew/Cellar/llvm/18.1.5/bin/clang CXX=/opt/homebrew/Cellar/llvm/18.1.5/bin/clang++
  • cmake ..
  • make && ./test

Result

ld: warning: dylib (/opt/homebrew/opt/llvm/lib/c++/libc++.dylib) was built for newer macOS version (12.7) than being linked (12.6)
[100%] Built target test
Throwing
libc++abi: terminating due to uncaught exception of type Error: hallo
Abort trap: 6

Minimal reproducible project

Here is a minimal cmake project (with build artifacts on my machine, in case that is relevant)

clang-wtf.zip

@EugeneZelenko EugeneZelenko removed the clang Clang issues not falling into any other category label May 14, 2024
@det
Copy link

det commented Jun 19, 2024

I am also seeing this on LLVM 18.1.2 and libc++abi.

edit: Only when I am using dynamic linking.
edit: Downgrading to libc++abi from 17.0.6 fixes the problem for me. I am unable to easily test older 18.1.X releases as there are no binary mac releases.
edit: libc++abi from 18.1.7 same problem.

@ngladitz
Copy link

I bisected this to 8f90e69.
As the added release notes in that commit suggests adding this to the CMake invocation seems to fix the issue for me:
-DLIBCXXABI_USE_LLVM_UNWINDER=OFF -DCOMPILER_RT_USE_LLVM_UNWINDER=OFF

@carlocab
Copy link
Contributor

From Homebrew/homebrew-core#175994, you can fix this by linking directly with the same libunwind used by libc++[abi]. For example, using the attached CMake project:

--- CMakeLists.txt.old	2024-07-24 12:29:07
+++ CMakeLists.txt	2024-07-24 12:29:32
@@ -6,6 +6,7 @@
 
 add_library(wtf src/lib.cpp)
 target_include_directories(wtf PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include/)
+target_link_libraries(wtf PRIVATE /opt/homebrew/opt/llvm/lib/libunwind.dylib)
 
 add_executable(test src/main.cpp)
 target_link_libraries(test PRIVATE wtf)

My guess is that dyld mistakenly uses the system-provided libunwind (i.e. /usr/lib/system/libunwind.dylib) which is not compatible with the one that libc++[abi] expects.

@adamjmurray
Copy link

This thread helped me figure out how to get clang++ 18 working on my ARM Mac when installed via Homebrew. I'm a CMake beginner, but I think this is a relatively clean solution if you are doing cross-platform builds:

if(CMAKE_SYSTEM_NAME MATCHES "Darwin"
        AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm64"
        AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"
        AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 18)
    link_libraries(/opt/homebrew/opt/llvm/lib/libunwind.dylib)
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/opt/homebrew/opt/llvm/lib/c++")
endif()

Note link_libraries() works for all targets, but it needs to be called before any add_executable() or similar statements. Otherwise you can use target_link_libraries() like @carlocab suggested.

I'm also having issues trying to use the stdlib with LLVM 18 installed via Homebrew. Calling things like std::println() gives linker errors (ld: Undefined symbols). The set(CMAKE_EXE_LINKER_FLAGS setting should fix that problem (thanks to this Reddit thread for helping me figure that out). That's probably a Homebrew bug and not relevant to the issue here, but I'm including it for reference to help other people run LLVM 18 on ARM MacOS.

AFAICT everything works fine once I add those settings near the top of my CMakeLists.txt file.

@carlocab
Copy link
Contributor

carlocab commented Aug 24, 2024

I'm also having issues trying to use the stdlib with LLVM 18 installed via Homebrew. Calling things like std::println() gives linker errors (ld: Undefined symbols).

std::println is available only in C++23 (or newer).1 This means that you need to use a suitable libc++, and that excludes the one provided by macOS at /usr/lib/libc++.1.dylib. So you need to follow the instructions regarding LDFLAGS shown by brew info llvm.

Footnotes

  1. https://en.cppreference.com/w/cpp/io/println

@adamjmurray
Copy link

std::println is available only in C++23 (or newer).1 This means that you need to use a suitable libc++, and that excludes the one provided by macOS at /usr/lib/libc++.1.dylib. So you need to follow the instructions regarding LDFLAGS shown by brew info llvm.

Thanks for the info. For some reason it just works with LLVM 17 and Homebrew. I didn't need to do anything special to use std::println. But after upgrading to LLVM 18, I cannot get it to work unless I explicitly add the LLVM stdlib as shown in my CMakeLists.txt snippet.

I want to say Homebrew is correctly setting up the LLVM stdlib for v17 installs, but is not doing so for v18 installs. But I really don't know what's going on with this stuff. Along with the Reddit post, I found several other people running into this issue, and it isn't a problem with LLVM 17, so it seems like a regression?

I didn't mean to distract from the issue at hand here, but there is a clear difference in behavior between LLVM 17 and 18 installed by Homebrew w.r.t. locating the correct stdlib for clang++.

@carlocab
Copy link
Contributor

carlocab commented Aug 24, 2024

there is a clear difference in behavior between LLVM 17 and 18 installed by Homebrew w.r.t. locating the correct stdlib for clang++

No, there isn't.

As far as I can tell, there has been a change in the implementation of std::println between LLVM 17 and 18. In particular, std::println in LLVM 18 makes use of std::__1::__is_posix_terminal, which is available only in LLVM 18's libc++.dylib. This function was not used (or available) in LLVM 17. That's why you need LLVM's libc++.dylib in LLVM 18 to use std::println but didn't for LLVM 17.

Edit:

Yup, it looks like this is exactly what happened. See 872fe20 and #80464.

xylar added a commit to xylar/kealib-feedstock that referenced this issue Oct 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants