diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -442,6 +442,13 @@ # define _LIBCPP_NO_EXCEPTIONS # endif +// Use this tag to avoid ODR violations when combining -fno-exceptions and -fexceptions code. +# ifdef _LIBCPP_NO_EXCEPTIONS +# define _LIBCPP_EXCEPTION_ABI_TAG __attribute__((__abi_tag__("no_exceptions"))) +# else +# define _LIBCPP_EXCEPTION_ABI_TAG +# endif + # define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp) # if defined(_LIBCPP_COMPILER_CLANG_BASED) diff --git a/libcxx/include/__utility/exception_guard.h b/libcxx/include/__utility/exception_guard.h --- a/libcxx/include/__utility/exception_guard.h +++ b/libcxx/include/__utility/exception_guard.h @@ -89,7 +89,7 @@ }; #else // _LIBCPP_NO_EXCEPTIONS template -struct __exception_guard { +struct _LIBCPP_EXCEPTION_ABI_TAG __exception_guard { __exception_guard() = delete; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NODEBUG explicit __exception_guard(_Rollback) {} diff --git a/libcxx/test/libcxx/utilities/exception_guard.odr.sh.cpp b/libcxx/test/libcxx/utilities/exception_guard.odr.sh.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/exception_guard.odr.sh.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Make sure that __exception_guard is a different symbol when compiled with -fno-exceptions. + +// RUN: %{cxx} %s %{flags} %{compile_flags} -c -o %t.except.o -g -Wno-private-header +// RUN: %{cxx} %s %{flags} %{compile_flags} -c -o %t.noexcept.o -g -fno-exceptions -Wno-private-header +// RUN: %{cxx} %{flags} %{link_flags} -o %t.exe %t.except.o %t.noexcept.o +// RUN: %{run} + +#include <__utility/exception_guard.h> +#include +#include +#include + +struct Rollback { + void operator()() {} +}; + +#if defined(__cpp_exceptions) && __cpp_exceptions >= 199711L + +const char* func(); + +int main(int, char**) { + assert(std::string(typeid(std::__exception_guard).name()) != func()); + + return 0; +} + +#else + +const char* func() { return typeid(std::__exception_guard).name(); } + +#endif