Update libcxxabi source to llvmorg-13.0.1

This commit is contained in:
Thomas A 2022-07-03 10:07:38 -07:00
parent b115be2d85
commit 443d929eb3
112 changed files with 2309 additions and 1902 deletions

View File

@ -1,4 +0,0 @@
{
"repository.callsign" : "CXXA",
"conduit_uri" : "https://reviews.llvm.org/"
}

View File

@ -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()

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -1,5 +0,0 @@
_Znam = _Znaj;
_ZnamRKSt9nothrow_t = _ZnajRKSt9nothrow_t;
_Znwm = _Znwj;
_ZnwmRKSt9nothrow_t = _ZnwjRKSt9nothrow_t;

View File

@ -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

View File

@ -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
View 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

View File

@ -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

View File

@ -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()

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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("{");

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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";
};

View File

@ -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();

View File

@ -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 {

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -248,4 +248,4 @@ public:
} // __cxxabiv1
#endif // __PRIVATE_TYPEINFO_H_
#endif // __PRIVATE_TYPEINFO_H_

View File

@ -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";
}

View File

@ -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);
}

View File

@ -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

View File

@ -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";
}

View File

@ -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})

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 (...) {

View File

@ -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 (...) {

View File

@ -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));

View File

@ -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>

View File

@ -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;
}

View File

@ -2172,10 +2172,12 @@ void test()
} // t3
int main()
int main(int, char**)
{
timer t;
t1::test();
t2::test();
t3::test();
return 0;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
/*

View File

@ -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 (...) {

View File

@ -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);

View 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

View 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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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
View 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.")

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03
// REQUIRES: libcxxabi-no-exceptions
// UNSUPPORTED: c++03
// REQUIRES: no-exceptions
#include <cxxabi.h>
#include <exception>

View File

@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03
// REQUIRES: libcxxabi-no-exceptions
// UNSUPPORTED: c++03
// REQUIRES: no-exceptions
#include <cxxabi.h>
#include <exception>

View File

@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03
// REQUIRES: libcxxabi-no-exceptions
// UNSUPPORTED: c++03
// REQUIRES: no-exceptions
#include <cxxabi.h>
#include <exception>

View File

@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
// REQUIRES: libcxxabi-no-exceptions
// REQUIRES: no-exceptions
#include <cxxabi.h>
#include <exception>

View File

@ -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:

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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
}
}

View File

@ -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;
}

View File

@ -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