Why redefine __cxa_throw cause compile error?

Viewed 64

I try to redefine __cxa_throw for tracing exception, but g++ and clang++ will generate compile errors with diffirent function signature.

#include <stdexcept>
extern "C" {
  void __cxa_throw(void*, std::type_info*, void(*)(void*)) {}
}
int main() {
  throw std::runtime_error("throw");
}

Above code compiled with clang++-12 without any specificed flags, but g++-10 genearated such error:

main.cpp: In function ‘int main()’:
main.cpp:6:35: error: invalid conversion from ‘void*’ to ‘std::type_info*’ [-fpermissive]
    6 | int main() { throw std::runtime_error("throw"); }
      |                                              ^
      |                                              |
      |                                              void*

If I changed the function signature with:

#include <stdexcept>
extern "C" {
  void __cxa_throw(void*, void*, void(*)(void*)) {}
}
int main() {
  throw std::runtime_error("throw");
}

std::type_info* now becomes void*, g++-10 and clang++-12 compiled.

But if I insert cxxabi.h into code:

#include <stdexcept>
#include <cxxabi.h>
extern "C" {
  void __cxa_throw(void*, void*, void(*)(void*)) {}
}
int main() {
  throw std::runtime_error("throw");
}

g++-10 still compiled and clang++-12 generated this error:

main.cpp:4:8: error: conflicting types for '__cxa_throw'
  void __cxa_throw(void*, void*, void (*) (void *)) {}
       ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/cxxabi.h:616:3: note: previous declaration is here
  __cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *))
  ^
1 error generated.

So it means the type of the second parameter in cxxabi.h is std::type_info*, but why g++-10 can't compile the first code?

My enviroment is wsl2 with Ubuntu20.04, g++10.3.0, clang++12.0.0.

1 Answers

I think the error messages indicate that gcc passes void* as the second parameters and gcc's __cxa_throw likewise accepts void* and that for clang, the type is std::type_info* instead. So I would try something like:

#include <stdexcept>
#include <cxxabi.h>
#include <stdlib.h>

extern "C" {

#if !__clang__
  void __cxa_throw(void*, void*, void(*)(void*)) { abort(); }
  //abort to avoid warnings about noreturn functions
#else
  void __cxa_throw(void*, std::type_info*, void(*)(void*)) { abort(); }
  

#endif

}
int main() {
  throw std::runtime_error("throw");
}

This compiles without errors on both gcc and clang: https://gcc.godbolt.org/z/a9qzrvxqT

Related