diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake index 7c416ea77b88..8f49299ddc6a 100644 --- a/flang-rt/cmake/modules/AddFlangRT.cmake +++ b/flang-rt/cmake/modules/AddFlangRT.cmake @@ -238,34 +238,31 @@ function (add_flangrt_library name) $<$:-fno-exceptions -fno-rtti -funwind-tables -fno-asynchronous-unwind-tables> ) - # We define our own _GLIBCXX_THROW_OR_ABORT here because, as of - # GCC 15.1, the libstdc++ header file uses - # (void)_EXC in its definition of _GLIBCXX_THROW_OR_ABORT to - # silence a warning. - # - # This is a problem for us because some compilers, specifically - # clang, do not always optimize away that (void)_EXC even though - # it is unreachable since it occurs after a call to - # _builtin_abort(). Because _EXC is typically an object derived - # from std::exception, (void)_EXC, when not optimized away, - # calls std::exception methods defined in the libstdc++ shared - # library. We shouldn't link against that library since our - # build version may conflict with the version used by a hybrid - # Fortran/C++ application. - # - # Redefining _GLIBCXX_THROW_OR_ABORT in this manner is not - # supported by the maintainers of libstdc++, so future changes - # to libstdc++ may require future changes to this build script - # and/or future changes to the Fortran runtime source code. - target_compile_options(${tgtname} PUBLIC "-D_GLIBCXX_THROW_OR_ABORT(_EXC)=(__builtin_abort())") + # Include header at the top of all compilation units to avoid dependency + # on the C++ STL (libstdc++ or libc++). + target_compile_options(${tgtname} PRIVATE + "$<$:-include${FLANG_RT_SOURCE_DIR}/lib/runtime/stl-overrides.h>" + ) elseif (MSVC) target_compile_options(${tgtname} PRIVATE $<$:/EHs-c- /GR-> ) + + # Include header at the top of all compilation units to avoid dependency + # on the C++ STL (libstdc++ or libc++). + target_compile_options(${tgtname} PRIVATE + "$<$:/FI${FLANG_RT_SOURCE_DIR}/lib/runtime/stl-overrides.h>" + ) elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL") target_compile_options(${tgtname} PRIVATE $<$:-qnoeh -qnortti> ) + + # Include header at the top of all compilation units to avoid dependency + # on the C++ STL (libstdc++ or libc++). + target_compile_options(${tgtname} PRIVATE + "$<$:-qinclude=${FLANG_RT_SOURCE_DIR}/lib/runtime/stl-overrides.h>" + ) endif () # Add target specific options if necessary. diff --git a/flang-rt/lib/runtime/CMakeLists.txt b/flang-rt/lib/runtime/CMakeLists.txt index 9dcc3fa4bfe4..ad3b1f187f28 100644 --- a/flang-rt/lib/runtime/CMakeLists.txt +++ b/flang-rt/lib/runtime/CMakeLists.txt @@ -59,6 +59,7 @@ set(supported_sources ragged.cpp reduction.cpp stat.cpp + stl-overrides.cpp stop.cpp sum.cpp support.cpp diff --git a/flang-rt/lib/runtime/io-api-minimal.cpp b/flang-rt/lib/runtime/io-api-minimal.cpp index fdf7183ed517..299d87179f1a 100644 --- a/flang-rt/lib/runtime/io-api-minimal.cpp +++ b/flang-rt/lib/runtime/io-api-minimal.cpp @@ -146,19 +146,4 @@ bool IODEF(OutputLogical)(Cookie cookie, bool truth) { } // namespace Fortran::runtime::io -#if defined(_LIBCPP_VERBOSE_ABORT) -// Provide own definition for `std::__libcpp_verbose_abort` to avoid dependency -// on the version provided by libc++. - -void std::__libcpp_verbose_abort(char const *format, ...) noexcept( - noexcept(std::__libcpp_verbose_abort(""))) { - va_list list; - va_start(list, format); - std::vfprintf(stderr, format, list); - va_end(list); - - std::abort(); -} -#endif - RT_EXT_API_GROUP_END diff --git a/flang-rt/lib/runtime/stl-overrides.cpp b/flang-rt/lib/runtime/stl-overrides.cpp new file mode 100644 index 000000000000..f112d522004f --- /dev/null +++ b/flang-rt/lib/runtime/stl-overrides.cpp @@ -0,0 +1,22 @@ +//===-- lib/runtime/stl-overrides.cpp ---------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +// Provide function that is used in place of `std::__libcpp_verbose_abort` to +// avoid dependency on the symbol provided by libc++. +void flang_rt_verbose_abort(char const *format, ...) { + va_list list; + va_start(list, format); + std::vfprintf(stderr, format, list); + va_end(list); + + std::abort(); +} diff --git a/flang-rt/lib/runtime/stl-overrides.h b/flang-rt/lib/runtime/stl-overrides.h new file mode 100644 index 000000000000..5311dc79d7a1 --- /dev/null +++ b/flang-rt/lib/runtime/stl-overrides.h @@ -0,0 +1,38 @@ +//===-- lib/runtime/stl-overrides.h -----------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// This file is inserted implicitly to all translation units using -include on +// the command line. The reason is that it configures the C++ standard +// template library (libc++ or libstdc++) using preprocessor macro definitions +// that must appear before any C++ library include. + +// We define our own _GLIBCXX_THROW_OR_ABORT here because, as of GCC 15.1, the +// libstdc++ header file uses (void)_EXC in its definition of +// _GLIBCXX_THROW_OR_ABORT to silence a warning. +// +// This is a problem for us because some compilers, specifically clang, do not +// always optimize away that (void)_EXC even though it is unreachable since it +// occurs after a call to _builtin_abort(). Because _EXC is typically an +// object derived from std::exception, (void)_EXC, when not optimized away, +// calls std::exception methods defined in the libstdc++ shared library. We +// shouldn't link against that library since our build version may conflict +// with the version used by a hybrid Fortran/C++ application. +// +// Redefining _GLIBCXX_THROW_OR_ABORT in this manner is not supported by the +// maintainers of libstdc++, so future changes to libstdc++ may require future +// changes to this build script and/or future changes to the Fortran runtime +// source code. +#define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort()) + +// Declare function that is used in place of `std::__libcpp_verbose_abort` to +// avoid dependency on the symbol provided by libc++. +#ifndef _LIBCPP_VERBOSE_ABORT +#define _LIBCPP_VERBOSE_ABORT(...) flang_rt_verbose_abort(__VA_ARGS__) +void flang_rt_verbose_abort(char const *format, ...) + __attribute__((format(printf, 1, 2))); +#endif