mirror of
https://github.com/darlinghq/darling-libcxxabi.git
synced 2024-11-23 12:19:48 +00:00
Update libcxxabi source to llvmorg-13.0.1
This commit is contained in:
parent
b115be2d85
commit
443d929eb3
@ -1,4 +0,0 @@
|
||||
{
|
||||
"repository.callsign" : "CXXA",
|
||||
"conduit_uri" : "https://reviews.llvm.org/"
|
||||
}
|
@ -1,124 +1,132 @@
|
||||
# See www/CMake.html for instructions on how to build libcxxabi with CMake.
|
||||
|
||||
if (NOT IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/../libcxx")
|
||||
message(FATAL_ERROR "libc++abi now requires being built in a monorepo layout with libcxx available")
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
# Setup Project
|
||||
#===============================================================================
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
cmake_minimum_required(VERSION 3.13.4)
|
||||
|
||||
if(POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW) # Set MACOSX_RPATH=YES by default
|
||||
endif()
|
||||
# Add path for custom modules
|
||||
set(CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
|
||||
${CMAKE_MODULE_PATH}
|
||||
)
|
||||
|
||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
project(libcxxabi)
|
||||
set(CMAKE_FOLDER "libc++")
|
||||
|
||||
# Rely on llvm-config.
|
||||
set(CONFIG_OUTPUT)
|
||||
find_program(LLVM_CONFIG "llvm-config")
|
||||
if(DEFINED LLVM_PATH)
|
||||
set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include")
|
||||
set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree")
|
||||
set(LLVM_MAIN_SRC_DIR ${LLVM_PATH})
|
||||
set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules")
|
||||
elseif(LLVM_CONFIG)
|
||||
message(STATUS "Found LLVM_CONFIG as ${LLVM_CONFIG}")
|
||||
set(CONFIG_COMMAND ${LLVM_CONFIG}
|
||||
"--includedir"
|
||||
"--prefix"
|
||||
"--src-root")
|
||||
execute_process(
|
||||
COMMAND ${CONFIG_COMMAND}
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE CONFIG_OUTPUT
|
||||
)
|
||||
if(NOT HAD_ERROR)
|
||||
string(REGEX REPLACE
|
||||
"[ \t]*[\r\n]+[ \t]*" ";"
|
||||
CONFIG_OUTPUT ${CONFIG_OUTPUT})
|
||||
else()
|
||||
string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}")
|
||||
message(STATUS "${CONFIG_COMMAND_STR}")
|
||||
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
|
||||
endif()
|
||||
set(LIBCXXABI_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(LIBCXXABI_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(LIBCXXABI_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
|
||||
"Specify path to libc++ source.")
|
||||
|
||||
list(GET CONFIG_OUTPUT 0 INCLUDE_DIR)
|
||||
list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT)
|
||||
list(GET CONFIG_OUTPUT 2 MAIN_SRC_DIR)
|
||||
|
||||
set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include")
|
||||
set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree")
|
||||
set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
|
||||
set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR}/share/llvm/cmake")
|
||||
set(LLVM_LIT_PATH "${LLVM_PATH}/utils/lit/lit.py")
|
||||
else()
|
||||
message(FATAL_ERROR "llvm-config not found and LLVM_MAIN_SRC_DIR not defined. "
|
||||
"Reconfigure with -DLLVM_CONFIG=path/to/llvm-config "
|
||||
"or -DLLVM_PATH=path/to/llvm-source-root.")
|
||||
endif()
|
||||
|
||||
if(EXISTS ${LLVM_CMAKE_PATH})
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
|
||||
include("${LLVM_CMAKE_PATH}/AddLLVM.cmake")
|
||||
include("${LLVM_CMAKE_PATH}/HandleLLVMOptions.cmake")
|
||||
else()
|
||||
message(FATAL_ERROR "Not found: ${LLVM_CMAKE_PATH}")
|
||||
endif()
|
||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXXABI_STANDALONE_BUILD)
|
||||
project(libcxxabi CXX C)
|
||||
|
||||
set(PACKAGE_NAME libcxxabi)
|
||||
set(PACKAGE_VERSION 3.7.0svn)
|
||||
set(PACKAGE_VERSION 13.0.1)
|
||||
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||
set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
|
||||
|
||||
if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
|
||||
set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
|
||||
else()
|
||||
# Seek installed Lit.
|
||||
find_program(LLVM_LIT "lit.py" ${LLVM_MAIN_SRC_DIR}/utils/lit
|
||||
DOC "Path to lit.py")
|
||||
endif()
|
||||
# Add the CMake module path of libcxx so we can reuse HandleOutOfTreeLLVM.cmake
|
||||
set(LIBCXXABI_LIBCXX_CMAKE_PATH "${LIBCXXABI_LIBCXX_PATH}/cmake/Modules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${LIBCXXABI_LIBCXX_CMAKE_PATH}")
|
||||
|
||||
if(LLVM_LIT)
|
||||
# Define the default arguments to use with 'lit', and an option for the user
|
||||
# to override.
|
||||
set(LIT_ARGS_DEFAULT "-sv")
|
||||
if (MSVC OR XCODE)
|
||||
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
|
||||
endif()
|
||||
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
|
||||
# In a standalone build, we don't have llvm to automatically generate the
|
||||
# llvm-lit script for us. So we need to provide an explicit directory that
|
||||
# the configurator should write the script into.
|
||||
set(LIBCXXABI_STANDALONE_BUILD 1)
|
||||
set(LLVM_LIT_OUTPUT_DIR "${LIBCXXABI_BINARY_DIR}/bin")
|
||||
|
||||
# On Win32 hosts, provide an option to specify the path to the GnuWin32 tools.
|
||||
if( WIN32 AND NOT CYGWIN )
|
||||
set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools")
|
||||
endif()
|
||||
else()
|
||||
set(LLVM_INCLUDE_TESTS OFF)
|
||||
endif()
|
||||
|
||||
set(LIBCXXABI_LIBDIR_SUFFIX "" CACHE STRING
|
||||
"Define suffix of library directory name (32/64)")
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
|
||||
|
||||
set(LIBCXXABI_BUILT_STANDALONE 1)
|
||||
else()
|
||||
set(LLVM_MAIN_SRC_DIR "${CMAKE_SOURCE_DIR}" CACHE PATH "Path to LLVM source tree")
|
||||
set(LLVM_LIT "${CMAKE_SOURCE_DIR}/utils/lit/lit.py")
|
||||
set(LIBCXXABI_LIBDIR_SUFFIX ${LLVM_LIBDIR_SUFFIX})
|
||||
# Find the LLVM sources and simulate LLVM CMake options.
|
||||
include(HandleOutOfTreeLLVM)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_STANDALONE_BUILD)
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
if(NOT Python3_Interpreter_FOUND)
|
||||
message(WARNING "Python3 not found, using python2 as a fallback")
|
||||
find_package(Python2 COMPONENTS Interpreter REQUIRED)
|
||||
if(Python2_VERSION VERSION_LESS 2.7)
|
||||
message(SEND_ERROR "Python 2.7 or newer is required")
|
||||
endif()
|
||||
|
||||
# Treat python2 as python3
|
||||
add_executable(Python3::Interpreter IMPORTED)
|
||||
set_target_properties(Python3::Interpreter PROPERTIES
|
||||
IMPORTED_LOCATION ${Python2_EXECUTABLE})
|
||||
set(Python3_EXECUTABLE ${Python2_EXECUTABLE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Require out of source build.
|
||||
include(MacroEnsureOutOfSourceBuild)
|
||||
MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
|
||||
"${PROJECT_NAME} requires an out of source build. Please create a separate
|
||||
build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there."
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# Setup CMake Options
|
||||
#===============================================================================
|
||||
include(CMakeDependentOption)
|
||||
include(HandleCompilerRT)
|
||||
|
||||
# Define options.
|
||||
option(LIBCXXABI_ENABLE_EXCEPTIONS
|
||||
"Provide support for exceptions in the runtime.
|
||||
When disabled, libc++abi does not support stack unwinding and other exceptions-related features." ON)
|
||||
option(LIBCXXABI_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON)
|
||||
option(LIBCXXABI_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
|
||||
option(LIBCXXABI_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
|
||||
option(LIBCXXABI_USE_LLVM_UNWINDER "Build and use the LLVM unwinder." OFF)
|
||||
option(LIBCXXABI_ENABLE_STATIC_UNWINDER "Statically link the LLVM unwinder." OFF)
|
||||
option(LIBCXXABI_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF)
|
||||
option(LIBCXXABI_ENABLE_THREADS "Build with threads enabled" ON)
|
||||
set(LIBCXXABI_GCC_TOOLCHAIN "" CACHE STRING "GCC toolchain for cross compiling.")
|
||||
set(LIBCXXABI_SYSROOT "" CACHE STRING "Sysroot for cross compiling.")
|
||||
set(LIBCXXABI_LIBCXX_LIBRARY_PATH "" CACHE STRING "The path to libc++ library.")
|
||||
option(LIBCXXABI_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF)
|
||||
option(LIBCXXABI_HAS_WIN32_THREAD_API "Ignore auto-detection and force use of win32 thread API" OFF)
|
||||
option(LIBCXXABI_HAS_EXTERNAL_THREAD_API
|
||||
"Build libc++abi with an externalized threading API.
|
||||
This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON." OFF)
|
||||
option(LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY
|
||||
"Build libc++abi with an externalized threading library.
|
||||
This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON" OFF)
|
||||
option(LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST
|
||||
"Make dynamic_cast more forgiving when type_info's mistakenly have hidden \
|
||||
visibility, and thus multiple type_infos can exist for a single type. \
|
||||
When the dynamic_cast would normally fail, this option will cause the \
|
||||
library to try comparing the type_info names to see if they are equal \
|
||||
instead." OFF)
|
||||
|
||||
option(LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS
|
||||
"Build libc++abi with definitions for operator new/delete. These are normally
|
||||
defined in libc++abi, but it is also possible to define them in libc++, in
|
||||
which case the definition in libc++abi should be turned off." ON)
|
||||
option(LIBCXXABI_BUILD_32_BITS "Build 32 bit libc++abi." ${LLVM_BUILD_32_BITS})
|
||||
option(LIBCXXABI_INCLUDE_TESTS "Generate build targets for the libc++abi unit tests." ${LLVM_INCLUDE_TESTS})
|
||||
set(LIBCXXABI_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
|
||||
"Define suffix of library directory name (32/64)")
|
||||
option(LIBCXXABI_INSTALL_LIBRARY "Install the libc++abi library." ON)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_TARGET)
|
||||
set(LIBCXXABI_DEFAULT_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}")
|
||||
else()
|
||||
set(LIBCXXABI_DEFAULT_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}")
|
||||
endif()
|
||||
set(LIBCXXABI_TARGET_TRIPLE "${LIBCXXABI_DEFAULT_TARGET_TRIPLE}" CACHE STRING "Target triple for cross compiling.")
|
||||
set(LIBCXXABI_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}" CACHE PATH "GCC toolchain for cross compiling.")
|
||||
set(LIBCXXABI_SYSROOT "${CMAKE_SYSROOT}" CACHE PATH "Sysroot for cross compiling.")
|
||||
|
||||
set(LIBCXXABI_LIBCXX_LIBRARY_PATH "" CACHE PATH "The path to libc++ library.")
|
||||
set(LIBCXXABI_LIBRARY_VERSION "1.0" CACHE STRING
|
||||
"Version of libc++abi. This will be reflected in the name of the shared \
|
||||
library produced. For example, -DLIBCXXABI_LIBRARY_VERSION=x.y will \
|
||||
result in the library being named libc++abi.x.y.dylib, along with the \
|
||||
usual symlinks pointing to that.")
|
||||
|
||||
# Default to building a shared library so that the default options still test
|
||||
# the libc++abi that is being built. There are two problems with testing a
|
||||
@ -129,39 +137,56 @@ set(LIBCXXABI_LIBCXX_LIBRARY_PATH "" CACHE STRING "The path to libc++ library.")
|
||||
option(LIBCXXABI_ENABLE_SHARED "Build libc++abi as a shared library." ON)
|
||||
option(LIBCXXABI_ENABLE_STATIC "Build libc++abi as a static library." ON)
|
||||
|
||||
cmake_dependent_option(LIBCXXABI_INSTALL_STATIC_LIBRARY
|
||||
"Install the static libc++abi library." ON
|
||||
"LIBCXXABI_ENABLE_STATIC;LIBCXXABI_INSTALL_LIBRARY" OFF)
|
||||
cmake_dependent_option(LIBCXXABI_INSTALL_SHARED_LIBRARY
|
||||
"Install the shared libc++abi library." ON
|
||||
"LIBCXXABI_ENABLE_SHARED;LIBCXXABI_INSTALL_LIBRARY" OFF)
|
||||
|
||||
cmake_dependent_option(LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY
|
||||
"Statically link the LLVM unwinder to static library" ON
|
||||
"LIBCXXABI_ENABLE_STATIC_UNWINDER;LIBCXXABI_ENABLE_STATIC" OFF)
|
||||
cmake_dependent_option(LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_SHARED_LIBRARY
|
||||
"Statically link the LLVM unwinder to shared library" ON
|
||||
"LIBCXXABI_ENABLE_STATIC_UNWINDER;LIBCXXABI_ENABLE_SHARED" OFF)
|
||||
|
||||
option(LIBCXXABI_BAREMETAL "Build libc++abi for baremetal targets." OFF)
|
||||
# The default terminate handler attempts to demangle uncaught exceptions, which
|
||||
# causes extra I/O and demangling code to be pulled in.
|
||||
option(LIBCXXABI_SILENT_TERMINATE "Set this to make the terminate handler default to a silent alternative" OFF)
|
||||
option(LIBCXXABI_NON_DEMANGLING_TERMINATE "Set this to make the terminate handler
|
||||
avoid demangling" OFF)
|
||||
|
||||
if (NOT LIBCXXABI_ENABLE_SHARED AND NOT LIBCXXABI_ENABLE_STATIC)
|
||||
message(FATAL_ERROR "libc++abi must be built as either a shared or static library.")
|
||||
endif()
|
||||
|
||||
find_path(
|
||||
LIBCXXABI_LIBCXX_INCLUDES
|
||||
vector
|
||||
PATHS ${LIBCXXABI_LIBCXX_INCLUDES}
|
||||
${LIBCXXABI_LIBCXX_PATH}/include
|
||||
${CMAKE_BINARY_DIR}/${LIBCXXABI_LIBCXX_INCLUDES}
|
||||
${LLVM_MAIN_SRC_DIR}/projects/libcxx/include
|
||||
${LLVM_INCLUDE_DIR}/c++/v1
|
||||
)
|
||||
|
||||
set(LIBCXXABI_LIBCXX_INCLUDES "${LIBCXXABI_LIBCXX_INCLUDES}" CACHE PATH
|
||||
"Specify path to libc++ includes." FORCE)
|
||||
|
||||
find_path(
|
||||
LIBCXXABI_LIBCXX_PATH
|
||||
test/libcxx/__init__.py
|
||||
PATHS ${LIBCXXABI_LIBCXX_PATH}
|
||||
${LIBCXXABI_LIBCXX_INCLUDES}/../
|
||||
${LLVM_MAIN_SRC_DIR}/projects/libcxx/
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if (LIBCXXABI_LIBCXX_PATH STREQUAL "LIBCXXABI_LIBCXX_PATH-NOTFOUND")
|
||||
message(WARNING "LIBCXXABI_LIBCXX_PATH was not specified and couldn't be infered.")
|
||||
set(LIBCXXABI_LIBCXX_PATH "")
|
||||
# TODO: This is a workaround for the fact that Standalone builds can't use
|
||||
# targets from the other runtimes (so the cxx-headers target doesn't exist).
|
||||
set(LIBCXXABI_LIBCXX_INCLUDES "" CACHE PATH
|
||||
"Specify path to libc++ includes.")
|
||||
if (LIBCXXABI_STANDALONE_BUILD)
|
||||
if (NOT IS_DIRECTORY ${LIBCXXABI_LIBCXX_INCLUDES})
|
||||
message(FATAL_ERROR
|
||||
"LIBCXXABI_LIBCXX_INCLUDES=${LIBCXXABI_LIBCXX_INCLUDES} is not a valid directory. "
|
||||
"Please provide the path to where the libc++ headers have been installed.")
|
||||
endif()
|
||||
add_library(cxx-headers INTERFACE)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC")
|
||||
target_compile_options(cxx-headers INTERFACE /I "${LIBCXXABI_LIBCXX_INCLUDES}")
|
||||
else()
|
||||
target_compile_options(cxx-headers INTERFACE -I "${LIBCXXABI_LIBCXX_INCLUDES}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(LIBCXXABI_LIBCXX_PATH "${LIBCXXABI_LIBCXX_PATH}" CACHE PATH
|
||||
"Specify path to libc++ source." FORCE)
|
||||
option(LIBCXXABI_HERMETIC_STATIC_LIBRARY
|
||||
"Do not export any symbols from the static library." OFF)
|
||||
|
||||
set(LIBCXXABI_TEST_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/test/lit.site.cfg.in" CACHE STRING
|
||||
"The Lit testing configuration to use when running the tests.")
|
||||
set(LIBCXXABI_TEST_PARAMS "" CACHE STRING
|
||||
"A list of parameters to run the Lit test suite with.")
|
||||
|
||||
#===============================================================================
|
||||
# Configure System
|
||||
@ -174,80 +199,170 @@ set(CMAKE_MODULE_PATH
|
||||
${CMAKE_MODULE_PATH}
|
||||
)
|
||||
|
||||
# Configure compiler.
|
||||
include(config-ix)
|
||||
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
|
||||
set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
|
||||
set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
|
||||
set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
|
||||
"Path where built libc++abi libraries should be installed.")
|
||||
if(LIBCXX_LIBDIR_SUBDIR)
|
||||
string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
|
||||
string(APPEND LIBCXXABI_INSTALL_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
|
||||
endif()
|
||||
elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
|
||||
set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
|
||||
set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
|
||||
set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
|
||||
"Path where built libc++abi libraries should be installed.")
|
||||
else()
|
||||
set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR})
|
||||
set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
|
||||
set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
|
||||
"Path where built libc++abi libraries should be installed.")
|
||||
endif()
|
||||
|
||||
set(LIBCXXABI_COMPILER ${CMAKE_CXX_COMPILER})
|
||||
set(LIBCXXABI_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(LIBCXXABI_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
|
||||
|
||||
# By default, for non-standalone builds, libcxx and libcxxabi share a library
|
||||
# directory.
|
||||
if (NOT LIBCXXABI_LIBCXX_LIBRARY_PATH)
|
||||
set(LIBCXXABI_LIBCXX_LIBRARY_PATH "${LIBCXXABI_LIBRARY_DIR}" CACHE PATH
|
||||
"The path to libc++ library." FORCE)
|
||||
endif()
|
||||
|
||||
# Check that we can build with 32 bits if requested.
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32)
|
||||
if (LIBCXXABI_BUILD_32_BITS AND NOT LLVM_BUILD_32_BITS) # Don't duplicate the output from LLVM
|
||||
message(STATUS "Building 32 bits executables and libraries.")
|
||||
endif()
|
||||
elseif(LIBCXXABI_BUILD_32_BITS)
|
||||
message(FATAL_ERROR "LIBCXXABI_BUILD_32_BITS=ON is not supported on this platform.")
|
||||
endif()
|
||||
|
||||
# Declare libc++abi configuration variables.
|
||||
# They are intended for use as follows:
|
||||
# LIBCXXABI_C_FLAGS: General flags for both the c++ compiler and linker.
|
||||
# LIBCXXABI_CXX_FLAGS: General flags for both the c++ compiler and linker.
|
||||
# LIBCXXABI_COMPILE_FLAGS: Compile only flags.
|
||||
# LIBCXXABI_LINK_FLAGS: Linker only flags.
|
||||
# LIBCXXABI_LIBRARIES: libraries libc++abi is linked to.
|
||||
|
||||
set(LIBCXXABI_C_FLAGS "")
|
||||
set(LIBCXXABI_CXX_FLAGS "")
|
||||
set(LIBCXXABI_COMPILE_FLAGS "")
|
||||
set(LIBCXXABI_LINK_FLAGS "")
|
||||
set(LIBCXXABI_LIBRARIES "")
|
||||
|
||||
# Include macros for adding and removing libc++abi flags.
|
||||
include(HandleLibcxxabiFlags)
|
||||
|
||||
#===============================================================================
|
||||
# Setup Compiler Flags
|
||||
#===============================================================================
|
||||
|
||||
# Get required flags.
|
||||
macro(append_if list condition var)
|
||||
if (${condition})
|
||||
list(APPEND ${list} ${var})
|
||||
endif()
|
||||
endmacro()
|
||||
# Configure target flags
|
||||
add_target_flags_if(LIBCXXABI_BUILD_32_BITS "-m32")
|
||||
|
||||
set(LIBCXXABI_C_FLAGS "")
|
||||
set(LIBCXXABI_CXX_FLAGS "-nostdlib -nostdinc -nostdinc++ -D__DARWIN_UNIX03=1 -D__DARWIN_NON_CANCELABLE=1")
|
||||
set(LIBCXXABI_COMPILE_FLAGS "")
|
||||
set(LIBCXXABI_LINK_FLAGS "")
|
||||
if(LIBCXXABI_TARGET_TRIPLE)
|
||||
add_target_flags_if_supported("--target=${LIBCXXABI_TARGET_TRIPLE}")
|
||||
endif()
|
||||
if(LIBCXXABI_GCC_TOOLCHAIN)
|
||||
add_target_flags_if_supported("--gcc-toolchain=${LIBCXXABI_GCC_TOOLCHAIN}")
|
||||
endif()
|
||||
if(LIBCXXABI_SYSROOT)
|
||||
add_target_flags_if_supported("--sysroot=${LIBCXXABI_SYSROOT}")
|
||||
endif()
|
||||
|
||||
# Configure compiler. Must happen after setting the target flags.
|
||||
include(config-ix)
|
||||
|
||||
if (LIBCXXABI_HAS_NOSTDINCXX_FLAG)
|
||||
list(APPEND LIBCXXABI_COMPILE_FLAGS -nostdinc++)
|
||||
# cmake 3.14 and above remove system include paths that are explicitly
|
||||
# passed on the command line. We build with -nostdinc++ and explicitly add
|
||||
# just the libcxx system include paths with -I on the command line.
|
||||
# Setting CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES effectively prevents cmake
|
||||
# from removing these.
|
||||
# See: https://gitlab.kitware.com/cmake/cmake/issues/19227
|
||||
set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "")
|
||||
# Remove -stdlib flags to prevent them from causing an unused flag warning.
|
||||
string(REPLACE "--stdlib=libc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "--stdlib=libstdc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "-stdlib=libc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "-stdlib=libstdc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
# Let the library headers know they are currently being used to build the
|
||||
# library.
|
||||
add_definitions(-D_LIBCXXABI_BUILDING_LIBRARY)
|
||||
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WERROR_FLAG -Werror=return-type)
|
||||
# libcxxabi needs to, for various reasons, include the libcpp headers as if
|
||||
# it is being built as part of libcxx.
|
||||
add_definitions(-D_LIBCPP_BUILDING_LIBRARY)
|
||||
|
||||
# Disable DLL annotations on Windows for static builds.
|
||||
if (WIN32 AND LIBCXXABI_ENABLE_STATIC AND NOT LIBCXXABI_ENABLE_SHARED)
|
||||
if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_STATIC_ABI_LIBRARY)
|
||||
# Building libcxxabi statically, but intending for it to be statically
|
||||
# linked into a shared libcxx; keep dllexport enabled within libcxxabi,
|
||||
# as the symbols will need to be exported from libcxx.
|
||||
else()
|
||||
# Regular static build; disable dllexports.
|
||||
add_definitions(-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_compile_flags_if_supported(-Werror=return-type)
|
||||
|
||||
# Get warning flags
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_W_FLAG -W)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WALL_FLAG -Wall)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WCHAR_SUBSCRIPTS_FLAG -Wchar-subscripts)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WCONVERSION_FLAG -Wconversion)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WMISMATCHED_TAGS_FLAG -Wmismatched-tags)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WMISSING_BRACES_FLAG -Wmissing-braces)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WNEWLINE_EOF_FLAG -Wnewline-eof)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WNO_UNUSED_FUNCTION_FLAG -Wno-unused-function)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSHADOW_FLAG -Wshadow)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSHORTEN_64_TO_32_FLAG -Wshorten-64-to-32)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSIGN_COMPARE_FLAG -Wsign-compare)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSIGN_CONVERSION_FLAG -Wsign-conversion)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSTRICT_ALIASING_FLAG -Wstrict-aliasing=2)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WSTRICT_OVERFLOW_FLAG -Wstrict-overflow=4)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WUNUSED_PARAMETER_FLAG -Wunused-parameter)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WUNUSED_VARIABLE_FLAG -Wunused-variable)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WWRITE_STRINGS_FLAG -Wwrite-strings)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WUNDEF_FLAG -Wundef)
|
||||
add_compile_flags_if_supported(-W)
|
||||
add_compile_flags_if_supported(-Wall)
|
||||
add_compile_flags_if_supported(-Wchar-subscripts)
|
||||
add_compile_flags_if_supported(-Wconversion)
|
||||
add_compile_flags_if_supported(-Wmismatched-tags)
|
||||
add_compile_flags_if_supported(-Wmissing-braces)
|
||||
add_compile_flags_if_supported(-Wnewline-eof)
|
||||
add_compile_flags_if_supported(-Wunused-function)
|
||||
add_compile_flags_if_supported(-Wshadow)
|
||||
add_compile_flags_if_supported(-Wshorten-64-to-32)
|
||||
add_compile_flags_if_supported(-Wsign-compare)
|
||||
add_compile_flags_if_supported(-Wsign-conversion)
|
||||
add_compile_flags_if_supported(-Wstrict-aliasing=2)
|
||||
add_compile_flags_if_supported(-Wstrict-overflow=4)
|
||||
add_compile_flags_if_supported(-Wunused-parameter)
|
||||
add_compile_flags_if_supported(-Wunused-variable)
|
||||
add_compile_flags_if_supported(-Wwrite-strings)
|
||||
add_compile_flags_if_supported(-Wundef)
|
||||
|
||||
add_compile_flags_if_supported(-Wno-suggest-override)
|
||||
|
||||
if (LIBCXXABI_ENABLE_WERROR)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WERROR_FLAG -Werror)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WX_FLAG -WX)
|
||||
add_compile_flags_if_supported(-Werror)
|
||||
add_compile_flags_if_supported(-WX)
|
||||
else()
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_WNO_ERROR_FLAG -Wno-error)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_NO_WX_FLAG -WX-)
|
||||
add_compile_flags_if_supported(-Wno-error)
|
||||
add_compile_flags_if_supported(-WX-)
|
||||
endif()
|
||||
if (LIBCXXABI_ENABLE_PEDANTIC)
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_HAS_PEDANTIC_FLAG -pedantic)
|
||||
add_compile_flags_if_supported(-pedantic)
|
||||
endif()
|
||||
|
||||
# Get feature flags.
|
||||
# Exceptions
|
||||
# Catches C++ exceptions only and tells the compiler to assume that extern C
|
||||
# functions never throw a C++ exception.
|
||||
append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_FSTRICT_ALIASING_FLAG -fstrict-aliasing)
|
||||
append_if(LIBCXXABI_CXX_FLAGS LIBCXXABI_HAS_EHSC_FLAG -EHsc)
|
||||
add_compile_flags_if_supported(-fstrict-aliasing)
|
||||
|
||||
append_if(LIBCXXABI_C_FLAGS LIBCXXABI_HAS_FUNWIND_TABLES -funwind-tables)
|
||||
# Exceptions
|
||||
if (LIBCXXABI_ENABLE_EXCEPTIONS)
|
||||
# Catches C++ exceptions only and tells the compiler to assume that extern C
|
||||
# functions never throw a C++ exception.
|
||||
add_compile_flags_if_supported(-EHsc)
|
||||
# Do we really need to be run through the C compiler ?
|
||||
add_c_compile_flags_if_supported(-funwind-tables)
|
||||
else()
|
||||
add_compile_flags_if_supported(-fno-exceptions)
|
||||
add_compile_flags_if_supported(-EHs-)
|
||||
add_compile_flags_if_supported(-EHa-)
|
||||
endif()
|
||||
|
||||
# Assert
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
|
||||
@ -266,31 +381,128 @@ else()
|
||||
list(APPEND LIBCXXABI_COMPILE_FLAGS -DNDEBUG)
|
||||
endif()
|
||||
endif()
|
||||
# Static library
|
||||
if (NOT LIBCXXABI_ENABLE_SHARED)
|
||||
list(APPEND LIBCXXABI_COMPILE_FLAGS -D_LIBCPP_BUILD_STATIC)
|
||||
endif()
|
||||
|
||||
# Threading
|
||||
if (NOT LIBCXXABI_ENABLE_THREADS)
|
||||
add_definitions(-DLIBCXXABI_HAS_NO_THREADS=1)
|
||||
if (LIBCXXABI_HAS_PTHREAD_API)
|
||||
message(FATAL_ERROR "LIBCXXABI_HAS_PTHREAD_API can only"
|
||||
" be set to ON when LIBCXXABI_ENABLE_THREADS"
|
||||
" is also set to ON.")
|
||||
endif()
|
||||
if (LIBCXXABI_HAS_WIN32_THREAD_API)
|
||||
message(FATAL_ERROR "LIBCXXABI_HAS_WIN32_THREAD_API can only"
|
||||
" be set to ON when LIBCXXABI_ENABLE_THREADS"
|
||||
" is also set to ON.")
|
||||
endif()
|
||||
if (LIBCXXABI_HAS_EXTERNAL_THREAD_API)
|
||||
message(FATAL_ERROR "LIBCXXABI_HAS_EXTERNAL_THREAD_API can only"
|
||||
" be set to ON when LIBCXXABI_ENABLE_THREADS"
|
||||
" is also set to ON.")
|
||||
endif()
|
||||
if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
message(FATAL_ERROR "LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY can only"
|
||||
" be set to ON when LIBCXXABI_ENABLE_THREADS"
|
||||
" is also set to ON.")
|
||||
endif()
|
||||
add_definitions(-D_LIBCXXABI_HAS_NO_THREADS)
|
||||
add_definitions(-D_LIBCPP_HAS_NO_THREADS)
|
||||
endif()
|
||||
|
||||
# This is the _ONLY_ place where add_definitions is called.
|
||||
if (LIBCXXABI_HAS_EXTERNAL_THREAD_API)
|
||||
if (LIBCXXABI_HAS_PTHREAD_API)
|
||||
message(FATAL_ERROR "The options LIBCXXABI_HAS_EXTERNAL_THREAD_API"
|
||||
" and LIBCXXABI_HAS_PTHREAD_API cannot be both"
|
||||
" set to ON at the same time.")
|
||||
endif()
|
||||
if (LIBCXXABI_HAS_WIN32_THREAD_API)
|
||||
message(FATAL_ERROR "The options LIBCXXABI_HAS_EXTERNAL_THREAD_API"
|
||||
" and LIBCXXABI_HAS_WIN32_THREAD_API cannot be both"
|
||||
" set to ON at the same time.")
|
||||
endif()
|
||||
if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
message(FATAL_ERROR "The options LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY"
|
||||
" and LIBCXXABI_HAS_EXTERNAL_THREAD_API cannot be both"
|
||||
" set to ON at the same time.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_HAS_PTHREAD_API)
|
||||
if (LIBCXXABI_HAS_WIN32_THREAD_API)
|
||||
message(FATAL_ERROR "The options LIBCXXABI_HAS_PTHREAD_API"
|
||||
"and LIBCXXABI_HAS_WIN32_THREAD_API cannot be both"
|
||||
"set to ON at the same time.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LLVM_ENABLE_MODULES)
|
||||
# Ignore that the rest of the modules flags are now unused.
|
||||
add_compile_flags_if_supported(-Wno-unused-command-line-argument)
|
||||
add_compile_flags(-fno-modules)
|
||||
endif()
|
||||
|
||||
set(LIBCXXABI_HAS_UNDEFINED_SYMBOLS OFF)
|
||||
if ((NOT LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS)
|
||||
OR (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY AND LIBCXXABI_ENABLE_SHARED)
|
||||
OR MINGW)
|
||||
set(LIBCXXABI_HAS_UNDEFINED_SYMBOLS ON)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_HAS_UNDEFINED_SYMBOLS)
|
||||
# Need to allow unresolved symbols if this is to work with shared library builds
|
||||
if (APPLE)
|
||||
list(APPEND LIBCXXABI_LINK_FLAGS "-undefined dynamic_lookup")
|
||||
else()
|
||||
# Relax this restriction from HandleLLVMOptions
|
||||
string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_HAS_PTHREAD_API)
|
||||
add_definitions(-D_LIBCPP_HAS_THREAD_API_PTHREAD)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_HAS_WIN32_THREAD_API)
|
||||
add_definitions(-D_LIBCPP_HAS_THREAD_API_WIN32)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_HAS_EXTERNAL_THREAD_API)
|
||||
add_definitions(-D_LIBCPP_HAS_THREAD_API_EXTERNAL)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
add_definitions(-D_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL)
|
||||
endif()
|
||||
|
||||
# Prevent libc++abi from having library dependencies on libc++
|
||||
add_definitions(-D_LIBCPP_DISABLE_EXTERN_TEMPLATE)
|
||||
|
||||
if (MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
# Define LIBCXXABI_USE_LLVM_UNWINDER for conditional compilation.
|
||||
if (LIBCXXABI_USE_LLVM_UNWINDER OR LLVM_NATIVE_ARCH MATCHES ARM)
|
||||
add_definitions(-DLIBCXXABI_USE_LLVM_UNWINDER=1)
|
||||
if (LIBCXXABI_USE_LLVM_UNWINDER)
|
||||
add_definitions(-DLIBCXXABI_USE_LLVM_UNWINDER)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_SILENT_TERMINATE)
|
||||
add_definitions(-DLIBCXXABI_SILENT_TERMINATE)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_NON_DEMANGLING_TERMINATE)
|
||||
add_definitions(-DLIBCXXABI_NON_DEMANGLING_TERMINATE)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_BAREMETAL)
|
||||
add_definitions(-DLIBCXXABI_BAREMETAL)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_HAS_COMMENT_LIB_PRAGMA)
|
||||
if (LIBCXXABI_HAS_PTHREAD_LIB)
|
||||
add_definitions(-D_LIBCXXABI_LINK_PTHREAD_LIB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_TARGET_TRIPLE
|
||||
"-target ${LIBCXXABI_TARGET_TRIPLE}")
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_GCC_TOOLCHAIN
|
||||
"-gcc-toolchain ${LIBCXXABI_GCC_TOOLCHAIN}")
|
||||
append_if(LIBCXXABI_COMPILE_FLAGS LIBCXXABI_SYSROOT
|
||||
"--sysroot ${LIBCXXABI_SYSROOT}")
|
||||
string(REPLACE ";" " " LIBCXXABI_CXX_FLAGS "${LIBCXXABI_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LIBCXXABI_CXX_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBCXXABI_C_FLAGS}")
|
||||
@ -306,47 +518,31 @@ set(LIBCXXABI_LIBUNWIND_PATH "${LIBCXXABI_LIBUNWIND_PATH}" CACHE PATH
|
||||
|
||||
include_directories(include)
|
||||
if (LIBCXXABI_USE_LLVM_UNWINDER OR LLVM_NATIVE_ARCH MATCHES ARM)
|
||||
find_path(
|
||||
LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL
|
||||
libunwind.h
|
||||
find_path(LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL libunwind.h
|
||||
PATHS ${LIBCXXABI_LIBUNWIND_INCLUDES}
|
||||
${LIBCXXABI_LIBUNWIND_PATH}/include
|
||||
${CMAKE_BINARY_DIR}/${LIBCXXABI_LIBUNWIND_INCLUDES}
|
||||
${LLVM_MAIN_SRC_DIR}/projects/libunwind/include
|
||||
${LLVM_MAIN_SRC_DIR}/runtimes/libunwind/include
|
||||
${LLVM_MAIN_SRC_DIR}/../libunwind/include
|
||||
NO_DEFAULT_PATH
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
|
||||
find_path(
|
||||
LIBCXXABI_LIBUNWIND_SOURCES
|
||||
libunwind_ext.h
|
||||
PATHS ${LIBCXXABI_LIBUNWIND_PATH}/src/
|
||||
${LIBCXXABI_LIBUNWIND_INCLUDES}/../src/
|
||||
${LLVM_MAIN_SRC_DIR}/projects/libunwind/src/
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if (LIBCXXABI_LIBUNWIND_SOURCES STREQUAL "LIBCXXABI_LIBUNWIND_SOURCES-NOTFOUND")
|
||||
message(WARNING "LIBCXXABI_LIBCXX_PATH was not specified and couldn't be infered.")
|
||||
set(LIBCXXABI_LIBUNWIND_SOURCES "")
|
||||
if (LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL STREQUAL "LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL-NOTFOUND")
|
||||
set(LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL "")
|
||||
endif()
|
||||
|
||||
include_directories("${LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL}")
|
||||
include_directories("${LIBCXXABI_LIBUNWIND_SOURCES}")
|
||||
endif ()
|
||||
if (NOT LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL STREQUAL "")
|
||||
include_directories("${LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add source code. This also contains all of the logic for deciding linker flags
|
||||
# soname, etc...
|
||||
add_subdirectory(src)
|
||||
|
||||
if(NOT LIBCXXABI_ENABLE_SHARED)
|
||||
# TODO: Fix the libc++ cmake files so that libc++abi can be statically linked.
|
||||
# As it is now, libc++ will prefer linking against a dynamic libc++abi in the
|
||||
# system library paths over a static libc++abi in the out directory. This
|
||||
# would test the system library rather than the one we just built, which isn't
|
||||
# very helpful.
|
||||
message(WARNING "The libc++abi tests are currently only valid when "
|
||||
"LIBCXXABI_ENABLE_SHARED is on, no check target will be "
|
||||
"available!")
|
||||
else()
|
||||
if (LIBCXXABI_INCLUDE_TESTS)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(fuzz)
|
||||
endif()
|
||||
|
@ -123,6 +123,17 @@ macro(add_target_flags_if condition)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Add all the flags supported by the compiler to all of
|
||||
# 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBCXXABI_COMPILE_FLAGS'
|
||||
# and 'LIBCXXABI_LINK_FLAGS'.
|
||||
macro(add_target_flags_if_supported)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "LIBCXXABI_SUPPORTS_${flagname}_FLAG")
|
||||
add_target_flags_if(LIBCXXABI_SUPPORTS_${flagname}_FLAG ${flag})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Add a specified list of flags to both 'LIBCXXABI_COMPILE_FLAGS' and
|
||||
# 'LIBCXXABI_LINK_FLAGS'.
|
||||
macro(add_flags)
|
||||
|
@ -1,142 +0,0 @@
|
||||
macro(find_llvm_parts)
|
||||
# Rely on llvm-config.
|
||||
set(CONFIG_OUTPUT)
|
||||
if(NOT LLVM_CONFIG_PATH)
|
||||
find_program(LLVM_CONFIG_PATH "llvm-config")
|
||||
endif()
|
||||
if(DEFINED LLVM_PATH)
|
||||
set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include")
|
||||
set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree")
|
||||
set(LLVM_MAIN_SRC_DIR ${LLVM_PATH})
|
||||
set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules")
|
||||
if (NOT IS_DIRECTORY "${LLVM_PATH}")
|
||||
message(FATAL_ERROR "The provided LLVM_PATH (${LLVM_PATH}) is not a valid directory")
|
||||
endif()
|
||||
elseif(LLVM_CONFIG_PATH)
|
||||
message(STATUS "Found LLVM_CONFIG_PATH as ${LLVM_CONFIG_PATH}")
|
||||
set(LIBCXXABI_USING_INSTALLED_LLVM 1)
|
||||
set(CONFIG_COMMAND ${LLVM_CONFIG_PATH}
|
||||
"--includedir"
|
||||
"--prefix"
|
||||
"--src-root")
|
||||
execute_process(
|
||||
COMMAND ${CONFIG_COMMAND}
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE CONFIG_OUTPUT
|
||||
)
|
||||
if(NOT HAD_ERROR)
|
||||
string(REGEX REPLACE
|
||||
"[ \t]*[\r\n]+[ \t]*" ";"
|
||||
CONFIG_OUTPUT ${CONFIG_OUTPUT})
|
||||
else()
|
||||
string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}")
|
||||
message(STATUS "${CONFIG_COMMAND_STR}")
|
||||
message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}")
|
||||
endif()
|
||||
|
||||
list(GET CONFIG_OUTPUT 0 INCLUDE_DIR)
|
||||
list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT)
|
||||
list(GET CONFIG_OUTPUT 2 MAIN_SRC_DIR)
|
||||
|
||||
set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include")
|
||||
set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree")
|
||||
set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree")
|
||||
|
||||
# --cmakedir is supported since llvm r291218 (4.0 release)
|
||||
execute_process(
|
||||
COMMAND ${LLVM_CONFIG_PATH} --cmakedir
|
||||
RESULT_VARIABLE HAD_ERROR
|
||||
OUTPUT_VARIABLE CONFIG_OUTPUT
|
||||
ERROR_QUIET)
|
||||
if(NOT HAD_ERROR)
|
||||
string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG)
|
||||
file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH)
|
||||
else()
|
||||
file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE)
|
||||
set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
|
||||
endif()
|
||||
else()
|
||||
set(LLVM_FOUND OFF)
|
||||
message(WARNING "UNSUPPORTED LIBCXXABI CONFIGURATION DETECTED: "
|
||||
"llvm-config not found and LLVM_PATH not defined.\n"
|
||||
"Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config "
|
||||
"or -DLLVM_PATH=path/to/llvm-source-root.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if (EXISTS "${LLVM_CMAKE_PATH}")
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}")
|
||||
elseif (EXISTS "${LLVM_MAIN_SRC_DIR}/cmake/modules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules")
|
||||
else()
|
||||
set(LLVM_FOUND OFF)
|
||||
message(WARNING "Neither ${LLVM_CMAKE_PATH} nor ${LLVM_MAIN_SRC_DIR}/cmake/modules found")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(LLVM_FOUND ON)
|
||||
endmacro(find_llvm_parts)
|
||||
|
||||
macro(configure_out_of_tree_llvm)
|
||||
message(STATUS "Configuring for standalone build.")
|
||||
set(LIBCXXABI_STANDALONE_BUILD 1)
|
||||
|
||||
find_llvm_parts()
|
||||
|
||||
# Add LLVM Functions --------------------------------------------------------
|
||||
if (LLVM_FOUND AND LIBCXXABI_USING_INSTALLED_LLVM)
|
||||
include(LLVMConfig) # For TARGET_TRIPLE
|
||||
else()
|
||||
if (WIN32)
|
||||
set(LLVM_ON_UNIX 0)
|
||||
set(LLVM_ON_WIN32 1)
|
||||
else()
|
||||
set(LLVM_ON_UNIX 1)
|
||||
set(LLVM_ON_WIN32 0)
|
||||
endif()
|
||||
endif()
|
||||
if (LLVM_FOUND)
|
||||
include(AddLLVM OPTIONAL)
|
||||
endif()
|
||||
|
||||
# LLVM Options --------------------------------------------------------------
|
||||
if (NOT DEFINED LLVM_INCLUDE_TESTS)
|
||||
set(LLVM_INCLUDE_TESTS ${LLVM_FOUND})
|
||||
endif()
|
||||
if (NOT DEFINED LLVM_INCLUDE_DOCS)
|
||||
set(LLVM_INCLUDE_DOCS ${LLVM_FOUND})
|
||||
endif()
|
||||
if (NOT DEFINED LLVM_ENABLE_SPHINX)
|
||||
set(LLVM_ENABLE_SPHINX OFF)
|
||||
endif()
|
||||
|
||||
# In a standalone build, we don't have llvm to automatically generate the
|
||||
# llvm-lit script for us. So we need to provide an explicit directory that
|
||||
# the configurator should write the script into.
|
||||
set(LLVM_LIT_OUTPUT_DIR "${libcxxabi_BINARY_DIR}/bin")
|
||||
|
||||
if (LLVM_INCLUDE_TESTS)
|
||||
# Required LIT Configuration ------------------------------------------------
|
||||
# Define the default arguments to use with 'lit', and an option for the user
|
||||
# to override.
|
||||
set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py")
|
||||
set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported")
|
||||
if (MSVC OR XCODE)
|
||||
set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar")
|
||||
endif()
|
||||
set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit")
|
||||
endif()
|
||||
|
||||
# Required doc configuration
|
||||
if (LLVM_ENABLE_SPHINX)
|
||||
find_package(Sphinx REQUIRED)
|
||||
endif()
|
||||
|
||||
if (LLVM_ON_UNIX AND NOT APPLE)
|
||||
set(LLVM_HAVE_LINK_VERSION_SCRIPT 1)
|
||||
else()
|
||||
set(LLVM_HAVE_LINK_VERSION_SCRIPT 0)
|
||||
endif()
|
||||
endmacro(configure_out_of_tree_llvm)
|
||||
|
||||
configure_out_of_tree_llvm()
|
@ -6,20 +6,34 @@ include(CheckCSourceCompiles)
|
||||
|
||||
check_library_exists(c fopen "" LIBCXXABI_HAS_C_LIB)
|
||||
if (NOT LIBCXXABI_USE_COMPILER_RT)
|
||||
check_library_exists(gcc_s __gcc_personality_v0 "" LIBCXXABI_HAS_GCC_S_LIB)
|
||||
check_library_exists(gcc __aeabi_uldivmod "" LIBCXXABI_HAS_GCC_LIB)
|
||||
if (ANDROID)
|
||||
check_library_exists(gcc __gcc_personality_v0 "" LIBCXXABI_HAS_GCC_LIB)
|
||||
else ()
|
||||
check_library_exists(gcc_s __gcc_personality_v0 "" LIBCXXABI_HAS_GCC_S_LIB)
|
||||
check_library_exists(gcc __aeabi_uldivmod "" LIBCXXABI_HAS_GCC_LIB)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# libc++abi is built with -nodefaultlibs, so we want all our checks to also
|
||||
# use this option, otherwise we may end up with an inconsistency between
|
||||
# libc++abi is using -nostdlib++ at the link step when available,
|
||||
# otherwise -nodefaultlibs is used. We want all our checks to also
|
||||
# use one of these options, otherwise we may end up with an inconsistency between
|
||||
# the flags we think we require during configuration (if the checks are
|
||||
# performed without -nodefaultlibs) and the flags that are actually
|
||||
# required during compilation (which has the -nodefaultlibs). libc is
|
||||
# required for the link to go through. We remove sanitizers from the
|
||||
# configuration checks to avoid spurious link errors.
|
||||
check_c_compiler_flag(-nodefaultlibs LIBCXXABI_HAS_NODEFAULTLIBS_FLAG)
|
||||
if (LIBCXXABI_HAS_NODEFAULTLIBS_FLAG)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
|
||||
|
||||
check_c_compiler_flag(-nostdlib++ LIBCXXABI_SUPPORTS_NOSTDLIBXX_FLAG)
|
||||
if (LIBCXXABI_SUPPORTS_NOSTDLIBXX_FLAG)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nostdlib++")
|
||||
else()
|
||||
check_c_compiler_flag(-nodefaultlibs LIBCXXABI_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
if (LIBCXXABI_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_SUPPORTS_NOSTDLIBXX_FLAG OR LIBCXXABI_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
if (LIBCXXABI_HAS_C_LIB)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES c)
|
||||
endif ()
|
||||
@ -71,8 +85,16 @@ endif()
|
||||
check_cxx_compiler_flag(-nostdinc++ LIBCXXABI_HAS_NOSTDINCXX_FLAG)
|
||||
|
||||
# Check libraries
|
||||
check_library_exists(dl dladdr "" LIBCXXABI_HAS_DL_LIB)
|
||||
check_library_exists(pthread pthread_once "" LIBCXXABI_HAS_PTHREAD_LIB)
|
||||
check_library_exists(c __cxa_thread_atexit_impl ""
|
||||
LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
|
||||
check_library_exists(System write "" LIBCXXABI_HAS_SYSTEM_LIB)
|
||||
if(FUCHSIA)
|
||||
set(LIBCXXABI_HAS_DL_LIB NO)
|
||||
set(LIBCXXABI_HAS_PTHREAD_LIB NO)
|
||||
check_library_exists(c __cxa_thread_atexit_impl ""
|
||||
LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
|
||||
set(LIBCXXABI_HAS_SYSTEM_LIB NO)
|
||||
else()
|
||||
check_library_exists(dl dladdr "" LIBCXXABI_HAS_DL_LIB)
|
||||
check_library_exists(pthread pthread_once "" LIBCXXABI_HAS_PTHREAD_LIB)
|
||||
check_library_exists(c __cxa_thread_atexit_impl ""
|
||||
LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
|
||||
check_library_exists(System write "" LIBCXXABI_HAS_SYSTEM_LIB)
|
||||
endif()
|
||||
|
@ -1,5 +0,0 @@
|
||||
_Znam = _Znaj;
|
||||
_ZnamRKSt9nothrow_t = _ZnajRKSt9nothrow_t;
|
||||
_Znwm = _Znwj;
|
||||
_ZnwmRKSt9nothrow_t = _ZnwjRKSt9nothrow_t;
|
||||
|
@ -18,6 +18,19 @@
|
||||
#define __has_attribute(_attribute_) 0
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# define _LIBCXXABI_COMPILER_CLANG
|
||||
# ifndef __apple_build_version__
|
||||
# define _LIBCXXABI_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# define _LIBCXXABI_COMPILER_GCC
|
||||
#elif defined(_MSC_VER)
|
||||
# define _LIBCXXABI_COMPILER_MSVC
|
||||
#elif defined(__IBMCPP__)
|
||||
# define _LIBCXXABI_COMPILER_IBM
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
#define _LIBCXXABI_HIDDEN
|
||||
@ -53,7 +66,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_LIBCXXABI_COMPILER_MSVC)
|
||||
#define _LIBCXXABI_WEAK
|
||||
#else
|
||||
#define _LIBCXXABI_WEAK __attribute__((__weak__))
|
||||
@ -72,8 +85,16 @@
|
||||
#endif
|
||||
|
||||
// wasm32 follows the arm32 ABI convention of using 32-bit guard.
|
||||
#if defined(__arm__) || defined(__wasm32__)
|
||||
#if defined(__arm__) || defined(__wasm32__) || defined(__ARM64_ARCH_8_32__)
|
||||
# define _LIBCXXABI_GUARD_ABI_ARM
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCXXABI_COMPILER_CLANG)
|
||||
# if !__has_feature(cxx_exceptions)
|
||||
# define _LIBCXXABI_NO_EXCEPTIONS
|
||||
# endif
|
||||
#elif defined(_LIBCXXABI_COMPILER_GCC) && !__EXCEPTIONS
|
||||
# define _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#endif // ____CXXABI_CONFIG_H
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#define _LIBCPPABI_VERSION 1002
|
||||
#define _LIBCXXABI_NORETURN __attribute__((noreturn))
|
||||
#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -78,13 +79,13 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void);
|
||||
|
||||
// 3.3.2 One-time Construction API
|
||||
#if defined(_LIBCXXABI_GUARD_ABI_ARM)
|
||||
extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint32_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint32_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint32_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *);
|
||||
#else
|
||||
extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint64_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint64_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint64_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *);
|
||||
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *);
|
||||
#endif
|
||||
|
||||
// 3.3.3 Array Construction and Destruction API
|
||||
@ -136,9 +137,9 @@ __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count,
|
||||
void (*destructor)(void *));
|
||||
|
||||
// 3.3.5.3 Runtime API
|
||||
extern _LIBCXXABI_FUNC_VIS int __cxa_atexit(void (*f)(void *), void *p,
|
||||
void *d);
|
||||
extern _LIBCXXABI_FUNC_VIS int __cxa_finalize(void *);
|
||||
// These functions are part of the C++ ABI, but they are not defined in libc++abi:
|
||||
// int __cxa_atexit(void (*)(void *), void *, void *);
|
||||
// void __cxa_finalize(void *);
|
||||
|
||||
// 3.4 Demangler API
|
||||
extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name,
|
||||
|
11
lib/exceptions.exp
Normal file
11
lib/exceptions.exp
Normal file
@ -0,0 +1,11 @@
|
||||
___cxa_allocate_dependent_exception
|
||||
___cxa_allocate_exception
|
||||
___cxa_begin_catch
|
||||
___cxa_call_unexpected
|
||||
___cxa_current_exception_type
|
||||
___cxa_end_catch
|
||||
___cxa_free_dependent_exception
|
||||
___cxa_free_exception
|
||||
___cxa_get_exception_ptr
|
||||
___cxa_rethrow
|
||||
___cxa_throw
|
@ -245,22 +245,13 @@ __ZTVSt9bad_alloc
|
||||
__ZTVSt9exception
|
||||
__ZTVSt9type_info
|
||||
|
||||
# Itanium C++ ABI requirements
|
||||
___cxa_allocate_dependent_exception
|
||||
___cxa_allocate_exception
|
||||
# Itanium C++ ABI requirements (minus most exception support)
|
||||
___cxa_bad_cast
|
||||
___cxa_bad_typeid
|
||||
___cxa_begin_catch
|
||||
___cxa_call_unexpected
|
||||
___cxa_current_exception_type
|
||||
___cxa_current_primary_exception
|
||||
___cxa_decrement_exception_refcount
|
||||
___cxa_deleted_virtual
|
||||
___cxa_demangle
|
||||
___cxa_end_catch
|
||||
___cxa_free_dependent_exception
|
||||
___cxa_free_exception
|
||||
___cxa_get_exception_ptr
|
||||
___cxa_get_globals
|
||||
___cxa_get_globals_fast
|
||||
___cxa_guard_abort
|
||||
@ -268,9 +259,7 @@ ___cxa_guard_acquire
|
||||
___cxa_guard_release
|
||||
___cxa_increment_exception_refcount
|
||||
___cxa_pure_virtual
|
||||
___cxa_rethrow
|
||||
___cxa_rethrow_primary_exception
|
||||
___cxa_throw
|
||||
___cxa_throw_bad_array_new_length
|
||||
___cxa_uncaught_exception
|
||||
___cxa_uncaught_exceptions
|
||||
|
@ -7,7 +7,6 @@ set(LIBCXXABI_SOURCES
|
||||
cxa_exception_storage.cpp
|
||||
cxa_guard.cpp
|
||||
cxa_handlers.cpp
|
||||
cxa_unexpected.cpp
|
||||
cxa_vector.cpp
|
||||
cxa_virtual.cpp
|
||||
# C++ STL files
|
||||
@ -21,7 +20,9 @@ set(LIBCXXABI_SOURCES
|
||||
)
|
||||
|
||||
if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS)
|
||||
list(APPEND LIBCXXABI_SOURCES stdlib_new_delete.cpp)
|
||||
list(APPEND LIBCXXABI_SOURCES
|
||||
stdlib_new_delete.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_ENABLE_EXCEPTIONS)
|
||||
@ -35,7 +36,8 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_ENABLE_THREADS AND (UNIX OR FUCHSIA) AND NOT (APPLE OR CYGWIN))
|
||||
if (LIBCXXABI_ENABLE_THREADS AND (UNIX OR FUCHSIA) AND NOT (APPLE OR CYGWIN)
|
||||
AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "AIX"))
|
||||
list(APPEND LIBCXXABI_SOURCES
|
||||
cxa_thread_atexit.cpp
|
||||
)
|
||||
@ -54,12 +56,17 @@ if (MSVC_IDE OR XCODE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories("${LIBCXXABI_LIBCXX_INCLUDES}")
|
||||
# stdlib_stdexcept.cpp depends on libc++ internals.
|
||||
include_directories("${LIBCXXABI_LIBCXX_PATH}")
|
||||
|
||||
if (LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
|
||||
add_definitions(-DHAVE___CXA_THREAD_ATEXIT_IMPL)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST)
|
||||
add_definitions(-D_LIBCXXABI_FORGIVING_DYNAMIC_CAST)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
add_library_flags_if(LIBCXXABI_HAS_SYSTEM_LIB System)
|
||||
else()
|
||||
@ -70,6 +77,11 @@ else()
|
||||
add_library_flags_if(LIBCXXABI_HAS_C_LIB c)
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_USE_COMPILER_RT)
|
||||
find_compiler_rt_library(builtins LIBCXXABI_BUILTINS_LIBRARY)
|
||||
list(APPEND LIBCXXABI_SHARED_LIBRARIES "${LIBCXXABI_BUILTINS_LIBRARY}")
|
||||
endif ()
|
||||
|
||||
if (LIBCXXABI_USE_LLVM_UNWINDER)
|
||||
# Prefer using the in-tree version of libunwind, either shared or static. If
|
||||
# none are found fall back to using -lunwind.
|
||||
@ -95,13 +107,20 @@ if (MINGW)
|
||||
# MINGW_LIBRARIES is defined in config-ix.cmake
|
||||
list(APPEND LIBCXXABI_LIBRARIES ${MINGW_LIBRARIES})
|
||||
endif()
|
||||
if (ANDROID AND ANDROID_PLATFORM_LEVEL LESS 21)
|
||||
list(APPEND LIBCXXABI_LIBRARIES android_support)
|
||||
endif()
|
||||
|
||||
if (NOT LIBCXXABI_USE_COMPILER_RT)
|
||||
add_library_flags_if(LIBCXXABI_HAS_GCC_LIB gcc)
|
||||
endif ()
|
||||
|
||||
# Setup flags.
|
||||
add_link_flags_if_supported(-nodefaultlibs)
|
||||
if (LIBCXXABI_SUPPORTS_NOSTDLIBXX_FLAG)
|
||||
add_link_flags_if_supported(-nostdlib++)
|
||||
else()
|
||||
add_link_flags_if_supported(-nodefaultlibs)
|
||||
endif()
|
||||
|
||||
if ( APPLE )
|
||||
if (LLVM_USE_SANITIZER)
|
||||
@ -128,6 +147,17 @@ if ( APPLE )
|
||||
add_link_flags("-Wl,-rpath,${LIBDIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Make sure we link in CrashReporterClient if we find it -- it's used by
|
||||
# abort() on Apple platforms when building the system dylib.
|
||||
find_library(CrashReporterClient NAMES libCrashReporterClient.a
|
||||
PATHS "${CMAKE_OSX_SYSROOT}/usr/local/lib")
|
||||
if (CrashReporterClient)
|
||||
message(STATUS "Linking with CrashReporterClient at ${CrashReporterClient}")
|
||||
add_library_flags("${CrashReporterClient}")
|
||||
else()
|
||||
message(STATUS "Could not find CrashReporterClient, not linking against it")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
split_list(LIBCXXABI_COMPILE_FLAGS)
|
||||
@ -143,64 +173,58 @@ if (NOT TARGET pstl::ParallelSTL)
|
||||
message(STATUS "Could not find ParallelSTL, libc++abi will not attempt to use it but the build may fail if the libc++ in use needs it to be available.")
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(armv6|armv7|armv7s)$")
|
||||
set(LIBCXXABI_USE_SJLJ_EXCEPTIONS ON)
|
||||
else()
|
||||
set(LIBCXXABI_USE_SJLJ_EXCEPTIONS OFF)
|
||||
endif()
|
||||
|
||||
# Build the shared library.
|
||||
if (LIBCXXABI_ENABLE_SHARED)
|
||||
add_library(cxxabi_shared SHARED ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS})
|
||||
if(COMMAND llvm_setup_rpath)
|
||||
llvm_setup_rpath(cxxabi_shared)
|
||||
endif()
|
||||
target_link_libraries(cxxabi_shared PRIVATE ${LIBCXXABI_SHARED_LIBRARIES} ${LIBCXXABI_LIBRARIES})
|
||||
target_link_libraries(cxxabi_shared PRIVATE cxx-headers ${LIBCXXABI_SHARED_LIBRARIES} ${LIBCXXABI_LIBRARIES})
|
||||
if (TARGET pstl::ParallelSTL)
|
||||
target_link_libraries(cxxabi_shared PUBLIC pstl::ParallelSTL)
|
||||
endif()
|
||||
set_target_properties(cxxabi_shared
|
||||
PROPERTIES
|
||||
CXX_EXTENSIONS
|
||||
OFF
|
||||
CXX_STANDARD
|
||||
11
|
||||
CXX_STANDARD_REQUIRED
|
||||
ON
|
||||
COMPILE_FLAGS
|
||||
"${LIBCXXABI_COMPILE_FLAGS}"
|
||||
LINK_FLAGS
|
||||
"${LIBCXXABI_LINK_FLAGS}"
|
||||
OUTPUT_NAME
|
||||
"c++abi"
|
||||
SOVERSION
|
||||
"1"
|
||||
VERSION
|
||||
"${LIBCXXABI_LIBRARY_VERSION}"
|
||||
DEFINE_SYMBOL
|
||||
"")
|
||||
|
||||
if(LIBCXXABI_ENABLE_PIC)
|
||||
set_target_properties(cxxabi_shared PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
PROPERTIES
|
||||
CXX_EXTENSIONS OFF
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED OFF
|
||||
COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}"
|
||||
OUTPUT_NAME "c++abi"
|
||||
SOVERSION "1"
|
||||
VERSION "${LIBCXXABI_LIBRARY_VERSION}"
|
||||
DEFINE_SYMBOL ""
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
|
||||
list(APPEND LIBCXXABI_BUILD_TARGETS "cxxabi_shared")
|
||||
if (LIBCXXABI_INSTALL_SHARED_LIBRARY)
|
||||
list(APPEND LIBCXXABI_INSTALL_TARGETS "cxxabi_shared")
|
||||
endif()
|
||||
|
||||
add_library(cxxabi-reexports INTERFACE)
|
||||
|
||||
# -exported_symbols_list is only available on Apple platforms
|
||||
if (APPLE)
|
||||
target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/itanium-base.exp")
|
||||
function(export_symbols file)
|
||||
target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${file}")
|
||||
endfunction()
|
||||
function(reexport_symbols file)
|
||||
export_symbols("${file}")
|
||||
target_link_libraries(cxxabi-reexports INTERFACE "-Wl,-reexported_symbols_list,${file}")
|
||||
endfunction()
|
||||
|
||||
export_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/itanium-base.exp")
|
||||
|
||||
if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS)
|
||||
target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/new-delete.exp")
|
||||
reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/new-delete.exp")
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_USE_SJLJ_EXCEPTIONS)
|
||||
target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-sjlj.exp")
|
||||
else()
|
||||
target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-v0.exp")
|
||||
if (LIBCXXABI_ENABLE_EXCEPTIONS)
|
||||
reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/exceptions.exp")
|
||||
|
||||
if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(armv6|armv7|armv7s)$")
|
||||
reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-sjlj.exp")
|
||||
else()
|
||||
reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-v0.exp")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@ -208,28 +232,20 @@ endif()
|
||||
# Build the static library.
|
||||
if (LIBCXXABI_ENABLE_STATIC)
|
||||
add_library(cxxabi_static STATIC ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS})
|
||||
target_link_libraries(cxxabi_static PRIVATE ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
|
||||
target_link_libraries(cxxabi_static PRIVATE cxx-headers ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
|
||||
if (TARGET pstl::ParallelSTL)
|
||||
target_link_libraries(cxxabi_static PUBLIC pstl::ParallelSTL)
|
||||
endif()
|
||||
set_target_properties(cxxabi_static
|
||||
PROPERTIES
|
||||
CXX_EXTENSIONS
|
||||
OFF
|
||||
CXX_STANDARD
|
||||
11
|
||||
CXX_STANDARD_REQUIRED
|
||||
ON
|
||||
COMPILE_FLAGS
|
||||
"${LIBCXXABI_COMPILE_FLAGS}"
|
||||
LINK_FLAGS
|
||||
"${LIBCXXABI_LINK_FLAGS}"
|
||||
OUTPUT_NAME
|
||||
"c++abi")
|
||||
|
||||
if(LIBCXXABI_ENABLE_PIC)
|
||||
set_target_properties(cxxabi_static PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
PROPERTIES
|
||||
CXX_EXTENSIONS OFF
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED OFF
|
||||
COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}"
|
||||
OUTPUT_NAME "c++abi"
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
|
||||
if(LIBCXXABI_HERMETIC_STATIC_LIBRARY)
|
||||
append_flags_if_supported(CXXABI_STATIC_LIBRARY_FLAGS -fvisibility=hidden)
|
||||
@ -255,10 +271,10 @@ if (LIBCXXABI_ENABLE_STATIC)
|
||||
set(MERGE_ARCHIVES_LIBTOOL "--use-libtool" "--libtool" "${CMAKE_LIBTOOL}")
|
||||
endif()
|
||||
|
||||
# Merge the the libc++abi.a and libunwind.a into one.
|
||||
# Merge the libc++abi.a and libunwind.a into one.
|
||||
if(LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
|
||||
add_custom_command(TARGET cxxabi_static POST_BUILD
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/merge_archives.py
|
||||
COMMAND ${Python3_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/merge_archives.py
|
||||
ARGS
|
||||
-o "$<TARGET_LINKER_FILE:cxxabi_static>"
|
||||
--ar "${CMAKE_AR}"
|
||||
@ -266,6 +282,7 @@ if (LIBCXXABI_ENABLE_STATIC)
|
||||
"$<TARGET_LINKER_FILE:cxxabi_static>"
|
||||
"$<TARGET_LINKER_FILE:unwind_static>"
|
||||
WORKING_DIRECTORY ${LIBCXXABI_BUILD_DIR}
|
||||
DEPENDS unwind_static
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
@ -275,8 +292,8 @@ add_custom_target(cxxabi DEPENDS ${LIBCXXABI_BUILD_TARGETS})
|
||||
|
||||
if (LIBCXXABI_INSTALL_LIBRARY)
|
||||
install(TARGETS ${LIBCXXABI_INSTALL_TARGETS}
|
||||
LIBRARY DESTINATION ${LIBCXXABI_INSTALL_PREFIX}${LIBCXXABI_INSTALL_LIBRARY_DIR} COMPONENT cxxabi
|
||||
ARCHIVE DESTINATION ${LIBCXXABI_INSTALL_PREFIX}${LIBCXXABI_INSTALL_LIBRARY_DIR} COMPONENT cxxabi
|
||||
LIBRARY DESTINATION ${LIBCXXABI_INSTALL_LIBRARY_DIR} COMPONENT cxxabi
|
||||
ARCHIVE DESTINATION ${LIBCXXABI_INSTALL_LIBRARY_DIR} COMPONENT cxxabi
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -292,7 +309,4 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND LIBCXXABI_INSTALL_LIBRARY)
|
||||
-DCMAKE_INSTALL_COMPONENT=cxxabi
|
||||
-DCMAKE_INSTALL_DO_STRIP=1
|
||||
-P "${LIBCXXABI_BINARY_DIR}/cmake_install.cmake")
|
||||
|
||||
# TODO: This is a legacy target name and should be removed at some point.
|
||||
add_custom_target(install-libcxxabi DEPENDS install-cxxabi)
|
||||
endif()
|
||||
|
@ -12,52 +12,54 @@
|
||||
#include "abort_message.h"
|
||||
|
||||
#ifdef __BIONIC__
|
||||
#include <android/api-level.h>
|
||||
#if __ANDROID_API__ >= 21
|
||||
#include <syslog.h>
|
||||
extern "C" void android_set_abort_message(const char* msg);
|
||||
#else
|
||||
#include <assert.h>
|
||||
#endif // __ANDROID_API__ >= 21
|
||||
# include <android/api-level.h>
|
||||
# if __ANDROID_API__ >= 21
|
||||
# include <syslog.h>
|
||||
extern "C" void android_set_abort_message(const char* msg);
|
||||
# else
|
||||
# include <assert.h>
|
||||
# endif // __ANDROID_API__ >= 21
|
||||
#endif // __BIONIC__
|
||||
|
||||
#ifdef __APPLE__
|
||||
# if defined(__has_include) && __has_include(<CrashReporterClient.h>)
|
||||
# define HAVE_CRASHREPORTERCLIENT_H
|
||||
# include <CrashReporterClient.h>
|
||||
# endif
|
||||
#if defined(__APPLE__) && __has_include(<CrashReporterClient.h>)
|
||||
# include <CrashReporterClient.h>
|
||||
# define _LIBCXXABI_USE_CRASHREPORTER_CLIENT
|
||||
#endif
|
||||
|
||||
void abort_message(const char* format, ...)
|
||||
{
|
||||
// write message to stderr
|
||||
// Write message to stderr. We do this before formatting into a
|
||||
// variable-size buffer so that we still get some information if
|
||||
// formatting into the variable-sized buffer fails.
|
||||
#if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL)
|
||||
#ifdef __APPLE__
|
||||
fprintf(stderr, "libc++abi.dylib: ");
|
||||
#endif
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
vfprintf(stderr, format, list);
|
||||
va_end(list);
|
||||
fprintf(stderr, "\n");
|
||||
{
|
||||
fprintf(stderr, "libc++abi: ");
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
vfprintf(stderr, format, list);
|
||||
va_end(list);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
|
||||
// record message in crash report
|
||||
// Format the arguments into an allocated buffer. We leak the buffer on
|
||||
// purpose, since we're about to abort() anyway.
|
||||
#if defined(_LIBCXXABI_USE_CRASHREPORTER_CLIENT)
|
||||
char* buffer;
|
||||
va_list list2;
|
||||
va_start(list2, format);
|
||||
vasprintf(&buffer, format, list2);
|
||||
va_end(list2);
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
vasprintf(&buffer, format, list);
|
||||
va_end(list);
|
||||
|
||||
CRSetCrashLogMessage(buffer);
|
||||
#elif defined(__BIONIC__)
|
||||
char* buffer;
|
||||
va_list list2;
|
||||
va_start(list2, format);
|
||||
vasprintf(&buffer, format, list2);
|
||||
va_end(list2);
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
vasprintf(&buffer, format, list);
|
||||
va_end(list);
|
||||
|
||||
#if __ANDROID_API__ >= 21
|
||||
# if __ANDROID_API__ >= 21
|
||||
// Show error in tombstone.
|
||||
android_set_abort_message(buffer);
|
||||
|
||||
@ -65,12 +67,12 @@ void abort_message(const char* format, ...)
|
||||
openlog("libc++abi", 0, 0);
|
||||
syslog(LOG_CRIT, "%s", buffer);
|
||||
closelog();
|
||||
#else
|
||||
# else
|
||||
// The good error reporting wasn't available in Android until L. Since we're
|
||||
// about to abort anyway, just call __assert2, which will log _somewhere_
|
||||
// (tombstone and/or logcat) in older releases.
|
||||
__assert2(__FILE__, __LINE__, __func__, buffer);
|
||||
#endif // __ANDROID_API__ >= 21
|
||||
# endif // __ANDROID_API__ >= 21
|
||||
#endif // __BIONIC__
|
||||
|
||||
abort();
|
||||
|
@ -11,16 +11,7 @@
|
||||
|
||||
#include "cxxabi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
_LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
|
||||
extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
|
||||
abort_message(const char *format, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "include/atomic_support.h"
|
||||
|
||||
#if !defined(LIBCXXABI_SILENT_TERMINATE)
|
||||
|
||||
_LIBCPP_SAFE_STATIC
|
||||
static const char* cause = "uncaught";
|
||||
|
||||
__attribute__((noreturn))
|
||||
@ -43,6 +45,7 @@ static void demangling_terminate_handler()
|
||||
exception_header + 1;
|
||||
const __shim_type_info* thrown_type =
|
||||
static_cast<const __shim_type_info*>(exception_header->exceptionType);
|
||||
#if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE)
|
||||
// Try to get demangled name of thrown_type
|
||||
int status;
|
||||
char buf[1024];
|
||||
@ -50,6 +53,9 @@ static void demangling_terminate_handler()
|
||||
const char* name = __cxa_demangle(thrown_type->name(), buf, &len, &status);
|
||||
if (status != 0)
|
||||
name = thrown_type->name();
|
||||
#else
|
||||
const char* name = thrown_type->name();
|
||||
#endif
|
||||
// If the uncaught exception can be caught with std::exception&
|
||||
const __shim_type_info* catch_type =
|
||||
static_cast<const __shim_type_info*>(&typeid(std::exception));
|
||||
@ -82,27 +88,27 @@ static void demangling_unexpected_handler()
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
static std::terminate_handler default_terminate_handler = demangling_terminate_handler;
|
||||
static std::terminate_handler default_unexpected_handler = demangling_unexpected_handler;
|
||||
static constexpr std::terminate_handler default_terminate_handler = demangling_terminate_handler;
|
||||
static constexpr std::terminate_handler default_unexpected_handler = demangling_unexpected_handler;
|
||||
#else
|
||||
static std::terminate_handler default_terminate_handler = ::abort;
|
||||
static std::terminate_handler default_unexpected_handler = std::terminate;
|
||||
static constexpr std::terminate_handler default_terminate_handler = ::abort;
|
||||
static constexpr std::terminate_handler default_unexpected_handler = std::terminate;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Global variables that hold the pointers to the current handler
|
||||
//
|
||||
_LIBCXXABI_DATA_VIS
|
||||
std::terminate_handler __cxa_terminate_handler = default_terminate_handler;
|
||||
_LIBCPP_SAFE_STATIC std::terminate_handler __cxa_terminate_handler = default_terminate_handler;
|
||||
|
||||
_LIBCXXABI_DATA_VIS
|
||||
std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;
|
||||
_LIBCPP_SAFE_STATIC std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler;
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
unexpected_handler
|
||||
set_unexpected(unexpected_handler func) _NOEXCEPT
|
||||
set_unexpected(unexpected_handler func) noexcept
|
||||
{
|
||||
if (func == 0)
|
||||
func = default_unexpected_handler;
|
||||
@ -111,7 +117,7 @@ set_unexpected(unexpected_handler func) _NOEXCEPT
|
||||
}
|
||||
|
||||
terminate_handler
|
||||
set_terminate(terminate_handler func) _NOEXCEPT
|
||||
set_terminate(terminate_handler func) noexcept
|
||||
{
|
||||
if (func == 0)
|
||||
func = default_terminate_handler;
|
||||
|
@ -86,14 +86,6 @@ struct DumpVisitor {
|
||||
else
|
||||
printStr("<null>");
|
||||
}
|
||||
void print(NodeOrString NS) {
|
||||
if (NS.isNode())
|
||||
print(NS.asNode());
|
||||
else if (NS.isString())
|
||||
print(NS.asString());
|
||||
else
|
||||
printStr("NodeOrString()");
|
||||
}
|
||||
void print(NodeArray A) {
|
||||
++Depth;
|
||||
printStr("{");
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "include/atomic_support.h"
|
||||
|
||||
#if __has_feature(address_sanitizer)
|
||||
extern "C" void __asan_handle_no_return(void);
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif
|
||||
|
||||
// +---------------------------+-----------------------------+---------------+
|
||||
@ -384,7 +384,7 @@ asm (
|
||||
" bl abort\n"
|
||||
" .popsection"
|
||||
);
|
||||
#endif // defined(_LIBCXXABI_ARM_EHABI)
|
||||
#endif // defined(_LIBCXXABI_ARM_EHABI)
|
||||
|
||||
/*
|
||||
This routine can catch foreign or native exceptions. If native, the exception
|
||||
|
@ -28,7 +28,12 @@ _LIBCXXABI_HIDDEN void __setExceptionClass ( _Unwind_Exception*, uint6
|
||||
_LIBCXXABI_HIDDEN bool __isOurExceptionClass(const _Unwind_Exception*);
|
||||
|
||||
struct _LIBCXXABI_HIDDEN __cxa_exception {
|
||||
#if defined(__LP64__) || defined(_LIBCXXABI_ARM_EHABI)
|
||||
#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
|
||||
// Now _Unwind_Exception is marked with __attribute__((aligned)),
|
||||
// which implies __cxa_exception is also aligned. Insert padding
|
||||
// in the beginning of the struct, rather than before unwindHeader.
|
||||
void *reserve;
|
||||
|
||||
// This is a new field to support C++ 0x exception_ptr.
|
||||
// For binary compatibility it is at the start of this
|
||||
// struct which is prepended to the object thrown in
|
||||
@ -57,7 +62,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
|
||||
void *adjustedPtr;
|
||||
#endif
|
||||
|
||||
#if !defined(__LP64__) && !defined(_LIBCXXABI_ARM_EHABI)
|
||||
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
|
||||
// This is a new field to support C++ 0x exception_ptr.
|
||||
// For binary compatibility it is placed where the compiler
|
||||
// previously adding padded to 64-bit align unwindHeader.
|
||||
@ -70,7 +75,8 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
|
||||
// The layout of this structure MUST match the layout of __cxa_exception, with
|
||||
// primaryException instead of referenceCount.
|
||||
struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
|
||||
#if defined(__LP64__) || defined(_LIBCXXABI_ARM_EHABI)
|
||||
#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
|
||||
void* reserve; // padding.
|
||||
void* primaryException;
|
||||
#endif
|
||||
|
||||
@ -94,12 +100,51 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
|
||||
void *adjustedPtr;
|
||||
#endif
|
||||
|
||||
#if !defined(__LP64__) && !defined(_LIBCXXABI_ARM_EHABI)
|
||||
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
|
||||
void* primaryException;
|
||||
#endif
|
||||
_Unwind_Exception unwindHeader;
|
||||
};
|
||||
|
||||
// Verify the negative offsets of different fields.
|
||||
static_assert(sizeof(_Unwind_Exception) +
|
||||
offsetof(__cxa_exception, unwindHeader) ==
|
||||
sizeof(__cxa_exception),
|
||||
"unwindHeader has wrong negative offsets");
|
||||
static_assert(sizeof(_Unwind_Exception) +
|
||||
offsetof(__cxa_dependent_exception, unwindHeader) ==
|
||||
sizeof(__cxa_dependent_exception),
|
||||
"unwindHeader has wrong negative offsets");
|
||||
|
||||
#if defined(_LIBCXXABI_ARM_EHABI)
|
||||
static_assert(offsetof(__cxa_exception, propagationCount) +
|
||||
sizeof(_Unwind_Exception) + sizeof(void*) ==
|
||||
sizeof(__cxa_exception),
|
||||
"propagationCount has wrong negative offset");
|
||||
static_assert(offsetof(__cxa_dependent_exception, propagationCount) +
|
||||
sizeof(_Unwind_Exception) + sizeof(void*) ==
|
||||
sizeof(__cxa_dependent_exception),
|
||||
"propagationCount has wrong negative offset");
|
||||
#elif defined(__LP64__) || defined(_WIN64)
|
||||
static_assert(offsetof(__cxa_exception, adjustedPtr) +
|
||||
sizeof(_Unwind_Exception) + sizeof(void*) ==
|
||||
sizeof(__cxa_exception),
|
||||
"adjustedPtr has wrong negative offset");
|
||||
static_assert(offsetof(__cxa_dependent_exception, adjustedPtr) +
|
||||
sizeof(_Unwind_Exception) + sizeof(void*) ==
|
||||
sizeof(__cxa_dependent_exception),
|
||||
"adjustedPtr has wrong negative offset");
|
||||
#else
|
||||
static_assert(offsetof(__cxa_exception, referenceCount) +
|
||||
sizeof(_Unwind_Exception) + sizeof(void*) ==
|
||||
sizeof(__cxa_exception),
|
||||
"referenceCount has wrong negative offset");
|
||||
static_assert(offsetof(__cxa_dependent_exception, primaryException) +
|
||||
sizeof(_Unwind_Exception) + sizeof(void*) ==
|
||||
sizeof(__cxa_dependent_exception),
|
||||
"primaryException has wrong negative offset");
|
||||
#endif
|
||||
|
||||
struct _LIBCXXABI_HIDDEN __cxa_eh_globals {
|
||||
__cxa_exception * caughtExceptions;
|
||||
unsigned int uncaughtExceptions;
|
||||
@ -116,4 +161,4 @@ extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * depen
|
||||
|
||||
} // namespace __cxxabiv1
|
||||
|
||||
#endif // _CXA_EXCEPTION_H
|
||||
#endif // _CXA_EXCEPTION_H
|
||||
|
@ -46,7 +46,7 @@ extern "C" {
|
||||
#include "abort_message.h"
|
||||
#include "fallback_malloc.h"
|
||||
|
||||
#if defined(__unix__) && !defined(__ANDROID__) && defined(__ELF__) && defined(_LIBCXXABI_HAS_COMMENT_LIB_PRAGMA)
|
||||
#if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include "__cxxabi_config.h"
|
||||
#include "include/atomic_support.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<sys/syscall.h>)
|
||||
# include <sys/syscall.h>
|
||||
@ -50,11 +49,19 @@
|
||||
#include <stdlib.h>
|
||||
#include <__threading_support>
|
||||
#ifndef _LIBCXXABI_HAS_NO_THREADS
|
||||
#if defined(__unix__) && !defined(__ANDROID__) && defined(__ELF__) && defined(_LIBCXXABI_HAS_COMMENT_LIB_PRAGMA)
|
||||
#if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Waddress"
|
||||
#endif
|
||||
|
||||
// To make testing possible, this header is included from both cxa_guard.cpp
|
||||
// and a number of tests.
|
||||
//
|
||||
@ -108,6 +115,32 @@ struct LazyValue {
|
||||
bool is_init = false;
|
||||
};
|
||||
|
||||
template <class IntType>
|
||||
class AtomicInt {
|
||||
public:
|
||||
using MemoryOrder = std::__libcpp_atomic_order;
|
||||
|
||||
explicit AtomicInt(IntType *b) : b_(b) {}
|
||||
AtomicInt(AtomicInt const&) = delete;
|
||||
AtomicInt& operator=(AtomicInt const&) = delete;
|
||||
|
||||
IntType load(MemoryOrder ord) {
|
||||
return std::__libcpp_atomic_load(b_, ord);
|
||||
}
|
||||
void store(IntType val, MemoryOrder ord) {
|
||||
std::__libcpp_atomic_store(b_, val, ord);
|
||||
}
|
||||
IntType exchange(IntType new_val, MemoryOrder ord) {
|
||||
return std::__libcpp_atomic_exchange(b_, new_val, ord);
|
||||
}
|
||||
bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
|
||||
return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure);
|
||||
}
|
||||
|
||||
private:
|
||||
IntType *b_;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PlatformGetThreadID
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -129,14 +162,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr;
|
||||
|
||||
|
||||
constexpr bool PlatformSupportsThreadID() {
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
|
||||
#endif
|
||||
return +PlatformThreadID != nullptr;
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -195,7 +221,7 @@ public:
|
||||
public:
|
||||
/// base_address - the address of the original guard object.
|
||||
void* const base_address;
|
||||
/// The address of the guord byte at offset 0.
|
||||
/// The address of the guard byte at offset 0.
|
||||
uint8_t* const guard_byte_address;
|
||||
/// The address of the byte used by the implementation during initialization.
|
||||
uint8_t* const init_byte_address;
|
||||
@ -350,18 +376,18 @@ private:
|
||||
LockGuard& operator=(LockGuard const&) = delete;
|
||||
|
||||
explicit LockGuard(const char* calling_func)
|
||||
: calling_func(calling_func) {
|
||||
: calling_func_(calling_func) {
|
||||
if (global_mutex.lock())
|
||||
ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func);
|
||||
ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_);
|
||||
}
|
||||
|
||||
~LockGuard() {
|
||||
if (global_mutex.unlock())
|
||||
ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func);
|
||||
ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func_);
|
||||
}
|
||||
|
||||
private:
|
||||
const char* const calling_func;
|
||||
const char* const calling_func_;
|
||||
};
|
||||
};
|
||||
|
||||
@ -386,14 +412,7 @@ constexpr void (*PlatformFutexWake)(int*) = nullptr;
|
||||
#endif
|
||||
|
||||
constexpr bool PlatformSupportsFutex() {
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
|
||||
#endif
|
||||
return +PlatformFutexWait != nullptr;
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
/// InitByteFutex - Manages initialization using atomics and the futex syscall
|
||||
@ -564,4 +583,10 @@ using SelectedImplementation =
|
||||
} // end namespace
|
||||
} // end namespace __cxxabiv1
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
|
||||
|
@ -23,7 +23,7 @@ namespace std
|
||||
{
|
||||
|
||||
unexpected_handler
|
||||
get_unexpected() _NOEXCEPT
|
||||
get_unexpected() noexcept
|
||||
{
|
||||
return __libcpp_atomic_load(&__cxa_unexpected_handler, _AO_Acquire);
|
||||
}
|
||||
@ -44,18 +44,18 @@ unexpected()
|
||||
}
|
||||
|
||||
terminate_handler
|
||||
get_terminate() _NOEXCEPT
|
||||
get_terminate() noexcept
|
||||
{
|
||||
return __libcpp_atomic_load(&__cxa_terminate_handler, _AO_Acquire);
|
||||
}
|
||||
|
||||
void
|
||||
__terminate(terminate_handler func) _NOEXCEPT
|
||||
__terminate(terminate_handler func) noexcept
|
||||
{
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
func();
|
||||
// handler should not return
|
||||
abort_message("terminate_handler unexpectedly returned");
|
||||
@ -66,12 +66,12 @@ __terminate(terminate_handler func) _NOEXCEPT
|
||||
// handler should not throw exception
|
||||
abort_message("terminate_handler unexpectedly threw an exception");
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
__attribute__((noreturn))
|
||||
void
|
||||
terminate() _NOEXCEPT
|
||||
terminate() noexcept
|
||||
{
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
// If there might be an uncaught exception
|
||||
@ -97,13 +97,13 @@ new_handler __cxa_new_handler = 0;
|
||||
}
|
||||
|
||||
new_handler
|
||||
set_new_handler(new_handler handler) _NOEXCEPT
|
||||
set_new_handler(new_handler handler) noexcept
|
||||
{
|
||||
return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
|
||||
}
|
||||
|
||||
new_handler
|
||||
get_new_handler() _NOEXCEPT
|
||||
get_new_handler() noexcept
|
||||
{
|
||||
return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
#ifndef _CXA_HANDLERS_H
|
||||
#define _CXA_HANDLERS_H
|
||||
|
||||
#include <__cxxabi_config.h>
|
||||
#include "__cxxabi_config.h"
|
||||
|
||||
#include <exception>
|
||||
|
||||
@ -25,7 +25,7 @@ __unexpected(unexpected_handler func);
|
||||
|
||||
_LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN
|
||||
void
|
||||
__terminate(terminate_handler func) _NOEXCEPT;
|
||||
__terminate(terminate_handler func) noexcept;
|
||||
|
||||
} // std
|
||||
|
||||
@ -52,4 +52,4 @@ _LIBCXXABI_DATA_VIS extern void (*__cxa_new_handler)();
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // _CXA_HANDLERS_H
|
||||
#endif // _CXA_HANDLERS_H
|
||||
|
@ -88,7 +88,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
|
||||
| +-------------+---------------------------------+------------------------------+ |
|
||||
| ... |
|
||||
+----------------------------------------------------------------------------------+
|
||||
#endif // __USING_SJLJ_EXCEPTIONS__
|
||||
#endif // __USING_SJLJ_EXCEPTIONS__
|
||||
+---------------------------------------------------------------------+
|
||||
| Beginning of Action Table ttypeIndex == 0 : cleanup |
|
||||
| ... ttypeIndex > 0 : catch |
|
||||
@ -241,10 +241,11 @@ readSLEB128(const uint8_t** data)
|
||||
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
|
||||
/// @param data reference variable holding memory pointer to decode from
|
||||
/// @param encoding dwarf encoding type
|
||||
/// @param base for adding relative offset, default to 0
|
||||
/// @returns decoded value
|
||||
static
|
||||
uintptr_t
|
||||
readEncodedPointer(const uint8_t** data, uint8_t encoding)
|
||||
readEncodedPointer(const uint8_t** data, uint8_t encoding, uintptr_t base = 0)
|
||||
{
|
||||
uintptr_t result = 0;
|
||||
if (encoding == DW_EH_PE_omit)
|
||||
@ -295,8 +296,12 @@ readEncodedPointer(const uint8_t** data, uint8_t encoding)
|
||||
if (result)
|
||||
result += (uintptr_t)(*data);
|
||||
break;
|
||||
case DW_EH_PE_textrel:
|
||||
case DW_EH_PE_datarel:
|
||||
assert((base != 0) && "DW_EH_PE_datarel is invalid with a base of 0");
|
||||
if (result)
|
||||
result += base;
|
||||
break;
|
||||
case DW_EH_PE_textrel:
|
||||
case DW_EH_PE_funcrel:
|
||||
case DW_EH_PE_aligned:
|
||||
default:
|
||||
@ -348,7 +353,7 @@ static const void* read_target2_value(const void* ptr)
|
||||
static const __shim_type_info*
|
||||
get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
|
||||
uint8_t ttypeEncoding, bool native_exception,
|
||||
_Unwind_Exception* unwind_exception)
|
||||
_Unwind_Exception* unwind_exception, uintptr_t /*base*/ = 0)
|
||||
{
|
||||
if (classInfo == 0)
|
||||
{
|
||||
@ -371,7 +376,7 @@ static
|
||||
const __shim_type_info*
|
||||
get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
|
||||
uint8_t ttypeEncoding, bool native_exception,
|
||||
_Unwind_Exception* unwind_exception)
|
||||
_Unwind_Exception* unwind_exception, uintptr_t base = 0)
|
||||
{
|
||||
if (classInfo == 0)
|
||||
{
|
||||
@ -400,7 +405,8 @@ get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
|
||||
call_terminate(native_exception, unwind_exception);
|
||||
}
|
||||
classInfo -= ttypeIndex;
|
||||
return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
|
||||
return (const __shim_type_info*)readEncodedPointer(&classInfo,
|
||||
ttypeEncoding, base);
|
||||
}
|
||||
#endif // !defined(_LIBCXXABI_ARM_EHABI)
|
||||
|
||||
@ -418,7 +424,8 @@ static
|
||||
bool
|
||||
exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
|
||||
uint8_t ttypeEncoding, const __shim_type_info* excpType,
|
||||
void* adjustedPtr, _Unwind_Exception* unwind_exception)
|
||||
void* adjustedPtr, _Unwind_Exception* unwind_exception,
|
||||
uintptr_t /*base*/ = 0)
|
||||
{
|
||||
if (classInfo == 0)
|
||||
{
|
||||
@ -463,7 +470,8 @@ static
|
||||
bool
|
||||
exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
|
||||
uint8_t ttypeEncoding, const __shim_type_info* excpType,
|
||||
void* adjustedPtr, _Unwind_Exception* unwind_exception)
|
||||
void* adjustedPtr, _Unwind_Exception* unwind_exception,
|
||||
uintptr_t base = 0)
|
||||
{
|
||||
if (classInfo == 0)
|
||||
{
|
||||
@ -485,7 +493,8 @@ exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
|
||||
classInfo,
|
||||
ttypeEncoding,
|
||||
true,
|
||||
unwind_exception);
|
||||
unwind_exception,
|
||||
base);
|
||||
void* tempPtr = adjustedPtr;
|
||||
if (catchType->can_catch(excpType, tempPtr))
|
||||
return false;
|
||||
@ -531,6 +540,9 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
|
||||
{
|
||||
#if defined(__USING_SJLJ_EXCEPTIONS__)
|
||||
#define __builtin_eh_return_data_regno(regno) regno
|
||||
#elif defined(__ibmxl__)
|
||||
// IBM xlclang++ compiler does not support __builtin_eh_return_data_regno.
|
||||
#define __builtin_eh_return_data_regno(regno) regno + 3
|
||||
#endif
|
||||
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
|
||||
reinterpret_cast<uintptr_t>(unwind_exception));
|
||||
@ -610,6 +622,11 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||
return;
|
||||
}
|
||||
results.languageSpecificData = lsda;
|
||||
#if defined(_AIX)
|
||||
uintptr_t base = _Unwind_GetDataRelBase(context);
|
||||
#else
|
||||
uintptr_t base = 0;
|
||||
#endif
|
||||
// Get the current instruction pointer and offset it before next
|
||||
// instruction in the current frame which threw the exception.
|
||||
uintptr_t ip = _Unwind_GetIP(context) - 1;
|
||||
@ -628,13 +645,14 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||
// ip is 1-based index into call site table
|
||||
#else // !__USING_SJLJ_EXCEPTIONS__
|
||||
uintptr_t ipOffset = ip - funcStart;
|
||||
#endif // !defined(_USING_SLJL_EXCEPTIONS__)
|
||||
#endif // !defined(_USING_SLJL_EXCEPTIONS__)
|
||||
const uint8_t* classInfo = NULL;
|
||||
// Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
|
||||
// dwarf emission
|
||||
// Parse LSDA header.
|
||||
uint8_t lpStartEncoding = *lsda++;
|
||||
const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
|
||||
const uint8_t* lpStart =
|
||||
(const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
|
||||
if (lpStart == 0)
|
||||
lpStart = (const uint8_t*)funcStart;
|
||||
uint8_t ttypeEncoding = *lsda++;
|
||||
@ -673,7 +691,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||
uintptr_t landingPad = readULEB128(&callSitePtr);
|
||||
uintptr_t actionEntry = readULEB128(&callSitePtr);
|
||||
if (--ip == 0)
|
||||
#endif // __USING_SJLJ_EXCEPTIONS__
|
||||
#endif // __USING_SJLJ_EXCEPTIONS__
|
||||
{
|
||||
// Found the call site containing ip.
|
||||
#ifndef __USING_SJLJ_EXCEPTIONS__
|
||||
@ -686,25 +704,19 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||
landingPad = (uintptr_t)lpStart + landingPad;
|
||||
#else // __USING_SJLJ_EXCEPTIONS__
|
||||
++landingPad;
|
||||
#endif // __USING_SJLJ_EXCEPTIONS__
|
||||
#endif // __USING_SJLJ_EXCEPTIONS__
|
||||
results.landingPad = landingPad;
|
||||
if (actionEntry == 0)
|
||||
{
|
||||
// Found a cleanup
|
||||
// If this is a type 1 or type 2 search, there are no handlers
|
||||
// If this is a type 3 search, you want to install the cleanup.
|
||||
if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
|
||||
{
|
||||
results.ttypeIndex = 0; // Redundant but clarifying
|
||||
results.landingPad = landingPad;
|
||||
results.reason = _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
// No handler here
|
||||
results.reason = _URC_CONTINUE_UNWIND;
|
||||
results.reason = actions & _UA_SEARCH_PHASE
|
||||
? _URC_CONTINUE_UNWIND
|
||||
: _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
// Convert 1-based byte offset into
|
||||
const uint8_t* action = actionTableStart + (actionEntry - 1);
|
||||
bool hasCleanup = false;
|
||||
// Scan action entries until you find a matching handler, cleanup, or the end of action list
|
||||
while (true)
|
||||
{
|
||||
@ -717,30 +729,21 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||
const __shim_type_info* catchType =
|
||||
get_shim_type_info(static_cast<uint64_t>(ttypeIndex),
|
||||
classInfo, ttypeEncoding,
|
||||
native_exception, unwind_exception);
|
||||
native_exception, unwind_exception,
|
||||
base);
|
||||
if (catchType == 0)
|
||||
{
|
||||
// Found catch (...) catches everything, including foreign exceptions
|
||||
// If this is a type 1 search save state and return _URC_HANDLER_FOUND
|
||||
// If this is a type 2 search save state and return _URC_HANDLER_FOUND
|
||||
// If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
|
||||
// If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
|
||||
if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
|
||||
{
|
||||
// Save state and return _URC_HANDLER_FOUND
|
||||
results.ttypeIndex = ttypeIndex;
|
||||
results.actionRecord = actionRecord;
|
||||
results.landingPad = landingPad;
|
||||
results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
||||
results.reason = _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
else if (!(actions & _UA_FORCE_UNWIND))
|
||||
{
|
||||
// It looks like the exception table has changed
|
||||
// on us. Likely stack corruption!
|
||||
call_terminate(native_exception, unwind_exception);
|
||||
}
|
||||
// Found catch (...) catches everything, including
|
||||
// foreign exceptions. This is search phase, cleanup
|
||||
// phase with foreign exception, or forced unwinding.
|
||||
assert(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME |
|
||||
_UA_FORCE_UNWIND));
|
||||
results.ttypeIndex = ttypeIndex;
|
||||
results.actionRecord = actionRecord;
|
||||
results.adjustedPtr =
|
||||
get_thrown_object_ptr(unwind_exception);
|
||||
results.reason = _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
// Else this is a catch (T) clause and will never
|
||||
// catch a foreign exception
|
||||
@ -757,36 +760,25 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||
}
|
||||
if (catchType->can_catch(excpType, adjustedPtr))
|
||||
{
|
||||
// Found a matching handler
|
||||
// If this is a type 1 search save state and return _URC_HANDLER_FOUND
|
||||
// If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1!
|
||||
// If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan
|
||||
if (actions & _UA_SEARCH_PHASE)
|
||||
{
|
||||
// Save state and return _URC_HANDLER_FOUND
|
||||
results.ttypeIndex = ttypeIndex;
|
||||
results.actionRecord = actionRecord;
|
||||
results.landingPad = landingPad;
|
||||
results.adjustedPtr = adjustedPtr;
|
||||
results.reason = _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
else if (!(actions & _UA_FORCE_UNWIND))
|
||||
{
|
||||
// It looks like the exception table has changed
|
||||
// on us. Likely stack corruption!
|
||||
call_terminate(native_exception, unwind_exception);
|
||||
}
|
||||
// Found a matching handler. This is either search
|
||||
// phase or forced unwinding.
|
||||
assert(actions &
|
||||
(_UA_SEARCH_PHASE | _UA_FORCE_UNWIND));
|
||||
results.ttypeIndex = ttypeIndex;
|
||||
results.actionRecord = actionRecord;
|
||||
results.adjustedPtr = adjustedPtr;
|
||||
results.reason = _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Scan next action ...
|
||||
}
|
||||
else if (ttypeIndex < 0)
|
||||
{
|
||||
// Found an exception spec. If this is a foreign exception,
|
||||
// it is always caught.
|
||||
if (native_exception)
|
||||
{
|
||||
// Found an exception specification.
|
||||
if (actions & _UA_FORCE_UNWIND) {
|
||||
// Skip if forced unwinding.
|
||||
} else if (native_exception) {
|
||||
// Does the exception spec catch this native exception?
|
||||
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
|
||||
void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
||||
@ -799,79 +791,41 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||
}
|
||||
if (exception_spec_can_catch(ttypeIndex, classInfo,
|
||||
ttypeEncoding, excpType,
|
||||
adjustedPtr, unwind_exception))
|
||||
adjustedPtr,
|
||||
unwind_exception, base))
|
||||
{
|
||||
// native exception caught by exception spec
|
||||
// If this is a type 1 search, save state and return _URC_HANDLER_FOUND
|
||||
// If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
|
||||
// If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
|
||||
if (actions & _UA_SEARCH_PHASE)
|
||||
{
|
||||
// Save state and return _URC_HANDLER_FOUND
|
||||
results.ttypeIndex = ttypeIndex;
|
||||
results.actionRecord = actionRecord;
|
||||
results.landingPad = landingPad;
|
||||
results.adjustedPtr = adjustedPtr;
|
||||
results.reason = _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
else if (!(actions & _UA_FORCE_UNWIND))
|
||||
{
|
||||
// It looks like the exception table has changed
|
||||
// on us. Likely stack corruption!
|
||||
call_terminate(native_exception, unwind_exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// foreign exception caught by exception spec
|
||||
// If this is a type 1 search, save state and return _URC_HANDLER_FOUND
|
||||
// If this is a type 2 search, save state and return _URC_HANDLER_FOUND
|
||||
// If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
|
||||
// If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
|
||||
if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
|
||||
{
|
||||
// Save state and return _URC_HANDLER_FOUND
|
||||
// Native exception caught by exception
|
||||
// specification.
|
||||
assert(actions & _UA_SEARCH_PHASE);
|
||||
results.ttypeIndex = ttypeIndex;
|
||||
results.actionRecord = actionRecord;
|
||||
results.landingPad = landingPad;
|
||||
results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
||||
results.adjustedPtr = adjustedPtr;
|
||||
results.reason = _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
else if (!(actions & _UA_FORCE_UNWIND))
|
||||
{
|
||||
// It looks like the exception table has changed
|
||||
// on us. Likely stack corruption!
|
||||
call_terminate(native_exception, unwind_exception);
|
||||
}
|
||||
}
|
||||
// Scan next action ...
|
||||
}
|
||||
else // ttypeIndex == 0
|
||||
{
|
||||
// Found a cleanup
|
||||
// If this is a type 1 search, ignore it and continue scan
|
||||
// If this is a type 2 search, ignore it and continue scan
|
||||
// If this is a type 3 search, save state and return _URC_HANDLER_FOUND
|
||||
if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
|
||||
{
|
||||
// Save state and return _URC_HANDLER_FOUND
|
||||
} else {
|
||||
// foreign exception caught by exception spec
|
||||
results.ttypeIndex = ttypeIndex;
|
||||
results.actionRecord = actionRecord;
|
||||
results.landingPad = landingPad;
|
||||
results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
|
||||
results.adjustedPtr =
|
||||
get_thrown_object_ptr(unwind_exception);
|
||||
results.reason = _URC_HANDLER_FOUND;
|
||||
return;
|
||||
}
|
||||
// Scan next action ...
|
||||
} else {
|
||||
hasCleanup = true;
|
||||
}
|
||||
const uint8_t* temp = action;
|
||||
int64_t actionOffset = readSLEB128(&temp);
|
||||
if (actionOffset == 0)
|
||||
{
|
||||
// End of action list, no matching handler or cleanup found
|
||||
results.reason = _URC_CONTINUE_UNWIND;
|
||||
// End of action list. If this is phase 2 and we have found
|
||||
// a cleanup (ttypeIndex=0), return _URC_HANDLER_FOUND;
|
||||
// otherwise return _URC_CONTINUE_UNWIND.
|
||||
results.reason = hasCleanup && actions & _UA_CLEANUP_PHASE
|
||||
? _URC_HANDLER_FOUND
|
||||
: _URC_CONTINUE_UNWIND;
|
||||
return;
|
||||
}
|
||||
// Go to next action
|
||||
@ -886,7 +840,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
|
||||
// Possible stack corruption.
|
||||
call_terminate(native_exception, unwind_exception);
|
||||
}
|
||||
#endif // !__USING_SJLJ_EXCEPTIONS__
|
||||
#endif // !__USING_SJLJ_EXCEPTIONS__
|
||||
} // there might be some tricky cases which break out of this loop
|
||||
|
||||
// It is possible that no eh table entry specify how to handle
|
||||
@ -962,78 +916,70 @@ __gxx_personality_v0
|
||||
bool native_exception = (exceptionClass & get_vendor_and_language) ==
|
||||
(kOurExceptionClass & get_vendor_and_language);
|
||||
scan_results results;
|
||||
// Process a catch handler for a native exception first.
|
||||
if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME) &&
|
||||
native_exception) {
|
||||
// Reload the results from the phase 1 cache.
|
||||
__cxa_exception* exception_header =
|
||||
(__cxa_exception*)(unwind_exception + 1) - 1;
|
||||
results.ttypeIndex = exception_header->handlerSwitchValue;
|
||||
results.actionRecord = exception_header->actionRecord;
|
||||
results.languageSpecificData = exception_header->languageSpecificData;
|
||||
results.landingPad =
|
||||
reinterpret_cast<uintptr_t>(exception_header->catchTemp);
|
||||
results.adjustedPtr = exception_header->adjustedPtr;
|
||||
|
||||
// Jump to the handler.
|
||||
set_registers(unwind_exception, context, results);
|
||||
// Cache base for calculating the address of ttype in
|
||||
// __cxa_call_unexpected.
|
||||
if (results.ttypeIndex < 0) {
|
||||
#if defined(_AIX)
|
||||
exception_header->catchTemp = (void *)_Unwind_GetDataRelBase(context);
|
||||
#else
|
||||
exception_header->catchTemp = 0;
|
||||
#endif
|
||||
}
|
||||
return _URC_INSTALL_CONTEXT;
|
||||
}
|
||||
|
||||
// In other cases we need to scan LSDA.
|
||||
scan_eh_tab(results, actions, native_exception, unwind_exception, context);
|
||||
if (results.reason == _URC_CONTINUE_UNWIND ||
|
||||
results.reason == _URC_FATAL_PHASE1_ERROR)
|
||||
return results.reason;
|
||||
|
||||
if (actions & _UA_SEARCH_PHASE)
|
||||
{
|
||||
// Phase 1 search: All we're looking for in phase 1 is a handler that
|
||||
// halts unwinding
|
||||
scan_eh_tab(results, actions, native_exception, unwind_exception, context);
|
||||
if (results.reason == _URC_HANDLER_FOUND)
|
||||
{
|
||||
// Found one. Can we cache the results somewhere to optimize phase 2?
|
||||
if (native_exception)
|
||||
{
|
||||
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
|
||||
exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
|
||||
exception_header->actionRecord = results.actionRecord;
|
||||
exception_header->languageSpecificData = results.languageSpecificData;
|
||||
exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad);
|
||||
exception_header->adjustedPtr = results.adjustedPtr;
|
||||
}
|
||||
return _URC_HANDLER_FOUND;
|
||||
assert(results.reason == _URC_HANDLER_FOUND);
|
||||
if (native_exception) {
|
||||
// For a native exception, cache the LSDA result.
|
||||
__cxa_exception* exc = (__cxa_exception*)(unwind_exception + 1) - 1;
|
||||
exc->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
|
||||
exc->actionRecord = results.actionRecord;
|
||||
exc->languageSpecificData = results.languageSpecificData;
|
||||
exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
|
||||
exc->adjustedPtr = results.adjustedPtr;
|
||||
}
|
||||
// Did not find a catching-handler. Return the results of the scan
|
||||
// (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR
|
||||
// if we were called improperly).
|
||||
return results.reason;
|
||||
return _URC_HANDLER_FOUND;
|
||||
}
|
||||
if (actions & _UA_CLEANUP_PHASE)
|
||||
{
|
||||
// Phase 2 search:
|
||||
// Did we find a catching handler in phase 1?
|
||||
if (actions & _UA_HANDLER_FRAME)
|
||||
{
|
||||
// Yes, phase 1 said we have a catching handler here.
|
||||
// Did we cache the results of the scan?
|
||||
if (native_exception)
|
||||
{
|
||||
// Yes, reload the results from the cache.
|
||||
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
|
||||
results.ttypeIndex = exception_header->handlerSwitchValue;
|
||||
results.actionRecord = exception_header->actionRecord;
|
||||
results.languageSpecificData = exception_header->languageSpecificData;
|
||||
results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp);
|
||||
results.adjustedPtr = exception_header->adjustedPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, do the scan again to reload the results.
|
||||
scan_eh_tab(results, actions, native_exception, unwind_exception, context);
|
||||
// Phase 1 told us we would find a handler. Now in Phase 2 we
|
||||
// didn't find a handler. The eh table should not be changing!
|
||||
if (results.reason != _URC_HANDLER_FOUND)
|
||||
call_terminate(native_exception, unwind_exception);
|
||||
}
|
||||
// Jump to the handler
|
||||
set_registers(unwind_exception, context, results);
|
||||
return _URC_INSTALL_CONTEXT;
|
||||
}
|
||||
// Either we didn't do a phase 1 search (due to forced unwinding), or
|
||||
// phase 1 reported no catching-handlers.
|
||||
// Search for a (non-catching) cleanup
|
||||
scan_eh_tab(results, actions, native_exception, unwind_exception, context);
|
||||
if (results.reason == _URC_HANDLER_FOUND)
|
||||
{
|
||||
// Found a non-catching handler. Jump to it:
|
||||
set_registers(unwind_exception, context, results);
|
||||
return _URC_INSTALL_CONTEXT;
|
||||
}
|
||||
// Did not find a cleanup. Return the results of the scan
|
||||
// (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR
|
||||
// if we were called improperly).
|
||||
return results.reason;
|
||||
|
||||
assert(actions & _UA_CLEANUP_PHASE);
|
||||
assert(results.reason == _URC_HANDLER_FOUND);
|
||||
set_registers(unwind_exception, context, results);
|
||||
// Cache base for calculating the address of ttype in __cxa_call_unexpected.
|
||||
if (results.ttypeIndex < 0) {
|
||||
__cxa_exception* exception_header =
|
||||
(__cxa_exception*)(unwind_exception + 1) - 1;
|
||||
#if defined(_AIX)
|
||||
exception_header->catchTemp = (void *)_Unwind_GetDataRelBase(context);
|
||||
#else
|
||||
exception_header->catchTemp = 0;
|
||||
#endif
|
||||
}
|
||||
// We were called improperly: neither a phase 1 or phase 2 search
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
return _URC_INSTALL_CONTEXT;
|
||||
}
|
||||
|
||||
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
|
||||
@ -1207,6 +1153,8 @@ __cxa_call_unexpected(void* arg)
|
||||
__cxa_exception* old_exception_header = 0;
|
||||
int64_t ttypeIndex;
|
||||
const uint8_t* lsda;
|
||||
uintptr_t base = 0;
|
||||
|
||||
if (native_old_exception)
|
||||
{
|
||||
old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
|
||||
@ -1220,6 +1168,7 @@ __cxa_call_unexpected(void* arg)
|
||||
#else
|
||||
ttypeIndex = old_exception_header->handlerSwitchValue;
|
||||
lsda = old_exception_header->languageSpecificData;
|
||||
base = (uintptr_t)old_exception_header->catchTemp;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@ -1243,11 +1192,13 @@ __cxa_call_unexpected(void* arg)
|
||||
// Have:
|
||||
// old_exception_header->languageSpecificData
|
||||
// old_exception_header->actionRecord
|
||||
// old_exception_header->catchTemp, base for calculating ttype
|
||||
// Need
|
||||
// const uint8_t* classInfo
|
||||
// uint8_t ttypeEncoding
|
||||
uint8_t lpStartEncoding = *lsda++;
|
||||
const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
|
||||
const uint8_t* lpStart =
|
||||
(const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
|
||||
(void)lpStart; // purposefully unused. Just needed to increment lsda.
|
||||
uint8_t ttypeEncoding = *lsda++;
|
||||
if (ttypeEncoding == DW_EH_PE_omit)
|
||||
@ -1274,7 +1225,8 @@ __cxa_call_unexpected(void* arg)
|
||||
((__cxa_dependent_exception*)new_exception_header)->primaryException :
|
||||
new_exception_header + 1;
|
||||
if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
|
||||
excpType, adjustedPtr, unwind_exception))
|
||||
excpType, adjustedPtr,
|
||||
unwind_exception, base))
|
||||
{
|
||||
// We need to __cxa_end_catch, but for the old exception,
|
||||
// not the new one. This is a little tricky ...
|
||||
@ -1303,7 +1255,8 @@ __cxa_call_unexpected(void* arg)
|
||||
std::bad_exception be;
|
||||
adjustedPtr = &be;
|
||||
if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
|
||||
excpType, adjustedPtr, unwind_exception))
|
||||
excpType, adjustedPtr,
|
||||
unwind_exception, base))
|
||||
{
|
||||
// We need to __cxa_end_catch for both the old exception and the
|
||||
// new exception. Technically we should do it in that order.
|
||||
@ -1319,6 +1272,15 @@ __cxa_call_unexpected(void* arg)
|
||||
std::__terminate(t_handler);
|
||||
}
|
||||
|
||||
#if defined(_AIX)
|
||||
// Personality routine for EH using the range table. Make it an alias of
|
||||
// __gxx_personality_v0().
|
||||
_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(
|
||||
int version, _Unwind_Action actions, uint64_t exceptionClass,
|
||||
_Unwind_Exception* unwind_exception, _Unwind_Context* context)
|
||||
__attribute__((__alias__("__gxx_personality_v0")));
|
||||
#endif
|
||||
|
||||
} // extern "C"
|
||||
|
||||
} // __cxxabiv1
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "cxxabi.h"
|
||||
#include <__threading_support>
|
||||
#ifndef _LIBCXXABI_HAS_NO_THREADS
|
||||
#if defined(__unix__) && !defined(__ANDROID__) && defined(__ELF__) && defined(_LIBCXXABI_HAS_COMMENT_LIB_PRAGMA)
|
||||
#if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
#endif
|
||||
@ -22,16 +22,12 @@ namespace __cxxabiv1 {
|
||||
using Dtor = void(*)(void*);
|
||||
|
||||
extern "C"
|
||||
#ifndef __APPLE__
|
||||
#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
|
||||
// A weak symbol is used to detect this function's presence in the C library
|
||||
// at runtime, even if libc++ is built against an older libc
|
||||
_LIBCXXABI_WEAK
|
||||
#endif
|
||||
int __cxa_thread_atexit_impl(Dtor, void*, void*);
|
||||
#else
|
||||
int (*__cxa_thread_atexit_impl)(Dtor, void*, void*) = nullptr;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
//===------------------------- cxa_unexpected.cpp -------------------------===//
|
||||
//
|
||||
// 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 <exception>
|
||||
#include "cxxabi.h"
|
||||
#include "cxa_exception.h"
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
} // namespace __cxxabiv1
|
||||
|
@ -24,9 +24,9 @@
|
||||
|
||||
namespace __cxxabiv1 {
|
||||
|
||||
#if 0
|
||||
#pragma mark --Helper routines and classes --
|
||||
#endif
|
||||
//
|
||||
// Helper routines and classes
|
||||
//
|
||||
|
||||
namespace {
|
||||
inline static size_t __get_element_count ( void *p ) {
|
||||
@ -111,9 +111,9 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
#if 0
|
||||
#pragma mark --Externally visible routines--
|
||||
#endif
|
||||
//
|
||||
// Externally visible routines
|
||||
//
|
||||
|
||||
namespace {
|
||||
_LIBCXXABI_NORETURN
|
||||
|
@ -82,6 +82,7 @@
|
||||
X(PostfixExpr) \
|
||||
X(ConditionalExpr) \
|
||||
X(MemberExpr) \
|
||||
X(SubobjectExpr) \
|
||||
X(EnclosingExpr) \
|
||||
X(CastExpr) \
|
||||
X(SizeofParamPackExpr) \
|
||||
@ -91,14 +92,14 @@
|
||||
X(PrefixExpr) \
|
||||
X(FunctionParam) \
|
||||
X(ConversionExpr) \
|
||||
X(PointerToMemberConversionExpr) \
|
||||
X(InitListExpr) \
|
||||
X(FoldExpr) \
|
||||
X(ThrowExpr) \
|
||||
X(UUIDOfExpr) \
|
||||
X(BoolExpr) \
|
||||
X(StringLiteral) \
|
||||
X(LambdaExpr) \
|
||||
X(IntegerCastExpr) \
|
||||
X(EnumLiteral) \
|
||||
X(IntegerLiteral) \
|
||||
X(FloatLiteral) \
|
||||
X(DoubleLiteral) \
|
||||
@ -279,17 +280,20 @@ public:
|
||||
class VendorExtQualType final : public Node {
|
||||
const Node *Ty;
|
||||
StringView Ext;
|
||||
const Node *TA;
|
||||
|
||||
public:
|
||||
VendorExtQualType(const Node *Ty_, StringView Ext_)
|
||||
: Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}
|
||||
VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
|
||||
: Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Ty, Ext); }
|
||||
template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
|
||||
|
||||
void printLeft(OutputStream &S) const override {
|
||||
Ty->print(S);
|
||||
S += " ";
|
||||
S += Ext;
|
||||
if (TA != nullptr)
|
||||
TA->print(S);
|
||||
}
|
||||
};
|
||||
|
||||
@ -607,48 +611,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class NodeOrString {
|
||||
const void *First;
|
||||
const void *Second;
|
||||
|
||||
public:
|
||||
/* implicit */ NodeOrString(StringView Str) {
|
||||
const char *FirstChar = Str.begin();
|
||||
const char *SecondChar = Str.end();
|
||||
if (SecondChar == nullptr) {
|
||||
assert(FirstChar == SecondChar);
|
||||
++FirstChar, ++SecondChar;
|
||||
}
|
||||
First = static_cast<const void *>(FirstChar);
|
||||
Second = static_cast<const void *>(SecondChar);
|
||||
}
|
||||
|
||||
/* implicit */ NodeOrString(Node *N)
|
||||
: First(static_cast<const void *>(N)), Second(nullptr) {}
|
||||
NodeOrString() : First(nullptr), Second(nullptr) {}
|
||||
|
||||
bool isString() const { return Second && First; }
|
||||
bool isNode() const { return First && !Second; }
|
||||
bool isEmpty() const { return !First && !Second; }
|
||||
|
||||
StringView asString() const {
|
||||
assert(isString());
|
||||
return StringView(static_cast<const char *>(First),
|
||||
static_cast<const char *>(Second));
|
||||
}
|
||||
|
||||
const Node *asNode() const {
|
||||
assert(isNode());
|
||||
return static_cast<const Node *>(First);
|
||||
}
|
||||
};
|
||||
|
||||
class ArrayType final : public Node {
|
||||
const Node *Base;
|
||||
NodeOrString Dimension;
|
||||
Node *Dimension;
|
||||
|
||||
public:
|
||||
ArrayType(const Node *Base_, NodeOrString Dimension_)
|
||||
ArrayType(const Node *Base_, Node *Dimension_)
|
||||
: Node(KArrayType,
|
||||
/*RHSComponentCache=*/Cache::Yes,
|
||||
/*ArrayCache=*/Cache::Yes),
|
||||
@ -665,10 +633,8 @@ public:
|
||||
if (S.back() != ']')
|
||||
S += " ";
|
||||
S += "[";
|
||||
if (Dimension.isString())
|
||||
S += Dimension.asString();
|
||||
else if (Dimension.isNode())
|
||||
Dimension.asNode()->print(S);
|
||||
if (Dimension)
|
||||
Dimension->print(S);
|
||||
S += "]";
|
||||
Base->printRight(S);
|
||||
}
|
||||
@ -934,10 +900,10 @@ public:
|
||||
|
||||
class VectorType final : public Node {
|
||||
const Node *BaseType;
|
||||
const NodeOrString Dimension;
|
||||
const Node *Dimension;
|
||||
|
||||
public:
|
||||
VectorType(const Node *BaseType_, NodeOrString Dimension_)
|
||||
VectorType(const Node *BaseType_, Node *Dimension_)
|
||||
: Node(KVectorType), BaseType(BaseType_),
|
||||
Dimension(Dimension_) {}
|
||||
|
||||
@ -946,19 +912,17 @@ public:
|
||||
void printLeft(OutputStream &S) const override {
|
||||
BaseType->print(S);
|
||||
S += " vector[";
|
||||
if (Dimension.isNode())
|
||||
Dimension.asNode()->print(S);
|
||||
else if (Dimension.isString())
|
||||
S += Dimension.asString();
|
||||
if (Dimension)
|
||||
Dimension->print(S);
|
||||
S += "]";
|
||||
}
|
||||
};
|
||||
|
||||
class PixelVectorType final : public Node {
|
||||
const NodeOrString Dimension;
|
||||
const Node *Dimension;
|
||||
|
||||
public:
|
||||
PixelVectorType(NodeOrString Dimension_)
|
||||
PixelVectorType(const Node *Dimension_)
|
||||
: Node(KPixelVectorType), Dimension(Dimension_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Dimension); }
|
||||
@ -966,7 +930,7 @@ public:
|
||||
void printLeft(OutputStream &S) const override {
|
||||
// FIXME: This should demangle as "vector pixel".
|
||||
S += "pixel vector[";
|
||||
S += Dimension.asString();
|
||||
Dimension->print(S);
|
||||
S += "]";
|
||||
}
|
||||
};
|
||||
@ -1696,6 +1660,40 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class SubobjectExpr : public Node {
|
||||
const Node *Type;
|
||||
const Node *SubExpr;
|
||||
StringView Offset;
|
||||
NodeArray UnionSelectors;
|
||||
bool OnePastTheEnd;
|
||||
|
||||
public:
|
||||
SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
|
||||
NodeArray UnionSelectors_, bool OnePastTheEnd_)
|
||||
: Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
|
||||
UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const {
|
||||
F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
|
||||
}
|
||||
|
||||
void printLeft(OutputStream &S) const override {
|
||||
SubExpr->print(S);
|
||||
S += ".<";
|
||||
Type->print(S);
|
||||
S += " at offset ";
|
||||
if (Offset.empty()) {
|
||||
S += "0";
|
||||
} else if (Offset[0] == 'n') {
|
||||
S += "-";
|
||||
S += Offset.dropFront();
|
||||
} else {
|
||||
S += Offset;
|
||||
}
|
||||
S += ">";
|
||||
}
|
||||
};
|
||||
|
||||
class EnclosingExpr : public Node {
|
||||
const StringView Prefix;
|
||||
const Node *Infix;
|
||||
@ -1883,6 +1881,28 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class PointerToMemberConversionExpr : public Node {
|
||||
const Node *Type;
|
||||
const Node *SubExpr;
|
||||
StringView Offset;
|
||||
|
||||
public:
|
||||
PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
|
||||
StringView Offset_)
|
||||
: Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_),
|
||||
Offset(Offset_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
|
||||
|
||||
void printLeft(OutputStream &S) const override {
|
||||
S += "(";
|
||||
Type->print(S);
|
||||
S += ")(";
|
||||
SubExpr->print(S);
|
||||
S += ")";
|
||||
}
|
||||
};
|
||||
|
||||
class InitListExpr : public Node {
|
||||
const Node *Ty;
|
||||
NodeArray Inits;
|
||||
@ -2017,21 +2037,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// MSVC __uuidof extension, generated by clang in -fms-extensions mode.
|
||||
class UUIDOfExpr : public Node {
|
||||
Node *Operand;
|
||||
public:
|
||||
UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Operand); }
|
||||
|
||||
void printLeft(OutputStream &S) const override {
|
||||
S << "__uuidof(";
|
||||
Operand->print(S);
|
||||
S << ")";
|
||||
}
|
||||
};
|
||||
|
||||
class BoolExpr : public Node {
|
||||
bool Value;
|
||||
|
||||
@ -2076,22 +2081,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class IntegerCastExpr : public Node {
|
||||
class EnumLiteral : public Node {
|
||||
// ty(integer)
|
||||
const Node *Ty;
|
||||
StringView Integer;
|
||||
|
||||
public:
|
||||
IntegerCastExpr(const Node *Ty_, StringView Integer_)
|
||||
: Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {}
|
||||
EnumLiteral(const Node *Ty_, StringView Integer_)
|
||||
: Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
|
||||
|
||||
template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
|
||||
|
||||
void printLeft(OutputStream &S) const override {
|
||||
S += "(";
|
||||
S << "(";
|
||||
Ty->print(S);
|
||||
S += ")";
|
||||
S += Integer;
|
||||
S << ")";
|
||||
|
||||
if (Integer[0] == 'n')
|
||||
S << "-" << Integer.dropFront(1);
|
||||
else
|
||||
S << Integer;
|
||||
}
|
||||
};
|
||||
|
||||
@ -2213,10 +2222,10 @@ class PODSmallVector {
|
||||
static_assert(std::is_pod<T>::value,
|
||||
"T is required to be a plain old data type");
|
||||
|
||||
T* First;
|
||||
T* Last;
|
||||
T* Cap;
|
||||
T Inline[N];
|
||||
T* First = nullptr;
|
||||
T* Last = nullptr;
|
||||
T* Cap = nullptr;
|
||||
T Inline[N] = {0};
|
||||
|
||||
bool isInline() const { return First == Inline; }
|
||||
|
||||
@ -2349,9 +2358,9 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
|
||||
TemplateParamList Params;
|
||||
|
||||
public:
|
||||
ScopedTemplateParamList(AbstractManglingParser *Parser)
|
||||
: Parser(Parser),
|
||||
OldNumTemplateParamLists(Parser->TemplateParams.size()) {
|
||||
ScopedTemplateParamList(AbstractManglingParser *TheParser)
|
||||
: Parser(TheParser),
|
||||
OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
|
||||
Parser->TemplateParams.push_back(&Params);
|
||||
}
|
||||
~ScopedTemplateParamList() {
|
||||
@ -2473,6 +2482,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
|
||||
Node *parseConversionExpr();
|
||||
Node *parseBracedExpr();
|
||||
Node *parseFoldExpr();
|
||||
Node *parsePointerToMemberConversionExpr();
|
||||
Node *parseSubobjectExpr();
|
||||
|
||||
/// Parse the <type> production.
|
||||
Node *parseType();
|
||||
@ -3548,7 +3559,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
|
||||
if (!consumeIf("Dv"))
|
||||
return nullptr;
|
||||
if (look() >= '1' && look() <= '9') {
|
||||
StringView DimensionNumber = parseNumber();
|
||||
Node *DimensionNumber = make<NameType>(parseNumber());
|
||||
if (!DimensionNumber)
|
||||
return nullptr;
|
||||
if (!consumeIf('_'))
|
||||
return nullptr;
|
||||
if (consumeIf('p'))
|
||||
@ -3573,7 +3586,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
|
||||
Node *ElemType = getDerived().parseType();
|
||||
if (!ElemType)
|
||||
return nullptr;
|
||||
return make<VectorType>(ElemType, StringView());
|
||||
return make<VectorType>(ElemType, /*Dimension=*/nullptr);
|
||||
}
|
||||
|
||||
// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
|
||||
@ -3599,10 +3612,12 @@ Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
|
||||
if (!consumeIf('A'))
|
||||
return nullptr;
|
||||
|
||||
NodeOrString Dimension;
|
||||
Node *Dimension = nullptr;
|
||||
|
||||
if (std::isdigit(look())) {
|
||||
Dimension = parseNumber();
|
||||
Dimension = make<NameType>(parseNumber());
|
||||
if (!Dimension)
|
||||
return nullptr;
|
||||
if (!consumeIf('_'))
|
||||
return nullptr;
|
||||
} else if (!consumeIf('_')) {
|
||||
@ -3668,8 +3683,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
|
||||
if (Qual.empty())
|
||||
return nullptr;
|
||||
|
||||
// FIXME parse the optional <template-args> here!
|
||||
|
||||
// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
|
||||
if (Qual.startsWith("objcproto")) {
|
||||
StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
|
||||
@ -3687,10 +3700,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
|
||||
return make<ObjCProtoName>(Child, Proto);
|
||||
}
|
||||
|
||||
Node *TA = nullptr;
|
||||
if (look() == 'I') {
|
||||
TA = getDerived().parseTemplateArgs();
|
||||
if (TA == nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node *Child = getDerived().parseQualifiedType();
|
||||
if (Child == nullptr)
|
||||
return nullptr;
|
||||
return make<VendorExtQualType>(Child, Qual);
|
||||
return make<VendorExtQualType>(Child, Qual, TA);
|
||||
}
|
||||
|
||||
Qualifiers Quals = parseCVQualifiers();
|
||||
@ -3863,7 +3883,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
|
||||
// ::= Dh # IEEE 754r half-precision floating point (16 bits)
|
||||
case 'h':
|
||||
First += 2;
|
||||
return make<NameType>("decimal16");
|
||||
return make<NameType>("half");
|
||||
// ::= Di # char32_t
|
||||
case 'i':
|
||||
First += 2;
|
||||
@ -4100,8 +4120,11 @@ Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
|
||||
// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
|
||||
// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
|
||||
// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
|
||||
// ::= fpT # 'this' expression (not part of standard?)
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
|
||||
if (consumeIf("fpT"))
|
||||
return make<NameType>("this");
|
||||
if (consumeIf("fp")) {
|
||||
parseCVQualifiers();
|
||||
StringView Num = parseNumber();
|
||||
@ -4261,7 +4284,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
|
||||
return getDerived().template parseFloatingLiteral<double>();
|
||||
case 'e':
|
||||
++First;
|
||||
#if defined(__powerpc__) || defined(__s390__)
|
||||
// Handle cases where long doubles encoded with e have the same size
|
||||
// and representation as doubles.
|
||||
return getDerived().template parseFloatingLiteral<double>();
|
||||
#else
|
||||
return getDerived().template parseFloatingLiteral<long double>();
|
||||
#endif
|
||||
case '_':
|
||||
if (consumeIf("_Z")) {
|
||||
Node *R = getDerived().parseEncoding();
|
||||
@ -4300,12 +4329,12 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
|
||||
Node *T = getDerived().parseType();
|
||||
if (T == nullptr)
|
||||
return nullptr;
|
||||
StringView N = parseNumber();
|
||||
StringView N = parseNumber(/*AllowNegative=*/true);
|
||||
if (N.empty())
|
||||
return nullptr;
|
||||
if (!consumeIf('E'))
|
||||
return nullptr;
|
||||
return make<IntegerCastExpr>(T, N);
|
||||
return make<EnumLiteral>(T, N);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4427,6 +4456,50 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
|
||||
return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
|
||||
}
|
||||
|
||||
// <expression> ::= mc <parameter type> <expr> [<offset number>] E
|
||||
//
|
||||
// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() {
|
||||
Node *Ty = getDerived().parseType();
|
||||
if (!Ty)
|
||||
return nullptr;
|
||||
Node *Expr = getDerived().parseExpr();
|
||||
if (!Expr)
|
||||
return nullptr;
|
||||
StringView Offset = getDerived().parseNumber(true);
|
||||
if (!consumeIf('E'))
|
||||
return nullptr;
|
||||
return make<PointerToMemberConversionExpr>(Ty, Expr, Offset);
|
||||
}
|
||||
|
||||
// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
|
||||
// <union-selector> ::= _ [<number>]
|
||||
//
|
||||
// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
|
||||
Node *Ty = getDerived().parseType();
|
||||
if (!Ty)
|
||||
return nullptr;
|
||||
Node *Expr = getDerived().parseExpr();
|
||||
if (!Expr)
|
||||
return nullptr;
|
||||
StringView Offset = getDerived().parseNumber(true);
|
||||
size_t SelectorsBegin = Names.size();
|
||||
while (consumeIf('_')) {
|
||||
Node *Selector = make<NameType>(parseNumber());
|
||||
if (!Selector)
|
||||
return nullptr;
|
||||
Names.push_back(Selector);
|
||||
}
|
||||
bool OnePastTheEnd = consumeIf('p');
|
||||
if (!consumeIf('E'))
|
||||
return nullptr;
|
||||
return make<SubobjectExpr>(
|
||||
Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
|
||||
}
|
||||
|
||||
// <expression> ::= <unary operator-name> <expression>
|
||||
// ::= <binary operator-name> <expression> <expression>
|
||||
// ::= <ternary operator-name> <expression> <expression> <expression>
|
||||
@ -4684,6 +4757,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
|
||||
return nullptr;
|
||||
case 'm':
|
||||
switch (First[1]) {
|
||||
case 'c':
|
||||
First += 2;
|
||||
return parsePointerToMemberConversionExpr();
|
||||
case 'i':
|
||||
First += 2;
|
||||
return getDerived().parseBinaryExpr("-");
|
||||
@ -4831,6 +4907,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
|
||||
return Ex;
|
||||
return make<CastExpr>("static_cast", T, Ex);
|
||||
}
|
||||
case 'o':
|
||||
First += 2;
|
||||
return parseSubobjectExpr();
|
||||
case 'p': {
|
||||
First += 2;
|
||||
Node *Child = getDerived().parseExpr();
|
||||
@ -4926,6 +5005,43 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
case 'u': {
|
||||
++First;
|
||||
Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
|
||||
if (!Name)
|
||||
return nullptr;
|
||||
// Special case legacy __uuidof mangling. The 't' and 'z' appear where the
|
||||
// standard encoding expects a <template-arg>, and would be otherwise be
|
||||
// interpreted as <type> node 'short' or 'ellipsis'. However, neither
|
||||
// __uuidof(short) nor __uuidof(...) can actually appear, so there is no
|
||||
// actual conflict here.
|
||||
if (Name->getBaseName() == "__uuidof") {
|
||||
if (numLeft() < 2)
|
||||
return nullptr;
|
||||
if (*First == 't') {
|
||||
++First;
|
||||
Node *Ty = getDerived().parseType();
|
||||
if (!Ty)
|
||||
return nullptr;
|
||||
return make<CallExpr>(Name, makeNodeArray(&Ty, &Ty + 1));
|
||||
}
|
||||
if (*First == 'z') {
|
||||
++First;
|
||||
Node *Ex = getDerived().parseExpr();
|
||||
if (!Ex)
|
||||
return nullptr;
|
||||
return make<CallExpr>(Name, makeNodeArray(&Ex, &Ex + 1));
|
||||
}
|
||||
}
|
||||
size_t ExprsBegin = Names.size();
|
||||
while (!consumeIf('E')) {
|
||||
Node *E = getDerived().parseTemplateArg();
|
||||
if (E == nullptr)
|
||||
return E;
|
||||
Names.push_back(E);
|
||||
}
|
||||
return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin));
|
||||
}
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
@ -4937,21 +5053,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
|
||||
case '9':
|
||||
return getDerived().parseUnresolvedName();
|
||||
}
|
||||
|
||||
if (consumeIf("u8__uuidoft")) {
|
||||
Node *Ty = getDerived().parseType();
|
||||
if (!Ty)
|
||||
return nullptr;
|
||||
return make<UUIDOfExpr>(Ty);
|
||||
}
|
||||
|
||||
if (consumeIf("u8__uuidofz")) {
|
||||
Node *Ex = getDerived().parseExpr();
|
||||
if (!Ex)
|
||||
return nullptr;
|
||||
return make<UUIDOfExpr>(Ex);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -4998,6 +5099,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
|
||||
switch (look()) {
|
||||
case 'T':
|
||||
switch (look(1)) {
|
||||
// TA <template-arg> # template parameter object
|
||||
//
|
||||
// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
|
||||
case 'A': {
|
||||
First += 2;
|
||||
Node *Arg = getDerived().parseTemplateArg();
|
||||
if (Arg == nullptr)
|
||||
return nullptr;
|
||||
return make<SpecialName>("template parameter object for ", Arg);
|
||||
}
|
||||
// TV <type> # virtual table
|
||||
case 'V': {
|
||||
First += 2;
|
||||
@ -5119,6 +5230,26 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
|
||||
// ::= <special-name>
|
||||
template <typename Derived, typename Alloc>
|
||||
Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
|
||||
// The template parameters of an encoding are unrelated to those of the
|
||||
// enclosing context.
|
||||
class SaveTemplateParams {
|
||||
AbstractManglingParser *Parser;
|
||||
decltype(TemplateParams) OldParams;
|
||||
decltype(OuterTemplateParams) OldOuterParams;
|
||||
|
||||
public:
|
||||
SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
|
||||
OldParams = std::move(Parser->TemplateParams);
|
||||
OldOuterParams = std::move(Parser->OuterTemplateParams);
|
||||
Parser->TemplateParams.clear();
|
||||
Parser->OuterTemplateParams.clear();
|
||||
}
|
||||
~SaveTemplateParams() {
|
||||
Parser->TemplateParams = std::move(OldParams);
|
||||
Parser->OuterTemplateParams = std::move(OldOuterParams);
|
||||
}
|
||||
} SaveTemplateParams(this);
|
||||
|
||||
if (look() == 'G' || look() == 'T')
|
||||
return getDerived().parseSpecialName();
|
||||
|
||||
@ -5210,7 +5341,12 @@ struct FloatData<long double>
|
||||
#else
|
||||
static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
|
||||
#endif
|
||||
static const size_t max_demangled_size = 40;
|
||||
// `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
|
||||
// 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
|
||||
// Negatives are one character longer than positives.
|
||||
// `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
|
||||
// same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
|
||||
static const size_t max_demangled_size = 42;
|
||||
static constexpr const char *spec = "%LaL";
|
||||
};
|
||||
|
||||
|
@ -36,8 +36,9 @@ public:
|
||||
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
|
||||
StringView() : First(nullptr), Last(nullptr) {}
|
||||
|
||||
StringView substr(size_t From) const {
|
||||
return StringView(begin() + From, size() - From);
|
||||
StringView substr(size_t Pos, size_t Len = npos) const {
|
||||
assert(Pos <= size());
|
||||
return StringView(begin() + Pos, std::min(Len, size() - Pos));
|
||||
}
|
||||
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
@ -51,14 +52,6 @@ public:
|
||||
return npos;
|
||||
}
|
||||
|
||||
StringView substr(size_t From, size_t To) const {
|
||||
if (To >= size())
|
||||
To = size() - 1;
|
||||
if (From >= size())
|
||||
From = size() - 1;
|
||||
return StringView(First + From, First + To);
|
||||
}
|
||||
|
||||
StringView dropFront(size_t N = 1) const {
|
||||
if (N >= size())
|
||||
N = size();
|
||||
|
@ -25,9 +25,9 @@ DEMANGLE_NAMESPACE_BEGIN
|
||||
// Stream that AST nodes write their string representation into after the AST
|
||||
// has been parsed.
|
||||
class OutputStream {
|
||||
char *Buffer;
|
||||
size_t CurrentPosition;
|
||||
size_t BufferCapacity;
|
||||
char *Buffer = nullptr;
|
||||
size_t CurrentPosition = 0;
|
||||
size_t BufferCapacity = 0;
|
||||
|
||||
// Ensure there is at least n more positions in buffer.
|
||||
void grow(size_t N) {
|
||||
@ -52,7 +52,7 @@ class OutputStream {
|
||||
char *TempPtr = std::end(Temp);
|
||||
|
||||
while (N) {
|
||||
*--TempPtr = '0' + char(N % 10);
|
||||
*--TempPtr = char('0' + N % 10);
|
||||
N /= 10;
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ public:
|
||||
|
||||
char *getBuffer() { return Buffer; }
|
||||
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
|
||||
size_t getBufferCapacity() { return BufferCapacity; }
|
||||
size_t getBufferCapacity() const { return BufferCapacity; }
|
||||
};
|
||||
|
||||
template <class T> class SwapAndRestore {
|
||||
|
@ -6,20 +6,18 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Define _LIBCPP_BUILDING_LIBRARY to ensure _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
|
||||
// is only defined when libc aligned allocation is not available.
|
||||
#define _LIBCPP_BUILDING_LIBRARY
|
||||
#include "fallback_malloc.h"
|
||||
|
||||
#include <__threading_support>
|
||||
#ifndef _LIBCXXABI_HAS_NO_THREADS
|
||||
#if defined(__unix__) && !defined(__ANDROID__) && defined(__ELF__) && defined(_LIBCXXABI_HAS_COMMENT_LIB_PRAGMA)
|
||||
#if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> // for malloc, calloc, free
|
||||
#include <string.h> // for memset
|
||||
#include <new> // for std::__libcpp_aligned_{alloc,free}
|
||||
|
||||
// A small, simple heap manager based (loosely) on
|
||||
// the startup heap manager from FreeBSD, optimized for space.
|
||||
@ -144,29 +142,26 @@ void fallback_free(void* ptr) {
|
||||
mutexor mtx(&heap_mutex);
|
||||
|
||||
#ifdef DEBUG_FALLBACK_MALLOC
|
||||
std::cout << "Freeing item at " << offset_from_node(cp) << " of size "
|
||||
<< cp->len << std::endl;
|
||||
std::printf("Freeing item at %d of size %d\n", offset_from_node(cp), cp->len);
|
||||
#endif
|
||||
|
||||
for (p = freelist, prev = 0; p && p != list_end;
|
||||
prev = p, p = node_from_offset(p->next_node)) {
|
||||
#ifdef DEBUG_FALLBACK_MALLOC
|
||||
std::cout << " p, cp, after (p), after(cp) " << offset_from_node(p) << ' '
|
||||
<< offset_from_node(cp) << ' ' << offset_from_node(after(p))
|
||||
<< ' ' << offset_from_node(after(cp)) << std::endl;
|
||||
std::printf(" p=%d, cp=%d, after(p)=%d, after(cp)=%d\n",
|
||||
offset_from_node(p), offset_from_node(cp),
|
||||
offset_from_node(after(p)), offset_from_node(after(cp)));
|
||||
#endif
|
||||
if (after(p) == cp) {
|
||||
#ifdef DEBUG_FALLBACK_MALLOC
|
||||
std::cout << " Appending onto chunk at " << offset_from_node(p)
|
||||
<< std::endl;
|
||||
std::printf(" Appending onto chunk at %d\n", offset_from_node(p));
|
||||
#endif
|
||||
p->len = static_cast<heap_size>(
|
||||
p->len + cp->len); // make the free heap_node larger
|
||||
return;
|
||||
} else if (after(cp) == p) { // there's a free heap_node right after
|
||||
#ifdef DEBUG_FALLBACK_MALLOC
|
||||
std::cout << " Appending free chunk at " << offset_from_node(p)
|
||||
<< std::endl;
|
||||
std::printf(" Appending free chunk at %d\n", offset_from_node(p));
|
||||
#endif
|
||||
cp->len = static_cast<heap_size>(cp->len + p->len);
|
||||
if (prev == 0) {
|
||||
@ -179,8 +174,7 @@ void fallback_free(void* ptr) {
|
||||
}
|
||||
// Nothing to merge with, add it to the start of the free list
|
||||
#ifdef DEBUG_FALLBACK_MALLOC
|
||||
std::cout << " Making new free list entry " << offset_from_node(cp)
|
||||
<< std::endl;
|
||||
std::printf(" Making new free list entry %d\n", offset_from_node(cp));
|
||||
#endif
|
||||
cp->next_node = offset_from_node(freelist);
|
||||
freelist = cp;
|
||||
@ -195,11 +189,11 @@ size_t print_free_list() {
|
||||
|
||||
for (p = freelist, prev = 0; p && p != list_end;
|
||||
prev = p, p = node_from_offset(p->next_node)) {
|
||||
std::cout << (prev == 0 ? "" : " ") << "Offset: " << offset_from_node(p)
|
||||
<< "\tsize: " << p->len << " Next: " << p->next_node << std::endl;
|
||||
std::printf("%sOffset: %d\tsize: %d Next: %d\n",
|
||||
(prev == 0 ? "" : " "), offset_from_node(p), p->len, p->next_node);
|
||||
total_free += p->len;
|
||||
}
|
||||
std::cout << "Total Free space: " << total_free << std::endl;
|
||||
std::printf("Total Free space: %d\n", total_free);
|
||||
return total_free;
|
||||
}
|
||||
#endif
|
||||
@ -211,7 +205,7 @@ struct __attribute__((aligned)) __aligned_type {};
|
||||
|
||||
void* __aligned_malloc_with_fallback(size_t size) {
|
||||
#if defined(_WIN32)
|
||||
if (void* dest = _aligned_malloc(size, alignof(__aligned_type)))
|
||||
if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size))
|
||||
return dest;
|
||||
#elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
|
||||
if (void* dest = ::malloc(size))
|
||||
@ -219,8 +213,7 @@ void* __aligned_malloc_with_fallback(size_t size) {
|
||||
#else
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
void* dest;
|
||||
if (::posix_memalign(&dest, __alignof(__aligned_type), size) == 0)
|
||||
if (void* dest = std::__libcpp_aligned_alloc(__alignof(__aligned_type), size))
|
||||
return dest;
|
||||
#endif
|
||||
return fallback_malloc(size);
|
||||
@ -241,10 +234,10 @@ void __aligned_free_with_fallback(void* ptr) {
|
||||
if (is_fallback_ptr(ptr))
|
||||
fallback_free(ptr);
|
||||
else {
|
||||
#if defined(_WIN32)
|
||||
::_aligned_free(ptr);
|
||||
#else
|
||||
#if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
|
||||
::free(ptr);
|
||||
#else
|
||||
std::__libcpp_aligned_free(ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -177,34 +177,4 @@ bool __libcpp_atomic_compare_exchange(_ValueType* __val,
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
namespace {
|
||||
|
||||
template <class IntType>
|
||||
class AtomicInt {
|
||||
public:
|
||||
using MemoryOrder = std::__libcpp_atomic_order;
|
||||
|
||||
explicit AtomicInt(IntType *b) : b(b) {}
|
||||
AtomicInt(AtomicInt const&) = delete;
|
||||
AtomicInt& operator=(AtomicInt const&) = delete;
|
||||
|
||||
IntType load(MemoryOrder ord) {
|
||||
return std::__libcpp_atomic_load(b, ord);
|
||||
}
|
||||
void store(IntType val, MemoryOrder ord) {
|
||||
std::__libcpp_atomic_store(b, val, ord);
|
||||
}
|
||||
IntType exchange(IntType new_val, MemoryOrder ord) {
|
||||
return std::__libcpp_atomic_exchange(b, new_val, ord);
|
||||
}
|
||||
bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
|
||||
return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
|
||||
}
|
||||
|
||||
private:
|
||||
IntType *b;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
#endif // ATOMIC_SUPPORT_H
|
||||
|
@ -1,131 +0,0 @@
|
||||
//===------------------------ __refstring ---------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of
|
||||
// duplicating the file in libc++abi we should require that the libc++ sources
|
||||
// are available when building libc++abi.
|
||||
|
||||
#ifndef _LIBCPPABI_REFSTRING_H
|
||||
#define _LIBCPPABI_REFSTRING_H
|
||||
|
||||
#include <__config>
|
||||
#include <stdexcept>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#ifdef __APPLE__
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
#include "atomic_support.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace __refstring_imp { namespace {
|
||||
typedef int count_t;
|
||||
|
||||
struct _Rep_base {
|
||||
std::size_t len;
|
||||
std::size_t cap;
|
||||
count_t count;
|
||||
};
|
||||
|
||||
inline _Rep_base* rep_from_data(const char *data_) noexcept {
|
||||
char *data = const_cast<char *>(data_);
|
||||
return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base));
|
||||
}
|
||||
|
||||
inline char * data_from_rep(_Rep_base *rep) noexcept {
|
||||
char *data = reinterpret_cast<char *>(rep);
|
||||
return data + sizeof(*rep);
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
inline
|
||||
const char* compute_gcc_empty_string_storage() _NOEXCEPT
|
||||
{
|
||||
void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD);
|
||||
if (handle == nullptr)
|
||||
return nullptr;
|
||||
void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE");
|
||||
if (sym == nullptr)
|
||||
return nullptr;
|
||||
return data_from_rep(reinterpret_cast<_Rep_base *>(sym));
|
||||
}
|
||||
|
||||
inline
|
||||
const char*
|
||||
get_gcc_empty_string_storage() _NOEXCEPT
|
||||
{
|
||||
static const char* p = compute_gcc_empty_string_storage();
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
}} // namespace __refstring_imp
|
||||
|
||||
using namespace __refstring_imp;
|
||||
|
||||
inline
|
||||
__libcpp_refstring::__libcpp_refstring(const char* msg) {
|
||||
std::size_t len = strlen(msg);
|
||||
_Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1));
|
||||
rep->len = len;
|
||||
rep->cap = len;
|
||||
rep->count = 0;
|
||||
char *data = data_from_rep(rep);
|
||||
std::memcpy(data, msg, len + 1);
|
||||
__imp_ = data;
|
||||
}
|
||||
|
||||
inline
|
||||
__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT
|
||||
: __imp_(s.__imp_)
|
||||
{
|
||||
if (__uses_refcount())
|
||||
__libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
|
||||
}
|
||||
|
||||
inline
|
||||
__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT {
|
||||
bool adjust_old_count = __uses_refcount();
|
||||
struct _Rep_base *old_rep = rep_from_data(__imp_);
|
||||
__imp_ = s.__imp_;
|
||||
if (__uses_refcount())
|
||||
__libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
|
||||
if (adjust_old_count)
|
||||
{
|
||||
if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0)
|
||||
{
|
||||
::operator delete(old_rep);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
__libcpp_refstring::~__libcpp_refstring() {
|
||||
if (__uses_refcount()) {
|
||||
_Rep_base* rep = rep_from_data(__imp_);
|
||||
if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) {
|
||||
::operator delete(rep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool __libcpp_refstring::__uses_refcount() const {
|
||||
#ifdef __APPLE__
|
||||
return __imp_ != get_gcc_empty_string_storage();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif //_LIBCPPABI_REFSTRING_H
|
@ -8,11 +8,11 @@
|
||||
|
||||
#include "private_typeinfo.h"
|
||||
|
||||
// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more
|
||||
// forgiving when type_info's mistakenly have hidden visibility and thus
|
||||
// multiple type_infos can exist for a single type.
|
||||
// The flag _LIBCXXABI_FORGIVING_DYNAMIC_CAST is used to make dynamic_cast
|
||||
// more forgiving when type_info's mistakenly have hidden visibility and
|
||||
// thus multiple type_infos can exist for a single type.
|
||||
//
|
||||
// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where
|
||||
// When _LIBCXXABI_FORGIVING_DYNAMIC_CAST is defined, and only in the case where
|
||||
// there is a detected inconsistency in the type_info hierarchy during a
|
||||
// dynamic_cast, then the equality operation will fall back to using strcmp
|
||||
// on type_info names to determine type_info equality.
|
||||
@ -23,7 +23,7 @@
|
||||
// algorithm and an inconsistency is still detected, dynamic_cast will call
|
||||
// abort with an appropriate message.
|
||||
//
|
||||
// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a
|
||||
// The current implementation of _LIBCXXABI_FORGIVING_DYNAMIC_CAST requires a
|
||||
// printf-like function called syslog:
|
||||
//
|
||||
// void syslog(int facility_priority, const char* format, ...);
|
||||
@ -31,21 +31,22 @@
|
||||
// If you want this functionality but your platform doesn't have syslog,
|
||||
// just implement it in terms of fprintf(stderr, ...).
|
||||
//
|
||||
// _LIBCXX_DYNAMIC_FALLBACK is currently off by default.
|
||||
// _LIBCXXABI_FORGIVING_DYNAMIC_CAST is currently off by default.
|
||||
|
||||
// On Windows, typeids are different between DLLs and EXEs, so comparing
|
||||
// type_info* will work for typeids from the same compiled file but fail
|
||||
// for typeids from a DLL and an executable. Among other things, exceptions
|
||||
// are not caught by handlers since can_catch() returns false.
|
||||
//
|
||||
// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls
|
||||
// Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST does not help since can_catch() calls
|
||||
// is_equal() with use_strcmp=false so the string names are not compared.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _LIBCXX_DYNAMIC_FALLBACK
|
||||
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
#include "abort_message.h"
|
||||
#include <sys/syslog.h>
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
static inline
|
||||
@ -60,6 +61,16 @@ is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
|
||||
return x == y || strcmp(x->name(), y->name()) == 0;
|
||||
}
|
||||
|
||||
static inline ptrdiff_t update_offset_to_base(const char* vtable,
|
||||
ptrdiff_t offset_to_base) {
|
||||
#if __has_feature(cxx_abi_relative_vtable)
|
||||
// VTable components are 32 bits in the relative vtables ABI.
|
||||
return *reinterpret_cast<const int32_t*>(vtable + offset_to_base);
|
||||
#else
|
||||
return *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
|
||||
@ -296,7 +307,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
|
||||
if (__offset_flags & __virtual_mask)
|
||||
{
|
||||
const char* vtable = *static_cast<const char*const*>(adjustedPtr);
|
||||
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
|
||||
offset_to_base = update_offset_to_base(vtable, offset_to_base);
|
||||
}
|
||||
}
|
||||
__base_type->has_unambiguous_public_base(
|
||||
@ -614,10 +625,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
|
||||
// Possible future optimization: Take advantage of src2dst_offset
|
||||
|
||||
// Get (dynamic_ptr, dynamic_type) from static_ptr
|
||||
#if __has_feature(cxx_abi_relative_vtable)
|
||||
// The vtable address will point to the first virtual function, which is 8
|
||||
// bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component).
|
||||
const int32_t* vtable =
|
||||
*reinterpret_cast<const int32_t* const*>(static_ptr);
|
||||
int32_t offset_to_derived = vtable[-2];
|
||||
const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
|
||||
|
||||
// The typeinfo component is now a relative offset to a proxy.
|
||||
int32_t offset_to_ti_proxy = vtable[-1];
|
||||
const uint8_t* ptr_to_ti_proxy =
|
||||
reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
|
||||
const __class_type_info* dynamic_type =
|
||||
*(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
|
||||
#else
|
||||
void **vtable = *static_cast<void ** const *>(static_ptr);
|
||||
ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
|
||||
const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
|
||||
const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
|
||||
#endif
|
||||
|
||||
// Initialize answer to nullptr. This will be changed from the search
|
||||
// results if a non-null answer is found. Regardless, this is what will
|
||||
@ -633,22 +660,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
|
||||
info.number_of_dst_type = 1;
|
||||
// Do the search
|
||||
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
|
||||
#ifdef _LIBCXX_DYNAMIC_FALLBACK
|
||||
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
// The following if should always be false because we should definitely
|
||||
// find (static_ptr, static_type), either on a public or private path
|
||||
if (info.path_dst_ptr_to_static_ptr == unknown)
|
||||
{
|
||||
// We get here only if there is some kind of visibility problem
|
||||
// in client code.
|
||||
syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
|
||||
"should have public visibility. At least one of them is hidden. %s"
|
||||
", %s.\n", static_type->name(), dynamic_type->name());
|
||||
static_assert(std::atomic<size_t>::is_always_lock_free, "");
|
||||
static std::atomic<size_t> error_count(0);
|
||||
size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
|
||||
if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
|
||||
syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
|
||||
"should have public visibility. At least one of them is hidden. %s"
|
||||
", %s.\n", static_type->name(), dynamic_type->name());
|
||||
// Redo the search comparing type_info's using strcmp
|
||||
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
|
||||
info.number_of_dst_type = 1;
|
||||
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
|
||||
}
|
||||
#endif // _LIBCXX_DYNAMIC_FALLBACK
|
||||
#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
// Query the search.
|
||||
if (info.path_dst_ptr_to_static_ptr == public_path)
|
||||
dst_ptr = dynamic_ptr;
|
||||
@ -657,22 +688,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
|
||||
{
|
||||
// Not using giant short cut. Do the search
|
||||
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
|
||||
#ifdef _LIBCXX_DYNAMIC_FALLBACK
|
||||
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
// The following if should always be false because we should definitely
|
||||
// find (static_ptr, static_type), either on a public or private path
|
||||
if (info.path_dst_ptr_to_static_ptr == unknown &&
|
||||
info.path_dynamic_ptr_to_static_ptr == unknown)
|
||||
{
|
||||
syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
|
||||
"has hidden visibility or is defined in more than one translation "
|
||||
"unit. They should all have public visibility. "
|
||||
"%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
|
||||
dst_type->name());
|
||||
static_assert(std::atomic<size_t>::is_always_lock_free, "");
|
||||
static std::atomic<size_t> error_count(0);
|
||||
size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
|
||||
if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
|
||||
syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
|
||||
"has hidden visibility or is defined in more than one translation "
|
||||
"unit. They should all have public visibility. "
|
||||
"%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
|
||||
dst_type->name());
|
||||
// Redo the search comparing type_info's using strcmp
|
||||
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
|
||||
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
|
||||
}
|
||||
#endif // _LIBCXX_DYNAMIC_FALLBACK
|
||||
#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
|
||||
// Query the search.
|
||||
switch (info.number_to_static_ptr)
|
||||
{
|
||||
@ -1258,7 +1293,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info,
|
||||
if (__offset_flags & __virtual_mask)
|
||||
{
|
||||
const char* vtable = *static_cast<const char*const*>(current_ptr);
|
||||
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
|
||||
offset_to_base = update_offset_to_base(vtable, offset_to_base);
|
||||
}
|
||||
__base_type->search_above_dst(info, dst_ptr,
|
||||
static_cast<const char*>(current_ptr) + offset_to_base,
|
||||
@ -1278,7 +1313,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
|
||||
if (__offset_flags & __virtual_mask)
|
||||
{
|
||||
const char* vtable = *static_cast<const char*const*>(current_ptr);
|
||||
offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
|
||||
offset_to_base = update_offset_to_base(vtable, offset_to_base);
|
||||
}
|
||||
__base_type->search_below_dst(info,
|
||||
static_cast<const char*>(current_ptr) + offset_to_base,
|
||||
|
@ -248,4 +248,4 @@ public:
|
||||
|
||||
} // __cxxabiv1
|
||||
|
||||
#endif // __PRIVATE_TYPEINFO_H_
|
||||
#endif // __PRIVATE_TYPEINFO_H_
|
||||
|
@ -6,7 +6,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define _LIBCPP_BUILDING_LIBRARY
|
||||
#include <new>
|
||||
#include <exception>
|
||||
|
||||
@ -15,22 +14,22 @@ namespace std
|
||||
|
||||
// exception
|
||||
|
||||
exception::~exception() _NOEXCEPT
|
||||
exception::~exception() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
const char* exception::what() const _NOEXCEPT
|
||||
const char* exception::what() const noexcept
|
||||
{
|
||||
return "std::exception";
|
||||
}
|
||||
|
||||
// bad_exception
|
||||
|
||||
bad_exception::~bad_exception() _NOEXCEPT
|
||||
bad_exception::~bad_exception() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
const char* bad_exception::what() const _NOEXCEPT
|
||||
const char* bad_exception::what() const noexcept
|
||||
{
|
||||
return "std::bad_exception";
|
||||
}
|
||||
@ -38,32 +37,32 @@ const char* bad_exception::what() const _NOEXCEPT
|
||||
|
||||
// bad_alloc
|
||||
|
||||
bad_alloc::bad_alloc() _NOEXCEPT
|
||||
bad_alloc::bad_alloc() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
bad_alloc::~bad_alloc() _NOEXCEPT
|
||||
bad_alloc::~bad_alloc() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_alloc::what() const _NOEXCEPT
|
||||
bad_alloc::what() const noexcept
|
||||
{
|
||||
return "std::bad_alloc";
|
||||
}
|
||||
|
||||
// bad_array_new_length
|
||||
|
||||
bad_array_new_length::bad_array_new_length() _NOEXCEPT
|
||||
bad_array_new_length::bad_array_new_length() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
bad_array_new_length::~bad_array_new_length() _NOEXCEPT
|
||||
bad_array_new_length::~bad_array_new_length() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_array_new_length::what() const _NOEXCEPT
|
||||
bad_array_new_length::what() const noexcept
|
||||
{
|
||||
return "bad_array_new_length";
|
||||
}
|
||||
|
@ -8,13 +8,12 @@
|
||||
// This file implements the new and delete operators.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define _LIBCPP_BUILDING_LIBRARY
|
||||
#include "__cxxabi_config.h"
|
||||
#include <new>
|
||||
#include <cstdlib>
|
||||
|
||||
#if !defined(_THROW_BAD_ALLOC) || !defined(_NOEXCEPT) || !defined(_LIBCXXABI_WEAK)
|
||||
#error The _THROW_BAD_ALLOC, _NOEXCEPT, and _LIBCXXABI_WEAK libc++ macros must \
|
||||
#if !defined(_THROW_BAD_ALLOC) || !defined(_LIBCXXABI_WEAK)
|
||||
#error The _THROW_BAD_ALLOC and _LIBCXXABI_WEAK libc++ macros must \
|
||||
already be defined by libc++.
|
||||
#endif
|
||||
// Implement all new and delete operators as weak definitions
|
||||
@ -28,7 +27,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
void* p;
|
||||
while ((p = ::malloc(size)) == 0)
|
||||
while ((p = ::malloc(size)) == nullptr)
|
||||
{
|
||||
// If malloc fails and there is a new_handler,
|
||||
// call it to try free up memory.
|
||||
@ -47,20 +46,20 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void*
|
||||
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
|
||||
operator new(size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = 0;
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
p = ::operator new(size);
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -73,62 +72,61 @@ operator new[](size_t size) _THROW_BAD_ALLOC
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void*
|
||||
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
|
||||
operator new[](size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = 0;
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
p = ::operator new[](size);
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete(void* ptr) _NOEXCEPT
|
||||
operator delete(void* ptr) noexcept
|
||||
{
|
||||
if (ptr)
|
||||
::free(ptr);
|
||||
::free(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
|
||||
operator delete(void* ptr, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete(void* ptr, size_t) _NOEXCEPT
|
||||
operator delete(void* ptr, size_t) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr) _NOEXCEPT
|
||||
operator delete[] (void* ptr) noexcept
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
|
||||
operator delete[] (void* ptr, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete[](ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr, size_t) _NOEXCEPT
|
||||
operator delete[] (void* ptr, size_t) noexcept
|
||||
{
|
||||
::operator delete[](ptr);
|
||||
}
|
||||
@ -143,15 +141,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
||||
size = 1;
|
||||
if (static_cast<size_t>(alignment) < sizeof(void*))
|
||||
alignment = std::align_val_t(sizeof(void*));
|
||||
|
||||
// Try allocating memory. If allocation fails and there is a new_handler,
|
||||
// call it to try free up memory, and try again until it succeeds, or until
|
||||
// the new_handler decides to terminate.
|
||||
//
|
||||
// If allocation fails and there is no new_handler, we throw bad_alloc
|
||||
// (or return nullptr if exceptions are disabled).
|
||||
void* p;
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
|
||||
#else
|
||||
while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
|
||||
#endif
|
||||
while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr)
|
||||
{
|
||||
// If posix_memalign fails and there is a new_handler,
|
||||
// call it to try free up memory.
|
||||
std::new_handler nh = std::get_new_handler();
|
||||
if (nh)
|
||||
nh();
|
||||
@ -159,7 +158,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
p = nullptr; // posix_memalign doesn't initialize 'p' on failure
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@ -169,20 +167,20 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void*
|
||||
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = 0;
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
p = ::operator new(size, alignment);
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -195,66 +193,61 @@ operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void*
|
||||
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = 0;
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
p = ::operator new[](size, alignment);
|
||||
#ifndef _LIBCXXABI_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
#endif // _LIBCXXABI_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete(void* ptr, std::align_val_t) _NOEXCEPT
|
||||
operator delete(void* ptr, std::align_val_t) noexcept
|
||||
{
|
||||
if (ptr)
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
::_aligned_free(ptr);
|
||||
#else
|
||||
::free(ptr);
|
||||
#endif
|
||||
std::__libcpp_aligned_free(ptr);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||
operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete(ptr, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
|
||||
operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept
|
||||
{
|
||||
::operator delete(ptr, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT
|
||||
operator delete[] (void* ptr, std::align_val_t alignment) noexcept
|
||||
{
|
||||
::operator delete(ptr, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||
operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
|
||||
{
|
||||
::operator delete[](ptr, alignment);
|
||||
}
|
||||
|
||||
_LIBCXXABI_WEAK
|
||||
void
|
||||
operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
|
||||
operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept
|
||||
{
|
||||
::operator delete[](ptr, alignment);
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "include/refstring.h"
|
||||
#include "stdexcept"
|
||||
#include "new"
|
||||
#include <cstdlib>
|
||||
@ -14,34 +13,37 @@
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
// This includes an implementation file from libc++.
|
||||
#include "src/include/refstring.h"
|
||||
|
||||
static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), "");
|
||||
|
||||
namespace std // purposefully not using versioning namespace
|
||||
{
|
||||
|
||||
logic_error::~logic_error() _NOEXCEPT {}
|
||||
logic_error::~logic_error() noexcept {}
|
||||
|
||||
const char*
|
||||
logic_error::what() const _NOEXCEPT
|
||||
logic_error::what() const noexcept
|
||||
{
|
||||
return __imp_.c_str();
|
||||
}
|
||||
|
||||
runtime_error::~runtime_error() _NOEXCEPT {}
|
||||
runtime_error::~runtime_error() noexcept {}
|
||||
|
||||
const char*
|
||||
runtime_error::what() const _NOEXCEPT
|
||||
runtime_error::what() const noexcept
|
||||
{
|
||||
return __imp_.c_str();
|
||||
}
|
||||
|
||||
domain_error::~domain_error() _NOEXCEPT {}
|
||||
invalid_argument::~invalid_argument() _NOEXCEPT {}
|
||||
length_error::~length_error() _NOEXCEPT {}
|
||||
out_of_range::~out_of_range() _NOEXCEPT {}
|
||||
domain_error::~domain_error() noexcept {}
|
||||
invalid_argument::~invalid_argument() noexcept {}
|
||||
length_error::~length_error() noexcept {}
|
||||
out_of_range::~out_of_range() noexcept {}
|
||||
|
||||
range_error::~range_error() _NOEXCEPT {}
|
||||
overflow_error::~overflow_error() _NOEXCEPT {}
|
||||
underflow_error::~underflow_error() _NOEXCEPT {}
|
||||
range_error::~range_error() noexcept {}
|
||||
overflow_error::~overflow_error() noexcept {}
|
||||
underflow_error::~underflow_error() noexcept {}
|
||||
|
||||
} // std
|
||||
|
@ -19,32 +19,32 @@ type_info::~type_info()
|
||||
|
||||
// bad_cast
|
||||
|
||||
bad_cast::bad_cast() _NOEXCEPT
|
||||
bad_cast::bad_cast() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
bad_cast::~bad_cast() _NOEXCEPT
|
||||
bad_cast::~bad_cast() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_cast::what() const _NOEXCEPT
|
||||
bad_cast::what() const noexcept
|
||||
{
|
||||
return "std::bad_cast";
|
||||
}
|
||||
|
||||
// bad_typeid
|
||||
|
||||
bad_typeid::bad_typeid() _NOEXCEPT
|
||||
bad_typeid::bad_typeid() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
bad_typeid::~bad_typeid() _NOEXCEPT
|
||||
bad_typeid::~bad_typeid() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_typeid::what() const _NOEXCEPT
|
||||
bad_typeid::what() const noexcept
|
||||
{
|
||||
return "std::bad_typeid";
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
include(AddLLVM) # for add_lit_testsuite
|
||||
include(AddLLVM) # for configure_lit_site_cfg and add_lit_testsuite
|
||||
macro(pythonize_bool var)
|
||||
if (${var})
|
||||
set(${var} True)
|
||||
@ -11,22 +11,47 @@ if (NOT DEFINED LIBCXX_ENABLE_SHARED)
|
||||
set(LIBCXX_ENABLE_SHARED ON)
|
||||
endif()
|
||||
|
||||
option(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI
|
||||
"Whether the libc++abi tests should link with the shared libc++abi library"
|
||||
${LIBCXXABI_ENABLE_SHARED})
|
||||
|
||||
option(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX
|
||||
"Whether the libc++abi tests should link with the shared libc++ library"
|
||||
${LIBCXX_ENABLE_SHARED})
|
||||
|
||||
if(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI AND NOT LIBCXXABI_ENABLE_SHARED)
|
||||
message(FATAL_ERROR "LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI being ON requires LIBCXXABI_ENABLE_SHARED to be ON")
|
||||
endif()
|
||||
|
||||
if(NOT LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI AND NOT LIBCXXABI_ENABLE_STATIC)
|
||||
message(FATAL_ERROR "LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI being OFF requires LIBCXXABI_ENABLE_STATIC to be ON")
|
||||
endif()
|
||||
|
||||
if(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX AND NOT LIBCXX_ENABLE_SHARED)
|
||||
message(FATAL_ERROR "LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX being ON requires LIBCXX_ENABLE_SHARED to be ON")
|
||||
endif()
|
||||
|
||||
if(DEFINED LIBCXX_ENABLE_STATIC
|
||||
AND NOT LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX
|
||||
AND NOT LIBCXX_ENABLE_STATIC)
|
||||
message(FATAL_ERROR "LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX being OFF requires LIBCXX_ENABLE_STATIC to be ON")
|
||||
endif()
|
||||
|
||||
pythonize_bool(LIBCXXABI_BUILD_32_BITS)
|
||||
pythonize_bool(LIBCXX_ENABLE_SHARED)
|
||||
pythonize_bool(LIBCXXABI_ENABLE_SHARED)
|
||||
pythonize_bool(LIBCXXABI_ENABLE_THREADS)
|
||||
pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS)
|
||||
pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
|
||||
pythonize_bool(LIBCXXABI_USE_COMPILER_RT)
|
||||
pythonize_bool(LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
pythonize_bool(LIBCXX_ENABLE_PARALLEL_ALGORITHMS)
|
||||
pythonize_bool(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX)
|
||||
pythonize_bool(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI)
|
||||
set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING
|
||||
"TargetInfo to use when setting up test environment.")
|
||||
set(LIBCXXABI_EXECUTOR "None" CACHE STRING
|
||||
set(LIBCXXABI_EXECUTOR "${Python3_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/run.py" CACHE STRING
|
||||
"Executor to use when running tests.")
|
||||
|
||||
set(AUTO_GEN_COMMENT "## Autogenerated by libcxxabi configuration.\n# Do not edit!")
|
||||
|
||||
if (LIBCXXABI_ENABLE_SHARED)
|
||||
set(LIBCXXABI_TEST_DEPS cxxabi_shared)
|
||||
else()
|
||||
@ -44,15 +69,42 @@ if (NOT LIBCXXABI_STANDALONE_BUILD)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(AUTO_GEN_COMMENT "## Autogenerated by libcxxabi configuration.\n# Do not edit!")
|
||||
set(SERIALIZED_LIT_PARAMS "# Lit parameters serialized here for llvm-lit to pick them up\n")
|
||||
|
||||
macro(serialize_lit_param param value)
|
||||
string(APPEND SERIALIZED_LIT_PARAMS "config.${param} = ${value}\n")
|
||||
endmacro()
|
||||
|
||||
if (NOT LIBCXXABI_ENABLE_EXCEPTIONS)
|
||||
serialize_lit_param(enable_exceptions False)
|
||||
endif()
|
||||
|
||||
serialize_lit_param(enable_experimental False)
|
||||
|
||||
if (LLVM_USE_SANITIZER)
|
||||
serialize_lit_param(use_sanitizer "\"${LLVM_USE_SANITIZER}\"")
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_TARGET_TRIPLE)
|
||||
serialize_lit_param(target_triple "\"${LIBCXXABI_TARGET_TRIPLE}\"")
|
||||
endif()
|
||||
|
||||
if (LIBCXXABI_BUILD_32_BITS)
|
||||
serialize_lit_param(enable_32bit True)
|
||||
endif()
|
||||
|
||||
foreach(param IN LISTS LIBCXXABI_TEST_PARAMS)
|
||||
string(REGEX REPLACE "(.+)=(.+)" "\\1" name "${param}")
|
||||
string(REGEX REPLACE "(.+)=(.+)" "\\2" value "${param}")
|
||||
serialize_lit_param("${name}" "\"${value}\"")
|
||||
endforeach()
|
||||
|
||||
configure_lit_site_cfg(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg)
|
||||
"${LIBCXXABI_TEST_CONFIG}"
|
||||
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
|
||||
MAIN_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py")
|
||||
|
||||
add_lit_testsuite(check-cxxabi "Running libcxxabi tests"
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS ${LIBCXXABI_TEST_DEPS}
|
||||
)
|
||||
|
||||
# TODO: This is a legacy target name and should be removed at some point.
|
||||
add_custom_target(check-libcxxabi DEPENDS check-cxxabi)
|
||||
DEPENDS ${LIBCXXABI_TEST_DEPS})
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
@ -48,7 +48,7 @@ void call1(size_t* ntraced, bool do_throw) {
|
||||
call2(ntraced, do_throw);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
size_t throw_ntraced = 0;
|
||||
size_t nothrow_ntraced = 0;
|
||||
|
||||
|
@ -11,11 +11,11 @@
|
||||
// GCC incorrectly allows array types to be caught by reference.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69372
|
||||
// XFAIL: gcc
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <cassert>
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
typedef char Array[4];
|
||||
Array a = {'H', 'i', '!', 0};
|
||||
@ -31,4 +31,6 @@ int main()
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,11 +7,11 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Can you have a catch clause of array type that catches anything?
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <cassert>
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
typedef char Array[4];
|
||||
Array a = {'H', 'i', '!', 0};
|
||||
@ -27,4 +27,6 @@ int main()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <exception>
|
||||
#include <stdlib.h>
|
||||
@ -43,7 +43,7 @@ void f2()
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -56,4 +56,6 @@ int main()
|
||||
assert(a.id_ == 3);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <exception>
|
||||
#include <stdlib.h>
|
||||
@ -67,7 +67,7 @@ void f2()
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -81,4 +81,6 @@ int main()
|
||||
}
|
||||
assert(A::count == 0);
|
||||
assert(B::count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,7 +12,13 @@
|
||||
check against.
|
||||
*/
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// FIXME: GCC doesn't allow turning off the warning for exceptions being caught
|
||||
// by earlier handlers, which this test is exercising. We have to disable
|
||||
// warnings altogether to remove the error.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675.
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-error
|
||||
|
||||
#include <exception>
|
||||
#include <stdlib.h>
|
||||
@ -181,7 +187,7 @@ void f4()
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -195,4 +201,6 @@ int main()
|
||||
assert(C1::count == 0);
|
||||
assert(C2::count == 0);
|
||||
assert(B::count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,7 +12,13 @@
|
||||
check against. It also checks that virtual bases work properly
|
||||
*/
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// FIXME: GCC doesn't allow turning off the warning for exceptions being caught
|
||||
// by earlier handlers, which this test is exercising. We have to disable
|
||||
// warnings altogether to remove the error.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675.
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-error
|
||||
|
||||
#include <exception>
|
||||
#include <stdlib.h>
|
||||
@ -204,7 +210,7 @@ void f5()
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -218,4 +224,6 @@ int main()
|
||||
assert(C1::count == 0);
|
||||
assert(C2::count == 0);
|
||||
assert(B::count == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -136,12 +136,13 @@ void test6() {}
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
int main(int, char**) {
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -11,7 +11,10 @@
|
||||
// GCC incorrectly allows function pointer to be caught by reference.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69372
|
||||
// XFAIL: gcc
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// 65ace9daa360 made it in the dylib in macOS 10.11
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10}}
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -23,7 +26,7 @@ bool can_convert(...) { return false; }
|
||||
|
||||
void f() {}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
typedef void Function();
|
||||
assert(!can_convert<Function&>(&f));
|
||||
@ -48,4 +51,6 @@ int main()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,13 +7,13 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Can you have a catch clause of array type that catches anything?
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <cassert>
|
||||
|
||||
void f() {}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
typedef void Function();
|
||||
try
|
||||
@ -28,4 +28,6 @@ int main()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,7 +7,10 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Can a noexcept function pointer be caught by a non-noexcept catch clause?
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-noexcept-function-type
|
||||
// UNSUPPORTED: no-exceptions, no-noexcept-function-type
|
||||
|
||||
// Support for catching a function pointer including noexcept was shipped in macOS 10.13
|
||||
// XFAIL: use_system_cxx_lib && {{.+}}-apple-macosx10.{{9|10|11|12}}
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -53,11 +56,13 @@ void check_deep() {
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
check<false, false>();
|
||||
check<false, true>();
|
||||
check<true, false>();
|
||||
check<true, true>();
|
||||
check_deep();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: c++03
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <exception>
|
||||
#include <stdlib.h>
|
||||
@ -29,7 +30,9 @@ void f1() noexcept
|
||||
assert(false);
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
f1();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// 1b00fc5d8133 made it in the dylib in macOS 10.11
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10}}
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -164,11 +167,13 @@ void test5()
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
// GCC incorrectly allows PMF type "void (T::*)()" to be caught as "void (T::*)() const"
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69375
|
||||
// XFAIL: gcc
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
#include <cassert>
|
||||
|
||||
struct A
|
||||
@ -161,10 +161,12 @@ void test_void()
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
test_derived();
|
||||
test_void();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,13 +6,15 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Can a noexcept member function pointer be caught by a non-noexcept catch
|
||||
// clause?
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-noexcept-function-type
|
||||
// Can a noexcept member function pointer be caught by a non-noexcept catch clause?
|
||||
// UNSUPPORTED: no-exceptions, no-noexcept-function-type
|
||||
|
||||
// Support for catching a function pointer including noexcept was shipped in macOS 10.13
|
||||
// XFAIL: use_system_cxx_lib && {{.+}}-apple-macosx10.{{9|10|11|12}}
|
||||
|
||||
// GCC 7 and 8 support noexcept function types but this test still fails.
|
||||
// This is likely a bug in their implementation. Investigation needed.
|
||||
// XFAIL: gcc-7, gcc-8, gcc-9, gcc-10
|
||||
// XFAIL: gcc-7, gcc-8, gcc-9, gcc-10, gcc-11
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -60,11 +62,13 @@ void check_deep() {
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
check<false, false>();
|
||||
check<false, true>();
|
||||
check<true, false>();
|
||||
check<true, true>();
|
||||
check_deep();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// Catching an exception thrown as nullptr was not properly handled before
|
||||
// 2f984cab4fa7, which landed in macOS 10.13
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}}
|
||||
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -67,8 +71,10 @@ void test2()
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,20 +6,23 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// 1b00fc5d8133 made it in the dylib in macOS 10.11
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10}}
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
// Roll our own assertion macro to get better error messages out of the tests.
|
||||
// In particular on systems that don't use __PRETTY_FUNCTION__ in assertions.
|
||||
#define my_assert(pred, msg) do_assert(pred, msg, __LINE__, __PRETTY_FUNCTION__)
|
||||
|
||||
void do_assert(bool assert_passed, const char* msg, int line, const char* func) {
|
||||
if (assert_passed) return;
|
||||
std::cerr << __FILE__ << ":" << line << " " << func
|
||||
<< ": Assertion Failed `" << msg << "'\n\n";
|
||||
if (assert_passed)
|
||||
return;
|
||||
std::printf("%s:%d %s: Assertion Failed '%s'\n\n", __FILE__, line, func, msg);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
@ -130,7 +133,7 @@ struct generate_tests_imp<Throw, Catch, 0, first> {
|
||||
template <class Throw, class Catch, int level>
|
||||
struct generate_tests : generate_tests_imp<Throw, Catch, level, true> {};
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
generate_tests<int, int, 3>()();
|
||||
generate_tests<Base, Derived, 2>()();
|
||||
@ -141,4 +144,6 @@ int main()
|
||||
generate_tests<int A::*, int A::*, 3>()();
|
||||
generate_tests<int A::*, void, 2>()();
|
||||
generate_tests<void, int A::*, 2>()();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, libcxxabi-no-exceptions
|
||||
// Catching an exception thrown as nullptr was not properly handled before
|
||||
// 2f984cab4fa7, which landed in macOS 10.13
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}}
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
@ -60,7 +65,7 @@ void catch_nullptr_test() {
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
// catch naked nullptrs
|
||||
test1();
|
||||
@ -71,4 +76,6 @@ int main()
|
||||
catch_nullptr_test<int A::*>();
|
||||
catch_nullptr_test<const int A::*>();
|
||||
catch_nullptr_test<int A::**>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,17 +14,17 @@
|
||||
// (ignoring the top-level cv-qualifiers), or
|
||||
// * the handler is of type cv T or cv T& and T is an unambiguous base
|
||||
// class of E, or
|
||||
// / * the handler is of type cv1 T* cv2 and E is a pointer type that can \
|
||||
// | be converted to the type of the handler by either or both of |
|
||||
// | o a standard pointer conversion (4.10 [conv.ptr]) not involving |
|
||||
// | conversions to private or protected or ambiguous classes |
|
||||
// \ o a qualification conversion /
|
||||
// > * the handler is of type cv1 T* cv2 and E is a pointer type that can <
|
||||
// > be converted to the type of the handler by either or both of <
|
||||
// > o a standard pointer conversion (4.10 [conv.ptr]) not involving <
|
||||
// > conversions to private or protected or ambiguous classes <
|
||||
// > o a qualification conversion <
|
||||
// * the handler is a pointer or pointer to member type and E is
|
||||
// std::nullptr_t
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <exception>
|
||||
#include <stdlib.h>
|
||||
@ -427,7 +427,7 @@ void f13()
|
||||
assert_cannot_catch<const volatile Base * const volatile &, Protected *, Protected>();
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
f1();
|
||||
f2();
|
||||
@ -442,4 +442,6 @@ int main()
|
||||
f11();
|
||||
f12();
|
||||
f13();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,7 +12,13 @@
|
||||
check against. It also checks that virtual bases work properly
|
||||
*/
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// FIXME: GCC doesn't allow turning off the warning for exceptions being caught
|
||||
// by earlier handlers, which this test is exercising. We have to disable
|
||||
// warnings altogether to remove the error.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675.
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-error
|
||||
|
||||
#include <exception>
|
||||
#include <stdlib.h>
|
||||
@ -72,11 +78,11 @@ struct A
|
||||
|
||||
int A::count = 0;
|
||||
|
||||
A a(5);
|
||||
A global_a(5);
|
||||
|
||||
void f1()
|
||||
{
|
||||
throw &a;
|
||||
throw &global_a;
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@ -176,7 +182,7 @@ void f5()
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -186,4 +192,6 @@ int main()
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,16 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// FIXME: GCC doesn't allow turning off the warning for exceptions being caught
|
||||
// by earlier handlers, which this test is exercising. We have to disable
|
||||
// warnings altogether to remove the error.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675.
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-error
|
||||
|
||||
// The fix for PR17222 made it in the dylib for macOS 10.10
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.9
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -198,7 +207,7 @@ void test10 ()
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
@ -210,4 +219,6 @@ int main()
|
||||
test8();
|
||||
test9();
|
||||
test10();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: c++03,
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
@ -24,7 +25,7 @@ static void catch_nullptr_test() {
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
using nullptr_t = decltype(nullptr);
|
||||
|
||||
@ -45,4 +46,6 @@ int main()
|
||||
catch_nullptr_test<int A::*, false>();
|
||||
catch_nullptr_test<int (A::*)(), false>();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <cassert>
|
||||
@ -14,6 +14,8 @@
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
class Base {
|
||||
virtual void foo() {};
|
||||
};
|
||||
@ -31,17 +33,17 @@ void my_terminate() { exit(0); }
|
||||
int main ()
|
||||
{
|
||||
// swap-out the terminate handler
|
||||
void (*default_handler)() = std::get_terminate();
|
||||
void (*default_handler)() = std::get_terminate();
|
||||
std::set_terminate(my_terminate);
|
||||
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
Derived &d = test_bad_cast(gB);
|
||||
assert(false);
|
||||
((void)d);
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
} catch (std::bad_cast) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
} catch (std::bad_cast const&) {
|
||||
// success
|
||||
return 0;
|
||||
} catch (...) {
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===------------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <cassert>
|
||||
@ -14,7 +14,8 @@
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
class Base {
|
||||
virtual void foo() {};
|
||||
@ -26,21 +27,21 @@ std::string test_bad_typeid(Derived *p) {
|
||||
return typeid(*p).name();
|
||||
}
|
||||
|
||||
void my_terminate() { std::cout << "A" << std::endl; exit(0); }
|
||||
void my_terminate() { exit(0); }
|
||||
|
||||
int main ()
|
||||
{
|
||||
// swap-out the terminate handler
|
||||
void (*default_handler)() = std::get_terminate();
|
||||
void (*default_handler)() = std::get_terminate();
|
||||
std::set_terminate(my_terminate);
|
||||
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
test_bad_typeid(nullptr);
|
||||
assert(false);
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
} catch (std::bad_typeid) {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
} catch (std::bad_typeid const&) {
|
||||
// success
|
||||
return 0;
|
||||
} catch (...) {
|
||||
|
@ -23,7 +23,7 @@ extern "C" int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj,
|
||||
return 4;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
int RV = __cxxabiv1::__cxa_thread_atexit(
|
||||
reinterpret_cast<void (*)(void *)>(1), reinterpret_cast<void *>(2),
|
||||
reinterpret_cast<void *>(3));
|
||||
|
@ -6,7 +6,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// PR41395 isn't fixed until the dylib shipped with macOS 10.15
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14}}
|
||||
|
||||
#include "cxxabi.h"
|
||||
#include <new>
|
||||
|
@ -6,12 +6,22 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// XFAIL: gcc-7, gcc-8, gcc-9
|
||||
|
||||
// PR33425 and PR33487 are not fixed until the dylib shipped with macOS 10.15
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.14
|
||||
|
||||
// PR33439 isn't fixed until the dylib shipped with macOS 10.14
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13}}
|
||||
|
||||
#include <cassert>
|
||||
|
||||
// This test explicitly tests dynamic cast with types that have inaccessible
|
||||
// bases.
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Winaccessible-base"
|
||||
# pragma clang diagnostic ignored "-Winaccessible-base"
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 10)
|
||||
# pragma GCC diagnostic ignored "-Winaccessible-base"
|
||||
#endif
|
||||
|
||||
typedef char Pad1[43981];
|
||||
@ -143,11 +153,13 @@ void test()
|
||||
|
||||
} // t5
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
t1::test();
|
||||
t2::test();
|
||||
t3::test();
|
||||
t4::test();
|
||||
t5::test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2172,10 +2172,12 @@ void test()
|
||||
|
||||
} // t3
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
timer t;
|
||||
t1::test();
|
||||
t2::test();
|
||||
t3::test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,13 +6,17 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// XFAIL: gcc-7, gcc-8, gcc-9
|
||||
|
||||
#include <cassert>
|
||||
#include "support/timer.h"
|
||||
|
||||
// This test explicitly tests dynamic cast with types that have inaccessible
|
||||
// bases.
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Winaccessible-base"
|
||||
# pragma clang diagnostic ignored "-Winaccessible-base"
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 10)
|
||||
# pragma GCC diagnostic ignored "-Winaccessible-base"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -1443,7 +1447,7 @@ void test()
|
||||
A1 A1
|
||||
| |
|
||||
A2 |
|
||||
\ |
|
||||
\ |
|
||||
A3
|
||||
|
||||
*/
|
||||
@ -1926,7 +1930,7 @@ void test()
|
||||
A1
|
||||
| \
|
||||
A2 \
|
||||
\ |
|
||||
\ |
|
||||
A3
|
||||
|
||||
*/
|
||||
@ -2412,7 +2416,7 @@ void test()
|
||||
|
||||
} // t41
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
timer t;
|
||||
t1::test();
|
||||
@ -2456,4 +2460,6 @@ int main()
|
||||
t39::test();
|
||||
t40::test();
|
||||
t41::test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,13 +6,17 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// XFAIL: gcc-7, gcc-8, gcc-9
|
||||
|
||||
#include <cassert>
|
||||
#include "support/timer.h"
|
||||
|
||||
// This test explicitly tests dynamic cast with types that have inaccessible
|
||||
// bases.
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Winaccessible-base"
|
||||
# pragma clang diagnostic ignored "-Winaccessible-base"
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 10)
|
||||
# pragma GCC diagnostic ignored "-Winaccessible-base"
|
||||
#endif
|
||||
|
||||
namespace t1
|
||||
@ -1305,7 +1309,7 @@ void test()
|
||||
} // t9
|
||||
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
timer t;
|
||||
t1::test();
|
||||
@ -1317,4 +1321,6 @@ int main()
|
||||
t7::test();
|
||||
t8::test();
|
||||
t9::test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
#include <cassert>
|
||||
#include <tuple>
|
||||
@ -63,9 +63,11 @@ void test()
|
||||
assert(b != 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
test();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// This test checks that the compiler does not make incorrect assumptions
|
||||
// about the alignment of the exception (only in that specific case, of
|
||||
@ -24,7 +24,7 @@ struct exception {
|
||||
|
||||
struct foo : exception { };
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
try {
|
||||
throw foo();
|
||||
} catch (...) {
|
||||
|
@ -6,7 +6,13 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// The situation for the alignment of exception objects is badly messed up
|
||||
// before macOS 10.14. The test fails on macOS 10.9 to 10.12, passes on macOS
|
||||
// 10.13 (no investigation done), and passes afterwards. Just mark all the OSes
|
||||
// before 10.14 as unsupported.
|
||||
// UNSUPPORTED: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13}}
|
||||
|
||||
// Check that the pointer __cxa_allocate_exception returns is aligned to the
|
||||
// default alignment for the target architecture.
|
||||
@ -21,7 +27,7 @@ struct S {
|
||||
int a[4];
|
||||
} __attribute__((aligned));
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
#if !defined(_LIBCXXABI_ARM_EHABI)
|
||||
void *p = __cxxabiv1::__cxa_allocate_exception(16);
|
||||
auto i = reinterpret_cast<uintptr_t>(p);
|
||||
|
87
test/forced_unwind1.pass.cpp
Normal file
87
test/forced_unwind1.pass.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// _Unwind_ForcedUnwind raised exception can be caught by catch (...) and be
|
||||
// rethrown. If not rethrown, exception_cleanup will be called.
|
||||
|
||||
// UNSUPPORTED: no-exceptions, c++03
|
||||
|
||||
// These tests fail on previously released dylibs, investigation needed.
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unwind.h>
|
||||
#include <tuple>
|
||||
#include <__cxxabi_config.h>
|
||||
|
||||
#if defined(_LIBCXXABI_ARM_EHABI)
|
||||
int main(int, char**) {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int bits = 0;
|
||||
|
||||
struct C {
|
||||
int bit;
|
||||
C(int b) : bit(b) {}
|
||||
~C() { bits |= bit; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Stop;
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct Stop<R (*)(Args...)> {
|
||||
// The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM
|
||||
// libunwind while _Unwind_Exception_Class in libgcc.
|
||||
typedef typename std::tuple_element<2, std::tuple<Args...>>::type type;
|
||||
|
||||
static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type,
|
||||
struct _Unwind_Exception*,
|
||||
struct _Unwind_Context*, void*) {
|
||||
if (actions & _UA_END_OF_STACK)
|
||||
abort();
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
};
|
||||
|
||||
static void cleanup(_Unwind_Reason_Code, struct _Unwind_Exception* exc) {
|
||||
bits |= 8;
|
||||
delete exc;
|
||||
}
|
||||
|
||||
static void forced_unwind() {
|
||||
_Unwind_Exception* exc = new _Unwind_Exception;
|
||||
exc->exception_class = 0;
|
||||
exc->exception_cleanup = cleanup;
|
||||
_Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0);
|
||||
abort();
|
||||
}
|
||||
|
||||
static void test() {
|
||||
try {
|
||||
C four(4);
|
||||
try {
|
||||
C one(1);
|
||||
forced_unwind();
|
||||
} catch (...) {
|
||||
bits |= 2;
|
||||
throw;
|
||||
}
|
||||
} catch (int) {
|
||||
} catch (...) {
|
||||
// __cxa_end_catch calls cleanup.
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
return bits != 15;
|
||||
}
|
||||
#endif
|
67
test/forced_unwind2.pass.cpp
Normal file
67
test/forced_unwind2.pass.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Forced unwinding causes std::terminate when going through noexcept.
|
||||
|
||||
// UNSUPPORTED: no-exceptions, c++03
|
||||
|
||||
// These tests fail on previously released dylibs, investigation needed.
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
|
||||
|
||||
#include <exception>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unwind.h>
|
||||
#include <tuple>
|
||||
#include <__cxxabi_config.h>
|
||||
|
||||
#if defined(_LIBCXXABI_ARM_EHABI)
|
||||
int main(int, char**) {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
struct Stop;
|
||||
|
||||
template <typename R, typename... Args>
|
||||
struct Stop<R (*)(Args...)> {
|
||||
// The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM
|
||||
// libunwind while _Unwind_Exception_Class in libgcc.
|
||||
typedef typename std::tuple_element<2, std::tuple<Args...>>::type type;
|
||||
|
||||
static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type,
|
||||
struct _Unwind_Exception*,
|
||||
struct _Unwind_Context*, void*) {
|
||||
if (actions & _UA_END_OF_STACK)
|
||||
abort();
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
};
|
||||
|
||||
static void forced_unwind() {
|
||||
_Unwind_Exception* exc = new _Unwind_Exception;
|
||||
exc->exception_class = 0;
|
||||
exc->exception_cleanup = 0;
|
||||
_Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0);
|
||||
abort();
|
||||
}
|
||||
|
||||
static void test() noexcept { forced_unwind(); }
|
||||
|
||||
static void terminate() { exit(0); }
|
||||
|
||||
int main(int, char**) {
|
||||
std::set_terminate(terminate);
|
||||
try {
|
||||
test();
|
||||
} catch (...) {
|
||||
}
|
||||
abort();
|
||||
}
|
||||
#endif
|
@ -6,12 +6,17 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
#define TESTING_CXA_GUARD
|
||||
#include "../src/cxa_guard_impl.h"
|
||||
#include <cassert>
|
||||
|
||||
// Disable GCC warning about tautological comparison of a function's address
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Waddress"
|
||||
#endif
|
||||
|
||||
using namespace __cxxabiv1;
|
||||
|
||||
template <class GuardType, class Impl>
|
||||
@ -109,7 +114,7 @@ void NopFutexWait(int*, int) { assert(false); }
|
||||
void NopFutexWake(int*) { assert(false); }
|
||||
uint32_t MockGetThreadID() { return 0; }
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
{
|
||||
#if defined(_LIBCXXABI_HAS_NO_THREADS)
|
||||
static_assert(CurrentImplementation == Implementation::NoThreads, "");
|
||||
@ -127,7 +132,7 @@ int main() {
|
||||
#endif
|
||||
}
|
||||
{
|
||||
#if defined(__APPLE__) || defined(__linux__)
|
||||
#if (defined(__APPLE__) || defined(__linux__)) && !defined(_LIBCXXABI_HAS_NO_THREADS)
|
||||
assert(PlatformThreadID);
|
||||
#endif
|
||||
if (PlatformSupportsThreadID()) {
|
||||
@ -152,4 +157,6 @@ int main() {
|
||||
Tests<uint32_t, FutexImpl>::test();
|
||||
Tests<uint64_t, FutexImpl>::test();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,8 +6,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// UNSUPPORTED: libcxxabi-no-threads, libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: c++03
|
||||
// UNSUPPORTED: libcxxabi-no-threads
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#define TESTING_CXA_GUARD
|
||||
#include "../src/cxa_guard_impl.h"
|
||||
@ -19,6 +20,9 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "make_test_thread.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
|
||||
using namespace __cxxabiv1;
|
||||
|
||||
@ -33,7 +37,7 @@ constexpr int TestSamples = 50;
|
||||
|
||||
|
||||
void BusyWait() {
|
||||
std::this_thread::yield();
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
void YieldAfterBarrier() {
|
||||
@ -87,13 +91,13 @@ InitResult check_guard(GuardType *g, Init init) {
|
||||
if (std::__libcpp_atomic_load(first_byte, std::_AO_Acquire) == 0) {
|
||||
Impl impl(g);
|
||||
if (impl.cxa_guard_acquire() == INIT_IS_PENDING) {
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
init();
|
||||
impl.cxa_guard_release();
|
||||
return PERFORMED;
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
impl.cxa_guard_abort();
|
||||
return ABORTED;
|
||||
@ -346,21 +350,21 @@ void test_futex_syscall() {
|
||||
int lock1 = 0;
|
||||
int lock2 = 0;
|
||||
int lock3 = 0;
|
||||
std::thread waiter1([&]() {
|
||||
std::thread waiter1 = support::make_test_thread([&]() {
|
||||
int expect = 0;
|
||||
PlatformFutexWait(&lock1, expect);
|
||||
assert(lock1 == 1);
|
||||
});
|
||||
std::thread waiter2([&]() {
|
||||
std::thread waiter2 = support::make_test_thread([&]() {
|
||||
int expect = 0;
|
||||
PlatformFutexWait(&lock2, expect);
|
||||
assert(lock2 == 2);
|
||||
});
|
||||
std::thread waiter3([&]() {
|
||||
std::thread waiter3 = support::make_test_thread([&]() {
|
||||
int expect = 42; // not the value
|
||||
PlatformFutexWait(&lock3, expect); // doesn't block
|
||||
});
|
||||
std::thread waker([&]() {
|
||||
std::thread waker = support::make_test_thread([&]() {
|
||||
lock1 = 1;
|
||||
PlatformFutexWake(&lock1);
|
||||
lock2 = 2;
|
||||
@ -372,9 +376,11 @@ void test_futex_syscall() {
|
||||
waker.join();
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
// Test each multi-threaded implementation with real threads.
|
||||
test_all_impls();
|
||||
// Test the basic sanity of the futex syscall wrappers.
|
||||
test_futex_syscall();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,16 +13,16 @@
|
||||
// incomplete flags set, equality can be tested by comparing the type_info
|
||||
// addresses.
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
// UNSUPPORTED: no-rtti
|
||||
|
||||
// NOTE: Pass -lc++abi explicitly and before -lc++ so that -lc++ doesn't drag
|
||||
// in the system libc++abi installation on OS X. (DYLD_LIBRARY_PATH is ignored
|
||||
// for shell tests because of Apple security features).
|
||||
// The fix for PR25898 landed in the system dylibs in macOS 10.13
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}}
|
||||
|
||||
// RUN: %cxx %flags %compile_flags -c %s -o %t.one.o
|
||||
// RUN: %cxx %flags %compile_flags -c %s -o %t.two.o -DTU_ONE
|
||||
// RUN: %cxx %flags %t.one.o %t.two.o -lc++abi %link_flags -o %t.exe
|
||||
// RUN: %t.exe
|
||||
// RUN: %{cxx} %{flags} %{compile_flags} -Wno-unreachable-code -c %s -o %t.one.o
|
||||
// RUN: %{cxx} %{flags} %{compile_flags} -Wno-unreachable-code -c %s -o %t.two.o -DTU_ONE
|
||||
// RUN: %{cxx} %{flags} %t.one.o %t.two.o %{link_flags} -o %t.exe
|
||||
// RUN: %{exec} %t.exe
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstring>
|
||||
@ -82,7 +82,7 @@ void ThrowNullptr() { throw nullptr; }
|
||||
|
||||
struct IncompleteAtThrow {};
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
AssertIncompleteTypeInfoEquals(ReturnTypeInfoNeverDefinedMP(), typeid(int NeverDefined::*));
|
||||
try {
|
||||
ThrowNeverDefinedMP();
|
||||
@ -204,7 +204,8 @@ int main() {
|
||||
assert(!p);
|
||||
}
|
||||
catch(...) { assert(!"FAIL: Didn't catch nullptr as NeverDefined::*" ); }
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -10,10 +10,10 @@
|
||||
//
|
||||
// C++ ABI 15.3:
|
||||
// A handler is a match for an exception object of type E if
|
||||
// / * The handler is of type cv T or cv T& and E and T are the same type \
|
||||
// | (ignoring the top-level cv-qualifiers), or |
|
||||
// | * the handler is of type cv T or cv T& and T is an unambiguous base |
|
||||
// \ class of E, or /
|
||||
// > * The handler is of type cv T or cv T& and E and T are the same type <
|
||||
// > (ignoring the top-level cv-qualifiers), or <
|
||||
// > * the handler is of type cv T or cv T& and T is an unambiguous base <
|
||||
// > class of E, or <
|
||||
// * the handler is of type cv1 T* cv2 and E is a pointer type that can
|
||||
// be converted to the type of the handler by either or both of
|
||||
// o a standard pointer conversion (4.10 [conv.ptr]) not involving
|
||||
@ -24,7 +24,13 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// FIXME: GCC doesn't allow turning off the warning for exceptions being caught
|
||||
// by earlier handlers, which this test is exercising. We have to disable
|
||||
// warnings altogether to remove the error.
|
||||
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97675.
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Wno-error
|
||||
|
||||
// Clang emits warnings about exceptions of type 'Child' being caught by
|
||||
// an earlier handler of type 'Base'. Congrats clang, you've just
|
||||
@ -71,7 +77,7 @@ void f3() {
|
||||
throw static_cast<Base2*>(&child);
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -170,4 +176,6 @@ int main()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -16,12 +16,16 @@ class Configuration(LibcxxConfiguration):
|
||||
# pylint: disable=redefined-outer-name
|
||||
def __init__(self, lit_config, config):
|
||||
super(Configuration, self).__init__(lit_config, config)
|
||||
self.libcxxabi_hdr_root = None
|
||||
self.libcxxabi_src_root = None
|
||||
self.libcxxabi_obj_root = None
|
||||
self.abi_library_path = None
|
||||
self.abi_library_root = None
|
||||
self.libcxx_src_root = None
|
||||
|
||||
def configure_src_root(self):
|
||||
self.libcxxabi_hdr_root = self.get_lit_conf(
|
||||
'libcxxabi_hdr_root',
|
||||
self.project_obj_root)
|
||||
self.libcxxabi_src_root = self.get_lit_conf(
|
||||
'libcxxabi_src_root',
|
||||
os.path.dirname(self.config.test_source_root))
|
||||
@ -33,18 +37,8 @@ class Configuration(LibcxxConfiguration):
|
||||
self.libcxxabi_obj_root = self.get_lit_conf('libcxxabi_obj_root')
|
||||
super(Configuration, self).configure_obj_root()
|
||||
|
||||
def has_cpp_feature(self, feature, required_value):
|
||||
return intMacroValue(self.cxx.dumpMacros().get('__cpp_' + feature, '0')) >= required_value
|
||||
|
||||
def configure_features(self):
|
||||
super(Configuration, self).configure_features()
|
||||
if not self.get_lit_bool('enable_exceptions', True):
|
||||
self.config.available_features.add('libcxxabi-no-exceptions')
|
||||
if not self.has_cpp_feature('noexcept_function_type', 201510):
|
||||
self.config.available_features.add('libcxxabi-no-noexcept-function-type')
|
||||
# test_exception_storage_nodynmem.pass.cpp fails under this specific configuration
|
||||
if self.get_lit_bool('cxx_ext_threads', False) and self.get_lit_bool('libcxxabi_shared', False):
|
||||
self.config.available_features.add('libcxxabi-shared-externally-threaded')
|
||||
if not self.get_lit_bool('llvm_unwinder', False):
|
||||
self.config.available_features.add('libcxxabi-has-system-unwinder')
|
||||
|
||||
@ -55,18 +49,14 @@ class Configuration(LibcxxConfiguration):
|
||||
]
|
||||
if self.get_lit_bool('enable_exceptions', True):
|
||||
self.cxx.compile_flags += ['-funwind-tables']
|
||||
else:
|
||||
self.cxx.compile_flags += ['-fno-exceptions', '-DLIBCXXABI_HAS_NO_EXCEPTIONS']
|
||||
if not self.get_lit_bool('enable_threads', True):
|
||||
self.cxx.compile_flags += ['-D_LIBCXXABI_HAS_NO_THREADS']
|
||||
self.config.available_features.add('libcxxabi-no-threads')
|
||||
super(Configuration, self).configure_compile_flags()
|
||||
|
||||
|
||||
def configure_compile_flags_header_includes(self):
|
||||
self.configure_config_site_header()
|
||||
cxx_headers = self.get_lit_conf(
|
||||
'cxx_headers',
|
||||
os.path.join(self.libcxx_src_root, '/include'))
|
||||
cxx_headers = self.get_lit_conf('cxx_headers', None) or \
|
||||
os.path.join(self.libcxxabi_hdr_root, 'include', 'c++', 'v1')
|
||||
if cxx_headers == '':
|
||||
self.lit_config.note('using the systems c++ headers')
|
||||
else:
|
||||
@ -74,6 +64,13 @@ class Configuration(LibcxxConfiguration):
|
||||
if not os.path.isdir(cxx_headers):
|
||||
self.lit_config.fatal("cxx_headers='%s' is not a directory."
|
||||
% cxx_headers)
|
||||
(path, version) = os.path.split(cxx_headers)
|
||||
(path, cxx) = os.path.split(path)
|
||||
triple = self.get_lit_conf('target_triple', None)
|
||||
if triple is not None:
|
||||
cxx_target_headers = os.path.join(path, triple, cxx, version)
|
||||
if os.path.isdir(cxx_target_headers):
|
||||
self.cxx.compile_flags += ['-I' + cxx_target_headers]
|
||||
self.cxx.compile_flags += ['-I' + cxx_headers]
|
||||
|
||||
libcxxabi_headers = self.get_lit_conf(
|
||||
@ -90,9 +87,3 @@ class Configuration(LibcxxConfiguration):
|
||||
self.lit_config.fatal("libunwind_headers='%s' is not a directory."
|
||||
% libunwind_headers)
|
||||
self.cxx.compile_flags += ['-I' + libunwind_headers]
|
||||
|
||||
def configure_compile_flags_exceptions(self):
|
||||
pass
|
||||
|
||||
def configure_compile_flags_rtti(self):
|
||||
pass
|
||||
|
67
test/lit.cfg
67
test/lit.cfg
@ -1,67 +0,0 @@
|
||||
# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
|
||||
|
||||
# Configuration file for the 'lit' test runner.
|
||||
|
||||
|
||||
import os
|
||||
import site
|
||||
|
||||
site.addsitedir(os.path.dirname(__file__))
|
||||
|
||||
|
||||
# Tell pylint that we know config and lit_config exist somewhere.
|
||||
if 'PYLINT_IMPORT' in os.environ:
|
||||
config = object()
|
||||
lit_config = object()
|
||||
|
||||
# name: The name of this test suite.
|
||||
config.name = 'libc++abi'
|
||||
|
||||
# suffixes: A list of file extensions to treat as test files.
|
||||
config.suffixes = ['.cpp', '.s']
|
||||
|
||||
# test_source_root: The root path where tests are located.
|
||||
config.test_source_root = os.path.dirname(__file__)
|
||||
|
||||
# Infer the libcxx_test_source_root for configuration import.
|
||||
# If libcxx_source_root isn't specified in the config, assume that the libcxx
|
||||
# and libcxxabi source directories are sibling directories.
|
||||
libcxx_src_root = getattr(config, 'libcxx_src_root', None)
|
||||
if not libcxx_src_root:
|
||||
libcxx_src_root = os.path.join(config.test_source_root, '../../libcxx')
|
||||
libcxx_test_src_root = os.path.join(libcxx_src_root, 'utils')
|
||||
if os.path.isfile(os.path.join(libcxx_test_src_root, 'libcxx', '__init__.py')):
|
||||
site.addsitedir(libcxx_test_src_root)
|
||||
else:
|
||||
lit_config.fatal('Could not find libcxx test directory for test imports'
|
||||
' in: %s' % libcxx_test_src_root)
|
||||
|
||||
# Infer the test_exec_root from the libcxx_object root.
|
||||
obj_root = getattr(config, 'libcxxabi_obj_root', None)
|
||||
|
||||
# Check that the test exec root is known.
|
||||
if obj_root is None:
|
||||
import libcxx.test.config
|
||||
libcxx.test.config.loadSiteConfig(
|
||||
lit_config, config, 'libcxxabi_site_config', 'LIBCXXABI_SITE_CONFIG')
|
||||
obj_root = getattr(config, 'libcxxabi_obj_root', None)
|
||||
if obj_root is None:
|
||||
import tempfile
|
||||
obj_root = tempfile.mkdtemp(prefix='libcxxabi-testsuite-')
|
||||
lit_config.warning('Creating temporary directory for object root: %s' %
|
||||
obj_root)
|
||||
|
||||
config.test_exec_root = os.path.join(obj_root, 'test')
|
||||
|
||||
cfg_variant = getattr(config, 'configuration_variant', 'libcxxabi')
|
||||
if cfg_variant:
|
||||
lit_config.note('Using configuration variant: %s' % cfg_variant)
|
||||
|
||||
# Load the Configuration class from the module name <cfg_variant>.test.config.
|
||||
config_module_name = '.'.join([cfg_variant, 'test', 'config'])
|
||||
config_module = __import__(config_module_name, fromlist=['Configuration'])
|
||||
|
||||
configuration = config_module.Configuration(lit_config, config)
|
||||
configuration.configure()
|
||||
configuration.print_config_info()
|
||||
config.test_format = configuration.get_test_format()
|
10
test/lit.cfg.py
Normal file
10
test/lit.cfg.py
Normal file
@ -0,0 +1,10 @@
|
||||
# All the Lit configuration is handled in the site configs -- this file is only
|
||||
# left as a canary to catch invocations of Lit that do not go through llvm-lit.
|
||||
#
|
||||
# Invocations that go through llvm-lit will automatically use the right Lit
|
||||
# site configuration inside the build directory.
|
||||
|
||||
lit_config.fatal(
|
||||
"You seem to be running Lit directly -- you should be running Lit through "
|
||||
"<build>/bin/llvm-lit, which will ensure that the right Lit configuration "
|
||||
"file is used.")
|
@ -1,9 +1,16 @@
|
||||
@AUTO_GEN_COMMENT@
|
||||
config.cxx_under_test = "@LIBCXXABI_COMPILER@"
|
||||
|
||||
@SERIALIZED_LIT_PARAMS@
|
||||
|
||||
import os
|
||||
import site
|
||||
|
||||
config.cxx_under_test = "@CMAKE_CXX_COMPILER@"
|
||||
config.project_obj_root = "@CMAKE_BINARY_DIR@"
|
||||
config.libcxxabi_hdr_root = "@LIBCXXABI_HEADER_DIR@"
|
||||
config.libcxxabi_src_root = "@LIBCXXABI_SOURCE_DIR@"
|
||||
config.libcxxabi_obj_root = "@LIBCXXABI_BINARY_DIR@"
|
||||
config.abi_library_path = "@LIBCXXABI_LIBRARY_DIR@"
|
||||
config.abi_library_root = "@LIBCXXABI_LIBRARY_DIR@"
|
||||
config.libcxx_src_root = "@LIBCXXABI_LIBCXX_PATH@"
|
||||
config.cxx_headers = "@LIBCXXABI_LIBCXX_INCLUDES@"
|
||||
config.libunwind_headers = "@LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL@"
|
||||
@ -11,17 +18,11 @@ config.cxx_library_root = "@LIBCXXABI_LIBCXX_LIBRARY_PATH@"
|
||||
config.llvm_unwinder = @LIBCXXABI_USE_LLVM_UNWINDER@
|
||||
config.builtins_library = "@LIBCXXABI_BUILTINS_LIBRARY@"
|
||||
config.enable_threads = @LIBCXXABI_ENABLE_THREADS@
|
||||
config.use_sanitizer = "@LLVM_USE_SANITIZER@"
|
||||
config.sanitizer_library = "@LIBCXXABI_SANITIZER_LIBRARY@"
|
||||
config.enable_32bit = @LIBCXXABI_BUILD_32_BITS@
|
||||
config.target_info = "@LIBCXXABI_TARGET_INFO@"
|
||||
config.executor = "@LIBCXXABI_EXECUTOR@"
|
||||
config.libcxxabi_shared = @LIBCXXABI_ENABLE_SHARED@
|
||||
config.enable_shared = @LIBCXX_ENABLE_SHARED@
|
||||
config.enable_exceptions = @LIBCXXABI_ENABLE_EXCEPTIONS@
|
||||
config.libcxxabi_shared = @LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI@
|
||||
config.enable_shared = @LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX@
|
||||
config.host_triple = "@LLVM_HOST_TRIPLE@"
|
||||
config.target_triple = "@TARGET_TRIPLE@"
|
||||
config.use_target = bool("@LIBCXXABI_TARGET_TRIPLE@")
|
||||
config.sysroot = "@LIBCXXABI_SYSROOT@"
|
||||
config.gcc_toolchain = "@LIBCXXABI_GCC_TOOLCHAIN@"
|
||||
config.cxx_ext_threads = @LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY@
|
||||
@ -29,5 +30,32 @@ config.cxx_ext_threads = @LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY@
|
||||
config.pstl_src_root = "@ParallelSTL_SOURCE_DIR@" if @LIBCXX_ENABLE_PARALLEL_ALGORITHMS@ else None
|
||||
config.pstl_obj_root = "@ParallelSTL_BINARY_DIR@" if @LIBCXX_ENABLE_PARALLEL_ALGORITHMS@ else None
|
||||
|
||||
# Let the main config do the real work.
|
||||
lit_config.load_config(config, "@LIBCXXABI_SOURCE_DIR@/test/lit.cfg")
|
||||
# Code signing
|
||||
config.llvm_codesign_identity = "@LLVM_CODESIGNING_IDENTITY@"
|
||||
|
||||
site.addsitedir(os.path.join(config.libcxxabi_src_root, 'test'))
|
||||
site.addsitedir(os.path.join(config.libcxx_src_root, 'utils'))
|
||||
|
||||
# name: The name of this test suite.
|
||||
config.name = 'libc++abi'
|
||||
|
||||
# suffixes: A list of file extensions to treat as test files.
|
||||
config.suffixes = ['.cpp', '.s']
|
||||
|
||||
# test_source_root: The root path where tests are located.
|
||||
config.test_source_root = os.path.join(config.libcxxabi_src_root, 'test')
|
||||
|
||||
# Allow expanding substitutions that are based on other substitutions
|
||||
config.recursiveExpansionLimit = 10
|
||||
|
||||
# Infer the test_exec_root from the build directory.
|
||||
config.test_exec_root = os.path.join(config.libcxxabi_obj_root, 'test')
|
||||
|
||||
import libcxx.test.format
|
||||
config.test_format = libcxx.test.format.CxxStandardLibraryTest()
|
||||
|
||||
lit_config.note('Using configuration variant: libcxxabi')
|
||||
import libcxxabi.test.config
|
||||
configuration = libcxxabi.test.config.Configuration(lit_config, config)
|
||||
configuration.configure()
|
||||
configuration.print_config_info()
|
||||
|
@ -1,6 +1,6 @@
|
||||
def is_arm_linux_eabi(triple):
|
||||
return ('arm' in triple) and ('linux' in triple) and ('eabi' in triple)
|
||||
|
||||
is_native = config.root.host_triple == config.root.target_triple
|
||||
is_native = hasattr(config.root, 'target_triple') and (config.root.host_triple == config.root.target_triple)
|
||||
if not is_native or not is_arm_linux_eabi(config.root.host_triple):
|
||||
config.unsupported = True
|
||||
|
@ -1,6 +1,6 @@
|
||||
@ RUN: %cxx %flags %link_flags %s -o %t.exe
|
||||
@ RUN: %{cxx} %{flags} %{link_flags} %s -o %t.exe
|
||||
@ RUN: %t.exe
|
||||
@ UNSUPPORTED: libcxxabi-no-exceptions
|
||||
@ UNSUPPORTED: no-exceptions
|
||||
|
||||
@ PURPOSE: Check that 0x00 is a valid value for ttype encoding. LLVM and
|
||||
@ GCC 4.6 are generating 0x00 as ttype encoding. libc++abi should provide
|
||||
|
@ -1,6 +1,6 @@
|
||||
@ RUN: %cxx %flags %link_flags %s -o %t.exe
|
||||
@ RUN: %{cxx} %{flags} %{link_flags} %s -o %t.exe
|
||||
@ RUN: %t.exe
|
||||
@ UNSUPPORTED: libcxxabi-no-exceptions
|
||||
@ UNSUPPORTED: no-exceptions
|
||||
|
||||
@ PURPOSE: Check that 0x90 is a valid value for ttype encoding.
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// REQUIRES: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: c++03
|
||||
// REQUIRES: no-exceptions
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <exception>
|
||||
|
@ -6,8 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// REQUIRES: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: c++03
|
||||
// REQUIRES: no-exceptions
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <exception>
|
||||
|
@ -6,8 +6,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// REQUIRES: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: c++03
|
||||
// REQUIRES: no-exceptions
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <exception>
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: libcxxabi-no-exceptions
|
||||
// REQUIRES: no-exceptions
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <exception>
|
||||
|
@ -13,7 +13,7 @@
|
||||
#ifndef LIBCXXABI_NO_TIMER
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
|
||||
class timer
|
||||
{
|
||||
@ -31,7 +31,7 @@ public:
|
||||
using std::chrono::duration_cast;
|
||||
TimePoint end = Clock::now();
|
||||
MicroSeconds us = duration_cast<MicroSeconds>(end - m_start);
|
||||
std::cout << us.count() << " microseconds\n";
|
||||
std::printf("%d microseconds\n", us.count());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -6,60 +6,57 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include <typeinfo>
|
||||
#include <iostream>
|
||||
|
||||
// Test taken from 5.2.8.2
|
||||
// When typeid is applied to a glvalue expression whose type is a polymorphic
|
||||
// class type, (10.3), the result refers to a std::type_info object
|
||||
// representing the type of the most derived object (1.8) (that is, the
|
||||
// dynamic type) to which the glvalue refers. If the glvalue expression is
|
||||
// obtained by applying the unary * operator to a pointer(68) and the pointer
|
||||
// is a null pointer value (4.10), the typeid expression throws the
|
||||
// When typeid is applied to a glvalue expression whose type is a polymorphic
|
||||
// class type, (10.3), the result refers to a std::type_info object
|
||||
// representing the type of the most derived object (1.8) (that is, the
|
||||
// dynamic type) to which the glvalue refers. If the glvalue expression is
|
||||
// obtained by applying the unary * operator to a pointer(68) and the pointer
|
||||
// is a null pointer value (4.10), the typeid expression throws the
|
||||
// std::bad_typeid exception (18.7.3).
|
||||
//
|
||||
// 68) If p is an expression of pointer type, then *p, (*p), *(p),
|
||||
// 68) If p is an expression of pointer type, then *p, (*p), *(p),
|
||||
// ((*p)), *((p)), and so on all meet this requirement.
|
||||
bool bad_typeid_test () {
|
||||
class A { virtual void f() {}};
|
||||
class B { virtual void g() {}};
|
||||
|
||||
class A { virtual void f() {}};
|
||||
class B { virtual void g() {}};
|
||||
|
||||
B *bp = NULL;
|
||||
try {bool b = typeid(*bp) == typeid (A); ((void)b); }
|
||||
catch ( const std::bad_typeid &) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The value of a failed cast to pointer type is the null pointer value of
|
||||
// the required result type. A failed cast to reference type throws
|
||||
|
||||
// The value of a failed cast to pointer type is the null pointer value of
|
||||
// the required result type. A failed cast to reference type throws
|
||||
// std::bad_cast (18.7.2).
|
||||
bool bad_cast_test () {
|
||||
class A { virtual void f() {}};
|
||||
class B { virtual void g() {}};
|
||||
class D : public virtual A, private B {};
|
||||
class D : public virtual A, private B {};
|
||||
|
||||
D d;
|
||||
B *bp = (B*)&d; // cast needed to break protection
|
||||
try { D &dr = dynamic_cast<D&> (*bp); ((void)dr); }
|
||||
catch ( const std::bad_cast & ) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main ( ) {
|
||||
int ret_val = 0;
|
||||
|
||||
|
||||
if ( !bad_typeid_test ()) {
|
||||
std::cerr << "TypeID test failed!" << std::endl;
|
||||
ret_val = 1;
|
||||
}
|
||||
|
||||
|
||||
if ( !bad_cast_test ()) {
|
||||
std::cerr << "Bad cast test failed!" << std::endl;
|
||||
ret_val = 1;
|
||||
ret_val = 2;
|
||||
}
|
||||
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,14 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
// ___cxa_throw_bad_array_new_length is re-exported from libc++ only starting
|
||||
// in macosx 10.15
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14}}
|
||||
|
||||
#include <iostream>
|
||||
#include <cxxabi.h>
|
||||
#include <new>
|
||||
|
||||
// If the expression passed to operator new[] would result in an overflow, the
|
||||
// allocation function is not called, and a std::bad_array_new_length exception
|
||||
@ -27,11 +31,10 @@ bool bad_array_new_length_test() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
int ret_val = 0;
|
||||
|
||||
if ( !bad_array_new_length_test ()) {
|
||||
std::cerr << "Bad array new length test failed!" << std::endl;
|
||||
ret_val = 1;
|
||||
}
|
||||
|
||||
|
@ -6,15 +6,20 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// The demangler does not pass all these tests with the system dylibs on macOS.
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
|
||||
|
||||
#include "support/timer.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cxxabi.h>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
// Is long double fp80? (Only x87 extended double has 64-bit mantissa)
|
||||
#define LDBL_FP80 (__LDBL_MANT_DIG__ == 64)
|
||||
// Is long double fp128?
|
||||
#define LDBL_FP128 (__LDBL_MANT_DIG__ == 113)
|
||||
|
||||
const char* cases[][2] =
|
||||
{
|
||||
@ -12990,9 +12995,9 @@ const char* cases[][2] =
|
||||
{"_ZN4llvm3X8621GetCondBranchFromCondENS0_8CondCodeE", "llvm::X86::GetCondBranchFromCond(llvm::X86::CondCode)"},
|
||||
{"_ZN4llvm3X8626GetOppositeBranchConditionENS0_8CondCodeE", "llvm::X86::GetOppositeBranchCondition(llvm::X86::CondCode)"},
|
||||
{"_ZNK4llvm12X86InstrInfo24isUnpredicatedTerminatorEPKNS_12MachineInstrE", "llvm::X86InstrInfo::isUnpredicatedTerminator(llvm::MachineInstr const*) const"},
|
||||
{"_ZNK4llvm12X86InstrInfo13AnalyzeBranchERNS_17MachineBasicBlockERPS1_S4_RNS_15SmallVectorImplINS_14MachineOperandEEEb", "llvm::X86InstrInfo::AnalyzeBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*&, llvm::MachineBasicBlock*&, llvm::SmallVectorImpl<llvm::MachineOperand>&, bool) const"},
|
||||
{"_ZNK4llvm12X86InstrInfo12RemoveBranchERNS_17MachineBasicBlockE", "llvm::X86InstrInfo::RemoveBranch(llvm::MachineBasicBlock&) const"},
|
||||
{"_ZNK4llvm12X86InstrInfo12InsertBranchERNS_17MachineBasicBlockEPS1_S3_RKNS_15SmallVectorImplINS_14MachineOperandEEENS_8DebugLocE", "llvm::X86InstrInfo::InsertBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*, llvm::SmallVectorImpl<llvm::MachineOperand> const&, llvm::DebugLoc) const"},
|
||||
{"_ZNK4llvm12X86InstrInfo13analyzeBranchERNS_17MachineBasicBlockERPS1_S4_RNS_15SmallVectorImplINS_14MachineOperandEEEb", "llvm::X86InstrInfo::analyzeBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*&, llvm::MachineBasicBlock*&, llvm::SmallVectorImpl<llvm::MachineOperand>&, bool) const"},
|
||||
{"_ZNK4llvm12X86InstrInfo12removeBranchERNS_17MachineBasicBlockE", "llvm::X86InstrInfo::removeBranch(llvm::MachineBasicBlock&) const"},
|
||||
{"_ZNK4llvm12X86InstrInfo12insertBranchERNS_17MachineBasicBlockEPS1_S3_RKNS_15SmallVectorImplINS_14MachineOperandEEENS_8DebugLocE", "llvm::X86InstrInfo::insertBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*, llvm::SmallVectorImpl<llvm::MachineOperand> const&, llvm::DebugLoc) const"},
|
||||
{"_ZNK4llvm12X86InstrInfo11copyPhysRegERNS_17MachineBasicBlockENS_14ilist_iteratorINS_12MachineInstrEEENS_8DebugLocEjjb", "llvm::X86InstrInfo::copyPhysReg(llvm::MachineBasicBlock&, llvm::ilist_iterator<llvm::MachineInstr>, llvm::DebugLoc, unsigned int, unsigned int, bool) const"},
|
||||
{"_ZNK4llvm12X86InstrInfo19storeRegToStackSlotERNS_17MachineBasicBlockENS_14ilist_iteratorINS_12MachineInstrEEEjbiPKNS_19TargetRegisterClassEPKNS_18TargetRegisterInfoE", "llvm::X86InstrInfo::storeRegToStackSlot(llvm::MachineBasicBlock&, llvm::ilist_iterator<llvm::MachineInstr>, unsigned int, bool, int, llvm::TargetRegisterClass const*, llvm::TargetRegisterInfo const*) const"},
|
||||
{"_ZN4llvm17addFrameReferenceERKNS_19MachineInstrBuilderEii", "llvm::addFrameReference(llvm::MachineInstrBuilder const&, int, int)"},
|
||||
@ -13545,9 +13550,9 @@ const char* cases[][2] =
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo28CreateTargetHazardRecognizerEPKNS_13TargetMachineEPKNS_11ScheduleDAGE", "llvm::ARMBaseInstrInfo::CreateTargetHazardRecognizer(llvm::TargetMachine const*, llvm::ScheduleDAG const*) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo34CreateTargetPostRAHazardRecognizerEPKNS_18InstrItineraryDataEPKNS_11ScheduleDAGE", "llvm::ARMBaseInstrInfo::CreateTargetPostRAHazardRecognizer(llvm::InstrItineraryData const*, llvm::ScheduleDAG const*) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo21convertToThreeAddressERNS_14ilist_iteratorINS_17MachineBasicBlockEEERNS1_INS_12MachineInstrEEEPNS_13LiveVariablesE", "llvm::ARMBaseInstrInfo::convertToThreeAddress(llvm::ilist_iterator<llvm::MachineBasicBlock>&, llvm::ilist_iterator<llvm::MachineInstr>&, llvm::LiveVariables*) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo13AnalyzeBranchERNS_17MachineBasicBlockERPS1_S4_RNS_15SmallVectorImplINS_14MachineOperandEEEb", "llvm::ARMBaseInstrInfo::AnalyzeBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*&, llvm::MachineBasicBlock*&, llvm::SmallVectorImpl<llvm::MachineOperand>&, bool) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo12RemoveBranchERNS_17MachineBasicBlockE", "llvm::ARMBaseInstrInfo::RemoveBranch(llvm::MachineBasicBlock&) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo12InsertBranchERNS_17MachineBasicBlockEPS1_S3_RKNS_15SmallVectorImplINS_14MachineOperandEEENS_8DebugLocE", "llvm::ARMBaseInstrInfo::InsertBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*, llvm::SmallVectorImpl<llvm::MachineOperand> const&, llvm::DebugLoc) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo13analyzeBranchERNS_17MachineBasicBlockERPS1_S4_RNS_15SmallVectorImplINS_14MachineOperandEEEb", "llvm::ARMBaseInstrInfo::analyzeBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*&, llvm::MachineBasicBlock*&, llvm::SmallVectorImpl<llvm::MachineOperand>&, bool) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo12removeBranchERNS_17MachineBasicBlockE", "llvm::ARMBaseInstrInfo::removeBranch(llvm::MachineBasicBlock&) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo12insertBranchERNS_17MachineBasicBlockEPS1_S3_RKNS_15SmallVectorImplINS_14MachineOperandEEENS_8DebugLocE", "llvm::ARMBaseInstrInfo::insertBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*, llvm::SmallVectorImpl<llvm::MachineOperand> const&, llvm::DebugLoc) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo22ReverseBranchConditionERNS_15SmallVectorImplINS_14MachineOperandEEE", "llvm::ARMBaseInstrInfo::ReverseBranchCondition(llvm::SmallVectorImpl<llvm::MachineOperand>&) const"},
|
||||
{"_ZNK4llvm16ARMBaseInstrInfo20PredicateInstructionEPNS_12MachineInstrERKNS_15SmallVectorImplINS_14MachineOperandEEE", "llvm::ARMBaseInstrInfo::PredicateInstruction(llvm::MachineInstr*, llvm::SmallVectorImpl<llvm::MachineOperand> const&) const"},
|
||||
{"_ZN4llvm27getMatchingCondBranchOpcodeEi", "llvm::getMatchingCondBranchOpcode(int)"},
|
||||
@ -14257,9 +14262,9 @@ const char* cases[][2] =
|
||||
{"_ZNK4llvm15TargetInstrInfo19isLoadFromStackSlotEPKNS_12MachineInstrERi", "llvm::TargetInstrInfo::isLoadFromStackSlot(llvm::MachineInstr const*, int&) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo18isStoreToStackSlotEPKNS_12MachineInstrERi", "llvm::TargetInstrInfo::isStoreToStackSlot(llvm::MachineInstr const*, int&) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo21convertToThreeAddressERNS_14ilist_iteratorINS_17MachineBasicBlockEEERNS1_INS_12MachineInstrEEEPNS_13LiveVariablesE", "llvm::TargetInstrInfo::convertToThreeAddress(llvm::ilist_iterator<llvm::MachineBasicBlock>&, llvm::ilist_iterator<llvm::MachineInstr>&, llvm::LiveVariables*) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo13AnalyzeBranchERNS_17MachineBasicBlockERPS1_S4_RNS_15SmallVectorImplINS_14MachineOperandEEEb", "llvm::TargetInstrInfo::AnalyzeBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*&, llvm::MachineBasicBlock*&, llvm::SmallVectorImpl<llvm::MachineOperand>&, bool) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo12RemoveBranchERNS_17MachineBasicBlockE", "llvm::TargetInstrInfo::RemoveBranch(llvm::MachineBasicBlock&) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo12InsertBranchERNS_17MachineBasicBlockEPS1_S3_RKNS_15SmallVectorImplINS_14MachineOperandEEENS_8DebugLocE", "llvm::TargetInstrInfo::InsertBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*, llvm::SmallVectorImpl<llvm::MachineOperand> const&, llvm::DebugLoc) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo13analyzeBranchERNS_17MachineBasicBlockERPS1_S4_RNS_15SmallVectorImplINS_14MachineOperandEEEb", "llvm::TargetInstrInfo::analyzeBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*&, llvm::MachineBasicBlock*&, llvm::SmallVectorImpl<llvm::MachineOperand>&, bool) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo12removeBranchERNS_17MachineBasicBlockE", "llvm::TargetInstrInfo::removeBranch(llvm::MachineBasicBlock&) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo12insertBranchERNS_17MachineBasicBlockEPS1_S3_RKNS_15SmallVectorImplINS_14MachineOperandEEENS_8DebugLocE", "llvm::TargetInstrInfo::insertBranch(llvm::MachineBasicBlock&, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*, llvm::SmallVectorImpl<llvm::MachineOperand> const&, llvm::DebugLoc) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo19isProfitableToIfCvtERNS_17MachineBasicBlockEjjff", "llvm::TargetInstrInfo::isProfitableToIfCvt(llvm::MachineBasicBlock&, unsigned int, unsigned int, float, float) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo19isProfitableToIfCvtERNS_17MachineBasicBlockEjjS2_jjff", "llvm::TargetInstrInfo::isProfitableToIfCvt(llvm::MachineBasicBlock&, unsigned int, unsigned int, llvm::MachineBasicBlock&, unsigned int, unsigned int, float, float) const"},
|
||||
{"_ZNK4llvm15TargetInstrInfo25isProfitableToDupForIfCvtERNS_17MachineBasicBlockEjff", "llvm::TargetInstrInfo::isProfitableToDupForIfCvt(llvm::MachineBasicBlock&, unsigned int, float, float) const"},
|
||||
@ -29590,7 +29595,7 @@ const char* cases[][2] =
|
||||
{"_Z1fPU11objcproto1A11objc_object", "f(id<A>)"},
|
||||
{"_Z1fPKU11objcproto1A7NSArray", "f(NSArray<A> const*)"},
|
||||
{"_ZNK1AIJ1Z1Y1XEEcv1BIJDpPT_EEIJS2_S1_S0_EEEv", "A<Z, Y, X>::operator B<X*, Y*, Z*><X, Y, Z>() const"},
|
||||
{"_ZNK3Ncr6Silver7Utility6detail12CallOnThreadIZ53-[DeploymentSetupController handleManualServerEntry:]E3$_5EclIJEEEDTclclL_ZNS2_4getTIS4_EERT_vEEspclsr3stdE7forwardIT_Efp_EEEDpOSA_", "decltype(-[DeploymentSetupController handleManualServerEntry:]::$_5& Ncr::Silver::Utility::detail::getT<-[DeploymentSetupController handleManualServerEntry:]::$_5>()()(std::forward<-[DeploymentSetupController handleManualServerEntry:]::$_5>(fp)...)) Ncr::Silver::Utility::detail::CallOnThread<-[DeploymentSetupController handleManualServerEntry:]::$_5>::operator()<>(-[DeploymentSetupController handleManualServerEntry:]::$_5&&...) const"},
|
||||
{"_ZNK3Ncr6Silver7Utility6detail12CallOnThreadIZ53-[DeploymentSetupController handleManualServerEntry:]E3$_5EclIJEEEDTclclL_ZNS2_4getTIS4_EERT_vEEspclsr3stdE7forwardIT_Efp_EEEDpOSA_", "decltype(-[DeploymentSetupController handleManualServerEntry:]::$_5& Ncr::Silver::Utility::detail::getT<-[DeploymentSetupController handleManualServerEntry:]::$_5>()()()) Ncr::Silver::Utility::detail::CallOnThread<-[DeploymentSetupController handleManualServerEntry:]::$_5>::operator()<>() const"},
|
||||
{"_Zli2_xy", "operator\"\" _x(unsigned long long)"},
|
||||
{"_Z1fIiEDcT_", "decltype(auto) f<int>(int)"},
|
||||
{"_ZZ4testvEN1g3fooE5Point", "test()::g::foo(Point)"},
|
||||
@ -29774,8 +29779,18 @@ const char* cases[][2] =
|
||||
// Vendor extension types are substitution candidates.
|
||||
{"_Z1fu3fooS_", "f(foo, foo)"},
|
||||
|
||||
{"_ZN3FooIXu8__uuidofzdeL_Z3sucEEEC1Ev", "Foo<__uuidof(*(suc))>::Foo()"},
|
||||
{"_ZN3FooIXu8__uuidoft13SomeUUIDClassEEC1Ev", "Foo<__uuidof(SomeUUIDClass)>::Foo()"},
|
||||
// alignof with type and expression, and __alignof__ with the same.
|
||||
{"_Z2f1IiEvDTatT_E", "void f1<int>(decltype(alignof (int)))"},
|
||||
{"_Z2f3IiEvDTazcvT_Li0EE", "void f3<int>(decltype(alignof ((int)(0))))"},
|
||||
{"_Z2f2IiEvDTu11__alignof__T_EE", "void f2<int>(decltype(__alignof__(int)))"},
|
||||
{"_Z2f4IiEvDTu11__alignof__XcvT_Li0EEEE", "void f4<int>(decltype(__alignof__((int)(0))))"},
|
||||
|
||||
// Legacy nonstandard mangling for __uuidof.
|
||||
{"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E", "void test_uuidofType<TestStruct>(decltype(__uuidof(TestStruct)))"},
|
||||
{"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr<HasMember>(decltype(__uuidof(HasMember::member)))"},
|
||||
// Current __uuidof mangling using vendor extended expression.
|
||||
{"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE", "void test_uuidofType<TestStruct>(decltype(__uuidof(TestStruct)))"},
|
||||
{"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr<HasMember>(decltype(__uuidof(HasMember::member)))"},
|
||||
|
||||
// C++2a char8_t:
|
||||
{"_ZTSPDu", "typeinfo name for char8_t*"},
|
||||
@ -29792,6 +29807,43 @@ const char* cases[][2] =
|
||||
// "auto inline_func()::'lambda'<int, int>(int, int) const"
|
||||
{"_ZZ11inline_funcvENKUlTyTyT_T0_E_clIiiEEDaS_S0_", "auto inline_func()::'lambda'<typename $T, typename $T0>($T, $T0)::operator()<int, int>($T, $T0) const"},
|
||||
{"_ZZ11inline_funcvENKUlTyTyT_T1_T0_E_clIiiiEEDaS_S0_S1_", "auto inline_func()::'lambda'<typename $T, typename $T0>($T, auto, $T0)::operator()<int, int, int>($T, auto, $T0) const"},
|
||||
{"_ZN1XIZ1fIiEvOT_EUlOT_DpT0_E_EclIJEEEvDpT_", "void X<void f<int>(int&&)::'lambda'(auto&&, auto...)>::operator()<>()"},
|
||||
// FIXME: This is wrong, should demangle to the same as the previous entry.
|
||||
// See https://github.com/itanium-cxx-abi/cxx-abi/issues/106.
|
||||
{"_ZN1XIZ1fIiEvOT_EUlS2_DpT0_E_EclIJEEEvDpT_", "void X<void f<int>(int&&)::'lambda'(int&&, auto...)>::operator()<>()"},
|
||||
{"_ZZZZN6abcdef9abcdefghi29abcdefabcdefabcdefabcefabcdef27xxxxxxxxxxxxxxxxxxxxxxxxxxxEN4absl8DurationERKNSt3__u12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEPNS1_19yyyyyyyyyyyyyyyyyyyEENK3$_5clEvENKUlvE_clEvE6zzzzzz", "abcdef::abcdefghi::abcdefabcdefabcdefabcefabcdef::xxxxxxxxxxxxxxxxxxxxxxxxxxx(absl::Duration, std::__u::basic_string<char, std::__u::char_traits<char>, std::__u::allocator<char> > const&, abcdef::abcdefghi::abcdefabcdefabcdefabcefabcdef::yyyyyyyyyyyyyyyyyyy*)::$_5::operator()() const::'lambda'()::operator()() const::zzzzzz"},
|
||||
|
||||
// C++2a class type non-type template parameters:
|
||||
{"_Z1fIXtl1BLPi0ELi1EEEEvv", "void f<B{(int*)0, 1}>()"},
|
||||
{"_Z1fIXtl1BLPi32EEEEvv", "void f<B{(int*)32}>()"},
|
||||
{"_Z1fIXtl1BrcPiLi0EEEEvv", "void f<B{reinterpret_cast<int*>(0)}>()"},
|
||||
{"_Z1fIXtl1BadsoiL_Z6nestedE_EEEEvv", "void f<B{&(nested.<int at offset 0>)}>()"},
|
||||
{"_Z1fIXtl1BadsoiL_Z6nestedE16_0pEEEEvv", "void f<B{&(nested.<int at offset 16>)}>()"},
|
||||
{"_Z1fIXtl2BRsoiL_Z7derivedE4EEEEvv", "void f<BR{derived.<int at offset 4>}>()"},
|
||||
{"_Z1fIXtl1BcvPiplcvPcadL_Z7derivedELl16EEEEvv", "void f<B{(int*)(((char*)(&(derived))) + (16l))}>()"},
|
||||
{"_Z1fIXtl1CadsoKiL_Z7derivedE4EEEEvv", "void f<C{&(derived.<int const at offset 4>)}>()"},
|
||||
{"_Z1fIXtl1DLM7DerivedKi0ELi1EEEEvv", "void f<D{(int const Derived::*)0, 1}>()"},
|
||||
// FIXME: This is not valid pointer-to-member syntax.
|
||||
{"_Z1fIXtl1DmcM7DerivedKiadL_ZN11MoreDerived1zEEn8EEEEvv", "void f<D{(int const Derived::*)(&(MoreDerived::z))}>()"},
|
||||
{"_Z1fIXtl1Edi1nLi42EEEEvv", "void f<E{.n = 42}>()"},
|
||||
{"_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEE", "template parameter object for S{char [32]{(char)104, (char)101, (char)108, (char)108, (char)111, (char)32, (char)119, (char)111, (char)114, (char)108, (char)100}}"},
|
||||
|
||||
// FIXME: This is wrong; the S2_ backref should expand to OT_ and then to
|
||||
// "double&&". But we can't cope with a substitution that represents a
|
||||
// different type the node it is a substitute for.
|
||||
// See https://github.com/itanium-cxx-abi/cxx-abi/issues/106.
|
||||
{"_Z1h1XIJZ1fIiEDaOT_E1AZ1gIdEDaS2_E1BEE", "h(X<auto f<int>(int&&)::A, auto g<double>(int&&)::B>)"},
|
||||
|
||||
{"_Z1fIL4Enumn1EEvv", "void f<(Enum)-1>()"},
|
||||
|
||||
{"_ZN1A1gIiEEDTcldtptfpT1b1fIT_EEEv", "decltype(this->b.f<int>()) A::g<int>()"},
|
||||
|
||||
// Optional template-args for vendor extended type qualifier.
|
||||
// See https://bugs.llvm.org/show_bug.cgi?id=48009.
|
||||
{"_Z3fooILi79EEbU7_ExtIntIXT_EEi", "bool foo<79>(int _ExtInt<79>)"},
|
||||
|
||||
{"_ZN3xxx3yyyIvNS_1AILm0EEEZNS_2bb2cc2ddILNS_1eE1EEEvRKNS_1fERKNS_1g1hINS_1iEEERKNS_1jEfRKNS_1kEiPhEUlvE_JEEEvT1_DpT2_", "void xxx::yyy<void, xxx::A<0ul>, void xxx::bb::cc::dd<(xxx::e)1>(xxx::f const&, xxx::g::h<xxx::i> const&, xxx::j const&, float, xxx::k const&, int, unsigned char*)::'lambda'()>(void xxx::bb::cc::dd<(xxx::e)1>(xxx::f const&, xxx::g::h<xxx::i> const&, xxx::j const&, float, xxx::k const&, int, unsigned char*)::'lambda'())"},
|
||||
|
||||
};
|
||||
|
||||
const unsigned N = sizeof(cases) / sizeof(cases[0]);
|
||||
@ -29822,6 +29874,11 @@ struct FPLiteralCase {
|
||||
"void test0::h<float>(char (&) [(unsigned int)((sizeof (float)) + (0xap-1L))])",
|
||||
}},
|
||||
#endif
|
||||
#if LDBL_FP128
|
||||
// This was found by libFuzzer+HWASan on aarch64 Android.
|
||||
{"1\006ILeeeEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE",
|
||||
{"\x6<-0x1.cecececececececececececececep+11983L>"}},
|
||||
#endif
|
||||
};
|
||||
const unsigned NF = sizeof(fp_literal_cases) / sizeof(fp_literal_cases[0]);
|
||||
const unsigned NEF = sizeof(fp_literal_cases[0].expecting) / sizeof(fp_literal_cases[0].expecting[0]);
|
||||
@ -29879,17 +29936,16 @@ void test()
|
||||
char* demang = __cxxabiv1::__cxa_demangle(cases[i][0], buf, &len, &status);
|
||||
if (demang == 0 || std::strcmp(demang, cases[i][1]) != 0)
|
||||
{
|
||||
std::cout << "ERROR demangling " << cases[i][0] << '\n'
|
||||
<< "expected: " << cases[i][1] << std::endl;
|
||||
std::printf("ERROR demangling %s\nexpected: %s\n", cases[i][0], cases[i][1]);
|
||||
if (demang)
|
||||
{
|
||||
std::cout << " reality: " << demang << '\n' << std::endl;
|
||||
std::printf(" reality: %s\n", demang);
|
||||
buf = demang;
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Got instead: NULL, " << status << '\n';
|
||||
std::printf("Got instead: NULL, %d\n", status);
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
@ -29912,7 +29968,8 @@ void test_invalid_cases()
|
||||
char* demang = __cxxabiv1::__cxa_demangle(invalid_cases[i], buf, &len, &status);
|
||||
if (status != -2)
|
||||
{
|
||||
std::cout << invalid_cases[i] << " should be invalid but is not\n" << " got status = " << status << '\n';
|
||||
std::printf("%s should be invalid but is not\n", invalid_cases[i]);
|
||||
std::printf("Got status %d\n", status);
|
||||
assert(status == -2);
|
||||
}
|
||||
else
|
||||
@ -29942,8 +29999,8 @@ void test_xfail_cases()
|
||||
char* demang = __cxxabiv1::__cxa_demangle(xfail_cases[i], buf, &len, &status);
|
||||
if (status != -2)
|
||||
{
|
||||
std::cout << xfail_cases[i] << " was documented as xfail but passed\n"
|
||||
<< "got status = " << status << '\n';
|
||||
std::printf("%s was documented as xfail but passed\n", xfail_cases[i]);
|
||||
std::printf("Got status = %d\n", status);
|
||||
assert(status == -2);
|
||||
}
|
||||
else
|
||||
@ -29965,8 +30022,8 @@ void testFPLiterals()
|
||||
char* demang = __cxxabiv1::__cxa_demangle(fpCase->mangled, buf, &len, &status);
|
||||
if (demang == 0)
|
||||
{
|
||||
std::cout << fpCase->mangled << " -> " << fpCase->expecting[0] << '\n';
|
||||
std::cout << "Got instead: NULL, " << status << '\n';
|
||||
std::printf("%s -> %s\n", fpCase->mangled, fpCase->expecting[0].c_str());
|
||||
std::printf("Got instead: NULL, %d\n", status);
|
||||
assert(false);
|
||||
continue;
|
||||
}
|
||||
@ -29974,8 +30031,8 @@ void testFPLiterals()
|
||||
std::string *e_end = fpCase->expecting + NEF;
|
||||
if (std::find(e_beg, e_end, demang) == e_end)
|
||||
{
|
||||
std::cout << fpCase->mangled << " -> " << fpCase->expecting[0] << '\n';
|
||||
std::cout << "Got instead: " << demang << '\n';
|
||||
std::printf("%s -> %s\n", fpCase->mangled, fpCase->expecting[0].c_str());
|
||||
std::printf("Got instead: %s\n", demang);
|
||||
assert(false);
|
||||
continue;
|
||||
}
|
||||
@ -29984,9 +30041,9 @@ void testFPLiterals()
|
||||
free(buf);
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
std::cout << "Testing " << N << " symbols." << std::endl;
|
||||
std::printf("Testing %d symbols.\n", N);
|
||||
{
|
||||
timer t;
|
||||
test();
|
||||
@ -30022,10 +30079,12 @@ int main()
|
||||
std::free(demang);
|
||||
break;
|
||||
case 1:
|
||||
std::cout << "not immplemented\n";
|
||||
std::cout << "not implemented\n";
|
||||
break;
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,13 +6,18 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// UNSUPPORTED: no-exceptions
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
// The system unwind.h on OS X provides an incorrectly aligned _Unwind_Exception
|
||||
// type. That causes these tests to fail. This XFAIL is my best attempt at
|
||||
// working around this failure.
|
||||
// XFAIL: darwin && libcxxabi-has-system-unwinder
|
||||
// The <unwind.h> header provided in the SDK of older Xcodes used to provide
|
||||
// an incorrectly aligned _Unwind_Exception type on non-ARM. That causes these
|
||||
// tests to fail when compiling against such a SDK, or when running against a
|
||||
// system libc++abi that was compiled with an incorrect definition of _Unwind_Exception.
|
||||
// XFAIL: apple-clang-12.0.0 && !target={{arm.*}}
|
||||
// XFAIL: apple-clang-11 && !target={{arm.*}}
|
||||
// XFAIL: apple-clang-10 && !target={{arm.*}}
|
||||
// XFAIL: apple-clang-9 && !target={{arm.*}}
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}}
|
||||
|
||||
// Test that the address of the exception object is properly aligned as required
|
||||
// by the relevant ABI
|
||||
@ -39,7 +44,7 @@ static_assert(alignof(_Unwind_Exception) == EXPECTED_ALIGNMENT,
|
||||
struct MinAligned { };
|
||||
static_assert(alignof(MinAligned) == 1 && sizeof(MinAligned) == 1, "");
|
||||
|
||||
int main() {
|
||||
int main(int, char**) {
|
||||
for (int i=0; i < 10; ++i) {
|
||||
try {
|
||||
throw MinAligned{};
|
||||
@ -47,4 +52,6 @@ int main() {
|
||||
assert(reinterpret_cast<uintptr_t>(&ref) % EXPECTED_ALIGNMENT == 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -6,9 +6,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <__threading_support>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -19,19 +19,21 @@ typedef __cxxabiv1::__cxa_eh_globals globals_t ;
|
||||
void *thread_code (void *parm) {
|
||||
size_t *result = (size_t *) parm;
|
||||
globals_t *glob1, *glob2;
|
||||
|
||||
|
||||
glob1 = __cxxabiv1::__cxa_get_globals ();
|
||||
if ( NULL == glob1 )
|
||||
std::cerr << "Got null result from __cxa_get_globals" << std::endl;
|
||||
std::printf("Got null result from __cxa_get_globals\n");
|
||||
|
||||
glob2 = __cxxabiv1::__cxa_get_globals_fast ();
|
||||
if ( glob1 != glob2 )
|
||||
std::cerr << "Got different globals!" << std::endl;
|
||||
|
||||
std::printf("Got different globals!\n");
|
||||
|
||||
*result = (size_t) glob1;
|
||||
#ifndef _LIBCXXABI_HAS_NO_THREADS
|
||||
sleep ( 1 );
|
||||
#endif
|
||||
return parm;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _LIBCXXABI_HAS_NO_THREADS
|
||||
#define NUMTHREADS 10
|
||||
@ -49,18 +51,20 @@ int main () {
|
||||
for ( int i = 0; i < NUMTHREADS; ++i )
|
||||
std::__libcpp_thread_join ( &threads [ i ] );
|
||||
|
||||
for ( int i = 0; i < NUMTHREADS; ++i )
|
||||
for ( int i = 0; i < NUMTHREADS; ++i ) {
|
||||
if ( 0 == thread_globals [ i ] ) {
|
||||
std::cerr << "Thread #" << i << " had a zero global" << std::endl;
|
||||
std::printf("Thread #%d had a zero global\n", i);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::sort ( thread_globals, thread_globals + NUMTHREADS );
|
||||
for ( int i = 1; i < NUMTHREADS; ++i )
|
||||
for ( int i = 1; i < NUMTHREADS; ++i ) {
|
||||
if ( thread_globals [ i - 1 ] == thread_globals [ i ] ) {
|
||||
std::cerr << "Duplicate thread globals (" << i-1 << " and " << i << ")" << std::endl;
|
||||
std::printf("Duplicate thread globals (%d and %d)\n", i-1, i);
|
||||
retVal = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // _LIBCXXABI_HAS_NO_THREADS
|
||||
size_t thread_globals;
|
||||
// Check that __cxa_get_globals() is not NULL.
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <deque>
|
||||
|
||||
#include <__threading_support>
|
||||
@ -20,169 +20,172 @@ typedef std::deque<void *> container;
|
||||
container alloc_series ( size_t sz ) {
|
||||
container ptrs;
|
||||
void *p;
|
||||
|
||||
|
||||
while ( NULL != ( p = fallback_malloc ( sz )))
|
||||
ptrs.push_back ( p );
|
||||
return ptrs;
|
||||
}
|
||||
}
|
||||
|
||||
container alloc_series ( size_t sz, float growth ) {
|
||||
container ptrs;
|
||||
void *p;
|
||||
|
||||
|
||||
while ( NULL != ( p = fallback_malloc ( sz ))) {
|
||||
ptrs.push_back ( p );
|
||||
sz *= growth;
|
||||
}
|
||||
}
|
||||
|
||||
return ptrs;
|
||||
}
|
||||
}
|
||||
|
||||
container alloc_series ( const size_t *first, size_t len ) {
|
||||
container ptrs;
|
||||
const size_t *last = first + len;
|
||||
void * p;
|
||||
|
||||
|
||||
for ( const size_t *iter = first; iter != last; ++iter ) {
|
||||
if ( NULL == (p = fallback_malloc ( *iter )))
|
||||
break;
|
||||
ptrs.push_back ( p );
|
||||
}
|
||||
}
|
||||
|
||||
return ptrs;
|
||||
}
|
||||
}
|
||||
|
||||
void *pop ( container &c, bool from_end ) {
|
||||
void *ptr;
|
||||
if ( from_end ) {
|
||||
ptr = c.back ();
|
||||
c.pop_back ();
|
||||
}
|
||||
}
|
||||
else {
|
||||
ptr = c.front ();
|
||||
c.pop_front ();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void exhaustion_test1 () {
|
||||
container ptrs;
|
||||
|
||||
|
||||
init_heap ();
|
||||
std::cout << "Constant exhaustion tests" << std::endl;
|
||||
|
||||
std::printf("Constant exhaustion tests\n");
|
||||
|
||||
// Delete in allocation order
|
||||
ptrs = alloc_series ( 32 );
|
||||
std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl;
|
||||
std::printf("Allocated %zu 32 byte chunks\n", ptrs.size());
|
||||
print_free_list ();
|
||||
for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter )
|
||||
fallback_free ( *iter );
|
||||
print_free_list ();
|
||||
std::cout << "----" << std::endl;
|
||||
std::printf("----\n");
|
||||
|
||||
// Delete in reverse order
|
||||
ptrs = alloc_series ( 32 );
|
||||
std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl;
|
||||
std::printf("Allocated %zu 32 byte chunks\n", ptrs.size());
|
||||
for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter )
|
||||
fallback_free ( *iter );
|
||||
print_free_list ();
|
||||
std::cout << "----" << std::endl;
|
||||
std::printf("----\n");
|
||||
|
||||
// Alternate deletions
|
||||
ptrs = alloc_series ( 32 );
|
||||
std::cout << "Allocated " << ptrs.size () << " 32 byte chunks" << std::endl;
|
||||
std::printf("Allocated %zu 32 byte chunks\n", ptrs.size());
|
||||
while ( ptrs.size () > 0 )
|
||||
fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 ));
|
||||
print_free_list ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void exhaustion_test2 () {
|
||||
container ptrs;
|
||||
init_heap ();
|
||||
|
||||
std::cout << "Growing exhaustion tests" << std::endl;
|
||||
|
||||
std::printf("Growing exhaustion tests\n");
|
||||
|
||||
// Delete in allocation order
|
||||
ptrs = alloc_series ( 32, 1.5 );
|
||||
std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... } byte chunks" << std::endl;
|
||||
|
||||
std::printf("Allocated %zu { 32, 48, 72, 108, 162 ... } byte chunks\n",
|
||||
ptrs.size());
|
||||
print_free_list ();
|
||||
for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter )
|
||||
fallback_free ( *iter );
|
||||
print_free_list ();
|
||||
std::cout << "----" << std::endl;
|
||||
|
||||
std::printf("----\n");
|
||||
|
||||
// Delete in reverse order
|
||||
print_free_list ();
|
||||
ptrs = alloc_series ( 32, 1.5 );
|
||||
std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... } byte chunks" << std::endl;
|
||||
std::printf("Allocated %zu { 32, 48, 72, 108, 162 ... } byte chunks\n",
|
||||
ptrs.size());
|
||||
for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter )
|
||||
fallback_free ( *iter );
|
||||
print_free_list ();
|
||||
std::cout << "----" << std::endl;
|
||||
std::printf("----\n");
|
||||
|
||||
// Alternate deletions
|
||||
ptrs = alloc_series ( 32, 1.5 );
|
||||
std::cout << "Allocated " << ptrs.size () << " { 32, 48, 72, 108, 162 ... } byte chunks" << std::endl;
|
||||
std::printf("Allocated %zu { 32, 48, 72, 108, 162 ... } byte chunks\n",
|
||||
ptrs.size());
|
||||
while ( ptrs.size () > 0 )
|
||||
fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 ));
|
||||
print_free_list ();
|
||||
|
||||
}
|
||||
print_free_list ();
|
||||
|
||||
}
|
||||
|
||||
void exhaustion_test3 () {
|
||||
const size_t allocs [] = { 124, 60, 252, 60, 4 };
|
||||
container ptrs;
|
||||
init_heap ();
|
||||
|
||||
std::cout << "Complete exhaustion tests" << std::endl;
|
||||
|
||||
std::printf("Complete exhaustion tests\n");
|
||||
|
||||
// Delete in allocation order
|
||||
ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] ));
|
||||
std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl;
|
||||
std::printf("Allocated %zu chunks\n", ptrs.size());
|
||||
print_free_list ();
|
||||
for ( container::iterator iter = ptrs.begin (); iter != ptrs.end (); ++iter )
|
||||
fallback_free ( *iter );
|
||||
print_free_list ();
|
||||
std::cout << "----" << std::endl;
|
||||
|
||||
std::printf("----\n");
|
||||
|
||||
// Delete in reverse order
|
||||
print_free_list ();
|
||||
ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] ));
|
||||
std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl;
|
||||
std::printf("Allocated %zu chunks\n", ptrs.size());
|
||||
for ( container::reverse_iterator iter = ptrs.rbegin (); iter != ptrs.rend (); ++iter )
|
||||
fallback_free ( *iter );
|
||||
print_free_list ();
|
||||
std::cout << "----" << std::endl;
|
||||
std::printf("----\n");
|
||||
|
||||
// Alternate deletions
|
||||
ptrs = alloc_series ( allocs, sizeof ( allocs ) / sizeof ( allocs[0] ));
|
||||
std::cout << "Allocated " << ptrs.size () << " chunks" << std::endl;
|
||||
std::printf("Allocated %zu chunks\n", ptrs.size());
|
||||
while ( ptrs.size () > 0 )
|
||||
fallback_free ( pop ( ptrs, ptrs.size () % 1 == 1 ));
|
||||
print_free_list ();
|
||||
|
||||
}
|
||||
print_free_list ();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main () {
|
||||
print_free_list ();
|
||||
|
||||
char *p = (char *) fallback_malloc ( 1024 ); // too big!
|
||||
std::cout << "fallback_malloc ( 1024 ) --> " << (unsigned long ) p << std::endl;
|
||||
std::printf("fallback_malloc ( 1024 ) --> %lu\n", (unsigned long ) p);
|
||||
print_free_list ();
|
||||
|
||||
|
||||
p = (char *) fallback_malloc ( 32 );
|
||||
std::cout << "fallback_malloc ( 32 ) --> " << (unsigned long) (p - heap) << std::endl;
|
||||
std::printf("fallback_malloc ( 32 ) --> %lu\n", (unsigned long) (p - heap));
|
||||
if ( !is_fallback_ptr ( p ))
|
||||
std::cout << "### p is not a fallback pointer!!" << std::endl;
|
||||
|
||||
std::printf("### p is not a fallback pointer!!\n");
|
||||
|
||||
print_free_list ();
|
||||
fallback_free ( p );
|
||||
print_free_list ();
|
||||
|
||||
std::cout << std::endl;
|
||||
exhaustion_test1 (); std::cout << std::endl;
|
||||
exhaustion_test2 (); std::cout << std::endl;
|
||||
exhaustion_test3 (); std::cout << std::endl;
|
||||
|
||||
exhaustion_test1();
|
||||
exhaustion_test2();
|
||||
exhaustion_test3();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,11 @@
|
||||
|
||||
#ifndef _LIBCXXABI_HAS_NO_THREADS
|
||||
#include <thread>
|
||||
#include "make_test_thread.h"
|
||||
#endif
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Ensure that we initialize each variable once and only once.
|
||||
namespace test1 {
|
||||
static int run_count = 0;
|
||||
@ -40,7 +43,7 @@ namespace test1 {
|
||||
// When initialization fails, ensure that we try to initialize it again next
|
||||
// time.
|
||||
namespace test2 {
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
static int run_count = 0;
|
||||
int increment() {
|
||||
++run_count;
|
||||
@ -95,7 +98,8 @@ namespace test4 {
|
||||
}
|
||||
|
||||
void test() {
|
||||
std::thread t1(helper), t2(helper);
|
||||
std::thread t1 = support::make_test_thread(helper);
|
||||
std::thread t2 = support::make_test_thread(helper);
|
||||
t1.join();
|
||||
t2.join();
|
||||
assert(run_count == 1);
|
||||
@ -122,19 +126,19 @@ namespace test5 {
|
||||
|
||||
void helper() {
|
||||
static int a = one(); ((void)a);
|
||||
std::thread t(another_helper);
|
||||
std::thread t = support::make_test_thread(another_helper);
|
||||
t.join();
|
||||
}
|
||||
|
||||
void test() {
|
||||
std::thread t(helper);
|
||||
std::thread t = support::make_test_thread(helper);
|
||||
t.join();
|
||||
assert(run_count == 1);
|
||||
}
|
||||
}
|
||||
#endif /* _LIBCXXABI_HAS_NO_THREADS */
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
test1::test();
|
||||
test2::test();
|
||||
@ -143,4 +147,6 @@ int main()
|
||||
test4::test();
|
||||
test5::test();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,34 +8,36 @@
|
||||
|
||||
#include "cxxabi.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Wrapper routines
|
||||
void *my_alloc2 ( size_t sz ) {
|
||||
void *p = std::malloc ( sz );
|
||||
// std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p );
|
||||
// std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p );
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void my_dealloc2 ( void *p ) {
|
||||
// std::printf ( "Freeing %lx\n", (unsigned long) p );
|
||||
std::free ( p );
|
||||
}
|
||||
// std::printf ( "Freeing %lx\n", (unsigned long) p );
|
||||
std::free ( p );
|
||||
}
|
||||
|
||||
void my_dealloc3 ( void *p, size_t ) {
|
||||
// std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
|
||||
std::free ( p );
|
||||
}
|
||||
// std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
|
||||
std::free ( p );
|
||||
}
|
||||
|
||||
void my_construct ( void * ) {
|
||||
// std::printf ( "Constructing %lx\n", (unsigned long) p );
|
||||
}
|
||||
}
|
||||
|
||||
void my_destruct ( void * ) {
|
||||
// std::printf ( "Destructing %lx\n", (unsigned long) p );
|
||||
}
|
||||
}
|
||||
|
||||
int gCounter;
|
||||
void count_construct ( void * ) { ++gCounter; }
|
||||
@ -47,14 +49,14 @@ int gConstructorThrowTarget;
|
||||
int gDestructorCounter;
|
||||
int gDestructorThrowTarget;
|
||||
void throw_construct ( void * ) {
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
if ( gConstructorCounter == gConstructorThrowTarget )
|
||||
throw 1;
|
||||
++gConstructorCounter;
|
||||
#endif
|
||||
}
|
||||
void throw_destruct ( void * ) {
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
if ( ++gDestructorCounter == gDestructorThrowTarget )
|
||||
throw 2;
|
||||
#endif
|
||||
@ -70,7 +72,7 @@ struct vec_on_stack {
|
||||
void *storage;
|
||||
vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {}
|
||||
~vec_on_stack () CAN_THROW {__cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); }
|
||||
};
|
||||
};
|
||||
|
||||
// Test calls with empty constructors and destructors
|
||||
int test_empty ( ) {
|
||||
@ -84,7 +86,7 @@ int test_empty ( ) {
|
||||
__cxxabiv1::__cxa_vec_delete ( one, 40, 0, NULL );
|
||||
__cxxabiv1::__cxa_vec_delete2( two, 40, 0, NULL, my_dealloc2 );
|
||||
__cxxabiv1::__cxa_vec_delete3( three, 40, 0, NULL, my_dealloc3 );
|
||||
|
||||
|
||||
// Try with no padding
|
||||
one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, my_construct, my_destruct );
|
||||
two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, my_construct, my_destruct, my_alloc2, my_dealloc2 );
|
||||
@ -94,7 +96,7 @@ int test_empty ( ) {
|
||||
__cxxabiv1::__cxa_vec_delete2( two, 40, 0, my_destruct, my_dealloc2 );
|
||||
__cxxabiv1::__cxa_vec_delete3( three, 40, 0, my_destruct, my_dealloc3 );
|
||||
|
||||
// Padding and no con/destructors
|
||||
// Padding and no con/destructors
|
||||
one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, NULL, NULL );
|
||||
two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc2 );
|
||||
three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, NULL, NULL, my_alloc2, my_dealloc3 );
|
||||
@ -103,7 +105,7 @@ int test_empty ( ) {
|
||||
__cxxabiv1::__cxa_vec_delete2( two, 40, 8, NULL, my_dealloc2 );
|
||||
__cxxabiv1::__cxa_vec_delete3( three, 40, 8, NULL, my_dealloc3 );
|
||||
|
||||
// Padding with con/destructors
|
||||
// Padding with con/destructors
|
||||
one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, my_construct, my_destruct );
|
||||
two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc2 );
|
||||
three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, my_construct, my_destruct, my_alloc2, my_dealloc3 );
|
||||
@ -113,7 +115,7 @@ int test_empty ( ) {
|
||||
__cxxabiv1::__cxa_vec_delete3( three, 40, 8, my_destruct, my_dealloc3 );
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the constructors and destructors are matched
|
||||
int test_counted ( ) {
|
||||
@ -121,24 +123,24 @@ int test_counted ( ) {
|
||||
void *one, *two, *three;
|
||||
|
||||
// Try with no padding
|
||||
gCounter = 0;
|
||||
gCounter = 0;
|
||||
one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, count_construct, count_destruct );
|
||||
two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc2 );
|
||||
three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, count_construct, count_destruct, my_alloc2, my_dealloc3 );
|
||||
|
||||
|
||||
__cxxabiv1::__cxa_vec_delete ( one, 40, 0, count_destruct );
|
||||
__cxxabiv1::__cxa_vec_delete2( two, 40, 0, count_destruct, my_dealloc2 );
|
||||
__cxxabiv1::__cxa_vec_delete3( three, 40, 0, count_destruct, my_dealloc3 );
|
||||
|
||||
// Since there was no padding, the # of elements in the array are not stored
|
||||
|
||||
// Since there was no padding, the # of elements in the array are not stored
|
||||
// and the destructors are not called.
|
||||
if ( gCounter != 30 ) {
|
||||
std::cerr << "Mismatched Constructor/Destructor calls (1)" << std::endl;
|
||||
std::cerr << " Expected 30, got " << gCounter << std::endl;
|
||||
std::printf("Mismatched Constructor/Destructor calls (1)\n");
|
||||
std::printf(" Expected 30, got %d\n", gCounter);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
gCounter = 0;
|
||||
}
|
||||
|
||||
gCounter = 0;
|
||||
one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, count_construct, count_destruct );
|
||||
two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc2 );
|
||||
three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, count_construct, count_destruct, my_alloc2, my_dealloc3 );
|
||||
@ -148,15 +150,15 @@ int test_counted ( ) {
|
||||
__cxxabiv1::__cxa_vec_delete3( three, 40, 8, count_destruct, my_dealloc3 );
|
||||
|
||||
if ( gCounter != 0 ) {
|
||||
std::cerr << "Mismatched Constructor/Destructor calls (2)" << std::endl;
|
||||
std::cerr << " Expected 0, got " << gCounter << std::endl;
|
||||
std::printf("Mismatched Constructor/Destructor calls (2)\n");
|
||||
std::printf(" Expected 0, got %d\n", gCounter);
|
||||
retVal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
// Make sure the constructors and destructors are matched
|
||||
int test_exception_in_constructor ( ) {
|
||||
int retVal = 0;
|
||||
@ -171,24 +173,23 @@ int test_exception_in_constructor ( ) {
|
||||
one = __cxxabiv1::__cxa_vec_new ( 10, 40, 0, throw_construct, throw_destruct );
|
||||
two = __cxxabiv1::__cxa_vec_new2( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
|
||||
three = __cxxabiv1::__cxa_vec_new3( 10, 40, 0, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
|
||||
}
|
||||
}
|
||||
catch ( int i ) {}
|
||||
|
||||
|
||||
__cxxabiv1::__cxa_vec_delete ( one, 40, 0, throw_destruct );
|
||||
__cxxabiv1::__cxa_vec_delete2( two, 40, 0, throw_destruct, my_dealloc2 );
|
||||
__cxxabiv1::__cxa_vec_delete3( three, 40, 0, throw_destruct, my_dealloc3 );
|
||||
|
||||
// Since there was no padding, the # of elements in the array are not stored
|
||||
|
||||
// Since there was no padding, the # of elements in the array are not stored
|
||||
// and the destructors are not called.
|
||||
// Since we threw after 15 calls to the constructor, we should see 5 calls to
|
||||
// the destructor from the partially constructed array.
|
||||
if ( gConstructorCounter - gDestructorCounter != 10 ) {
|
||||
std::cerr << "Mismatched Constructor/Destructor calls (1C)" << std::endl;
|
||||
std::cerr << gConstructorCounter << " constructors, but " <<
|
||||
gDestructorCounter << " destructors" << std::endl;
|
||||
std::printf("Mismatched Constructor/Destructor calls (1C)\n");
|
||||
std::printf("%d constructors, but %d destructors\n", gConstructorCounter, gDestructorCounter);
|
||||
retVal = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gConstructorCounter = gDestructorCounter = 0;
|
||||
gConstructorThrowTarget = 15;
|
||||
gDestructorThrowTarget = -1;
|
||||
@ -197,25 +198,24 @@ int test_exception_in_constructor ( ) {
|
||||
one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
|
||||
two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
|
||||
three = __cxxabiv1::__cxa_vec_new3( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc3 );
|
||||
}
|
||||
}
|
||||
catch ( int i ) {}
|
||||
|
||||
|
||||
__cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
|
||||
__cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
|
||||
__cxxabiv1::__cxa_vec_delete3( three, 40, 8, throw_destruct, my_dealloc3 );
|
||||
|
||||
if ( gConstructorCounter != gDestructorCounter ) {
|
||||
std::cerr << "Mismatched Constructor/Destructor calls (2C)" << std::endl;
|
||||
std::cerr << gConstructorCounter << " constructors, but " <<
|
||||
gDestructorCounter << " destructors" << std::endl;
|
||||
std::printf("Mismatched Constructor/Destructor calls (2C)\n");
|
||||
std::printf("%d constructors, but %d destructors\n", gConstructorCounter, gDestructorCounter);
|
||||
retVal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
// Make sure the constructors and destructors are matched
|
||||
int test_exception_in_destructor ( ) {
|
||||
int retVal = 0;
|
||||
@ -230,25 +230,24 @@ int test_exception_in_destructor ( ) {
|
||||
one = two = NULL;
|
||||
one = __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct );
|
||||
two = __cxxabiv1::__cxa_vec_new2( 10, 40, 8, throw_construct, throw_destruct, my_alloc2, my_dealloc2 );
|
||||
}
|
||||
}
|
||||
catch ( int i ) {}
|
||||
|
||||
|
||||
try {
|
||||
__cxxabiv1::__cxa_vec_delete ( one, 40, 8, throw_destruct );
|
||||
__cxxabiv1::__cxa_vec_delete2( two, 40, 8, throw_destruct, my_dealloc2 );
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
catch ( int i ) {}
|
||||
|
||||
|
||||
// We should have thrown in the middle of cleaning up "two", which means that
|
||||
// there should be 20 calls to the destructor and the try block should exit
|
||||
// before the assertion.
|
||||
if ( gConstructorCounter != 20 || gDestructorCounter != 20 ) {
|
||||
std::cerr << "Unexpected Constructor/Destructor calls (1D)" << std::endl;
|
||||
std::cerr << "Expected (20, 20), but got (" << gConstructorCounter << ", " <<
|
||||
gDestructorCounter << ")" << std::endl;
|
||||
std::printf("Unexpected Constructor/Destructor calls (1D)\n");
|
||||
std::printf("Expected (20, 20), but got (%d, %d)\n", gConstructorCounter, gDestructorCounter);
|
||||
retVal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Try throwing from a destructor - should be fine.
|
||||
gConstructorCounter = gDestructorCounter = 0;
|
||||
@ -256,25 +255,24 @@ int test_exception_in_destructor ( ) {
|
||||
gDestructorThrowTarget = 5;
|
||||
try { vec_on_stack v; }
|
||||
catch ( int i ) {}
|
||||
|
||||
|
||||
if ( gConstructorCounter != gDestructorCounter ) {
|
||||
std::cerr << "Mismatched Constructor/Destructor calls (2D)" << std::endl;
|
||||
std::cerr << gConstructorCounter << " constructors, but " <<
|
||||
gDestructorCounter << " destructors" << std::endl;
|
||||
std::printf("Mismatched Constructor/Destructor calls (2D)\n");
|
||||
std::printf("%d constructors, but %d destructors\n", gConstructorCounter, gDestructorCounter);
|
||||
retVal = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main () {
|
||||
int main(int, char**) {
|
||||
int retVal = 0;
|
||||
retVal += test_empty ();
|
||||
retVal += test_counted ();
|
||||
#ifndef LIBCXXABI_HAS_NO_EXCEPTIONS
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
retVal += test_exception_in_constructor ();
|
||||
retVal += test_exception_in_destructor ();
|
||||
#endif
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
@ -6,39 +6,40 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include "cxxabi.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
|
||||
void my_terminate () { exit ( 0 ); }
|
||||
|
||||
// Wrapper routines
|
||||
void *my_alloc2 ( size_t sz ) {
|
||||
void *p = std::malloc ( sz );
|
||||
// std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p );
|
||||
// std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p );
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void my_dealloc2 ( void *p ) {
|
||||
// std::printf ( "Freeing %lx\n", (unsigned long) p );
|
||||
std::free ( p );
|
||||
}
|
||||
// std::printf ( "Freeing %lx\n", (unsigned long) p );
|
||||
std::free ( p );
|
||||
}
|
||||
|
||||
void my_dealloc3 ( void *p, size_t ) {
|
||||
// std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
|
||||
std::free ( p );
|
||||
}
|
||||
// std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz );
|
||||
std::free ( p );
|
||||
}
|
||||
|
||||
void my_construct ( void *) {
|
||||
// std::printf ( "Constructing %lx\n", (unsigned long) p );
|
||||
}
|
||||
}
|
||||
|
||||
void my_destruct ( void *) {
|
||||
// std::printf ( "Destructing %lx\n", (unsigned long) p );
|
||||
}
|
||||
}
|
||||
|
||||
int gCounter;
|
||||
void count_construct ( void * ) { ++gCounter; }
|
||||
@ -56,7 +57,7 @@ struct vec_on_stack {
|
||||
void *storage;
|
||||
vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {}
|
||||
~vec_on_stack () { __cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); }
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Make sure the constructors and destructors are matched
|
||||
@ -69,16 +70,17 @@ void test_exception_in_destructor ( ) {
|
||||
try {
|
||||
vec_on_stack v;
|
||||
throw 3;
|
||||
}
|
||||
catch ( int i ) {}
|
||||
} catch ( int i ) {
|
||||
|
||||
std::cerr << "should never get here" << std::endl;
|
||||
}
|
||||
|
||||
assert(false && "should never get here");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main () {
|
||||
std::set_terminate ( my_terminate );
|
||||
test_exception_in_destructor ();
|
||||
return 1; // we failed if we get here
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: libcxxabi-no-exceptions
|
||||
// UNSUPPORTED: no-exceptions
|
||||
|
||||
#include "cxxabi.h"
|
||||
|
||||
@ -17,6 +17,11 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Disable warning about throw always calling terminate.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wterminate"
|
||||
#endif
|
||||
|
||||
// use dtors instead of try/catch
|
||||
namespace test1 {
|
||||
struct B {
|
||||
@ -47,7 +52,7 @@ void destroy(void* v)
|
||||
t->~T();
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int, char**)
|
||||
{
|
||||
std::set_terminate(my_terminate);
|
||||
{
|
||||
@ -56,4 +61,6 @@ int main()
|
||||
__cxxabiv1::__cxa_vec_dtor(a, 10, sizeof(test1::A), destroy<test1::A>);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
126
test/testit
126
test/testit
@ -1,126 +0,0 @@
|
||||
#!/bin/sh
|
||||
#===------------------------------ testit ----------------------------------===#
|
||||
#
|
||||
# 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
|
||||
#
|
||||
#===------------------------------------------------------------------------===#
|
||||
|
||||
if [ -z "$CC" ]
|
||||
then
|
||||
CC=clang++
|
||||
fi
|
||||
|
||||
if [ -z "$OPTIONS" ]
|
||||
then
|
||||
OPTIONS="-std=c++0x -stdlib=libc++"
|
||||
fi
|
||||
|
||||
case $TRIPLE in
|
||||
*-*-mingw* | *-*-cygwin* | *-*-win*)
|
||||
TEST_EXE=test.exe
|
||||
;;
|
||||
*)
|
||||
TEST_EXE=a.out
|
||||
;;
|
||||
esac
|
||||
|
||||
FAIL=0
|
||||
PASS=0
|
||||
UNIMPLEMENTED=0
|
||||
IMPLEMENTED_FAIL=0
|
||||
IMPLEMENTED_PASS=0
|
||||
|
||||
afunc()
|
||||
{
|
||||
fail=0
|
||||
pass=0
|
||||
if (ls *.fail.cpp > /dev/null 2>&1)
|
||||
then
|
||||
for FILE in $(ls *.fail.cpp); do
|
||||
if $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o ./$TEST_EXE > /dev/null 2>&1
|
||||
then
|
||||
rm ./$TEST_EXE
|
||||
echo "$FILE should not compile"
|
||||
fail=$(($fail + 1))
|
||||
else
|
||||
pass=$(($pass + 1))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if (ls *.cpp > /dev/null 2>&1)
|
||||
then
|
||||
for FILE in $(ls *.pass.cpp); do
|
||||
if $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o ./$TEST_EXE
|
||||
then
|
||||
if ./$TEST_EXE
|
||||
then
|
||||
rm ./$TEST_EXE
|
||||
pass=$(($pass + 1))
|
||||
else
|
||||
echo "$FILE failed at run time"
|
||||
fail=$(($fail + 1))
|
||||
rm ./$TEST_EXE
|
||||
fi
|
||||
else
|
||||
echo "$FILE failed to compile"
|
||||
fail=$(($fail + 1))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ $fail -gt 0 ]
|
||||
then
|
||||
echo "failed $fail tests in `pwd`"
|
||||
IMPLEMENTED_FAIL=$(($IMPLEMENTED_FAIL + 1))
|
||||
fi
|
||||
if [ $pass -gt 0 ]
|
||||
then
|
||||
echo "passed $pass tests in `pwd`"
|
||||
if [ $fail -eq 0 ]
|
||||
then
|
||||
IMPLEMENTED_PASS=$(($IMPLEMENTED_PASS + 1))
|
||||
fi
|
||||
fi
|
||||
if [ $fail -eq 0 -a $pass -eq 0 ]
|
||||
then
|
||||
echo "not implemented: `pwd`"
|
||||
UNIMPLEMENTED=$(($UNIMPLEMENTED + 1))
|
||||
fi
|
||||
|
||||
FAIL=$(($FAIL + $fail))
|
||||
PASS=$(($PASS + $pass))
|
||||
|
||||
for FILE in *
|
||||
do
|
||||
if [ -d "$FILE" ];
|
||||
then
|
||||
cd $FILE
|
||||
afunc
|
||||
cd ..
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
afunc
|
||||
|
||||
echo "****************************************************"
|
||||
echo "Results for `pwd`:"
|
||||
echo "using `$CC --version`"
|
||||
echo "with $OPTIONS $HEADER_INCLUDE $SOURCE_LIB"
|
||||
echo "----------------------------------------------------"
|
||||
echo "sections without tests : $UNIMPLEMENTED"
|
||||
echo "sections with failures : $IMPLEMENTED_FAIL"
|
||||
echo "sections without failures: $IMPLEMENTED_PASS"
|
||||
echo " + ----"
|
||||
echo "total number of sections : $(($UNIMPLEMENTED+$IMPLEMENTED_FAIL+$IMPLEMENTED_PASS))"
|
||||
echo "----------------------------------------------------"
|
||||
echo "number of tests failed : $FAIL"
|
||||
echo "number of tests passed : $PASS"
|
||||
echo " + ----"
|
||||
echo "total number of tests : $(($FAIL+$PASS))"
|
||||
echo "****************************************************"
|
||||
|
||||
exit $FAIL
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user