├── .arcconfig ├── .clang-format ├── .gitignore ├── CMakeLists.txt ├── CREDITS.TXT ├── LICENSE.TXT ├── cmake ├── Modules │ ├── HandleCompilerRT.cmake │ ├── HandleLibcxxabiFlags.cmake │ ├── HandleOutOfTreeLLVM.cmake │ └── MacroEnsureOutOfSourceBuild.cmake └── config-ix.cmake ├── fuzz ├── CMakeLists.txt └── cxa_demangle_fuzzer.cpp ├── include ├── __cxxabi_config.h └── cxxabi.h ├── lib ├── itanium-base.exp ├── new-delete.exp ├── personality-sjlj.exp └── personality-v0.exp ├── src ├── CMakeLists.txt ├── abort_message.cpp ├── abort_message.h ├── cxa_aux_runtime.cpp ├── cxa_default_handlers.cpp ├── cxa_demangle.cpp ├── cxa_exception.cpp ├── cxa_exception.h ├── cxa_exception_storage.cpp ├── cxa_guard.cpp ├── cxa_guard_impl.h ├── cxa_handlers.cpp ├── cxa_handlers.h ├── cxa_noexception.cpp ├── cxa_personality.cpp ├── cxa_thread_atexit.cpp ├── cxa_unexpected.cpp ├── cxa_vector.cpp ├── cxa_virtual.cpp ├── demangle │ ├── .clang-format │ ├── DemangleConfig.h │ ├── ItaniumDemangle.h │ ├── README.txt │ ├── StringView.h │ ├── Utility.h │ └── cp-to-llvm.sh ├── fallback_malloc.cpp ├── fallback_malloc.h ├── include │ ├── atomic_support.h │ └── refstring.h ├── private_typeinfo.cpp ├── private_typeinfo.h ├── stdlib_exception.cpp ├── stdlib_new_delete.cpp ├── stdlib_stdexcept.cpp └── stdlib_typeinfo.cpp ├── test ├── CMakeLists.txt ├── backtrace_test.pass.cpp ├── catch_array_01.pass.cpp ├── catch_array_02.pass.cpp ├── catch_class_01.pass.cpp ├── catch_class_02.pass.cpp ├── catch_class_03.pass.cpp ├── catch_class_04.pass.cpp ├── catch_const_pointer_nullptr.pass.cpp ├── catch_function_01.pass.cpp ├── catch_function_02.pass.cpp ├── catch_function_03.pass.cpp ├── catch_in_noexcept.pass.cpp ├── catch_member_data_pointer_01.pass.cpp ├── catch_member_function_pointer_01.pass.cpp ├── catch_member_function_pointer_02.pass.cpp ├── catch_member_pointer_nullptr.pass.cpp ├── catch_multi_level_pointer.pass.cpp ├── catch_pointer_nullptr.pass.cpp ├── catch_pointer_reference.pass.cpp ├── catch_ptr.pass.cpp ├── catch_ptr_02.pass.cpp ├── catch_reference_nullptr.pass.cpp ├── cxa_bad_cast.pass.cpp ├── cxa_bad_typeid.pass.cpp ├── cxa_thread_atexit_test.pass.cpp ├── cxa_vec_new_overflow_PR41395.pass.cpp ├── dynamic_cast.pass.cpp ├── dynamic_cast14.pass.cpp ├── dynamic_cast3.pass.cpp ├── dynamic_cast5.pass.cpp ├── dynamic_cast_stress.pass.cpp ├── exception_object_alignment.2.pass.cpp ├── exception_object_alignment.pass.cpp ├── guard_test_basic.pass.cpp ├── guard_threaded_test.pass.cpp ├── incomplete_type.sh.cpp ├── inherited_exception.pass.cpp ├── libcxxabi │ ├── __init__.py │ └── test │ │ ├── __init__.py │ │ └── config.py ├── lit.cfg ├── lit.site.cfg.in ├── native │ └── arm-linux-eabi │ │ ├── lit.local.cfg │ │ ├── ttype-encoding-00.pass.sh.s │ │ └── ttype-encoding-90.pass.sh.s ├── noexception1.pass.cpp ├── noexception2.pass.cpp ├── noexception3.pass.cpp ├── noexception4.pass.cpp ├── support │ └── timer.h ├── test_aux_runtime.pass.cpp ├── test_aux_runtime_op_array_new.pass.cpp ├── test_demangle.pass.cpp ├── test_exception_address_alignment.pass.cpp ├── test_exception_storage.pass.cpp ├── test_fallback_malloc.pass.cpp ├── test_guard.pass.cpp ├── test_vector1.pass.cpp ├── test_vector2.pass.cpp ├── test_vector3.pass.cpp ├── testit ├── thread_local_destruction_order.pass.cpp ├── uncaught_exception.pass.cpp ├── uncaught_exceptions.pass.cpp ├── unittest_demangle.pass.cpp ├── unwind_01.pass.cpp ├── unwind_02.pass.cpp ├── unwind_03.pass.cpp ├── unwind_04.pass.cpp ├── unwind_05.pass.cpp └── unwind_06.pass.cpp └── www ├── content.css ├── index.html ├── menu.css └── spec.html /.arcconfig: -------------------------------------------------------------------------------- 1 | { 2 | "repository.callsign" : "CXXA", 3 | "conduit_uri" : "https://reviews.llvm.org/" 4 | } 5 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | 3 | --- 4 | Language: Cpp 5 | 6 | AlwaysBreakTemplateDeclarations: true 7 | PointerAlignment: Left 8 | 9 | # Disable formatting options which may break tests. 10 | SortIncludes: false 11 | ReflowComments: false 12 | --- 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # vim swap files 6 | .*.sw? 7 | .sw? 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | #lib/ # We actually have things checked in to lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | 47 | # Translations 48 | *.mo 49 | *.pot 50 | 51 | # Django stuff: 52 | *.log 53 | 54 | # Sphinx documentation 55 | docs/_build/ 56 | 57 | # PyBuilder 58 | target/ 59 | -------------------------------------------------------------------------------- /CREDITS.TXT: -------------------------------------------------------------------------------- 1 | This file is a partial list of people who have contributed to the LLVM/libc++abi 2 | project. If you have contributed a patch or made some other contribution to 3 | LLVM/libc++abi, please submit a patch to this file to add yourself, and it will be 4 | done! 5 | 6 | The list is sorted by surname and formatted to allow easy grepping and 7 | beautification by scripts. The fields are: name (N), email (E), web-address 8 | (W), PGP key ID and fingerprint (P), description (D), and snail-mail address 9 | (S). 10 | 11 | N: Aaron Ballman 12 | E: aaron@aaronballman.com 13 | D: Minor patches 14 | 15 | N: Logan Chien 16 | E: logan.chien@mediatek.com 17 | D: ARM EHABI Unwind & Exception Handling 18 | 19 | N: Marshall Clow 20 | E: mclow.lists@gmail.com 21 | E: marshall@idio.com 22 | D: Architect and primary coauthor of libc++abi 23 | 24 | N: Matthew Dempsky 25 | E: matthew@dempsky.org 26 | D: Minor patches and bug fixes. 27 | 28 | N: Nowar Gu 29 | E: wenhan.gu@gmail.com 30 | D: Minor patches and fixes 31 | 32 | N: Howard Hinnant 33 | E: hhinnant@apple.com 34 | D: Architect and primary coauthor of libc++abi 35 | 36 | N: Dana Jansens 37 | E: danakj@chromium.org 38 | D: ARM EHABI Unwind & Exception Handling 39 | 40 | N: Nick Kledzik 41 | E: kledzik@apple.com 42 | 43 | N: Antoine Labour 44 | E: piman@chromium.org 45 | D: ARM EHABI Unwind & Exception Handling 46 | 47 | N: Bruce Mitchener, Jr. 48 | E: bruce.mitchener@gmail.com 49 | D: Minor typo fixes 50 | 51 | N: Andrew Morrow 52 | E: andrew.c.morrow@gmail.com 53 | D: Minor patches and fixes 54 | 55 | N: Erik Olofsson 56 | E: erik.olofsson@hansoft.se 57 | E: erik@olofsson.info 58 | D: Minor patches and fixes 59 | 60 | N: Jon Roelofs 61 | E: jroelofs@jroelofs.com 62 | D: ARM EHABI Unwind & Exception Handling, Bare-metal 63 | 64 | N: Nico Weber 65 | E: thakis@chromium.org 66 | D: ARM EHABI Unwind & Exception Handling 67 | 68 | N: Albert J. Wong 69 | E: ajwong@google.com 70 | D: ARM EHABI Unwind & Exception Handling 71 | 72 | -------------------------------------------------------------------------------- /cmake/Modules/HandleCompilerRT.cmake: -------------------------------------------------------------------------------- 1 | function(find_compiler_rt_library name dest) 2 | if (NOT DEFINED LIBCXXABI_COMPILE_FLAGS) 3 | message(FATAL_ERROR "LIBCXXABI_COMPILE_FLAGS must be defined when using this function") 4 | endif() 5 | set(dest "" PARENT_SCOPE) 6 | set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBCXXABI_COMPILE_FLAGS} 7 | "--rtlib=compiler-rt" "--print-libgcc-file-name") 8 | if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_CXX_COMPILER_TARGET) 9 | list(APPEND CLANG_COMMAND "--target=${CMAKE_CXX_COMPILER_TARGET}") 10 | endif() 11 | get_property(LIBCXXABI_CXX_FLAGS CACHE CMAKE_CXX_FLAGS PROPERTY VALUE) 12 | string(REPLACE " " ";" LIBCXXABI_CXX_FLAGS "${LIBCXXABI_CXX_FLAGS}") 13 | list(APPEND CLANG_COMMAND ${LIBCXXABI_CXX_FLAGS}) 14 | execute_process( 15 | COMMAND ${CLANG_COMMAND} 16 | RESULT_VARIABLE HAD_ERROR 17 | OUTPUT_VARIABLE LIBRARY_FILE 18 | ) 19 | string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE) 20 | file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE) 21 | string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}") 22 | if (NOT HAD_ERROR AND EXISTS "${LIBRARY_FILE}") 23 | message(STATUS "Found compiler-rt library: ${LIBRARY_FILE}") 24 | set(${dest} "${LIBRARY_FILE}" PARENT_SCOPE) 25 | else() 26 | message(STATUS "Failed to find compiler-rt library") 27 | endif() 28 | endfunction() 29 | 30 | function(find_compiler_rt_dir dest) 31 | if (NOT DEFINED LIBCXXABI_COMPILE_FLAGS) 32 | message(FATAL_ERROR "LIBCXXABI_COMPILE_FLAGS must be defined when using this function") 33 | endif() 34 | set(dest "" PARENT_SCOPE) 35 | if (APPLE) 36 | set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBCXXABI_COMPILE_FLAGS} 37 | "-print-file-name=lib") 38 | execute_process( 39 | COMMAND ${CLANG_COMMAND} 40 | RESULT_VARIABLE HAD_ERROR 41 | OUTPUT_VARIABLE LIBRARY_DIR 42 | ) 43 | string(STRIP "${LIBRARY_DIR}" LIBRARY_DIR) 44 | file(TO_CMAKE_PATH "${LIBRARY_DIR}" LIBRARY_DIR) 45 | set(LIBRARY_DIR "${LIBRARY_DIR}/darwin") 46 | else() 47 | set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBCXXABI_COMPILE_FLAGS} 48 | "--rtlib=compiler-rt" "--print-libgcc-file-name") 49 | execute_process( 50 | COMMAND ${CLANG_COMMAND} 51 | RESULT_VARIABLE HAD_ERROR 52 | OUTPUT_VARIABLE LIBRARY_FILE 53 | ) 54 | string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE) 55 | file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE) 56 | get_filename_component(LIBRARY_DIR "${LIBRARY_FILE}" DIRECTORY) 57 | endif() 58 | if (NOT HAD_ERROR AND EXISTS "${LIBRARY_DIR}") 59 | message(STATUS "Found compiler-rt directory: ${LIBRARY_DIR}") 60 | set(${dest} "${LIBRARY_DIR}" PARENT_SCOPE) 61 | else() 62 | message(STATUS "Failed to find compiler-rt directory") 63 | endif() 64 | endfunction() 65 | -------------------------------------------------------------------------------- /cmake/Modules/HandleOutOfTreeLLVM.cmake: -------------------------------------------------------------------------------- 1 | macro(find_llvm_parts) 2 | # Rely on llvm-config. 3 | set(CONFIG_OUTPUT) 4 | if(NOT LLVM_CONFIG_PATH) 5 | find_program(LLVM_CONFIG_PATH "llvm-config") 6 | endif() 7 | if(DEFINED LLVM_PATH) 8 | set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include") 9 | set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree") 10 | set(LLVM_MAIN_SRC_DIR ${LLVM_PATH}) 11 | set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules") 12 | if (NOT IS_DIRECTORY "${LLVM_PATH}") 13 | message(FATAL_ERROR "The provided LLVM_PATH (${LLVM_PATH}) is not a valid directory") 14 | endif() 15 | elseif(LLVM_CONFIG_PATH) 16 | message(STATUS "Found LLVM_CONFIG_PATH as ${LLVM_CONFIG_PATH}") 17 | set(LIBCXXABI_USING_INSTALLED_LLVM 1) 18 | set(CONFIG_COMMAND ${LLVM_CONFIG_PATH} 19 | "--includedir" 20 | "--prefix" 21 | "--src-root") 22 | execute_process( 23 | COMMAND ${CONFIG_COMMAND} 24 | RESULT_VARIABLE HAD_ERROR 25 | OUTPUT_VARIABLE CONFIG_OUTPUT 26 | ) 27 | if(NOT HAD_ERROR) 28 | string(REGEX REPLACE 29 | "[ \t]*[\r\n]+[ \t]*" ";" 30 | CONFIG_OUTPUT ${CONFIG_OUTPUT}) 31 | else() 32 | string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}") 33 | message(STATUS "${CONFIG_COMMAND_STR}") 34 | message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") 35 | endif() 36 | 37 | list(GET CONFIG_OUTPUT 0 INCLUDE_DIR) 38 | list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT) 39 | list(GET CONFIG_OUTPUT 2 MAIN_SRC_DIR) 40 | 41 | set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include") 42 | set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree") 43 | set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") 44 | 45 | # --cmakedir is supported since llvm r291218 (4.0 release) 46 | execute_process( 47 | COMMAND ${LLVM_CONFIG_PATH} --cmakedir 48 | RESULT_VARIABLE HAD_ERROR 49 | OUTPUT_VARIABLE CONFIG_OUTPUT 50 | ERROR_QUIET) 51 | if(NOT HAD_ERROR) 52 | string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG) 53 | file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH) 54 | else() 55 | file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE) 56 | set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") 57 | endif() 58 | else() 59 | set(LLVM_FOUND OFF) 60 | message(WARNING "UNSUPPORTED LIBCXXABI CONFIGURATION DETECTED: " 61 | "llvm-config not found and LLVM_PATH not defined.\n" 62 | "Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config " 63 | "or -DLLVM_PATH=path/to/llvm-source-root.") 64 | return() 65 | endif() 66 | 67 | if (EXISTS "${LLVM_CMAKE_PATH}") 68 | list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") 69 | elseif (EXISTS "${LLVM_MAIN_SRC_DIR}/cmake/modules") 70 | list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") 71 | else() 72 | set(LLVM_FOUND OFF) 73 | message(WARNING "Neither ${LLVM_CMAKE_PATH} nor ${LLVM_MAIN_SRC_DIR}/cmake/modules found") 74 | return() 75 | endif() 76 | 77 | set(LLVM_FOUND ON) 78 | endmacro(find_llvm_parts) 79 | 80 | macro(configure_out_of_tree_llvm) 81 | message(STATUS "Configuring for standalone build.") 82 | set(LIBCXXABI_STANDALONE_BUILD 1) 83 | 84 | find_llvm_parts() 85 | 86 | # Add LLVM Functions -------------------------------------------------------- 87 | if (LLVM_FOUND AND LIBCXXABI_USING_INSTALLED_LLVM) 88 | include(LLVMConfig) # For TARGET_TRIPLE 89 | else() 90 | if (WIN32) 91 | set(LLVM_ON_UNIX 0) 92 | set(LLVM_ON_WIN32 1) 93 | else() 94 | set(LLVM_ON_UNIX 1) 95 | set(LLVM_ON_WIN32 0) 96 | endif() 97 | endif() 98 | if (LLVM_FOUND) 99 | include(AddLLVM OPTIONAL) 100 | endif() 101 | 102 | # LLVM Options -------------------------------------------------------------- 103 | if (NOT DEFINED LLVM_INCLUDE_TESTS) 104 | set(LLVM_INCLUDE_TESTS ${LLVM_FOUND}) 105 | endif() 106 | if (NOT DEFINED LLVM_INCLUDE_DOCS) 107 | set(LLVM_INCLUDE_DOCS ${LLVM_FOUND}) 108 | endif() 109 | if (NOT DEFINED LLVM_ENABLE_SPHINX) 110 | set(LLVM_ENABLE_SPHINX OFF) 111 | endif() 112 | 113 | # In a standalone build, we don't have llvm to automatically generate the 114 | # llvm-lit script for us. So we need to provide an explicit directory that 115 | # the configurator should write the script into. 116 | set(LLVM_LIT_OUTPUT_DIR "${libcxxabi_BINARY_DIR}/bin") 117 | 118 | if (LLVM_INCLUDE_TESTS) 119 | # Required LIT Configuration ------------------------------------------------ 120 | # Define the default arguments to use with 'lit', and an option for the user 121 | # to override. 122 | set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py") 123 | set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported") 124 | if (MSVC OR XCODE) 125 | set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") 126 | endif() 127 | set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") 128 | endif() 129 | 130 | # Required doc configuration 131 | if (LLVM_ENABLE_SPHINX) 132 | find_package(Sphinx REQUIRED) 133 | endif() 134 | 135 | if (LLVM_ON_UNIX AND NOT APPLE) 136 | set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) 137 | else() 138 | set(LLVM_HAVE_LINK_VERSION_SCRIPT 0) 139 | endif() 140 | endmacro(configure_out_of_tree_llvm) 141 | 142 | configure_out_of_tree_llvm() 143 | -------------------------------------------------------------------------------- /cmake/Modules/MacroEnsureOutOfSourceBuild.cmake: -------------------------------------------------------------------------------- 1 | # MACRO_ENSURE_OUT_OF_SOURCE_BUILD() 2 | 3 | macro( MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage ) 4 | 5 | string( COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource ) 6 | if( _insource ) 7 | message( SEND_ERROR "${_errorMessage}" ) 8 | message( FATAL_ERROR 9 | "In-source builds are not allowed. 10 | CMake would overwrite the makefiles distributed with libcxxabi. 11 | Please create a directory and run cmake from there, passing the path 12 | to this source directory as the last argument. 13 | This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. 14 | Please delete them." 15 | ) 16 | endif( _insource ) 17 | 18 | endmacro( MACRO_ENSURE_OUT_OF_SOURCE_BUILD ) 19 | -------------------------------------------------------------------------------- /cmake/config-ix.cmake: -------------------------------------------------------------------------------- 1 | include(CMakePushCheckState) 2 | include(CheckLibraryExists) 3 | include(CheckCCompilerFlag) 4 | include(CheckCXXCompilerFlag) 5 | include(CheckCSourceCompiles) 6 | 7 | check_library_exists(c fopen "" LIBCXXABI_HAS_C_LIB) 8 | if (NOT LIBCXXABI_USE_COMPILER_RT) 9 | check_library_exists(gcc_s __gcc_personality_v0 "" LIBCXXABI_HAS_GCC_S_LIB) 10 | check_library_exists(gcc __aeabi_uldivmod "" LIBCXXABI_HAS_GCC_LIB) 11 | endif () 12 | 13 | # libc++abi is built with -nodefaultlibs, so we want all our checks to also 14 | # use this option, otherwise we may end up with an inconsistency between 15 | # the flags we think we require during configuration (if the checks are 16 | # performed without -nodefaultlibs) and the flags that are actually 17 | # required during compilation (which has the -nodefaultlibs). libc is 18 | # required for the link to go through. We remove sanitizers from the 19 | # configuration checks to avoid spurious link errors. 20 | check_c_compiler_flag(-nodefaultlibs LIBCXXABI_HAS_NODEFAULTLIBS_FLAG) 21 | if (LIBCXXABI_HAS_NODEFAULTLIBS_FLAG) 22 | set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs") 23 | if (LIBCXXABI_HAS_C_LIB) 24 | list(APPEND CMAKE_REQUIRED_LIBRARIES c) 25 | endif () 26 | if (LIBCXXABI_USE_COMPILER_RT) 27 | list(APPEND CMAKE_REQUIRED_FLAGS -rtlib=compiler-rt) 28 | find_compiler_rt_library(builtins LIBCXXABI_BUILTINS_LIBRARY) 29 | list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBCXXABI_BUILTINS_LIBRARY}") 30 | else () 31 | if (LIBCXXABI_HAS_GCC_S_LIB) 32 | list(APPEND CMAKE_REQUIRED_LIBRARIES gcc_s) 33 | endif () 34 | if (LIBCXXABI_HAS_GCC_LIB) 35 | list(APPEND CMAKE_REQUIRED_LIBRARIES gcc) 36 | endif () 37 | endif () 38 | if (MINGW) 39 | # Mingw64 requires quite a few "C" runtime libraries in order for basic 40 | # programs to link successfully with -nodefaultlibs. 41 | if (LIBCXXABI_USE_COMPILER_RT) 42 | set(MINGW_RUNTIME ${LIBCXXABI_BUILTINS_LIBRARY}) 43 | else () 44 | set(MINGW_RUNTIME gcc_s gcc) 45 | endif() 46 | set(MINGW_LIBRARIES mingw32 ${MINGW_RUNTIME} moldname mingwex msvcrt advapi32 47 | shell32 user32 kernel32 mingw32 ${MINGW_RUNTIME} 48 | moldname mingwex msvcrt) 49 | list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES}) 50 | endif() 51 | if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize) 52 | set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all") 53 | endif () 54 | if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage) 55 | set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters") 56 | endif () 57 | endif () 58 | 59 | # Check compiler pragmas 60 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 61 | cmake_push_check_state() 62 | set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unknown-pragmas") 63 | check_c_source_compiles(" 64 | #pragma comment(lib, \"c\") 65 | int main() { return 0; } 66 | " LIBCXXABI_HAS_COMMENT_LIB_PRAGMA) 67 | cmake_pop_check_state() 68 | endif() 69 | 70 | # Check compiler flags 71 | check_cxx_compiler_flag(-nostdinc++ LIBCXXABI_HAS_NOSTDINCXX_FLAG) 72 | 73 | # Check libraries 74 | check_library_exists(dl dladdr "" LIBCXXABI_HAS_DL_LIB) 75 | check_library_exists(pthread pthread_once "" LIBCXXABI_HAS_PTHREAD_LIB) 76 | check_library_exists(c __cxa_thread_atexit_impl "" 77 | LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL) 78 | check_library_exists(System write "" LIBCXXABI_HAS_SYSTEM_LIB) 79 | -------------------------------------------------------------------------------- /fuzz/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # See http://llvm.org/docs/LibFuzzer.html 2 | if( LLVM_USE_SANITIZE_COVERAGE ) 3 | add_executable(cxa_demangle_fuzzer 4 | cxa_demangle_fuzzer.cpp 5 | ../src/cxa_demangle.cpp 6 | ) 7 | 8 | target_link_libraries(cxa_demangle_fuzzer 9 | LLVMFuzzer 10 | ) 11 | endif() 12 | -------------------------------------------------------------------------------- /fuzz/cxa_demangle_fuzzer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | extern "C" char * 6 | __cxa_demangle(const char *mangled_name, char *buf, size_t *n, int *status); 7 | 8 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 9 | char *str = new char[size+1]; 10 | memcpy(str, data, size); 11 | str[size] = 0; 12 | free(__cxa_demangle(str, 0, 0, 0)); 13 | delete [] str; 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /include/__cxxabi_config.h: -------------------------------------------------------------------------------- 1 | //===-------------------------- __cxxabi_config.h -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef ____CXXABI_CONFIG_H 10 | #define ____CXXABI_CONFIG_H 11 | 12 | #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ 13 | !defined(__ARM_DWARF_EH__) 14 | #define _LIBCXXABI_ARM_EHABI 15 | #endif 16 | 17 | #if !defined(__has_attribute) 18 | #define __has_attribute(_attribute_) 0 19 | #endif 20 | 21 | #if defined(_WIN32) 22 | #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) 23 | #define _LIBCXXABI_HIDDEN 24 | #define _LIBCXXABI_DATA_VIS 25 | #define _LIBCXXABI_FUNC_VIS 26 | #define _LIBCXXABI_TYPE_VIS 27 | #elif defined(_LIBCXXABI_BUILDING_LIBRARY) 28 | #define _LIBCXXABI_HIDDEN 29 | #define _LIBCXXABI_DATA_VIS __declspec(dllexport) 30 | #define _LIBCXXABI_FUNC_VIS __declspec(dllexport) 31 | #define _LIBCXXABI_TYPE_VIS __declspec(dllexport) 32 | #else 33 | #define _LIBCXXABI_HIDDEN 34 | #define _LIBCXXABI_DATA_VIS __declspec(dllimport) 35 | #define _LIBCXXABI_FUNC_VIS __declspec(dllimport) 36 | #define _LIBCXXABI_TYPE_VIS __declspec(dllimport) 37 | #endif 38 | #else 39 | #if !defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) 40 | #define _LIBCXXABI_HIDDEN __attribute__((__visibility__("hidden"))) 41 | #define _LIBCXXABI_DATA_VIS __attribute__((__visibility__("default"))) 42 | #define _LIBCXXABI_FUNC_VIS __attribute__((__visibility__("default"))) 43 | #if __has_attribute(__type_visibility__) 44 | #define _LIBCXXABI_TYPE_VIS __attribute__((__type_visibility__("default"))) 45 | #else 46 | #define _LIBCXXABI_TYPE_VIS __attribute__((__visibility__("default"))) 47 | #endif 48 | #else 49 | #define _LIBCXXABI_HIDDEN 50 | #define _LIBCXXABI_DATA_VIS 51 | #define _LIBCXXABI_FUNC_VIS 52 | #define _LIBCXXABI_TYPE_VIS 53 | #endif 54 | #endif 55 | 56 | #if defined(_WIN32) 57 | #define _LIBCXXABI_WEAK 58 | #else 59 | #define _LIBCXXABI_WEAK __attribute__((__weak__)) 60 | #endif 61 | 62 | #if defined(__clang__) 63 | #define _LIBCXXABI_COMPILER_CLANG 64 | #elif defined(__GNUC__) 65 | #define _LIBCXXABI_COMPILER_GCC 66 | #endif 67 | 68 | #if __has_attribute(__no_sanitize__) && defined(_LIBCXXABI_COMPILER_CLANG) 69 | #define _LIBCXXABI_NO_CFI __attribute__((__no_sanitize__("cfi"))) 70 | #else 71 | #define _LIBCXXABI_NO_CFI 72 | #endif 73 | 74 | // wasm32 follows the arm32 ABI convention of using 32-bit guard. 75 | #if defined(__arm__) || defined(__wasm32__) 76 | # define _LIBCXXABI_GUARD_ABI_ARM 77 | #endif 78 | 79 | #endif // ____CXXABI_CONFIG_H 80 | -------------------------------------------------------------------------------- /lib/new-delete.exp: -------------------------------------------------------------------------------- 1 | __Znwm 2 | __ZnwmRKSt9nothrow_t 3 | __ZnwmSt11align_val_t 4 | __ZnwmSt11align_val_tRKSt9nothrow_t 5 | __ZdaPv 6 | __ZdaPvm 7 | __ZdaPvmSt11align_val_t 8 | __ZdaPvRKSt9nothrow_t 9 | __ZdaPvSt11align_val_t 10 | __ZdaPvSt11align_val_tRKSt9nothrow_t 11 | __ZdlPv 12 | __ZdlPvm 13 | __ZdlPvmSt11align_val_t 14 | __ZdlPvRKSt9nothrow_t 15 | __ZdlPvSt11align_val_t 16 | __ZdlPvSt11align_val_tRKSt9nothrow_t 17 | __Znam 18 | __ZnamRKSt9nothrow_t 19 | __ZnamSt11align_val_t 20 | __ZnamSt11align_val_tRKSt9nothrow_t 21 | -------------------------------------------------------------------------------- /lib/personality-sjlj.exp: -------------------------------------------------------------------------------- 1 | ___gxx_personality_sj0 2 | -------------------------------------------------------------------------------- /lib/personality-v0.exp: -------------------------------------------------------------------------------- 1 | ___gxx_personality_v0 2 | -------------------------------------------------------------------------------- /src/abort_message.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- abort_message.cpp --------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | #include 12 | #include "abort_message.h" 13 | 14 | #ifdef __BIONIC__ 15 | #include 16 | #if __ANDROID_API__ >= 21 17 | #include 18 | extern "C" void android_set_abort_message(const char* msg); 19 | #else 20 | #include 21 | #endif // __ANDROID_API__ >= 21 22 | #endif // __BIONIC__ 23 | 24 | #ifdef __APPLE__ 25 | # if defined(__has_include) && __has_include() 26 | # define HAVE_CRASHREPORTERCLIENT_H 27 | # include 28 | # endif 29 | #endif 30 | 31 | void abort_message(const char* format, ...) 32 | { 33 | // write message to stderr 34 | #if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL) 35 | #ifdef __APPLE__ 36 | fprintf(stderr, "libc++abi.dylib: "); 37 | #endif 38 | va_list list; 39 | va_start(list, format); 40 | vfprintf(stderr, format, list); 41 | va_end(list); 42 | fprintf(stderr, "\n"); 43 | #endif 44 | 45 | #if defined(__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) 46 | // record message in crash report 47 | char* buffer; 48 | va_list list2; 49 | va_start(list2, format); 50 | vasprintf(&buffer, format, list2); 51 | va_end(list2); 52 | CRSetCrashLogMessage(buffer); 53 | #elif defined(__BIONIC__) 54 | char* buffer; 55 | va_list list2; 56 | va_start(list2, format); 57 | vasprintf(&buffer, format, list2); 58 | va_end(list2); 59 | 60 | #if __ANDROID_API__ >= 21 61 | // Show error in tombstone. 62 | android_set_abort_message(buffer); 63 | 64 | // Show error in logcat. 65 | openlog("libc++abi", 0, 0); 66 | syslog(LOG_CRIT, "%s", buffer); 67 | closelog(); 68 | #else 69 | // The good error reporting wasn't available in Android until L. Since we're 70 | // about to abort anyway, just call __assert2, which will log _somewhere_ 71 | // (tombstone and/or logcat) in older releases. 72 | __assert2(__FILE__, __LINE__, __func__, buffer); 73 | #endif // __ANDROID_API__ >= 21 74 | #endif // __BIONIC__ 75 | 76 | abort(); 77 | } 78 | -------------------------------------------------------------------------------- /src/abort_message.h: -------------------------------------------------------------------------------- 1 | //===-------------------------- abort_message.h-----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef __ABORT_MESSAGE_H_ 10 | #define __ABORT_MESSAGE_H_ 11 | 12 | #include "cxxabi.h" 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void 19 | abort_message(const char *format, ...) __attribute__((format(printf, 1, 2))); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | 27 | -------------------------------------------------------------------------------- /src/cxa_aux_runtime.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------ cxa_aux_runtime.cpp -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | // 8 | // This file implements the "Auxiliary Runtime APIs" 9 | // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#cxx-aux 10 | //===----------------------------------------------------------------------===// 11 | 12 | #include "cxxabi.h" 13 | #include 14 | #include 15 | 16 | namespace __cxxabiv1 { 17 | extern "C" { 18 | _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_bad_cast(void) { 19 | #ifndef _LIBCXXABI_NO_EXCEPTIONS 20 | throw std::bad_cast(); 21 | #else 22 | std::terminate(); 23 | #endif 24 | } 25 | 26 | _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_bad_typeid(void) { 27 | #ifndef _LIBCXXABI_NO_EXCEPTIONS 28 | throw std::bad_typeid(); 29 | #else 30 | std::terminate(); 31 | #endif 32 | } 33 | 34 | _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void 35 | __cxa_throw_bad_array_new_length(void) { 36 | #ifndef _LIBCXXABI_NO_EXCEPTIONS 37 | throw std::bad_array_new_length(); 38 | #else 39 | std::terminate(); 40 | #endif 41 | } 42 | } // extern "C" 43 | } // abi 44 | -------------------------------------------------------------------------------- /src/cxa_default_handlers.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- cxa_default_handlers.cpp -------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | // 8 | // This file implements the default terminate_handler and unexpected_handler. 9 | //===----------------------------------------------------------------------===// 10 | 11 | #include 12 | #include 13 | #include "abort_message.h" 14 | #include "cxxabi.h" 15 | #include "cxa_handlers.h" 16 | #include "cxa_exception.h" 17 | #include "private_typeinfo.h" 18 | #include "include/atomic_support.h" 19 | 20 | #if !defined(LIBCXXABI_SILENT_TERMINATE) 21 | static const char* cause = "uncaught"; 22 | 23 | __attribute__((noreturn)) 24 | static void demangling_terminate_handler() 25 | { 26 | #ifndef _LIBCXXABI_NO_EXCEPTIONS 27 | // If there might be an uncaught exception 28 | using namespace __cxxabiv1; 29 | __cxa_eh_globals* globals = __cxa_get_globals_fast(); 30 | if (globals) 31 | { 32 | __cxa_exception* exception_header = globals->caughtExceptions; 33 | // If there is an uncaught exception 34 | if (exception_header) 35 | { 36 | _Unwind_Exception* unwind_exception = 37 | reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; 38 | if (__isOurExceptionClass(unwind_exception)) 39 | { 40 | void* thrown_object = 41 | __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ? 42 | ((__cxa_dependent_exception*)exception_header)->primaryException : 43 | exception_header + 1; 44 | const __shim_type_info* thrown_type = 45 | static_cast(exception_header->exceptionType); 46 | // Try to get demangled name of thrown_type 47 | int status; 48 | char buf[1024]; 49 | size_t len = sizeof(buf); 50 | const char* name = __cxa_demangle(thrown_type->name(), buf, &len, &status); 51 | if (status != 0) 52 | name = thrown_type->name(); 53 | // If the uncaught exception can be caught with std::exception& 54 | const __shim_type_info* catch_type = 55 | static_cast(&typeid(std::exception)); 56 | if (catch_type->can_catch(thrown_type, thrown_object)) 57 | { 58 | // Include the what() message from the exception 59 | const std::exception* e = static_cast(thrown_object); 60 | abort_message("terminating with %s exception of type %s: %s", 61 | cause, name, e->what()); 62 | } 63 | else 64 | // Else just note that we're terminating with an exception 65 | abort_message("terminating with %s exception of type %s", 66 | cause, name); 67 | } 68 | else 69 | // Else we're terminating with a foreign exception 70 | abort_message("terminating with %s foreign exception", cause); 71 | } 72 | } 73 | #endif 74 | // Else just note that we're terminating 75 | abort_message("terminating"); 76 | } 77 | 78 | __attribute__((noreturn)) 79 | static void demangling_unexpected_handler() 80 | { 81 | cause = "unexpected"; 82 | std::terminate(); 83 | } 84 | 85 | static std::terminate_handler default_terminate_handler = demangling_terminate_handler; 86 | static std::terminate_handler default_unexpected_handler = demangling_unexpected_handler; 87 | #else 88 | static std::terminate_handler default_terminate_handler = ::abort; 89 | static std::terminate_handler default_unexpected_handler = std::terminate; 90 | #endif 91 | 92 | // 93 | // Global variables that hold the pointers to the current handler 94 | // 95 | _LIBCXXABI_DATA_VIS 96 | std::terminate_handler __cxa_terminate_handler = default_terminate_handler; 97 | 98 | _LIBCXXABI_DATA_VIS 99 | std::unexpected_handler __cxa_unexpected_handler = default_unexpected_handler; 100 | 101 | namespace std 102 | { 103 | 104 | unexpected_handler 105 | set_unexpected(unexpected_handler func) _NOEXCEPT 106 | { 107 | if (func == 0) 108 | func = default_unexpected_handler; 109 | return __libcpp_atomic_exchange(&__cxa_unexpected_handler, func, 110 | _AO_Acq_Rel); 111 | } 112 | 113 | terminate_handler 114 | set_terminate(terminate_handler func) _NOEXCEPT 115 | { 116 | if (func == 0) 117 | func = default_terminate_handler; 118 | return __libcpp_atomic_exchange(&__cxa_terminate_handler, func, 119 | _AO_Acq_Rel); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/cxa_exception.h: -------------------------------------------------------------------------------- 1 | //===------------------------- cxa_exception.h ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | // 8 | // This file implements the "Exception Handling APIs" 9 | // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #ifndef _CXA_EXCEPTION_H 14 | #define _CXA_EXCEPTION_H 15 | 16 | #include // for std::unexpected_handler and std::terminate_handler 17 | #include "cxxabi.h" 18 | #include "unwind.h" 19 | 20 | namespace __cxxabiv1 { 21 | 22 | static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC++\0 23 | static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1 24 | static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++ 25 | 26 | _LIBCXXABI_HIDDEN uint64_t __getExceptionClass (const _Unwind_Exception*); 27 | _LIBCXXABI_HIDDEN void __setExceptionClass ( _Unwind_Exception*, uint64_t); 28 | _LIBCXXABI_HIDDEN bool __isOurExceptionClass(const _Unwind_Exception*); 29 | 30 | struct _LIBCXXABI_HIDDEN __cxa_exception { 31 | #if defined(__LP64__) || defined(_LIBCXXABI_ARM_EHABI) 32 | // This is a new field to support C++ 0x exception_ptr. 33 | // For binary compatibility it is at the start of this 34 | // struct which is prepended to the object thrown in 35 | // __cxa_allocate_exception. 36 | size_t referenceCount; 37 | #endif 38 | 39 | // Manage the exception object itself. 40 | std::type_info *exceptionType; 41 | void (*exceptionDestructor)(void *); 42 | std::unexpected_handler unexpectedHandler; 43 | std::terminate_handler terminateHandler; 44 | 45 | __cxa_exception *nextException; 46 | 47 | int handlerCount; 48 | 49 | #if defined(_LIBCXXABI_ARM_EHABI) 50 | __cxa_exception* nextPropagatingException; 51 | int propagationCount; 52 | #else 53 | int handlerSwitchValue; 54 | const unsigned char *actionRecord; 55 | const unsigned char *languageSpecificData; 56 | void *catchTemp; 57 | void *adjustedPtr; 58 | #endif 59 | 60 | #if !defined(__LP64__) && !defined(_LIBCXXABI_ARM_EHABI) 61 | // This is a new field to support C++ 0x exception_ptr. 62 | // For binary compatibility it is placed where the compiler 63 | // previously adding padded to 64-bit align unwindHeader. 64 | size_t referenceCount; 65 | #endif 66 | _Unwind_Exception unwindHeader; 67 | }; 68 | 69 | // http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html 70 | // The layout of this structure MUST match the layout of __cxa_exception, with 71 | // primaryException instead of referenceCount. 72 | struct _LIBCXXABI_HIDDEN __cxa_dependent_exception { 73 | #if defined(__LP64__) || defined(_LIBCXXABI_ARM_EHABI) 74 | void* primaryException; 75 | #endif 76 | 77 | std::type_info *exceptionType; 78 | void (*exceptionDestructor)(void *); 79 | std::unexpected_handler unexpectedHandler; 80 | std::terminate_handler terminateHandler; 81 | 82 | __cxa_exception *nextException; 83 | 84 | int handlerCount; 85 | 86 | #if defined(_LIBCXXABI_ARM_EHABI) 87 | __cxa_exception* nextPropagatingException; 88 | int propagationCount; 89 | #else 90 | int handlerSwitchValue; 91 | const unsigned char *actionRecord; 92 | const unsigned char *languageSpecificData; 93 | void * catchTemp; 94 | void *adjustedPtr; 95 | #endif 96 | 97 | #if !defined(__LP64__) && !defined(_LIBCXXABI_ARM_EHABI) 98 | void* primaryException; 99 | #endif 100 | _Unwind_Exception unwindHeader; 101 | }; 102 | 103 | struct _LIBCXXABI_HIDDEN __cxa_eh_globals { 104 | __cxa_exception * caughtExceptions; 105 | unsigned int uncaughtExceptions; 106 | #if defined(_LIBCXXABI_ARM_EHABI) 107 | __cxa_exception* propagatingExceptions; 108 | #endif 109 | }; 110 | 111 | extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals (); 112 | extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast (); 113 | 114 | extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception (); 115 | extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception); 116 | 117 | } // namespace __cxxabiv1 118 | 119 | #endif // _CXA_EXCEPTION_H 120 | -------------------------------------------------------------------------------- /src/cxa_exception_storage.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------- cxa_exception_storage.cpp ----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | // 8 | // This file implements the storage for the "Caught Exception Stack" 9 | // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#cxx-exc-stack 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "cxa_exception.h" 14 | 15 | #include <__threading_support> 16 | 17 | #if defined(_LIBCXXABI_HAS_NO_THREADS) 18 | 19 | namespace __cxxabiv1 { 20 | extern "C" { 21 | static __cxa_eh_globals eh_globals; 22 | __cxa_eh_globals *__cxa_get_globals() { return &eh_globals; } 23 | __cxa_eh_globals *__cxa_get_globals_fast() { return &eh_globals; } 24 | } 25 | } 26 | 27 | #elif defined(HAS_THREAD_LOCAL) 28 | 29 | namespace __cxxabiv1 { 30 | 31 | namespace { 32 | __cxa_eh_globals * __globals () { 33 | static thread_local __cxa_eh_globals eh_globals; 34 | return &eh_globals; 35 | } 36 | } 37 | 38 | extern "C" { 39 | __cxa_eh_globals * __cxa_get_globals () { return __globals (); } 40 | __cxa_eh_globals * __cxa_get_globals_fast () { return __globals (); } 41 | } 42 | } 43 | 44 | #else 45 | 46 | #include "abort_message.h" 47 | #include "fallback_malloc.h" 48 | 49 | #if defined(__unix__) && !defined(__ANDROID__) && defined(__ELF__) && defined(_LIBCXXABI_HAS_COMMENT_LIB_PRAGMA) 50 | #pragma comment(lib, "pthread") 51 | #endif 52 | 53 | // In general, we treat all threading errors as fatal. 54 | // We cannot call std::terminate() because that will in turn 55 | // call __cxa_get_globals() and cause infinite recursion. 56 | 57 | namespace __cxxabiv1 { 58 | namespace { 59 | std::__libcpp_tls_key key_; 60 | std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER; 61 | 62 | void _LIBCPP_TLS_DESTRUCTOR_CC destruct_ (void *p) { 63 | __free_with_fallback ( p ); 64 | if ( 0 != std::__libcpp_tls_set ( key_, NULL ) ) 65 | abort_message("cannot zero out thread value for __cxa_get_globals()"); 66 | } 67 | 68 | void construct_ () { 69 | if ( 0 != std::__libcpp_tls_create ( &key_, destruct_ ) ) 70 | abort_message("cannot create thread specific key for __cxa_get_globals()"); 71 | } 72 | } 73 | 74 | extern "C" { 75 | __cxa_eh_globals * __cxa_get_globals () { 76 | // Try to get the globals for this thread 77 | __cxa_eh_globals* retVal = __cxa_get_globals_fast (); 78 | 79 | // If this is the first time we've been asked for these globals, create them 80 | if ( NULL == retVal ) { 81 | retVal = static_cast<__cxa_eh_globals*> 82 | (__calloc_with_fallback (1, sizeof (__cxa_eh_globals))); 83 | if ( NULL == retVal ) 84 | abort_message("cannot allocate __cxa_eh_globals"); 85 | if ( 0 != std::__libcpp_tls_set ( key_, retVal ) ) 86 | abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()"); 87 | } 88 | return retVal; 89 | } 90 | 91 | // Note that this implementation will reliably return NULL if not 92 | // preceded by a call to __cxa_get_globals(). This is an extension 93 | // to the Itanium ABI and is taken advantage of in several places in 94 | // libc++abi. 95 | __cxa_eh_globals * __cxa_get_globals_fast () { 96 | // First time through, create the key. 97 | if (0 != std::__libcpp_execute_once(&flag_, construct_)) 98 | abort_message("execute once failure in __cxa_get_globals_fast()"); 99 | // static int init = construct_(); 100 | return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_)); 101 | } 102 | 103 | } 104 | } 105 | #endif 106 | -------------------------------------------------------------------------------- /src/cxa_guard.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------------- cxa_guard.cpp ---------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "__cxxabi_config.h" 10 | #include "cxxabi.h" 11 | 12 | // Tell the implementation that we're building the actual implementation 13 | // (and not testing it) 14 | #define BUILDING_CXA_GUARD 15 | #include "cxa_guard_impl.h" 16 | 17 | /* 18 | This implementation must be careful to not call code external to this file 19 | which will turn around and try to call __cxa_guard_acquire reentrantly. 20 | For this reason, the headers of this file are as restricted as possible. 21 | Previous implementations of this code for __APPLE__ have used 22 | std::__libcpp_mutex_lock and the abort_message utility without problem. This 23 | implementation also uses std::__libcpp_condvar_wait which has tested 24 | to not be a problem. 25 | */ 26 | 27 | namespace __cxxabiv1 { 28 | 29 | #if defined(_LIBCXXABI_GUARD_ABI_ARM) 30 | using guard_type = uint32_t; 31 | #else 32 | using guard_type = uint64_t; 33 | #endif 34 | 35 | extern "C" 36 | { 37 | _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type* raw_guard_object) { 38 | SelectedImplementation imp(raw_guard_object); 39 | return static_cast(imp.cxa_guard_acquire()); 40 | } 41 | 42 | _LIBCXXABI_FUNC_VIS void __cxa_guard_release(guard_type *raw_guard_object) { 43 | SelectedImplementation imp(raw_guard_object); 44 | imp.cxa_guard_release(); 45 | } 46 | 47 | _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *raw_guard_object) { 48 | SelectedImplementation imp(raw_guard_object); 49 | imp.cxa_guard_abort(); 50 | } 51 | } // extern "C" 52 | 53 | } // __cxxabiv1 54 | -------------------------------------------------------------------------------- /src/cxa_handlers.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- cxa_handlers.cpp ---------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | // 8 | // This file implements the functionality associated with the terminate_handler, 9 | // unexpected_handler, and new_handler. 10 | //===----------------------------------------------------------------------===// 11 | 12 | #include 13 | #include 14 | #include 15 | #include "abort_message.h" 16 | #include "cxxabi.h" 17 | #include "cxa_handlers.h" 18 | #include "cxa_exception.h" 19 | #include "private_typeinfo.h" 20 | #include "include/atomic_support.h" 21 | 22 | namespace std 23 | { 24 | 25 | unexpected_handler 26 | get_unexpected() _NOEXCEPT 27 | { 28 | return __libcpp_atomic_load(&__cxa_unexpected_handler, _AO_Acquire); 29 | } 30 | 31 | void 32 | __unexpected(unexpected_handler func) 33 | { 34 | func(); 35 | // unexpected handler should not return 36 | abort_message("unexpected_handler unexpectedly returned"); 37 | } 38 | 39 | __attribute__((noreturn)) 40 | void 41 | unexpected() 42 | { 43 | __unexpected(get_unexpected()); 44 | } 45 | 46 | terminate_handler 47 | get_terminate() _NOEXCEPT 48 | { 49 | return __libcpp_atomic_load(&__cxa_terminate_handler, _AO_Acquire); 50 | } 51 | 52 | void 53 | __terminate(terminate_handler func) _NOEXCEPT 54 | { 55 | #ifndef _LIBCXXABI_NO_EXCEPTIONS 56 | try 57 | { 58 | #endif // _LIBCXXABI_NO_EXCEPTIONS 59 | func(); 60 | // handler should not return 61 | abort_message("terminate_handler unexpectedly returned"); 62 | #ifndef _LIBCXXABI_NO_EXCEPTIONS 63 | } 64 | catch (...) 65 | { 66 | // handler should not throw exception 67 | abort_message("terminate_handler unexpectedly threw an exception"); 68 | } 69 | #endif // _LIBCXXABI_NO_EXCEPTIONS 70 | } 71 | 72 | __attribute__((noreturn)) 73 | void 74 | terminate() _NOEXCEPT 75 | { 76 | #ifndef _LIBCXXABI_NO_EXCEPTIONS 77 | // If there might be an uncaught exception 78 | using namespace __cxxabiv1; 79 | __cxa_eh_globals* globals = __cxa_get_globals_fast(); 80 | if (globals) 81 | { 82 | __cxa_exception* exception_header = globals->caughtExceptions; 83 | if (exception_header) 84 | { 85 | _Unwind_Exception* unwind_exception = 86 | reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; 87 | if (__isOurExceptionClass(unwind_exception)) 88 | __terminate(exception_header->terminateHandler); 89 | } 90 | } 91 | #endif 92 | __terminate(get_terminate()); 93 | } 94 | 95 | extern "C" { 96 | new_handler __cxa_new_handler = 0; 97 | } 98 | 99 | new_handler 100 | set_new_handler(new_handler handler) _NOEXCEPT 101 | { 102 | return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel); 103 | } 104 | 105 | new_handler 106 | get_new_handler() _NOEXCEPT 107 | { 108 | return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire); 109 | } 110 | 111 | } // std 112 | -------------------------------------------------------------------------------- /src/cxa_handlers.h: -------------------------------------------------------------------------------- 1 | //===------------------------- cxa_handlers.h -----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | // 8 | // This file implements the functionality associated with the terminate_handler, 9 | // unexpected_handler, and new_handler. 10 | //===----------------------------------------------------------------------===// 11 | 12 | #ifndef _CXA_HANDLERS_H 13 | #define _CXA_HANDLERS_H 14 | 15 | #include <__cxxabi_config.h> 16 | 17 | #include 18 | 19 | namespace std 20 | { 21 | 22 | _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN 23 | void 24 | __unexpected(unexpected_handler func); 25 | 26 | _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN 27 | void 28 | __terminate(terminate_handler func) _NOEXCEPT; 29 | 30 | } // std 31 | 32 | extern "C" 33 | { 34 | 35 | _LIBCXXABI_DATA_VIS extern void (*__cxa_terminate_handler)(); 36 | _LIBCXXABI_DATA_VIS extern void (*__cxa_unexpected_handler)(); 37 | _LIBCXXABI_DATA_VIS extern void (*__cxa_new_handler)(); 38 | 39 | /* 40 | 41 | At some point in the future these three symbols will become 42 | C++11 atomic variables: 43 | 44 | extern std::atomic __cxa_terminate_handler; 45 | extern std::atomic __cxa_unexpected_handler; 46 | extern std::atomic __cxa_new_handler; 47 | 48 | This change will not impact their ABI. But it will allow for a 49 | portable performance optimization. 50 | 51 | */ 52 | 53 | } // extern "C" 54 | 55 | #endif // _CXA_HANDLERS_H 56 | -------------------------------------------------------------------------------- /src/cxa_noexception.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- cxa_exception.cpp --------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | // 8 | // This file implements the "Exception Handling APIs" 9 | // https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | // Support functions for the no-exceptions libc++ library 14 | 15 | #include "cxxabi.h" 16 | 17 | #include // for std::terminate 18 | #include "cxa_exception.h" 19 | #include "cxa_handlers.h" 20 | 21 | namespace __cxxabiv1 { 22 | 23 | extern "C" { 24 | 25 | void 26 | __cxa_increment_exception_refcount(void *thrown_object) throw() { 27 | if (thrown_object != nullptr) 28 | std::terminate(); 29 | } 30 | 31 | void 32 | __cxa_decrement_exception_refcount(void *thrown_object) throw() { 33 | if (thrown_object != nullptr) 34 | std::terminate(); 35 | } 36 | 37 | 38 | void *__cxa_current_primary_exception() throw() { return nullptr; } 39 | 40 | void 41 | __cxa_rethrow_primary_exception(void* thrown_object) { 42 | if (thrown_object != nullptr) 43 | std::terminate(); 44 | } 45 | 46 | bool 47 | __cxa_uncaught_exception() throw() { return false; } 48 | 49 | unsigned int 50 | __cxa_uncaught_exceptions() throw() { return 0; } 51 | 52 | } // extern "C" 53 | 54 | // provide dummy implementations for the 'no exceptions' case. 55 | uint64_t __getExceptionClass (const _Unwind_Exception*) { return 0; } 56 | void __setExceptionClass ( _Unwind_Exception*, uint64_t) {} 57 | bool __isOurExceptionClass(const _Unwind_Exception*) { return false; } 58 | 59 | } // abi 60 | -------------------------------------------------------------------------------- /src/cxa_thread_atexit.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- cxa_thread_atexit.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "abort_message.h" 10 | #include "cxxabi.h" 11 | #include <__threading_support> 12 | #ifndef _LIBCXXABI_HAS_NO_THREADS 13 | #if defined(__unix__) && !defined(__ANDROID__) && defined(__ELF__) && defined(_LIBCXXABI_HAS_COMMENT_LIB_PRAGMA) 14 | #pragma comment(lib, "pthread") 15 | #endif 16 | #endif 17 | 18 | #include 19 | 20 | namespace __cxxabiv1 { 21 | 22 | using Dtor = void(*)(void*); 23 | 24 | extern "C" 25 | #ifndef HAVE___CXA_THREAD_ATEXIT_IMPL 26 | // A weak symbol is used to detect this function's presence in the C library 27 | // at runtime, even if libc++ is built against an older libc 28 | _LIBCXXABI_WEAK 29 | #endif 30 | int __cxa_thread_atexit_impl(Dtor, void*, void*); 31 | 32 | #ifndef HAVE___CXA_THREAD_ATEXIT_IMPL 33 | 34 | namespace { 35 | // This implementation is used if the C library does not provide 36 | // __cxa_thread_atexit_impl() for us. It has a number of limitations that are 37 | // difficult to impossible to address without ..._impl(): 38 | // 39 | // - dso_symbol is ignored. This means that a shared library may be unloaded 40 | // (via dlclose()) before its thread_local destructors have run. 41 | // 42 | // - thread_local destructors for the main thread are run by the destructor of 43 | // a static object. This is later than expected; they should run before the 44 | // destructors of any objects with static storage duration. 45 | // 46 | // - thread_local destructors on non-main threads run on the first iteration 47 | // through the __libccpp_tls_key destructors. 48 | // std::notify_all_at_thread_exit() and similar functions must be careful to 49 | // wait until the second iteration to provide their intended ordering 50 | // guarantees. 51 | // 52 | // Another limitation, though one shared with ..._impl(), is that any 53 | // thread_locals that are first initialized after non-thread_local global 54 | // destructors begin to run will not be destroyed. [basic.start.term] states 55 | // that all thread_local destructors are sequenced before the destruction of 56 | // objects with static storage duration, resulting in a contradiction if a 57 | // thread_local is constructed after that point. Thus we consider such 58 | // programs ill-formed, and don't bother to run those destructors. (If the 59 | // program terminates abnormally after such a thread_local is constructed, 60 | // the destructor is not expected to run and thus there is no contradiction. 61 | // So construction still has to work.) 62 | 63 | struct DtorList { 64 | Dtor dtor; 65 | void* obj; 66 | DtorList* next; 67 | }; 68 | 69 | // The linked list of thread-local destructors to run 70 | __thread DtorList* dtors = nullptr; 71 | // True if the destructors are currently scheduled to run on this thread 72 | __thread bool dtors_alive = false; 73 | // Used to trigger destructors on thread exit; value is ignored 74 | std::__libcpp_tls_key dtors_key; 75 | 76 | void run_dtors(void*) { 77 | while (auto head = dtors) { 78 | dtors = head->next; 79 | head->dtor(head->obj); 80 | ::free(head); 81 | } 82 | 83 | dtors_alive = false; 84 | } 85 | 86 | struct DtorsManager { 87 | DtorsManager() { 88 | // There is intentionally no matching std::__libcpp_tls_delete call, as 89 | // __cxa_thread_atexit() may be called arbitrarily late (for example, from 90 | // global destructors or atexit() handlers). 91 | if (std::__libcpp_tls_create(&dtors_key, run_dtors) != 0) { 92 | abort_message("std::__libcpp_tls_create() failed in __cxa_thread_atexit()"); 93 | } 94 | } 95 | 96 | ~DtorsManager() { 97 | // std::__libcpp_tls_key destructors do not run on threads that call exit() 98 | // (including when the main thread returns from main()), so we explicitly 99 | // call the destructor here. This runs at exit time (potentially earlier 100 | // if libc++abi is dlclose()'d). Any thread_locals initialized after this 101 | // point will not be destroyed. 102 | run_dtors(nullptr); 103 | } 104 | }; 105 | } // namespace 106 | 107 | #endif // HAVE___CXA_THREAD_ATEXIT_IMPL 108 | 109 | extern "C" { 110 | 111 | _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void* obj, void* dso_symbol) throw() { 112 | #ifdef HAVE___CXA_THREAD_ATEXIT_IMPL 113 | return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); 114 | #else 115 | if (__cxa_thread_atexit_impl) { 116 | return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); 117 | } else { 118 | // Initialize the dtors std::__libcpp_tls_key (uses __cxa_guard_*() for 119 | // one-time initialization and __cxa_atexit() for destruction) 120 | static DtorsManager manager; 121 | 122 | if (!dtors_alive) { 123 | if (std::__libcpp_tls_set(dtors_key, &dtors_key) != 0) { 124 | return -1; 125 | } 126 | dtors_alive = true; 127 | } 128 | 129 | auto head = static_cast(::malloc(sizeof(DtorList))); 130 | if (!head) { 131 | return -1; 132 | } 133 | 134 | head->dtor = dtor; 135 | head->obj = obj; 136 | head->next = dtors; 137 | dtors = head; 138 | 139 | return 0; 140 | } 141 | #endif // HAVE___CXA_THREAD_ATEXIT_IMPL 142 | } 143 | 144 | } // extern "C" 145 | } // namespace __cxxabiv1 146 | -------------------------------------------------------------------------------- /src/cxa_unexpected.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- cxa_unexpected.cpp -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include "cxxabi.h" 11 | #include "cxa_exception.h" 12 | 13 | namespace __cxxabiv1 14 | { 15 | 16 | extern "C" 17 | { 18 | 19 | } 20 | 21 | } // namespace __cxxabiv1 22 | 23 | -------------------------------------------------------------------------------- /src/cxa_virtual.cpp: -------------------------------------------------------------------------------- 1 | //===-------------------------- cxa_virtual.cpp ---------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "cxxabi.h" 10 | #include "abort_message.h" 11 | 12 | namespace __cxxabiv1 { 13 | extern "C" { 14 | _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN 15 | void __cxa_pure_virtual(void) { 16 | abort_message("Pure virtual function called!"); 17 | } 18 | 19 | _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN 20 | void __cxa_deleted_virtual(void) { 21 | abort_message("Deleted virtual function called!"); 22 | } 23 | } // extern "C" 24 | } // abi 25 | -------------------------------------------------------------------------------- /src/demangle/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | 3 | -------------------------------------------------------------------------------- /src/demangle/DemangleConfig.h: -------------------------------------------------------------------------------- 1 | //===--- DemangleConfig.h --------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | // This file is contains a subset of macros copied from 8 | // llvm/include/llvm/Demangle/DemangleConfig.h 9 | //===----------------------------------------------------------------------===// 10 | 11 | #ifndef LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H 12 | #define LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H 13 | 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | // snprintf is implemented in VS 2015 18 | #if _MSC_VER < 1900 19 | #define snprintf _snprintf_s 20 | #endif 21 | #endif 22 | 23 | #ifndef __has_feature 24 | #define __has_feature(x) 0 25 | #endif 26 | 27 | #ifndef __has_cpp_attribute 28 | #define __has_cpp_attribute(x) 0 29 | #endif 30 | 31 | #ifndef __has_attribute 32 | #define __has_attribute(x) 0 33 | #endif 34 | 35 | #ifndef __has_builtin 36 | #define __has_builtin(x) 0 37 | #endif 38 | 39 | #ifndef DEMANGLE_GNUC_PREREQ 40 | #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) 41 | #define DEMANGLE_GNUC_PREREQ(maj, min, patch) \ 42 | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ 43 | ((maj) << 20) + ((min) << 10) + (patch)) 44 | #elif defined(__GNUC__) && defined(__GNUC_MINOR__) 45 | #define DEMANGLE_GNUC_PREREQ(maj, min, patch) \ 46 | ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) 47 | #else 48 | #define DEMANGLE_GNUC_PREREQ(maj, min, patch) 0 49 | #endif 50 | #endif 51 | 52 | #if __has_attribute(used) || DEMANGLE_GNUC_PREREQ(3, 1, 0) 53 | #define DEMANGLE_ATTRIBUTE_USED __attribute__((__used__)) 54 | #else 55 | #define DEMANGLE_ATTRIBUTE_USED 56 | #endif 57 | 58 | #if __has_builtin(__builtin_unreachable) || DEMANGLE_GNUC_PREREQ(4, 5, 0) 59 | #define DEMANGLE_UNREACHABLE __builtin_unreachable() 60 | #elif defined(_MSC_VER) 61 | #define DEMANGLE_UNREACHABLE __assume(false) 62 | #else 63 | #define DEMANGLE_UNREACHABLE 64 | #endif 65 | 66 | #if __has_attribute(noinline) || DEMANGLE_GNUC_PREREQ(3, 4, 0) 67 | #define DEMANGLE_ATTRIBUTE_NOINLINE __attribute__((noinline)) 68 | #elif defined(_MSC_VER) 69 | #define DEMANGLE_ATTRIBUTE_NOINLINE __declspec(noinline) 70 | #else 71 | #define DEMANGLE_ATTRIBUTE_NOINLINE 72 | #endif 73 | 74 | #if !defined(NDEBUG) 75 | #define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE DEMANGLE_ATTRIBUTE_USED 76 | #else 77 | #define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE 78 | #endif 79 | 80 | #if __cplusplus > 201402L && __has_cpp_attribute(fallthrough) 81 | #define DEMANGLE_FALLTHROUGH [[fallthrough]] 82 | #elif __has_cpp_attribute(gnu::fallthrough) 83 | #define DEMANGLE_FALLTHROUGH [[gnu::fallthrough]] 84 | #elif !__cplusplus 85 | // Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious 86 | // error when __has_cpp_attribute is given a scoped attribute in C mode. 87 | #define DEMANGLE_FALLTHROUGH 88 | #elif __has_cpp_attribute(clang::fallthrough) 89 | #define DEMANGLE_FALLTHROUGH [[clang::fallthrough]] 90 | #else 91 | #define DEMANGLE_FALLTHROUGH 92 | #endif 93 | 94 | #define DEMANGLE_NAMESPACE_BEGIN namespace { namespace itanium_demangle { 95 | #define DEMANGLE_NAMESPACE_END } } 96 | 97 | #endif // LIBCXXABI_DEMANGLE_DEMANGLE_CONFIG_H 98 | -------------------------------------------------------------------------------- /src/demangle/README.txt: -------------------------------------------------------------------------------- 1 | Itanium Name Demangler Library 2 | ============================== 3 | 4 | Introduction 5 | ------------ 6 | 7 | This directory contains the generic itanium name demangler library. The main 8 | purpose of the library is to demangle C++ symbols, i.e. convert the string 9 | "_Z1fv" into "f()". You can also use the CRTP base ManglingParser to perform 10 | some simple analysis on the mangled name, or (in LLVM) use the opaque 11 | ItaniumPartialDemangler to query the demangled AST. 12 | 13 | Why are there multiple copies of the this library in the source tree? 14 | --------------------------------------------------------------------- 15 | 16 | This directory is mirrored between libcxxabi/demangle and 17 | llvm/include/llvm/Demangle. The simple reason for this is that both projects 18 | need to demangle symbols, but neither can depend on each other. libcxxabi needs 19 | the demangler to implement __cxa_demangle, which is part of the itanium ABI 20 | spec. LLVM needs a copy for a bunch of places, but doesn't want to use the 21 | system's __cxa_demangle because it a) might not be available (i.e., on Windows), 22 | and b) probably isn't that up-to-date on the latest language features. 23 | 24 | The copy of the demangler in LLVM has some extra stuff that aren't needed in 25 | libcxxabi (ie, the MSVC demangler, ItaniumPartialDemangler), which depend on the 26 | shared generic components. Despite these differences, we want to keep the "core" 27 | generic demangling library identical between both copies to simplify development 28 | and testing. 29 | 30 | If you're working on the generic library, then do the work first in libcxxabi, 31 | then run the cp-to-llvm.sh script in src/demangle. This script takes as an 32 | argument the path to llvm, and re-copies the changes you made to libcxxabi over. 33 | Note that this script just blindly overwrites all changes to the generic library 34 | in llvm, so be careful. 35 | 36 | Because the core demangler needs to work in libcxxabi, everything needs to be 37 | declared in an anonymous namespace (see DEMANGLE_NAMESPACE_BEGIN), and you can't 38 | introduce any code that depends on the libcxx dylib. 39 | 40 | Hopefully, when LLVM becomes a monorepo, we can de-duplicate this code, and have 41 | both LLVM and libcxxabi depend on a shared demangler library. 42 | 43 | Testing 44 | ------- 45 | 46 | The tests are split up between libcxxabi/test/{unit,}test_demangle.cpp, and 47 | llvm/unittest/Demangle. The llvm directory should only get tests for stuff not 48 | included in the core library. In the future though, we should probably move all 49 | the tests to LLVM. 50 | 51 | It is also a really good idea to run libFuzzer after non-trivial changes, see 52 | libcxxabi/fuzz/cxa_demangle_fuzzer.cpp and https://llvm.org/docs/LibFuzzer.html. 53 | -------------------------------------------------------------------------------- /src/demangle/StringView.h: -------------------------------------------------------------------------------- 1 | //===--- StringView.h -------------------------------------------*- C++ -*-===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // FIXME: Use std::string_view instead when we support C++17. 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #ifndef DEMANGLE_STRINGVIEW_H 14 | #define DEMANGLE_STRINGVIEW_H 15 | 16 | #include "DemangleConfig.h" 17 | #include 18 | #include 19 | #include 20 | 21 | DEMANGLE_NAMESPACE_BEGIN 22 | 23 | class StringView { 24 | const char *First; 25 | const char *Last; 26 | 27 | public: 28 | static const size_t npos = ~size_t(0); 29 | 30 | template 31 | StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {} 32 | StringView(const char *First_, const char *Last_) 33 | : First(First_), Last(Last_) {} 34 | StringView(const char *First_, size_t Len) 35 | : First(First_), Last(First_ + Len) {} 36 | StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {} 37 | StringView() : First(nullptr), Last(nullptr) {} 38 | 39 | StringView substr(size_t From) const { 40 | return StringView(begin() + From, size() - From); 41 | } 42 | 43 | size_t find(char C, size_t From = 0) const { 44 | size_t FindBegin = std::min(From, size()); 45 | // Avoid calling memchr with nullptr. 46 | if (FindBegin < size()) { 47 | // Just forward to memchr, which is faster than a hand-rolled loop. 48 | if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin)) 49 | return size_t(static_cast(P) - First); 50 | } 51 | return npos; 52 | } 53 | 54 | StringView substr(size_t From, size_t To) const { 55 | if (To >= size()) 56 | To = size() - 1; 57 | if (From >= size()) 58 | From = size() - 1; 59 | return StringView(First + From, First + To); 60 | } 61 | 62 | StringView dropFront(size_t N = 1) const { 63 | if (N >= size()) 64 | N = size(); 65 | return StringView(First + N, Last); 66 | } 67 | 68 | StringView dropBack(size_t N = 1) const { 69 | if (N >= size()) 70 | N = size(); 71 | return StringView(First, Last - N); 72 | } 73 | 74 | char front() const { 75 | assert(!empty()); 76 | return *begin(); 77 | } 78 | 79 | char back() const { 80 | assert(!empty()); 81 | return *(end() - 1); 82 | } 83 | 84 | char popFront() { 85 | assert(!empty()); 86 | return *First++; 87 | } 88 | 89 | bool consumeFront(char C) { 90 | if (!startsWith(C)) 91 | return false; 92 | *this = dropFront(1); 93 | return true; 94 | } 95 | 96 | bool consumeFront(StringView S) { 97 | if (!startsWith(S)) 98 | return false; 99 | *this = dropFront(S.size()); 100 | return true; 101 | } 102 | 103 | bool startsWith(char C) const { return !empty() && *begin() == C; } 104 | 105 | bool startsWith(StringView Str) const { 106 | if (Str.size() > size()) 107 | return false; 108 | return std::equal(Str.begin(), Str.end(), begin()); 109 | } 110 | 111 | const char &operator[](size_t Idx) const { return *(begin() + Idx); } 112 | 113 | const char *begin() const { return First; } 114 | const char *end() const { return Last; } 115 | size_t size() const { return static_cast(Last - First); } 116 | bool empty() const { return First == Last; } 117 | }; 118 | 119 | inline bool operator==(const StringView &LHS, const StringView &RHS) { 120 | return LHS.size() == RHS.size() && 121 | std::equal(LHS.begin(), LHS.end(), RHS.begin()); 122 | } 123 | 124 | DEMANGLE_NAMESPACE_END 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /src/demangle/cp-to-llvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copies the 'demangle' library, excluding 'DemangleConfig.h', to llvm. If no 4 | # llvm directory is specified, then assume a monorepo layout. 5 | 6 | set -e 7 | 8 | FILES="ItaniumDemangle.h StringView.h Utility.h README.txt" 9 | LLVM_DEMANGLE_DIR=$1 10 | 11 | if [[ -z "$LLVM_DEMANGLE_DIR" ]]; then 12 | LLVM_DEMANGLE_DIR="../../../llvm/include/llvm/Demangle" 13 | fi 14 | 15 | if [[ ! -d "$LLVM_DEMANGLE_DIR" ]]; then 16 | echo "No such directory: $LLVM_DEMANGLE_DIR" >&2 17 | exit 1 18 | fi 19 | 20 | read -p "This will overwrite the copies of $FILES in $LLVM_DEMANGLE_DIR; are you sure? [y/N]" -n 1 -r ANSWER 21 | echo 22 | 23 | if [[ $ANSWER =~ ^[Yy]$ ]]; then 24 | for I in $FILES ; do 25 | cp $I $LLVM_DEMANGLE_DIR/$I 26 | done 27 | fi 28 | -------------------------------------------------------------------------------- /src/fallback_malloc.h: -------------------------------------------------------------------------------- 1 | //===------------------------- fallback_malloc.h --------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #ifndef _FALLBACK_MALLOC_H 10 | #define _FALLBACK_MALLOC_H 11 | 12 | #include "__cxxabi_config.h" 13 | #include // for size_t 14 | 15 | namespace __cxxabiv1 { 16 | 17 | // Allocate some memory from _somewhere_ 18 | _LIBCXXABI_HIDDEN void * __aligned_malloc_with_fallback(size_t size); 19 | 20 | // Allocate and zero-initialize memory from _somewhere_ 21 | _LIBCXXABI_HIDDEN void * __calloc_with_fallback(size_t count, size_t size); 22 | 23 | _LIBCXXABI_HIDDEN void __aligned_free_with_fallback(void *ptr); 24 | _LIBCXXABI_HIDDEN void __free_with_fallback(void *ptr); 25 | 26 | } // namespace __cxxabiv1 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/refstring.h: -------------------------------------------------------------------------------- 1 | //===------------------------ __refstring ---------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of 10 | // duplicating the file in libc++abi we should require that the libc++ sources 11 | // are available when building libc++abi. 12 | 13 | #ifndef _LIBCPPABI_REFSTRING_H 14 | #define _LIBCPPABI_REFSTRING_H 15 | 16 | #include <__config> 17 | #include 18 | #include 19 | #include 20 | #ifdef __APPLE__ 21 | #include 22 | #include 23 | #endif 24 | #include "atomic_support.h" 25 | 26 | _LIBCPP_BEGIN_NAMESPACE_STD 27 | 28 | namespace __refstring_imp { namespace { 29 | typedef int count_t; 30 | 31 | struct _Rep_base { 32 | std::size_t len; 33 | std::size_t cap; 34 | count_t count; 35 | }; 36 | 37 | inline _Rep_base* rep_from_data(const char *data_) noexcept { 38 | char *data = const_cast(data_); 39 | return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); 40 | } 41 | 42 | inline char * data_from_rep(_Rep_base *rep) noexcept { 43 | char *data = reinterpret_cast(rep); 44 | return data + sizeof(*rep); 45 | } 46 | 47 | #if defined(__APPLE__) 48 | inline 49 | const char* compute_gcc_empty_string_storage() _NOEXCEPT 50 | { 51 | void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); 52 | if (handle == nullptr) 53 | return nullptr; 54 | void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); 55 | if (sym == nullptr) 56 | return nullptr; 57 | return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); 58 | } 59 | 60 | inline 61 | const char* 62 | get_gcc_empty_string_storage() _NOEXCEPT 63 | { 64 | static const char* p = compute_gcc_empty_string_storage(); 65 | return p; 66 | } 67 | #endif 68 | 69 | }} // namespace __refstring_imp 70 | 71 | using namespace __refstring_imp; 72 | 73 | inline 74 | __libcpp_refstring::__libcpp_refstring(const char* msg) { 75 | std::size_t len = strlen(msg); 76 | _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); 77 | rep->len = len; 78 | rep->cap = len; 79 | rep->count = 0; 80 | char *data = data_from_rep(rep); 81 | std::memcpy(data, msg, len + 1); 82 | __imp_ = data; 83 | } 84 | 85 | inline 86 | __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT 87 | : __imp_(s.__imp_) 88 | { 89 | if (__uses_refcount()) 90 | __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); 91 | } 92 | 93 | inline 94 | __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { 95 | bool adjust_old_count = __uses_refcount(); 96 | struct _Rep_base *old_rep = rep_from_data(__imp_); 97 | __imp_ = s.__imp_; 98 | if (__uses_refcount()) 99 | __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); 100 | if (adjust_old_count) 101 | { 102 | if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) 103 | { 104 | ::operator delete(old_rep); 105 | } 106 | } 107 | return *this; 108 | } 109 | 110 | inline 111 | __libcpp_refstring::~__libcpp_refstring() { 112 | if (__uses_refcount()) { 113 | _Rep_base* rep = rep_from_data(__imp_); 114 | if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) { 115 | ::operator delete(rep); 116 | } 117 | } 118 | } 119 | 120 | inline 121 | bool __libcpp_refstring::__uses_refcount() const { 122 | #ifdef __APPLE__ 123 | return __imp_ != get_gcc_empty_string_storage(); 124 | #else 125 | return true; 126 | #endif 127 | } 128 | 129 | _LIBCPP_END_NAMESPACE_STD 130 | 131 | #endif //_LIBCPPABI_REFSTRING_H 132 | -------------------------------------------------------------------------------- /src/stdlib_exception.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------------- exception.cpp ---------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #define _LIBCPP_BUILDING_LIBRARY 10 | #include 11 | #include 12 | 13 | namespace std 14 | { 15 | 16 | // exception 17 | 18 | exception::~exception() _NOEXCEPT 19 | { 20 | } 21 | 22 | const char* exception::what() const _NOEXCEPT 23 | { 24 | return "std::exception"; 25 | } 26 | 27 | // bad_exception 28 | 29 | bad_exception::~bad_exception() _NOEXCEPT 30 | { 31 | } 32 | 33 | const char* bad_exception::what() const _NOEXCEPT 34 | { 35 | return "std::bad_exception"; 36 | } 37 | 38 | 39 | // bad_alloc 40 | 41 | bad_alloc::bad_alloc() _NOEXCEPT 42 | { 43 | } 44 | 45 | bad_alloc::~bad_alloc() _NOEXCEPT 46 | { 47 | } 48 | 49 | const char* 50 | bad_alloc::what() const _NOEXCEPT 51 | { 52 | return "std::bad_alloc"; 53 | } 54 | 55 | // bad_array_new_length 56 | 57 | bad_array_new_length::bad_array_new_length() _NOEXCEPT 58 | { 59 | } 60 | 61 | bad_array_new_length::~bad_array_new_length() _NOEXCEPT 62 | { 63 | } 64 | 65 | const char* 66 | bad_array_new_length::what() const _NOEXCEPT 67 | { 68 | return "bad_array_new_length"; 69 | } 70 | 71 | } // std 72 | -------------------------------------------------------------------------------- /src/stdlib_stdexcept.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------ stdexcept.cpp -------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "include/refstring.h" 10 | #include "stdexcept" 11 | #include "new" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), ""); 18 | 19 | namespace std // purposefully not using versioning namespace 20 | { 21 | 22 | logic_error::~logic_error() _NOEXCEPT {} 23 | 24 | const char* 25 | logic_error::what() const _NOEXCEPT 26 | { 27 | return __imp_.c_str(); 28 | } 29 | 30 | runtime_error::~runtime_error() _NOEXCEPT {} 31 | 32 | const char* 33 | runtime_error::what() const _NOEXCEPT 34 | { 35 | return __imp_.c_str(); 36 | } 37 | 38 | domain_error::~domain_error() _NOEXCEPT {} 39 | invalid_argument::~invalid_argument() _NOEXCEPT {} 40 | length_error::~length_error() _NOEXCEPT {} 41 | out_of_range::~out_of_range() _NOEXCEPT {} 42 | 43 | range_error::~range_error() _NOEXCEPT {} 44 | overflow_error::~overflow_error() _NOEXCEPT {} 45 | underflow_error::~underflow_error() _NOEXCEPT {} 46 | 47 | } // std 48 | -------------------------------------------------------------------------------- /src/stdlib_typeinfo.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------- typeinfo.cpp ---------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | 11 | namespace std 12 | { 13 | 14 | // type_info 15 | 16 | type_info::~type_info() 17 | { 18 | } 19 | 20 | // bad_cast 21 | 22 | bad_cast::bad_cast() _NOEXCEPT 23 | { 24 | } 25 | 26 | bad_cast::~bad_cast() _NOEXCEPT 27 | { 28 | } 29 | 30 | const char* 31 | bad_cast::what() const _NOEXCEPT 32 | { 33 | return "std::bad_cast"; 34 | } 35 | 36 | // bad_typeid 37 | 38 | bad_typeid::bad_typeid() _NOEXCEPT 39 | { 40 | } 41 | 42 | bad_typeid::~bad_typeid() _NOEXCEPT 43 | { 44 | } 45 | 46 | const char* 47 | bad_typeid::what() const _NOEXCEPT 48 | { 49 | return "std::bad_typeid"; 50 | } 51 | 52 | } // std 53 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(AddLLVM) # for add_lit_testsuite 2 | macro(pythonize_bool var) 3 | if (${var}) 4 | set(${var} True) 5 | else() 6 | set(${var} False) 7 | endif() 8 | endmacro() 9 | 10 | if (NOT DEFINED LIBCXX_ENABLE_SHARED) 11 | set(LIBCXX_ENABLE_SHARED ON) 12 | endif() 13 | 14 | pythonize_bool(LIBCXXABI_BUILD_32_BITS) 15 | pythonize_bool(LIBCXX_ENABLE_SHARED) 16 | pythonize_bool(LIBCXXABI_ENABLE_SHARED) 17 | pythonize_bool(LIBCXXABI_ENABLE_THREADS) 18 | pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS) 19 | pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER) 20 | pythonize_bool(LIBCXXABI_USE_COMPILER_RT) 21 | pythonize_bool(LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY) 22 | pythonize_bool(LIBCXX_ENABLE_PARALLEL_ALGORITHMS) 23 | set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING 24 | "TargetInfo to use when setting up test environment.") 25 | set(LIBCXXABI_EXECUTOR "None" CACHE STRING 26 | "Executor to use when running tests.") 27 | 28 | set(AUTO_GEN_COMMENT "## Autogenerated by libcxxabi configuration.\n# Do not edit!") 29 | 30 | if (LIBCXXABI_ENABLE_SHARED) 31 | set(LIBCXXABI_TEST_DEPS cxxabi_shared) 32 | else() 33 | set(LIBCXXABI_TEST_DEPS cxxabi_static) 34 | endif() 35 | 36 | if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY) 37 | list(APPEND LIBCXXABI_TEST_DEPS cxx_external_threads) 38 | endif() 39 | 40 | if (NOT LIBCXXABI_STANDALONE_BUILD) 41 | list(APPEND LIBCXXABI_TEST_DEPS cxx) 42 | if (LIBCXXABI_USE_LLVM_UNWINDER) 43 | list(APPEND LIBCXXABI_TEST_DEPS unwind) 44 | endif() 45 | endif() 46 | 47 | 48 | configure_lit_site_cfg( 49 | ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in 50 | ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg) 51 | 52 | add_lit_testsuite(check-cxxabi "Running libcxxabi tests" 53 | ${CMAKE_CURRENT_BINARY_DIR} 54 | DEPENDS ${LIBCXXABI_TEST_DEPS} 55 | ) 56 | 57 | # TODO: This is a legacy target name and should be removed at some point. 58 | add_custom_target(check-libcxxabi DEPENDS check-cxxabi) 59 | -------------------------------------------------------------------------------- /test/backtrace_test.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- backtrace_test.cpp ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | extern "C" _Unwind_Reason_Code 16 | trace_function(struct _Unwind_Context*, void* ntraced) { 17 | (*reinterpret_cast(ntraced))++; 18 | // We should never have a call stack this deep... 19 | assert(*reinterpret_cast(ntraced) < 20); 20 | return _URC_NO_REASON; 21 | } 22 | 23 | __attribute__ ((__noinline__)) 24 | void call3_throw(size_t* ntraced) { 25 | try { 26 | _Unwind_Backtrace(trace_function, ntraced); 27 | } catch (...) { 28 | assert(false); 29 | } 30 | } 31 | 32 | __attribute__ ((__noinline__, __disable_tail_calls__)) 33 | void call3_nothrow(size_t* ntraced) { 34 | _Unwind_Backtrace(trace_function, ntraced); 35 | } 36 | 37 | __attribute__ ((__noinline__, __disable_tail_calls__)) 38 | void call2(size_t* ntraced, bool do_throw) { 39 | if (do_throw) { 40 | call3_throw(ntraced); 41 | } else { 42 | call3_nothrow(ntraced); 43 | } 44 | } 45 | 46 | __attribute__ ((__noinline__, __disable_tail_calls__)) 47 | void call1(size_t* ntraced, bool do_throw) { 48 | call2(ntraced, do_throw); 49 | } 50 | 51 | int main() { 52 | size_t throw_ntraced = 0; 53 | size_t nothrow_ntraced = 0; 54 | 55 | call1(¬hrow_ntraced, false); 56 | 57 | try { 58 | call1(&throw_ntraced, true); 59 | } catch (...) { 60 | assert(false); 61 | } 62 | 63 | // Different platforms (and different runtimes) will unwind a different number 64 | // of times, so we can't make any better assumptions than this. 65 | assert(nothrow_ntraced > 1); 66 | assert(throw_ntraced == nothrow_ntraced); // Make sure we unwind through catch 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /test/catch_array_01.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_array_01.cpp ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // Can you have a catch clause of array type that catches anything? 10 | 11 | // GCC incorrectly allows array types to be caught by reference. 12 | // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69372 13 | // XFAIL: gcc 14 | // UNSUPPORTED: libcxxabi-no-exceptions 15 | 16 | #include 17 | 18 | int main() 19 | { 20 | typedef char Array[4]; 21 | Array a = {'H', 'i', '!', 0}; 22 | try 23 | { 24 | throw a; // converts to char* 25 | assert(false); 26 | } 27 | catch (Array& b) // can't catch char* 28 | { 29 | assert(false); 30 | } 31 | catch (...) 32 | { 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/catch_array_02.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_array_02.cpp ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // Can you have a catch clause of array type that catches anything? 10 | // UNSUPPORTED: libcxxabi-no-exceptions 11 | 12 | #include 13 | 14 | int main() 15 | { 16 | typedef char Array[4]; 17 | Array a = {'H', 'i', '!', 0}; 18 | try 19 | { 20 | throw a; // converts to char* 21 | assert(false); 22 | } 23 | catch (Array b) // equivalent to char* 24 | { 25 | } 26 | catch (...) 27 | { 28 | assert(false); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/catch_class_01.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_class_01.cpp ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | struct A 16 | { 17 | static int count; 18 | int id_; 19 | explicit A(int id) : id_(id) {count++;} 20 | A(const A& a) : id_(a.id_) {count++;} 21 | ~A() {count--;} 22 | }; 23 | 24 | int A::count = 0; 25 | 26 | void f1() 27 | { 28 | throw A(3); 29 | } 30 | 31 | void f2() 32 | { 33 | try 34 | { 35 | assert(A::count == 0); 36 | f1(); 37 | } 38 | catch (A a) 39 | { 40 | assert(A::count != 0); 41 | assert(a.id_ == 3); 42 | throw; 43 | } 44 | } 45 | 46 | int main() 47 | { 48 | try 49 | { 50 | f2(); 51 | assert(false); 52 | } 53 | catch (const A& a) 54 | { 55 | assert(A::count != 0); 56 | assert(a.id_ == 3); 57 | } 58 | assert(A::count == 0); 59 | } 60 | -------------------------------------------------------------------------------- /test/catch_class_02.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_class_02.cpp ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | struct B 16 | { 17 | static int count; 18 | int id_; 19 | explicit B(int id) : id_(id) {count++;} 20 | B(const B& a) : id_(a.id_) {count++;} 21 | ~B() {count--;} 22 | }; 23 | 24 | int B::count = 0; 25 | 26 | struct A 27 | : B 28 | { 29 | static int count; 30 | int id_; 31 | explicit A(int id) : B(id-1), id_(id) {count++;} 32 | A(const A& a) : B(a.id_-1), id_(a.id_) {count++;} 33 | ~A() {count--;} 34 | }; 35 | 36 | int A::count = 0; 37 | 38 | void f1() 39 | { 40 | assert(A::count == 0); 41 | assert(B::count == 0); 42 | A a(3); 43 | assert(A::count == 1); 44 | assert(B::count == 1); 45 | throw a; 46 | assert(false); 47 | } 48 | 49 | void f2() 50 | { 51 | try 52 | { 53 | assert(A::count == 0); 54 | f1(); 55 | assert(false); 56 | } 57 | catch (A a) 58 | { 59 | assert(A::count != 0); 60 | assert(B::count != 0); 61 | assert(a.id_ == 3); 62 | throw; 63 | } 64 | catch (B b) 65 | { 66 | assert(false); 67 | } 68 | } 69 | 70 | int main() 71 | { 72 | try 73 | { 74 | f2(); 75 | assert(false); 76 | } 77 | catch (const B& b) 78 | { 79 | assert(B::count != 0); 80 | assert(b.id_ == 2); 81 | } 82 | assert(A::count == 0); 83 | assert(B::count == 0); 84 | } 85 | -------------------------------------------------------------------------------- /test/catch_class_03.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_class_03.cpp ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | /* 10 | This test checks that adjustedPtr is correct as there exist offsets in this 11 | object for the various subobjects, all of which have a unique id_ to 12 | check against. 13 | */ 14 | 15 | // UNSUPPORTED: libcxxabi-no-exceptions 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | // Clang emits warnings about exceptions of type 'Child' being caught by 22 | // an earlier handler of type 'Base'. Congrats clang, you've just 23 | // diagnosed the behavior under test. 24 | #if defined(__clang__) 25 | #pragma clang diagnostic ignored "-Wexceptions" 26 | #endif 27 | 28 | struct B 29 | { 30 | static int count; 31 | int id_; 32 | explicit B(int id) : id_(id) {count++;} 33 | B(const B& a) : id_(a.id_) {count++;} 34 | ~B() {count--;} 35 | }; 36 | 37 | int B::count = 0; 38 | 39 | struct C1 40 | : B 41 | { 42 | static int count; 43 | int id_; 44 | explicit C1(int id) : B(id-2), id_(id) {count++;} 45 | C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;} 46 | ~C1() {count--;} 47 | }; 48 | 49 | int C1::count = 0; 50 | 51 | struct C2 52 | : B 53 | { 54 | static int count; 55 | int id_; 56 | explicit C2(int id) : B(id-2), id_(id) {count++;} 57 | C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;} 58 | ~C2() {count--;} 59 | }; 60 | 61 | int C2::count = 0; 62 | 63 | struct A 64 | : C1, C2 65 | { 66 | static int count; 67 | int id_; 68 | explicit A(int id) : C1(id-1), C2(id-2), id_(id) {count++;} 69 | A(const A& a) : C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;} 70 | ~A() {count--;} 71 | }; 72 | 73 | int A::count = 0; 74 | 75 | void f1() 76 | { 77 | assert(A::count == 0); 78 | assert(C1::count == 0); 79 | assert(C2::count == 0); 80 | assert(B::count == 0); 81 | A a(5); 82 | assert(A::count == 1); 83 | assert(C1::count == 1); 84 | assert(C2::count == 1); 85 | assert(B::count == 2); 86 | 87 | assert(a.id_ == 5); 88 | assert(static_cast(a).id_ == 4); 89 | assert(static_cast(a).id_ == 3); 90 | assert(static_cast(static_cast(a)).id_ == 2); 91 | assert(static_cast(static_cast(a)).id_ == 1); 92 | throw a; 93 | assert(false); 94 | } 95 | 96 | void f2() 97 | { 98 | try 99 | { 100 | assert(A::count == 0); 101 | assert(C1::count == 0); 102 | assert(C2::count == 0); 103 | assert(B::count == 0); 104 | f1(); 105 | assert(false); 106 | } 107 | catch (const A& a) // can catch A 108 | { 109 | assert(a.id_ == 5); 110 | assert(static_cast(a).id_ == 4); 111 | assert(static_cast(a).id_ == 3); 112 | assert(static_cast(static_cast(a)).id_ == 2); 113 | assert(static_cast(static_cast(a)).id_ == 1); 114 | throw; 115 | } 116 | catch (const C1&) 117 | { 118 | assert(false); 119 | } 120 | catch (const C2&) 121 | { 122 | assert(false); 123 | } 124 | catch (const B&) 125 | { 126 | assert(false); 127 | } 128 | } 129 | 130 | void f3() 131 | { 132 | try 133 | { 134 | assert(A::count == 0); 135 | assert(C1::count == 0); 136 | assert(C2::count == 0); 137 | assert(B::count == 0); 138 | f2(); 139 | assert(false); 140 | } 141 | catch (const B& a) // can not catch B (ambiguous base) 142 | { 143 | assert(false); 144 | } 145 | catch (const C1& c1) // can catch C1 146 | { 147 | assert(c1.id_ == 4); 148 | assert(static_cast(c1).id_ == 2); 149 | throw; 150 | } 151 | catch (const C2&) 152 | { 153 | assert(false); 154 | } 155 | } 156 | 157 | void f4() 158 | { 159 | try 160 | { 161 | assert(A::count == 0); 162 | assert(C1::count == 0); 163 | assert(C2::count == 0); 164 | assert(B::count == 0); 165 | f3(); 166 | assert(false); 167 | } 168 | catch (const B& a) // can not catch B (ambiguous base) 169 | { 170 | assert(false); 171 | } 172 | catch (const C2& c2) // can catch C2 173 | { 174 | assert(c2.id_ == 3); 175 | assert(static_cast(c2).id_ == 1); 176 | throw; 177 | } 178 | catch (const C1&) 179 | { 180 | assert(false); 181 | } 182 | } 183 | 184 | int main() 185 | { 186 | try 187 | { 188 | f4(); 189 | assert(false); 190 | } 191 | catch (...) 192 | { 193 | } 194 | assert(A::count == 0); 195 | assert(C1::count == 0); 196 | assert(C2::count == 0); 197 | assert(B::count == 0); 198 | } 199 | -------------------------------------------------------------------------------- /test/catch_class_04.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_class_04.cpp ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | /* 10 | This test checks that adjustedPtr is correct as there exist offsets in this 11 | object for the various subobjects, all of which have a unique id_ to 12 | check against. It also checks that virtual bases work properly 13 | */ 14 | 15 | // UNSUPPORTED: libcxxabi-no-exceptions 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | // Clang emits warnings about exceptions of type 'Child' being caught by 22 | // an earlier handler of type 'Base'. Congrats clang, you've just 23 | // diagnosed the behavior under test. 24 | #if defined(__clang__) 25 | #pragma clang diagnostic ignored "-Wexceptions" 26 | #endif 27 | 28 | struct B 29 | { 30 | static int count; 31 | int id_; 32 | explicit B(int id) : id_(id) {count++;} 33 | B(const B& a) : id_(a.id_) {count++;} 34 | ~B() {count--;} 35 | }; 36 | 37 | int B::count = 0; 38 | 39 | struct C1 40 | : virtual B 41 | { 42 | static int count; 43 | int id_; 44 | explicit C1(int id) : B(id-2), id_(id) {count++;} 45 | C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;} 46 | ~C1() {count--;} 47 | }; 48 | 49 | int C1::count = 0; 50 | 51 | struct C2 52 | : virtual private B 53 | { 54 | static int count; 55 | int id_; 56 | explicit C2(int id) : B(id-2), id_(id) {count++;} 57 | C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;} 58 | ~C2() {count--;} 59 | }; 60 | 61 | int C2::count = 0; 62 | 63 | struct A 64 | : C1, C2 65 | { 66 | static int count; 67 | int id_; 68 | explicit A(int id) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;} 69 | A(const A& a) : B(a.id_+3), C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;} 70 | ~A() {count--;} 71 | }; 72 | 73 | int A::count = 0; 74 | 75 | void f1() 76 | { 77 | assert(A::count == 0); 78 | assert(C1::count == 0); 79 | assert(C2::count == 0); 80 | assert(B::count == 0); 81 | A a(5); 82 | assert(A::count == 1); 83 | assert(C1::count == 1); 84 | assert(C2::count == 1); 85 | assert(B::count == 1); 86 | 87 | assert(a.id_ == 5); 88 | assert(static_cast(a).id_ == 4); 89 | assert(static_cast(a).id_ == 3); 90 | assert(static_cast(a).id_ == 8); 91 | throw a; 92 | assert(false); 93 | } 94 | 95 | void f2() 96 | { 97 | try 98 | { 99 | assert(A::count == 0); 100 | assert(C1::count == 0); 101 | assert(C2::count == 0); 102 | assert(B::count == 0); 103 | f1(); 104 | assert(false); 105 | } 106 | catch (const A& a) // can catch A 107 | { 108 | assert(a.id_ == 5); 109 | assert(static_cast(a).id_ == 4); 110 | assert(static_cast(a).id_ == 3); 111 | assert(static_cast(a).id_ == 8); 112 | throw; 113 | } 114 | catch (const C1&) 115 | { 116 | assert(false); 117 | } 118 | catch (const C2&) 119 | { 120 | assert(false); 121 | } 122 | catch (const B&) 123 | { 124 | assert(false); 125 | } 126 | } 127 | 128 | void f3() 129 | { 130 | try 131 | { 132 | assert(A::count == 0); 133 | assert(C1::count == 0); 134 | assert(C2::count == 0); 135 | assert(B::count == 0); 136 | f2(); 137 | assert(false); 138 | } 139 | catch (const B& a) // can catch B 140 | { 141 | assert(static_cast(a).id_ == 8); 142 | throw; 143 | } 144 | catch (const C1& c1) 145 | { 146 | assert(false); 147 | } 148 | catch (const C2&) 149 | { 150 | assert(false); 151 | } 152 | } 153 | 154 | void f4() 155 | { 156 | try 157 | { 158 | assert(A::count == 0); 159 | assert(C1::count == 0); 160 | assert(C2::count == 0); 161 | assert(B::count == 0); 162 | f3(); 163 | assert(false); 164 | } 165 | catch (const C2& c2) // can catch C2 166 | { 167 | assert(c2.id_ == 3); 168 | throw; 169 | } 170 | catch (const B& a) // can not catch B (ambiguous base) 171 | { 172 | assert(false); 173 | } 174 | catch (const C1&) 175 | { 176 | assert(false); 177 | } 178 | } 179 | 180 | void f5() 181 | { 182 | try 183 | { 184 | assert(A::count == 0); 185 | assert(C1::count == 0); 186 | assert(C2::count == 0); 187 | assert(B::count == 0); 188 | f4(); 189 | assert(false); 190 | } 191 | catch (const C1& c1) // can catch C1 192 | { 193 | assert(c1.id_ == 4); 194 | assert(static_cast(c1).id_ == 8); 195 | throw; 196 | } 197 | catch (const B& a) 198 | { 199 | assert(false); 200 | } 201 | catch (const C2&) 202 | { 203 | assert(false); 204 | } 205 | } 206 | 207 | int main() 208 | { 209 | try 210 | { 211 | f5(); 212 | assert(false); 213 | } 214 | catch (...) 215 | { 216 | } 217 | assert(A::count == 0); 218 | assert(C1::count == 0); 219 | assert(C2::count == 0); 220 | assert(B::count == 0); 221 | } 222 | -------------------------------------------------------------------------------- /test/catch_const_pointer_nullptr.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------- catch_const_pointer_nullptr.cpp ----------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | 13 | // Clang emits warnings about exceptions of type 'Child' being caught by 14 | // an earlier handler of type 'Base'. Congrats clang, you've just 15 | // diagnosed the behavior under test. 16 | #if defined(__clang__) 17 | #pragma clang diagnostic ignored "-Wexceptions" 18 | #endif 19 | 20 | #if __has_feature(cxx_nullptr) 21 | 22 | struct A {}; 23 | 24 | void test1() 25 | { 26 | try 27 | { 28 | throw nullptr; 29 | assert(false); 30 | } 31 | catch (A* p) 32 | { 33 | assert(!p); 34 | } 35 | catch (const A*) 36 | { 37 | assert(false); 38 | } 39 | } 40 | 41 | 42 | void test2() 43 | { 44 | try 45 | { 46 | throw nullptr; 47 | assert(false); 48 | } 49 | catch (const A* p) 50 | { 51 | assert(!p); 52 | } 53 | catch (A*) 54 | { 55 | assert(false); 56 | } 57 | } 58 | 59 | void test3() 60 | { 61 | try 62 | { 63 | throw nullptr; 64 | assert(false); 65 | } 66 | catch (const A* const p) 67 | { 68 | assert(!p); 69 | } 70 | catch (A*) 71 | { 72 | assert(false); 73 | } 74 | } 75 | 76 | void test4() 77 | { 78 | try 79 | { 80 | throw nullptr; 81 | assert(false); 82 | } 83 | catch (A* p) 84 | { 85 | assert(!p); 86 | } 87 | catch (const A* const) 88 | { 89 | assert(false); 90 | } 91 | } 92 | 93 | void test5() 94 | { 95 | try 96 | { 97 | throw nullptr; 98 | assert(false); 99 | } 100 | catch (A const* p) 101 | { 102 | assert(!p); 103 | } 104 | catch (A*) 105 | { 106 | assert(false); 107 | } 108 | } 109 | 110 | void test6() 111 | { 112 | try 113 | { 114 | throw nullptr; 115 | assert(false); 116 | } 117 | catch (A* p) 118 | { 119 | assert(!p); 120 | } 121 | catch (A const*) 122 | { 123 | assert(false); 124 | } 125 | } 126 | 127 | 128 | #else 129 | 130 | void test1() {} 131 | void test2() {} 132 | void test3() {} 133 | void test4() {} 134 | void test5() {} 135 | void test6() {} 136 | 137 | #endif 138 | 139 | int main() 140 | { 141 | test1(); 142 | test2(); 143 | test3(); 144 | test4(); 145 | test5(); 146 | test6(); 147 | } 148 | -------------------------------------------------------------------------------- /test/catch_function_01.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- catch_function_01.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // Can you have a catch clause of array type that catches anything? 10 | 11 | // GCC incorrectly allows function pointer to be caught by reference. 12 | // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69372 13 | // XFAIL: gcc 14 | // UNSUPPORTED: libcxxabi-no-exceptions 15 | 16 | #include 17 | 18 | template 19 | bool can_convert(Tp) { return true; } 20 | 21 | template 22 | bool can_convert(...) { return false; } 23 | 24 | void f() {} 25 | 26 | int main() 27 | { 28 | typedef void Function(); 29 | assert(!can_convert(&f)); 30 | assert(!can_convert(&f)); 31 | try 32 | { 33 | throw f; // converts to void (*)() 34 | assert(false); 35 | } 36 | catch (Function& b) // can't catch void (*)() 37 | { 38 | assert(false); 39 | } 40 | catch (void*) // can't catch as void* 41 | { 42 | assert(false); 43 | } 44 | catch(Function*) 45 | { 46 | } 47 | catch (...) 48 | { 49 | assert(false); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/catch_function_02.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_function_02.cpp -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // Can you have a catch clause of array type that catches anything? 10 | // UNSUPPORTED: libcxxabi-no-exceptions 11 | 12 | #include 13 | 14 | void f() {} 15 | 16 | int main() 17 | { 18 | typedef void Function(); 19 | try 20 | { 21 | throw f; // converts to void (*)() 22 | assert(false); 23 | } 24 | catch (Function b) // equivalent to void (*)() 25 | { 26 | } 27 | catch (...) 28 | { 29 | assert(false); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/catch_function_03.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_function_03.cpp -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // Can a noexcept function pointer be caught by a non-noexcept catch clause? 10 | // UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-noexcept-function-type 11 | 12 | #include 13 | 14 | template void f() noexcept(Noexcept) {} 15 | template using FnType = void() noexcept(Noexcept); 16 | 17 | template 18 | void check() 19 | { 20 | try 21 | { 22 | auto *p = f; 23 | throw p; 24 | assert(false); 25 | } 26 | catch (FnType *p) 27 | { 28 | assert(ThrowNoexcept || !CatchNoexcept); 29 | assert(p == &f); 30 | } 31 | catch (...) 32 | { 33 | assert(!ThrowNoexcept && CatchNoexcept); 34 | } 35 | } 36 | 37 | void check_deep() { 38 | auto *p = f; 39 | try 40 | { 41 | throw &p; 42 | } 43 | catch (FnType **q) 44 | { 45 | assert(false); 46 | } 47 | catch (FnType **q) 48 | { 49 | } 50 | catch (...) 51 | { 52 | assert(false); 53 | } 54 | } 55 | 56 | int main() 57 | { 58 | check(); 59 | check(); 60 | check(); 61 | check(); 62 | check_deep(); 63 | } 64 | -------------------------------------------------------------------------------- /test/catch_in_noexcept.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_in_noexcept.cpp--------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03, libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | struct A {}; 16 | 17 | // Despite being marked as noexcept, this function must have an EHT entry that 18 | // is not 'cantunwind', so that the unwinder can correctly deal with the throw. 19 | void f1() noexcept 20 | { 21 | try { 22 | A a; 23 | throw a; 24 | assert(false); 25 | } catch (...) { 26 | assert(true); 27 | return; 28 | } 29 | assert(false); 30 | } 31 | 32 | int main() 33 | { 34 | f1(); 35 | } 36 | -------------------------------------------------------------------------------- /test/catch_member_data_pointer_01.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------- catch_member_data_pointer_01.cpp -------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | 13 | struct A 14 | { 15 | A() : i(0), j(0) {} // explicitly initialize 'i' to prevent warnings 16 | const int i; 17 | int j; 18 | }; 19 | 20 | typedef const int A::*md1; 21 | typedef int A::*md2; 22 | 23 | struct B : public A 24 | { 25 | B() : k(0), l(0) {} // explicitly initialize 'k' to prevent warnings. 26 | const int k; 27 | int l; 28 | }; 29 | 30 | typedef const int B::*der1; 31 | typedef int B::*der2; 32 | 33 | void test1() 34 | { 35 | try 36 | { 37 | throw &A::i; 38 | assert(false); 39 | } 40 | catch (md2) 41 | { 42 | assert(false); 43 | } 44 | catch (md1) 45 | { 46 | } 47 | } 48 | 49 | // Check that cv qualified conversions are allowed. 50 | void test2() 51 | { 52 | try 53 | { 54 | throw &A::j; 55 | } 56 | catch (md2) 57 | { 58 | } 59 | catch (...) 60 | { 61 | assert(false); 62 | } 63 | 64 | try 65 | { 66 | throw &A::j; 67 | assert(false); 68 | } 69 | catch (md1) 70 | { 71 | } 72 | catch (...) 73 | { 74 | assert(false); 75 | } 76 | } 77 | 78 | // Check that Base -> Derived conversions are NOT allowed. 79 | void test3() 80 | { 81 | try 82 | { 83 | throw &A::i; 84 | assert(false); 85 | } 86 | catch (md2) 87 | { 88 | assert(false); 89 | } 90 | catch (der2) 91 | { 92 | assert(false); 93 | } 94 | catch (der1) 95 | { 96 | assert(false); 97 | } 98 | catch (md1) 99 | { 100 | } 101 | } 102 | 103 | // Check that Base -> Derived conversions NOT are allowed with different cv 104 | // qualifiers. 105 | void test4() 106 | { 107 | try 108 | { 109 | throw &A::j; 110 | assert(false); 111 | } 112 | catch (der2) 113 | { 114 | assert(false); 115 | } 116 | catch (der1) 117 | { 118 | assert(false); 119 | } 120 | catch (md2) 121 | { 122 | } 123 | catch (...) 124 | { 125 | assert(false); 126 | } 127 | } 128 | 129 | // Check that no Derived -> Base conversions are allowed. 130 | void test5() 131 | { 132 | try 133 | { 134 | throw &B::k; 135 | assert(false); 136 | } 137 | catch (md1) 138 | { 139 | assert(false); 140 | } 141 | catch (md2) 142 | { 143 | assert(false); 144 | } 145 | catch (der1) 146 | { 147 | } 148 | 149 | try 150 | { 151 | throw &B::l; 152 | assert(false); 153 | } 154 | catch (md1) 155 | { 156 | assert(false); 157 | } 158 | catch (md2) 159 | { 160 | assert(false); 161 | } 162 | catch (der2) 163 | { 164 | } 165 | } 166 | 167 | int main() 168 | { 169 | test1(); 170 | test2(); 171 | test3(); 172 | test4(); 173 | test5(); 174 | } 175 | -------------------------------------------------------------------------------- /test/catch_member_function_pointer_01.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------- catch_member_function_pointer_01.cpp -----------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // GCC incorrectly allows PMF type "void (T::*)()" to be caught as "void (T::*)() const" 10 | // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69375 11 | // XFAIL: gcc 12 | // UNSUPPORTED: libcxxabi-no-exceptions 13 | #include 14 | 15 | struct A 16 | { 17 | void foo() {} 18 | void bar() const {} 19 | }; 20 | 21 | typedef void (A::*mf1)(); 22 | typedef void (A::*mf2)() const; 23 | 24 | struct B : public A 25 | { 26 | }; 27 | 28 | typedef void (B::*dmf1)(); 29 | typedef void (B::*dmf2)() const; 30 | 31 | template 32 | bool can_convert(Tp) { return true; } 33 | 34 | template 35 | bool can_convert(...) { return false; } 36 | 37 | 38 | void test1() 39 | { 40 | try 41 | { 42 | throw &A::foo; 43 | assert(false); 44 | } 45 | catch (mf2) 46 | { 47 | assert(false); 48 | } 49 | catch (mf1) 50 | { 51 | } 52 | } 53 | 54 | void test2() 55 | { 56 | try 57 | { 58 | throw &A::bar; 59 | assert(false); 60 | } 61 | catch (mf1) 62 | { 63 | assert(false); 64 | } 65 | catch (mf2) 66 | { 67 | } 68 | } 69 | 70 | 71 | 72 | void test_derived() 73 | { 74 | try 75 | { 76 | throw (mf1)0; 77 | assert(false); 78 | } 79 | catch (dmf2) 80 | { 81 | assert(false); 82 | } 83 | catch (dmf1) 84 | { 85 | assert(false); 86 | } 87 | catch (mf1) 88 | { 89 | } 90 | 91 | try 92 | { 93 | throw (mf2)0; 94 | assert(false); 95 | } 96 | catch (dmf1) 97 | { 98 | assert(false); 99 | } 100 | catch (dmf2) 101 | { 102 | assert(false); 103 | } 104 | catch (mf2) 105 | { 106 | } 107 | 108 | assert(!can_convert((dmf1)0)); 109 | assert(!can_convert((dmf1)0)); 110 | try 111 | { 112 | throw (dmf1)0; 113 | assert(false); 114 | } 115 | catch (mf2) 116 | { 117 | assert(false); 118 | } 119 | catch (mf1) 120 | { 121 | assert(false); 122 | } 123 | catch (...) 124 | { 125 | } 126 | 127 | assert(!can_convert((dmf2)0)); 128 | assert(!can_convert((dmf2)0)); 129 | try 130 | { 131 | throw (dmf2)0; 132 | assert(false); 133 | } 134 | catch (mf2) 135 | { 136 | assert(false); 137 | } 138 | catch (mf1) 139 | { 140 | assert(false); 141 | } 142 | catch (...) 143 | { 144 | } 145 | } 146 | 147 | void test_void() 148 | { 149 | assert(!can_convert(&A::foo)); 150 | try 151 | { 152 | throw &A::foo; 153 | assert(false); 154 | } 155 | catch (void*) 156 | { 157 | assert(false); 158 | } 159 | catch(...) 160 | { 161 | } 162 | } 163 | 164 | int main() 165 | { 166 | test1(); 167 | test2(); 168 | test_derived(); 169 | test_void(); 170 | } 171 | -------------------------------------------------------------------------------- /test/catch_member_function_pointer_02.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------- catch_member_function_pointer_02.cpp -----------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // Can a noexcept member function pointer be caught by a non-noexcept catch 10 | // clause? 11 | // UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-noexcept-function-type 12 | 13 | // GCC 7 and 8 support noexcept function types but this test still fails. 14 | // This is likely a bug in their implementation. Investigation needed. 15 | // XFAIL: gcc-7, gcc-8, gcc-9, gcc-10 16 | 17 | #include 18 | 19 | struct X { 20 | template void f() noexcept(Noexcept) {} 21 | }; 22 | template using FnType = void (X::*)() noexcept(Noexcept); 23 | 24 | template 25 | void check() 26 | { 27 | try 28 | { 29 | auto p = &X::f; 30 | throw p; 31 | assert(false); 32 | } 33 | catch (FnType p) 34 | { 35 | assert(ThrowNoexcept || !CatchNoexcept); 36 | assert(p == &X::f); 37 | } 38 | catch (...) 39 | { 40 | assert(!ThrowNoexcept && CatchNoexcept); 41 | } 42 | } 43 | 44 | void check_deep() { 45 | FnType p = &X::f; 46 | try 47 | { 48 | throw &p; 49 | } 50 | catch (FnType *q) 51 | { 52 | assert(false); 53 | } 54 | catch (FnType *q) 55 | { 56 | } 57 | catch (...) 58 | { 59 | assert(false); 60 | } 61 | } 62 | 63 | int main() 64 | { 65 | check(); 66 | check(); 67 | check(); 68 | check(); 69 | check_deep(); 70 | } 71 | -------------------------------------------------------------------------------- /test/catch_member_pointer_nullptr.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------- catch_member_pointer_nullptr.cpp -------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | 13 | #if __has_feature(cxx_nullptr) 14 | 15 | struct A 16 | { 17 | const int i; 18 | int j; 19 | }; 20 | 21 | typedef const int A::*md1; 22 | typedef int A::*md2; 23 | 24 | void test1() 25 | { 26 | try 27 | { 28 | throw nullptr; 29 | assert(false); 30 | } 31 | catch (md2 p) 32 | { 33 | assert(!p); 34 | } 35 | catch (md1) 36 | { 37 | assert(false); 38 | } 39 | } 40 | 41 | void test2() 42 | { 43 | try 44 | { 45 | throw nullptr; 46 | assert(false); 47 | } 48 | catch (md1 p) 49 | { 50 | assert(!p); 51 | } 52 | catch (md2) 53 | { 54 | assert(false); 55 | } 56 | } 57 | 58 | #else 59 | 60 | void test1() 61 | { 62 | } 63 | 64 | void test2() 65 | { 66 | } 67 | 68 | #endif 69 | 70 | int main() 71 | { 72 | test1(); 73 | test2(); 74 | } 75 | -------------------------------------------------------------------------------- /test/catch_multi_level_pointer.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------- catch_pointer_nullptr.cpp ----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // Roll our own assertion macro to get better error messages out of the tests. 16 | // In particular on systems that don't use __PRETTY_FUNCTION__ in assertions. 17 | #define my_assert(pred, msg) do_assert(pred, msg, __LINE__, __PRETTY_FUNCTION__) 18 | 19 | void do_assert(bool assert_passed, const char* msg, int line, const char* func) { 20 | if (assert_passed) return; 21 | std::cerr << __FILE__ << ":" << line << " " << func 22 | << ": Assertion Failed `" << msg << "'\n\n"; 23 | std::abort(); 24 | } 25 | 26 | struct A {}; 27 | struct Base {}; 28 | struct Derived : public Base {}; 29 | 30 | template 31 | bool test_conversion(To) { return true; } 32 | 33 | template 34 | bool test_conversion(...) { return false; } 35 | 36 | template 37 | struct CreatePointer { 38 | Pointer operator()() const { 39 | return (Pointer)0; 40 | } 41 | }; 42 | 43 | template 44 | struct CreatePointer { 45 | Tp* operator()() const { 46 | return (Tp*)42; 47 | } 48 | }; 49 | 50 | template 51 | void catch_pointer_test() { 52 | Throw throw_ptr = CreatePointer()(); 53 | // Use the compiler to determine if the exception of type Throw can be 54 | // implicitly converted to type Catch. 55 | const bool can_convert = test_conversion(throw_ptr); 56 | try { 57 | throw throw_ptr; 58 | assert(false); 59 | } catch (Catch catch_ptr) { 60 | Catch catch2 = CreatePointer()(); 61 | my_assert(can_convert, "non-convertible type incorrectly caught"); 62 | my_assert(catch_ptr == catch2, 63 | "Thrown pointer does not match caught ptr"); 64 | } catch (...) { 65 | my_assert(!can_convert, "convertible type incorrectly not caught"); 66 | } 67 | } 68 | 69 | // Generate CV qualified pointer typedefs. 70 | template 71 | struct TestTypes { 72 | typedef Tp* Type; 73 | typedef Tp const* CType; 74 | typedef Tp volatile* VType; 75 | typedef Tp const volatile* CVType; 76 | }; 77 | 78 | // Special case for cv-qualifying a pointer-to-member without adding an extra 79 | // pointer to it. 80 | template 81 | struct TestTypes { 82 | typedef Member (Class::*Type); 83 | typedef const Member (Class::*CType); 84 | typedef volatile Member (Class::*VType); 85 | typedef const volatile Member (Class::*CVType); 86 | }; 87 | 88 | template 89 | struct generate_tests_imp { 90 | typedef TestTypes ThrowTypes; 91 | typedef TestTypes CatchTypes; 92 | void operator()() { 93 | typedef typename ThrowTypes::Type Type; 94 | typedef typename ThrowTypes::CType CType; 95 | typedef typename ThrowTypes::VType VType; 96 | typedef typename ThrowTypes::CVType CVType; 97 | 98 | run_catch_tests(); 99 | run_catch_tests(); 100 | run_catch_tests(); 101 | run_catch_tests(); 102 | } 103 | 104 | template 105 | void run_catch_tests() { 106 | typedef typename CatchTypes::Type Type; 107 | typedef typename CatchTypes::CType CType; 108 | typedef typename CatchTypes::VType VType; 109 | typedef typename CatchTypes::CVType CVType; 110 | 111 | catch_pointer_test(); 112 | catch_pointer_test(); 113 | catch_pointer_test(); 114 | catch_pointer_test(); 115 | 116 | generate_tests_imp()(); 117 | generate_tests_imp()(); 118 | generate_tests_imp()(); 119 | generate_tests_imp()(); 120 | } 121 | }; 122 | 123 | template 124 | struct generate_tests_imp { 125 | void operator()() { 126 | catch_pointer_test(); 127 | } 128 | }; 129 | 130 | template 131 | struct generate_tests : generate_tests_imp {}; 132 | 133 | int main() 134 | { 135 | generate_tests()(); 136 | generate_tests()(); 137 | generate_tests()(); 138 | generate_tests()(); 139 | generate_tests()(); 140 | 141 | generate_tests()(); 142 | generate_tests()(); 143 | generate_tests()(); 144 | } 145 | -------------------------------------------------------------------------------- /test/catch_pointer_nullptr.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------- catch_pointer_nullptr.cpp ----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03, libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | 14 | struct A {}; 15 | 16 | void test1() 17 | { 18 | try 19 | { 20 | throw nullptr; 21 | assert(false); 22 | } 23 | catch (int* p) 24 | { 25 | assert(!p); 26 | } 27 | catch (long*) 28 | { 29 | assert(false); 30 | } 31 | } 32 | 33 | void test2() 34 | { 35 | try 36 | { 37 | throw nullptr; 38 | assert(false); 39 | } 40 | catch (A* p) 41 | { 42 | assert(!p); 43 | } 44 | catch (int*) 45 | { 46 | assert(false); 47 | } 48 | } 49 | 50 | template 51 | void catch_nullptr_test() { 52 | try { 53 | throw nullptr; 54 | assert(false); 55 | } catch (Catch c) { 56 | assert(!c); 57 | } catch (...) { 58 | assert(false); 59 | } 60 | } 61 | 62 | 63 | int main() 64 | { 65 | // catch naked nullptrs 66 | test1(); 67 | test2(); 68 | 69 | catch_nullptr_test(); 70 | catch_nullptr_test(); 71 | catch_nullptr_test(); 72 | catch_nullptr_test(); 73 | catch_nullptr_test(); 74 | } 75 | -------------------------------------------------------------------------------- /test/catch_ptr.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------------- catch_class_04.cpp ----------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | /* 10 | This test checks that adjustedPtr is correct as there exist offsets in this 11 | object for the various subobjects, all of which have a unique id_ to 12 | check against. It also checks that virtual bases work properly 13 | */ 14 | 15 | // UNSUPPORTED: libcxxabi-no-exceptions 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | // Clang emits warnings about exceptions of type 'Child' being caught by 22 | // an earlier handler of type 'Base'. Congrats clang, you've just 23 | // diagnosed the behavior under test. 24 | #if defined(__clang__) 25 | #pragma clang diagnostic ignored "-Wexceptions" 26 | #endif 27 | 28 | struct B 29 | { 30 | static int count; 31 | int id_; 32 | explicit B(int id) : id_(id) {count++;} 33 | B(const B& a) : id_(a.id_) {count++;} 34 | ~B() {count--;} 35 | }; 36 | 37 | int B::count = 0; 38 | 39 | struct C1 40 | : virtual B 41 | { 42 | static int count; 43 | int id_; 44 | explicit C1(int id) : B(id-2), id_(id) {count++;} 45 | C1(const C1& a) : B(a.id_-2), id_(a.id_) {count++;} 46 | ~C1() {count--;} 47 | }; 48 | 49 | int C1::count = 0; 50 | 51 | struct C2 52 | : virtual private B 53 | { 54 | static int count; 55 | int id_; 56 | explicit C2(int id) : B(id-2), id_(id) {count++;} 57 | C2(const C2& a) : B(a.id_-2), id_(a.id_) {count++;} 58 | ~C2() {count--;} 59 | }; 60 | 61 | int C2::count = 0; 62 | 63 | struct A 64 | : C1, C2 65 | { 66 | static int count; 67 | int id_; 68 | explicit A(int id) : B(id+3), C1(id-1), C2(id-2), id_(id) {count++;} 69 | A(const A& a) : B(a.id_+3), C1(a.id_-1), C2(a.id_-2), id_(a.id_) {count++;} 70 | ~A() {count--;} 71 | }; 72 | 73 | int A::count = 0; 74 | 75 | A a(5); 76 | 77 | void f1() 78 | { 79 | throw &a; 80 | assert(false); 81 | } 82 | 83 | void f2() 84 | { 85 | try 86 | { 87 | f1(); 88 | assert(false); 89 | } 90 | catch (const A* a) // can catch A 91 | { 92 | assert(a->id_ == 5); 93 | assert(static_cast(a)->id_ == 4); 94 | assert(static_cast(a)->id_ == 3); 95 | assert(static_cast(a)->id_ == 8); 96 | throw; 97 | } 98 | catch (const C1*) 99 | { 100 | assert(false); 101 | } 102 | catch (const C2*) 103 | { 104 | assert(false); 105 | } 106 | catch (const B*) 107 | { 108 | assert(false); 109 | } 110 | } 111 | 112 | void f3() 113 | { 114 | try 115 | { 116 | f2(); 117 | assert(false); 118 | } 119 | catch (const B* a) // can catch B 120 | { 121 | assert(static_cast(a)->id_ == 8); 122 | throw; 123 | } 124 | catch (const C1* c1) 125 | { 126 | assert(false); 127 | } 128 | catch (const C2*) 129 | { 130 | assert(false); 131 | } 132 | } 133 | 134 | void f4() 135 | { 136 | try 137 | { 138 | f3(); 139 | assert(false); 140 | } 141 | catch (const C2* c2) // can catch C2 142 | { 143 | assert(c2->id_ == 3); 144 | throw; 145 | } 146 | catch (const B* a) 147 | { 148 | assert(false); 149 | } 150 | catch (const C1*) 151 | { 152 | assert(false); 153 | } 154 | } 155 | 156 | void f5() 157 | { 158 | try 159 | { 160 | f4(); 161 | assert(false); 162 | } 163 | catch (const C1* c1) // can catch C1 164 | { 165 | assert(c1->id_ == 4); 166 | assert(static_cast(c1)->id_ == 8); 167 | throw; 168 | } 169 | catch (const B* a) 170 | { 171 | assert(false); 172 | } 173 | catch (const C2*) 174 | { 175 | assert(false); 176 | } 177 | } 178 | 179 | int main() 180 | { 181 | try 182 | { 183 | f5(); 184 | assert(false); 185 | } 186 | catch (...) 187 | { 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /test/catch_ptr_02.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- catch_ptr_02.cpp ---------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | 13 | // Clang emits warnings about exceptions of type 'Child' being caught by 14 | // an earlier handler of type 'Base'. Congrats clang, you've just 15 | // diagnosed the behavior under test. 16 | #if defined(__clang__) 17 | #pragma clang diagnostic ignored "-Wexceptions" 18 | #endif 19 | 20 | #if __cplusplus < 201103L 21 | #define DISABLE_NULLPTR_TESTS 22 | #endif 23 | 24 | struct A {}; 25 | A a; 26 | const A ca = A(); 27 | 28 | void test1 () 29 | { 30 | try 31 | { 32 | throw &a; 33 | assert(false); 34 | } 35 | catch ( const A* ) 36 | { 37 | } 38 | catch ( A *) 39 | { 40 | assert (false); 41 | } 42 | } 43 | 44 | void test2 () 45 | { 46 | try 47 | { 48 | throw &a; 49 | assert(false); 50 | } 51 | catch ( A* ) 52 | { 53 | } 54 | catch ( const A *) 55 | { 56 | assert (false); 57 | } 58 | } 59 | 60 | void test3 () 61 | { 62 | try 63 | { 64 | throw &ca; 65 | assert(false); 66 | } 67 | catch ( const A* ) 68 | { 69 | } 70 | catch ( A *) 71 | { 72 | assert (false); 73 | } 74 | } 75 | 76 | void test4 () 77 | { 78 | try 79 | { 80 | throw &ca; 81 | assert(false); 82 | } 83 | catch ( A *) 84 | { 85 | assert (false); 86 | } 87 | catch ( const A* ) 88 | { 89 | } 90 | } 91 | 92 | struct base1 {int x;}; 93 | struct base2 {int x;}; 94 | struct derived : base1, base2 {}; 95 | 96 | void test5 () 97 | { 98 | try 99 | { 100 | throw (derived*)0; 101 | assert(false); 102 | } 103 | catch (base2 *p) { 104 | assert (p == 0); 105 | } 106 | catch (...) 107 | { 108 | assert (false); 109 | } 110 | } 111 | 112 | void test6 () 113 | { 114 | #if !defined(DISABLE_NULLPTR_TESTS) 115 | try 116 | { 117 | throw nullptr; 118 | assert(false); 119 | } 120 | catch (base2 *p) { 121 | assert (p == nullptr); 122 | } 123 | catch (...) 124 | { 125 | assert (false); 126 | } 127 | #endif 128 | } 129 | 130 | void test7 () 131 | { 132 | try 133 | { 134 | throw (derived*)12; 135 | assert(false); 136 | } 137 | catch (base2 *p) { 138 | assert ((unsigned long)p == 12+sizeof(base1)); 139 | } 140 | catch (...) 141 | { 142 | assert (false); 143 | } 144 | } 145 | 146 | 147 | struct vBase {}; 148 | struct vDerived : virtual public vBase {}; 149 | 150 | void test8 () 151 | { 152 | vDerived derived; 153 | try 154 | { 155 | throw &derived; 156 | assert(false); 157 | } 158 | catch (vBase *p) { 159 | assert(p != 0); 160 | } 161 | catch (...) 162 | { 163 | assert (false); 164 | } 165 | } 166 | 167 | void test9 () 168 | { 169 | #if !defined(DISABLE_NULLPTR_TESTS) 170 | try 171 | { 172 | throw nullptr; 173 | assert(false); 174 | } 175 | catch (vBase *p) { 176 | assert(p == 0); 177 | } 178 | catch (...) 179 | { 180 | assert (false); 181 | } 182 | #endif 183 | } 184 | 185 | void test10 () 186 | { 187 | try 188 | { 189 | throw (vDerived*)0; 190 | assert(false); 191 | } 192 | catch (vBase *p) { 193 | assert(p == 0); 194 | } 195 | catch (...) 196 | { 197 | assert (false); 198 | } 199 | } 200 | 201 | int main() 202 | { 203 | test1(); 204 | test2(); 205 | test3(); 206 | test4(); 207 | test5(); 208 | test6(); 209 | test7(); 210 | test8(); 211 | test9(); 212 | test10(); 213 | } 214 | -------------------------------------------------------------------------------- /test/catch_reference_nullptr.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------- catch_pointer_nullptr.cpp ----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03, libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | 14 | struct A {}; 15 | 16 | template 17 | static void catch_nullptr_test() { 18 | try { 19 | throw nullptr; 20 | } catch (T &p) { 21 | assert(CanCatchNullptr && !static_cast(p)); 22 | } catch (...) { 23 | assert(!CanCatchNullptr); 24 | } 25 | } 26 | 27 | int main() 28 | { 29 | using nullptr_t = decltype(nullptr); 30 | 31 | // A reference to nullptr_t can catch nullptr. 32 | catch_nullptr_test(); 33 | catch_nullptr_test(); 34 | catch_nullptr_test(); 35 | catch_nullptr_test(); 36 | 37 | // No other reference type can. 38 | #if 0 39 | // FIXME: These tests fail, because the ABI provides no way for us to 40 | // distinguish this from catching by value. 41 | catch_nullptr_test(); 42 | catch_nullptr_test(); 43 | catch_nullptr_test(); 44 | catch_nullptr_test(); 45 | catch_nullptr_test(); 46 | catch_nullptr_test(); 47 | #endif 48 | } 49 | -------------------------------------------------------------------------------- /test/cxa_bad_cast.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- cxa_bad_cast.pass.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class Base { 18 | virtual void foo() {}; 19 | }; 20 | 21 | class Derived : public Base {}; 22 | 23 | Derived &test_bad_cast(Base& b) { 24 | return dynamic_cast(b); 25 | } 26 | 27 | Base gB; 28 | 29 | void my_terminate() { exit(0); } 30 | 31 | int main () 32 | { 33 | // swap-out the terminate handler 34 | void (*default_handler)() = std::get_terminate(); 35 | std::set_terminate(my_terminate); 36 | 37 | #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS 38 | try { 39 | #endif 40 | Derived &d = test_bad_cast(gB); 41 | assert(false); 42 | ((void)d); 43 | #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS 44 | } catch (std::bad_cast) { 45 | // success 46 | return 0; 47 | } catch (...) { 48 | assert(false); 49 | } 50 | #endif 51 | 52 | // failure, restore the default terminate handler and fire 53 | std::set_terminate(default_handler); 54 | std::terminate(); 55 | } 56 | -------------------------------------------------------------------------------- /test/cxa_bad_typeid.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- cxa_bad_typeid.pass.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===------------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | class Base { 20 | virtual void foo() {}; 21 | }; 22 | 23 | class Derived : public Base {}; 24 | 25 | std::string test_bad_typeid(Derived *p) { 26 | return typeid(*p).name(); 27 | } 28 | 29 | void my_terminate() { std::cout << "A" << std::endl; exit(0); } 30 | 31 | int main () 32 | { 33 | // swap-out the terminate handler 34 | void (*default_handler)() = std::get_terminate(); 35 | std::set_terminate(my_terminate); 36 | 37 | #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS 38 | try { 39 | #endif 40 | test_bad_typeid(nullptr); 41 | assert(false); 42 | #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS 43 | } catch (std::bad_typeid) { 44 | // success 45 | return 0; 46 | } catch (...) { 47 | assert(false); 48 | } 49 | #endif 50 | 51 | // failure, restore the default terminate handler and fire 52 | std::set_terminate(default_handler); 53 | std::terminate(); 54 | } 55 | -------------------------------------------------------------------------------- /test/cxa_thread_atexit_test.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------- cxa_thread_atexit_test.cpp ---------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-threads 10 | // REQUIRES: linux 11 | 12 | #include 13 | #include 14 | 15 | static bool AtexitImplCalled = false; 16 | 17 | extern "C" int __cxa_thread_atexit_impl(void (*dtor)(void *), void *obj, 18 | void *dso_symbol) { 19 | assert(dtor == reinterpret_cast(1)); 20 | assert(obj == reinterpret_cast(2)); 21 | assert(dso_symbol == reinterpret_cast(3)); 22 | AtexitImplCalled = true; 23 | return 4; 24 | } 25 | 26 | int main() { 27 | int RV = __cxxabiv1::__cxa_thread_atexit( 28 | reinterpret_cast(1), reinterpret_cast(2), 29 | reinterpret_cast(3)); 30 | assert(RV == 4); 31 | assert(AtexitImplCalled); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /test/cxa_vec_new_overflow_PR41395.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include "cxxabi.h" 12 | #include 13 | #include 14 | 15 | void dummy_ctor(void*) { assert(false && "should not be called"); } 16 | void dummy_dtor(void*) { assert(false && "should not be called"); } 17 | 18 | void *dummy_alloc(size_t) { assert(false && "should not be called"); } 19 | void dummy_dealloc(void*) { assert(false && "should not be called"); } 20 | void dummy_dealloc_sized(void*, size_t) { assert(false && "should not be called"); } 21 | 22 | 23 | bool check_mul_overflows(size_t x, size_t y) { 24 | size_t tmp = x * y; 25 | if (tmp / x != y) 26 | return true; 27 | return false; 28 | } 29 | 30 | bool check_add_overflows(size_t x, size_t y) { 31 | size_t tmp = x + y; 32 | if (tmp < x) 33 | return true; 34 | 35 | return false; 36 | } 37 | 38 | void test_overflow_in_multiplication() { 39 | const size_t elem_count = std::size_t(1) << (sizeof(std::size_t) * 8 - 2); 40 | const size_t elem_size = 8; 41 | const size_t padding = 0; 42 | assert(check_mul_overflows(elem_count, elem_size)); 43 | 44 | try { 45 | __cxxabiv1::__cxa_vec_new(elem_count, elem_size, padding, dummy_ctor, 46 | dummy_dtor); 47 | assert(false && "allocation should fail"); 48 | } catch (std::bad_array_new_length const&) { 49 | // OK 50 | } catch (...) { 51 | assert(false && "unexpected exception"); 52 | } 53 | 54 | try { 55 | __cxxabiv1::__cxa_vec_new2(elem_count, elem_size, padding, dummy_ctor, 56 | dummy_dtor, &dummy_alloc, &dummy_dealloc); 57 | assert(false && "allocation should fail"); 58 | } catch (std::bad_array_new_length const&) { 59 | // OK 60 | } catch (...) { 61 | assert(false && "unexpected exception"); 62 | } 63 | 64 | try { 65 | __cxxabiv1::__cxa_vec_new3(elem_count, elem_size, padding, dummy_ctor, 66 | dummy_dtor, &dummy_alloc, &dummy_dealloc_sized); 67 | assert(false && "allocation should fail"); 68 | } catch (std::bad_array_new_length const&) { 69 | // OK 70 | } catch (...) { 71 | assert(false && "unexpected exception"); 72 | } 73 | } 74 | 75 | void test_overflow_in_addition() { 76 | const size_t elem_size = 4; 77 | const size_t elem_count = static_cast(-1) / 4u; 78 | #if defined(_LIBCXXABI_ARM_EHABI) 79 | const size_t padding = 8; 80 | #else 81 | const size_t padding = sizeof(std::size_t); 82 | #endif 83 | assert(!check_mul_overflows(elem_count, elem_size)); 84 | assert(check_add_overflows(elem_count * elem_size, padding)); 85 | try { 86 | __cxxabiv1::__cxa_vec_new(elem_count, elem_size, padding, dummy_ctor, 87 | dummy_dtor); 88 | assert(false && "allocation should fail"); 89 | } catch (std::bad_array_new_length const&) { 90 | // OK 91 | } catch (...) { 92 | assert(false && "unexpected exception"); 93 | } 94 | 95 | 96 | try { 97 | __cxxabiv1::__cxa_vec_new2(elem_count, elem_size, padding, dummy_ctor, 98 | dummy_dtor, &dummy_alloc, &dummy_dealloc); 99 | assert(false && "allocation should fail"); 100 | } catch (std::bad_array_new_length const&) { 101 | // OK 102 | } catch (...) { 103 | assert(false && "unexpected exception"); 104 | } 105 | 106 | try { 107 | __cxxabiv1::__cxa_vec_new3(elem_count, elem_size, padding, dummy_ctor, 108 | dummy_dtor, &dummy_alloc, &dummy_dealloc_sized); 109 | assert(false && "allocation should fail"); 110 | } catch (std::bad_array_new_length const&) { 111 | // OK 112 | } catch (...) { 113 | assert(false && "unexpected exception"); 114 | } 115 | } 116 | 117 | int main(int, char**) { 118 | test_overflow_in_multiplication(); 119 | test_overflow_in_addition(); 120 | 121 | return 0; 122 | } 123 | -------------------------------------------------------------------------------- /test/dynamic_cast.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- dynamic_cast.pass.cpp ----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | 11 | // This test explicitly tests dynamic cast with types that have inaccessible 12 | // bases. 13 | #if defined(__clang__) 14 | #pragma clang diagnostic ignored "-Winaccessible-base" 15 | #endif 16 | 17 | typedef char Pad1[43981]; 18 | typedef char Pad2[34981]; 19 | typedef char Pad3[93481]; 20 | typedef char Pad4[13489]; 21 | typedef char Pad5[81349]; 22 | typedef char Pad6[34819]; 23 | typedef char Pad7[3489]; 24 | 25 | namespace t1 26 | { 27 | 28 | // PR33425 29 | struct C3 { virtual ~C3() {} Pad1 _; }; 30 | struct C5 : protected virtual C3 { Pad2 _; }; 31 | struct C6 : virtual C5 { Pad3 _; }; 32 | struct C7 : virtual C3 { Pad4 _; }; 33 | struct C9 : C6, C7 { Pad5 _; }; 34 | 35 | C9 c9; 36 | C3 *c3 = &c9; 37 | 38 | void test() 39 | { 40 | assert(dynamic_cast(c3) == static_cast(&c9)); 41 | assert(dynamic_cast(c3) == static_cast(&c9)); 42 | assert(dynamic_cast(c3) == static_cast(&c9)); 43 | assert(dynamic_cast(c3) == static_cast(&c9)); 44 | assert(dynamic_cast(c3) == static_cast(&c9)); 45 | } 46 | 47 | } // t1 48 | 49 | namespace t2 50 | { 51 | 52 | // PR33425 53 | struct Src { virtual ~Src() {} Pad1 _; }; 54 | struct Mask : protected virtual Src { Pad2 _; }; 55 | struct Dest : Mask { Pad3 _; }; 56 | struct Root : Dest, virtual Src { Pad4 _; }; 57 | 58 | Root root; 59 | Src *src = &root; 60 | 61 | void test() 62 | { 63 | assert(dynamic_cast(src) == static_cast(&root)); 64 | assert(dynamic_cast(src) == static_cast(&root)); 65 | assert(dynamic_cast(src) == static_cast(&root)); 66 | assert(dynamic_cast(src) == static_cast(&root)); 67 | } 68 | 69 | } // t2 70 | 71 | namespace t3 72 | { 73 | 74 | // PR33487 75 | struct Class1 { virtual ~Class1() {} Pad1 _; }; 76 | struct Shared : virtual Class1 { Pad2 _; }; 77 | struct Class6 : virtual Shared { Pad3 _; }; 78 | struct Left : Class6 { Pad4 _; }; 79 | struct Right : Class6 { Pad5 _; }; 80 | struct Main : Left, Right { Pad6 _; }; 81 | 82 | Main m; 83 | Class1 *c1 = &m; 84 | 85 | void test() 86 | { 87 | assert(dynamic_cast(c1) == static_cast(&m)); 88 | assert(dynamic_cast(c1) == static_cast(&m)); 89 | assert(dynamic_cast(c1) == 0); 90 | assert(dynamic_cast(c1) == static_cast(&m)); 91 | assert(dynamic_cast(c1) == static_cast(&m)); 92 | assert(dynamic_cast(c1) == static_cast(&m)); 93 | } 94 | 95 | } // t3 96 | 97 | namespace t4 98 | { 99 | 100 | // PR33439 101 | struct C2 { virtual ~C2() {} Pad1 _; }; 102 | struct C3 { virtual ~C3() {} Pad2 _; }; 103 | struct C4 : C3 { Pad3 _; }; 104 | struct C8 : C2, virtual C4 { Pad4 _; }; 105 | struct C9 : C4, C8 { Pad5 _; }; 106 | 107 | C9 c9; 108 | C2 *c2 = &c9; 109 | 110 | void test() 111 | { 112 | assert(dynamic_cast(c2) == static_cast(&c9)); 113 | assert(dynamic_cast(c2) == 0); 114 | assert(dynamic_cast(c2) == 0); 115 | assert(dynamic_cast(c2) == static_cast(&c9)); 116 | assert(dynamic_cast(c2) == static_cast(&c9)); 117 | } 118 | 119 | } // t4 120 | 121 | namespace t5 122 | { 123 | 124 | // PR33439 125 | struct Dummy { virtual ~Dummy() {} Pad1 _; }; 126 | struct Src { virtual ~Src() {} Pad2 _; }; 127 | struct Dest : Dummy { Pad3 _; }; 128 | struct A1 : Dest { Pad4 _; }; 129 | struct A2 : Dest { Pad5 _; }; 130 | struct Root : Src, A1, A2 { Pad6 _; }; 131 | 132 | Root root; 133 | Src *src = &root; 134 | 135 | void test() 136 | { 137 | assert(dynamic_cast(src) == 0); 138 | assert(dynamic_cast(src) == static_cast(&root)); 139 | assert(dynamic_cast(src) == 0); 140 | assert(dynamic_cast(src) == static_cast(&root)); 141 | assert(dynamic_cast(src) == static_cast(&root)); 142 | } 143 | 144 | } // t5 145 | 146 | int main() 147 | { 148 | t1::test(); 149 | t2::test(); 150 | t3::test(); 151 | t4::test(); 152 | t5::test(); 153 | } 154 | -------------------------------------------------------------------------------- /test/dynamic_cast_stress.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- dynamic_cast_stress.cpp --------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03 10 | 11 | #include 12 | #include 13 | #include "support/timer.h" 14 | 15 | template 16 | struct C 17 | : public virtual C, 18 | public virtual C 19 | { 20 | virtual ~C() {} 21 | }; 22 | 23 | template 24 | struct C 25 | { 26 | virtual ~C() {} 27 | }; 28 | 29 | template 30 | struct B 31 | : public virtual C, 32 | public virtual C 33 | { 34 | }; 35 | 36 | template 37 | struct makeB; 38 | 39 | template 40 | struct makeB, Depth> 41 | : public B... 42 | { 43 | }; 44 | 45 | template 46 | struct A 47 | : public makeB::type, Depth> 48 | { 49 | }; 50 | 51 | void test() 52 | { 53 | const std::size_t Width = 10; 54 | const std::size_t Depth = 5; 55 | A a; 56 | typedef B Destination; 57 | // typedef A Destination; 58 | Destination *b = nullptr; 59 | { 60 | timer t; 61 | b = dynamic_cast((C*)&a); 62 | } 63 | assert(b != 0); 64 | } 65 | 66 | int main() 67 | { 68 | test(); 69 | } 70 | 71 | /* 72 | Timing results I'm seeing (median of 3 microseconds): 73 | 74 | libc++abi gcc's dynamic_cast 75 | B -O3 48.334 93.190 libc++abi 93% faster 76 | B -Os 58.535 94.103 libc++abi 61% faster 77 | A -O3 11.515 33.134 libc++abi 188% faster 78 | A -Os 12.631 31.553 libc++abi 150% faster 79 | 80 | */ 81 | -------------------------------------------------------------------------------- /test/exception_object_alignment.2.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | // This test checks that the compiler does not make incorrect assumptions 12 | // about the alignment of the exception (only in that specific case, of 13 | // course). 14 | // 15 | // There was a bug where Clang would emit a call to memset assuming a 16-byte 16 | // aligned exception even when back-deploying to older Darwin systems where 17 | // exceptions are 8-byte aligned, which caused a segfault on those systems. 18 | 19 | struct exception { 20 | exception() : x(0) { } 21 | virtual ~exception() { } 22 | int x; 23 | }; 24 | 25 | struct foo : exception { }; 26 | 27 | int main() { 28 | try { 29 | throw foo(); 30 | } catch (...) { 31 | 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /test/exception_object_alignment.pass.cpp: -------------------------------------------------------------------------------- 1 | //===---------------- exception_object_alignment.pass.cpp -----------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | // Check that the pointer __cxa_allocate_exception returns is aligned to the 12 | // default alignment for the target architecture. 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include <__cxxabi_config.h> 19 | 20 | struct S { 21 | int a[4]; 22 | } __attribute__((aligned)); 23 | 24 | int main() { 25 | #if !defined(_LIBCXXABI_ARM_EHABI) 26 | void *p = __cxxabiv1::__cxa_allocate_exception(16); 27 | auto i = reinterpret_cast(p); 28 | auto a = std::alignment_of::value; 29 | assert(i % a == 0); 30 | __cxxabiv1::__cxa_free_exception(p); 31 | #endif 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /test/guard_test_basic.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // UNSUPPORTED: c++98, c++03 10 | 11 | #define TESTING_CXA_GUARD 12 | #include "../src/cxa_guard_impl.h" 13 | #include 14 | 15 | using namespace __cxxabiv1; 16 | 17 | template 18 | struct Tests { 19 | private: 20 | Tests() : g{}, impl(&g) {} 21 | GuardType g; 22 | Impl impl; 23 | 24 | uint8_t first_byte() { 25 | uint8_t first; 26 | std::memcpy(&first, &g, 1); 27 | return first; 28 | } 29 | 30 | void reset() { g = {}; } 31 | 32 | public: 33 | // Test the post conditions on cxa_guard_acquire, cxa_guard_abort, and 34 | // cxa_guard_release. Specifically, that they leave the first byte with 35 | // the value 0 or 1 as specified by the ARM or Itanium specification. 36 | static void test() { 37 | Tests tests; 38 | tests.test_acquire(); 39 | tests.test_abort(); 40 | tests.test_release(); 41 | } 42 | 43 | void test_acquire() { 44 | { 45 | reset(); 46 | assert(first_byte() == 0); 47 | assert(impl.cxa_guard_acquire() == INIT_IS_PENDING); 48 | assert(first_byte() == 0); 49 | } 50 | { 51 | reset(); 52 | assert(first_byte() == 0); 53 | assert(impl.cxa_guard_acquire() == INIT_IS_PENDING); 54 | impl.cxa_guard_release(); 55 | assert(first_byte() == 1); 56 | assert(impl.cxa_guard_acquire() == INIT_IS_DONE); 57 | } 58 | } 59 | 60 | void test_release() { 61 | { 62 | reset(); 63 | assert(first_byte() == 0); 64 | assert(impl.cxa_guard_acquire() == INIT_IS_PENDING); 65 | assert(first_byte() == 0); 66 | impl.cxa_guard_release(); 67 | assert(first_byte() == 1); 68 | } 69 | } 70 | 71 | void test_abort() { 72 | { 73 | reset(); 74 | assert(first_byte() == 0); 75 | assert(impl.cxa_guard_acquire() == INIT_IS_PENDING); 76 | assert(first_byte() == 0); 77 | impl.cxa_guard_abort(); 78 | assert(first_byte() == 0); 79 | assert(impl.cxa_guard_acquire() == INIT_IS_PENDING); 80 | assert(first_byte() == 0); 81 | } 82 | } 83 | }; 84 | 85 | struct NopMutex { 86 | bool lock() { 87 | assert(!is_locked); 88 | is_locked = true; 89 | return false; 90 | } 91 | bool unlock() { 92 | assert(is_locked); 93 | is_locked = false; 94 | return false; 95 | } 96 | 97 | private: 98 | bool is_locked = false; 99 | }; 100 | NopMutex global_nop_mutex = {}; 101 | 102 | struct NopCondVar { 103 | bool broadcast() { return false; } 104 | bool wait(NopMutex&) { return false; } 105 | }; 106 | NopCondVar global_nop_cond = {}; 107 | 108 | void NopFutexWait(int*, int) { assert(false); } 109 | void NopFutexWake(int*) { assert(false); } 110 | uint32_t MockGetThreadID() { return 0; } 111 | 112 | int main() { 113 | { 114 | #if defined(_LIBCXXABI_HAS_NO_THREADS) 115 | static_assert(CurrentImplementation == Implementation::NoThreads, ""); 116 | static_assert( 117 | std::is_same::value, ""); 118 | #else 119 | static_assert(CurrentImplementation == Implementation::GlobalLock, ""); 120 | static_assert( 121 | std::is_same< 122 | SelectedImplementation, 123 | InitByteGlobalMutex::instance, 125 | GlobalStatic::instance>>::value, 126 | ""); 127 | #endif 128 | } 129 | { 130 | #if defined(__APPLE__) || defined(__linux__) 131 | assert(PlatformThreadID); 132 | #endif 133 | if (PlatformSupportsThreadID()) { 134 | assert(PlatformThreadID() != 0); 135 | assert(PlatformThreadID() == PlatformThreadID()); 136 | } 137 | } 138 | { 139 | Tests::test(); 140 | Tests::test(); 141 | } 142 | { 143 | using MutexImpl = 144 | InitByteGlobalMutex; 146 | Tests::test(); 147 | Tests::test(); 148 | } 149 | { 150 | using FutexImpl = 151 | InitByteFutex<&NopFutexWait, &NopFutexWake, &MockGetThreadID>; 152 | Tests::test(); 153 | Tests::test(); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /test/inherited_exception.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------- inherited_exception.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | // 9 | // This test case checks specifically the cases under C++ ABI 15.3.1, and 15.3.2 10 | // 11 | // C++ ABI 15.3: 12 | // A handler is a match for an exception object of type E if 13 | // / * The handler is of type cv T or cv T& and E and T are the same type \ 14 | // | (ignoring the top-level cv-qualifiers), or | 15 | // | * the handler is of type cv T or cv T& and T is an unambiguous base | 16 | // \ class of E, or / 17 | // * the handler is of type cv1 T* cv2 and E is a pointer type that can 18 | // be converted to the type of the handler by either or both of 19 | // o a standard pointer conversion (4.10 [conv.ptr]) not involving 20 | // conversions to private or protected or ambiguous classes 21 | // o a qualification conversion 22 | // * the handler is a pointer or pointer to member type and E is 23 | // std::nullptr_t 24 | // 25 | //===----------------------------------------------------------------------===// 26 | 27 | // UNSUPPORTED: libcxxabi-no-exceptions 28 | 29 | // Clang emits warnings about exceptions of type 'Child' being caught by 30 | // an earlier handler of type 'Base'. Congrats clang, you've just 31 | // diagnosed the behavior under test. 32 | #if defined(__clang__) 33 | #pragma clang diagnostic ignored "-Wexceptions" 34 | #endif 35 | 36 | #include 37 | 38 | struct Base { 39 | int b1; 40 | }; 41 | 42 | struct Base2 { 43 | int b2; 44 | }; 45 | 46 | struct Child : public Base, public Base2 { 47 | int c; 48 | }; 49 | 50 | void f1() { 51 | Child child; 52 | child.b1 = 10; 53 | child.b2 = 11; 54 | child.c = 12; 55 | throw child; 56 | } 57 | 58 | void f2() { 59 | Child child; 60 | child.b1 = 10; 61 | child.b2 = 11; 62 | child.c = 12; 63 | throw static_cast(child); 64 | } 65 | 66 | void f3() { 67 | static Child child; 68 | child.b1 = 10; 69 | child.b2 = 11; 70 | child.c = 12; 71 | throw static_cast(&child); 72 | } 73 | 74 | int main() 75 | { 76 | try 77 | { 78 | f1(); 79 | assert(false); 80 | } 81 | catch (const Child& c) 82 | { 83 | assert(true); 84 | } 85 | catch (const Base& b) 86 | { 87 | assert(false); 88 | } 89 | catch (...) 90 | { 91 | assert(false); 92 | } 93 | 94 | try 95 | { 96 | f1(); 97 | assert(false); 98 | } 99 | catch (const Base& c) 100 | { 101 | assert(true); 102 | } 103 | catch (const Child& b) 104 | { 105 | assert(false); 106 | } 107 | catch (...) 108 | { 109 | assert(false); 110 | } 111 | 112 | try 113 | { 114 | f1(); 115 | assert(false); 116 | } 117 | catch (const Base2& c) 118 | { 119 | assert(true); 120 | } 121 | catch (const Child& b) 122 | { 123 | assert(false); 124 | } 125 | catch (...) 126 | { 127 | assert(false); 128 | } 129 | 130 | try 131 | { 132 | f2(); 133 | assert(false); 134 | } 135 | catch (const Child& c) 136 | { 137 | assert(false); 138 | } 139 | catch (const Base& b) 140 | { 141 | assert(false); 142 | } 143 | catch (const Base2& b) 144 | { 145 | assert(true); 146 | } 147 | catch (...) 148 | { 149 | assert(false); 150 | } 151 | 152 | try 153 | { 154 | f3(); 155 | assert(false); 156 | } 157 | catch (const Base* c) 158 | { 159 | assert(false); 160 | } 161 | catch (const Child* b) 162 | { 163 | assert(false); 164 | } 165 | catch (const Base2* c) 166 | { 167 | assert(true); 168 | } 169 | catch (...) 170 | { 171 | assert(false); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /test/libcxxabi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llvm-mirror/libcxxabi/ce3db128f9e4d6d19d1cdbe39bb45fcc64a5adb0/test/libcxxabi/__init__.py -------------------------------------------------------------------------------- /test/libcxxabi/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llvm-mirror/libcxxabi/ce3db128f9e4d6d19d1cdbe39bb45fcc64a5adb0/test/libcxxabi/test/__init__.py -------------------------------------------------------------------------------- /test/libcxxabi/test/config.py: -------------------------------------------------------------------------------- 1 | #===----------------------------------------------------------------------===## 2 | # 3 | # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | # See https://llvm.org/LICENSE.txt for license information. 5 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | # 7 | #===----------------------------------------------------------------------===## 8 | import os 9 | import sys 10 | 11 | from libcxx.test.config import Configuration as LibcxxConfiguration 12 | from libcxx.test.config import intMacroValue 13 | 14 | 15 | class Configuration(LibcxxConfiguration): 16 | # pylint: disable=redefined-outer-name 17 | def __init__(self, lit_config, config): 18 | super(Configuration, self).__init__(lit_config, config) 19 | self.libcxxabi_src_root = None 20 | self.libcxxabi_obj_root = None 21 | self.abi_library_path = None 22 | self.libcxx_src_root = None 23 | 24 | def configure_src_root(self): 25 | self.libcxxabi_src_root = self.get_lit_conf( 26 | 'libcxxabi_src_root', 27 | os.path.dirname(self.config.test_source_root)) 28 | self.libcxx_src_root = self.get_lit_conf( 29 | 'libcxx_src_root', 30 | os.path.join(self.libcxxabi_src_root, '/../libcxx')) 31 | 32 | def configure_obj_root(self): 33 | self.libcxxabi_obj_root = self.get_lit_conf('libcxxabi_obj_root') 34 | super(Configuration, self).configure_obj_root() 35 | 36 | def has_cpp_feature(self, feature, required_value): 37 | return intMacroValue(self.cxx.dumpMacros().get('__cpp_' + feature, '0')) >= required_value 38 | 39 | def configure_features(self): 40 | super(Configuration, self).configure_features() 41 | if not self.get_lit_bool('enable_exceptions', True): 42 | self.config.available_features.add('libcxxabi-no-exceptions') 43 | if not self.has_cpp_feature('noexcept_function_type', 201510): 44 | self.config.available_features.add('libcxxabi-no-noexcept-function-type') 45 | # test_exception_storage_nodynmem.pass.cpp fails under this specific configuration 46 | if self.get_lit_bool('cxx_ext_threads', False) and self.get_lit_bool('libcxxabi_shared', False): 47 | self.config.available_features.add('libcxxabi-shared-externally-threaded') 48 | if not self.get_lit_bool('llvm_unwinder', False): 49 | self.config.available_features.add('libcxxabi-has-system-unwinder') 50 | 51 | def configure_compile_flags(self): 52 | self.cxx.compile_flags += [ 53 | '-DLIBCXXABI_NO_TIMER', 54 | '-D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS', 55 | ] 56 | if self.get_lit_bool('enable_exceptions', True): 57 | self.cxx.compile_flags += ['-funwind-tables'] 58 | else: 59 | self.cxx.compile_flags += ['-fno-exceptions', '-DLIBCXXABI_HAS_NO_EXCEPTIONS'] 60 | if not self.get_lit_bool('enable_threads', True): 61 | self.cxx.compile_flags += ['-D_LIBCXXABI_HAS_NO_THREADS'] 62 | self.config.available_features.add('libcxxabi-no-threads') 63 | super(Configuration, self).configure_compile_flags() 64 | 65 | def configure_compile_flags_header_includes(self): 66 | self.configure_config_site_header() 67 | cxx_headers = self.get_lit_conf( 68 | 'cxx_headers', 69 | os.path.join(self.libcxx_src_root, '/include')) 70 | if cxx_headers == '': 71 | self.lit_config.note('using the systems c++ headers') 72 | else: 73 | self.cxx.compile_flags += ['-nostdinc++'] 74 | if not os.path.isdir(cxx_headers): 75 | self.lit_config.fatal("cxx_headers='%s' is not a directory." 76 | % cxx_headers) 77 | self.cxx.compile_flags += ['-I' + cxx_headers] 78 | 79 | libcxxabi_headers = self.get_lit_conf( 80 | 'libcxxabi_headers', 81 | os.path.join(self.libcxxabi_src_root, 'include')) 82 | if not os.path.isdir(libcxxabi_headers): 83 | self.lit_config.fatal("libcxxabi_headers='%s' is not a directory." 84 | % libcxxabi_headers) 85 | self.cxx.compile_flags += ['-I' + libcxxabi_headers] 86 | 87 | libunwind_headers = self.get_lit_conf('libunwind_headers', None) 88 | if self.get_lit_bool('llvm_unwinder', False) and libunwind_headers: 89 | if not os.path.isdir(libunwind_headers): 90 | self.lit_config.fatal("libunwind_headers='%s' is not a directory." 91 | % libunwind_headers) 92 | self.cxx.compile_flags += ['-I' + libunwind_headers] 93 | 94 | def configure_compile_flags_exceptions(self): 95 | pass 96 | 97 | def configure_compile_flags_rtti(self): 98 | pass 99 | -------------------------------------------------------------------------------- /test/lit.cfg: -------------------------------------------------------------------------------- 1 | # -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79: 2 | 3 | # Configuration file for the 'lit' test runner. 4 | 5 | 6 | import os 7 | import site 8 | 9 | site.addsitedir(os.path.dirname(__file__)) 10 | 11 | 12 | # Tell pylint that we know config and lit_config exist somewhere. 13 | if 'PYLINT_IMPORT' in os.environ: 14 | config = object() 15 | lit_config = object() 16 | 17 | # name: The name of this test suite. 18 | config.name = 'libc++abi' 19 | 20 | # suffixes: A list of file extensions to treat as test files. 21 | config.suffixes = ['.cpp', '.s'] 22 | 23 | # test_source_root: The root path where tests are located. 24 | config.test_source_root = os.path.dirname(__file__) 25 | 26 | # Infer the libcxx_test_source_root for configuration import. 27 | # If libcxx_source_root isn't specified in the config, assume that the libcxx 28 | # and libcxxabi source directories are sibling directories. 29 | libcxx_src_root = getattr(config, 'libcxx_src_root', None) 30 | if not libcxx_src_root: 31 | libcxx_src_root = os.path.join(config.test_source_root, '../../libcxx') 32 | libcxx_test_src_root = os.path.join(libcxx_src_root, 'utils') 33 | if os.path.isfile(os.path.join(libcxx_test_src_root, 'libcxx', '__init__.py')): 34 | site.addsitedir(libcxx_test_src_root) 35 | else: 36 | lit_config.fatal('Could not find libcxx test directory for test imports' 37 | ' in: %s' % libcxx_test_src_root) 38 | 39 | # Infer the test_exec_root from the libcxx_object root. 40 | obj_root = getattr(config, 'libcxxabi_obj_root', None) 41 | 42 | # Check that the test exec root is known. 43 | if obj_root is None: 44 | import libcxx.test.config 45 | libcxx.test.config.loadSiteConfig( 46 | lit_config, config, 'libcxxabi_site_config', 'LIBCXXABI_SITE_CONFIG') 47 | obj_root = getattr(config, 'libcxxabi_obj_root', None) 48 | if obj_root is None: 49 | import tempfile 50 | obj_root = tempfile.mkdtemp(prefix='libcxxabi-testsuite-') 51 | lit_config.warning('Creating temporary directory for object root: %s' % 52 | obj_root) 53 | 54 | config.test_exec_root = os.path.join(obj_root, 'test') 55 | 56 | cfg_variant = getattr(config, 'configuration_variant', 'libcxxabi') 57 | if cfg_variant: 58 | lit_config.note('Using configuration variant: %s' % cfg_variant) 59 | 60 | # Load the Configuration class from the module name .test.config. 61 | config_module_name = '.'.join([cfg_variant, 'test', 'config']) 62 | config_module = __import__(config_module_name, fromlist=['Configuration']) 63 | 64 | configuration = config_module.Configuration(lit_config, config) 65 | configuration.configure() 66 | configuration.print_config_info() 67 | config.test_format = configuration.get_test_format() 68 | -------------------------------------------------------------------------------- /test/lit.site.cfg.in: -------------------------------------------------------------------------------- 1 | @AUTO_GEN_COMMENT@ 2 | config.cxx_under_test = "@LIBCXXABI_COMPILER@" 3 | config.project_obj_root = "@CMAKE_BINARY_DIR@" 4 | config.libcxxabi_src_root = "@LIBCXXABI_SOURCE_DIR@" 5 | config.libcxxabi_obj_root = "@LIBCXXABI_BINARY_DIR@" 6 | config.abi_library_path = "@LIBCXXABI_LIBRARY_DIR@" 7 | config.libcxx_src_root = "@LIBCXXABI_LIBCXX_PATH@" 8 | config.cxx_headers = "@LIBCXXABI_LIBCXX_INCLUDES@" 9 | config.libunwind_headers = "@LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL@" 10 | config.cxx_library_root = "@LIBCXXABI_LIBCXX_LIBRARY_PATH@" 11 | config.llvm_unwinder = @LIBCXXABI_USE_LLVM_UNWINDER@ 12 | config.builtins_library = "@LIBCXXABI_BUILTINS_LIBRARY@" 13 | config.enable_threads = @LIBCXXABI_ENABLE_THREADS@ 14 | config.use_sanitizer = "@LLVM_USE_SANITIZER@" 15 | config.sanitizer_library = "@LIBCXXABI_SANITIZER_LIBRARY@" 16 | config.enable_32bit = @LIBCXXABI_BUILD_32_BITS@ 17 | config.target_info = "@LIBCXXABI_TARGET_INFO@" 18 | config.executor = "@LIBCXXABI_EXECUTOR@" 19 | config.libcxxabi_shared = @LIBCXXABI_ENABLE_SHARED@ 20 | config.enable_shared = @LIBCXX_ENABLE_SHARED@ 21 | config.enable_exceptions = @LIBCXXABI_ENABLE_EXCEPTIONS@ 22 | config.host_triple = "@LLVM_HOST_TRIPLE@" 23 | config.target_triple = "@TARGET_TRIPLE@" 24 | config.use_target = bool("@LIBCXXABI_TARGET_TRIPLE@") 25 | config.sysroot = "@LIBCXXABI_SYSROOT@" 26 | config.gcc_toolchain = "@LIBCXXABI_GCC_TOOLCHAIN@" 27 | config.cxx_ext_threads = @LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY@ 28 | 29 | config.pstl_src_root = "@ParallelSTL_SOURCE_DIR@" if @LIBCXX_ENABLE_PARALLEL_ALGORITHMS@ else None 30 | config.pstl_obj_root = "@ParallelSTL_BINARY_DIR@" if @LIBCXX_ENABLE_PARALLEL_ALGORITHMS@ else None 31 | 32 | # Let the main config do the real work. 33 | lit_config.load_config(config, "@LIBCXXABI_SOURCE_DIR@/test/lit.cfg") 34 | -------------------------------------------------------------------------------- /test/native/arm-linux-eabi/lit.local.cfg: -------------------------------------------------------------------------------- 1 | def is_arm_linux_eabi(triple): 2 | return ('arm' in triple) and ('linux' in triple) and ('eabi' in triple) 3 | 4 | is_native = config.root.host_triple == config.root.target_triple 5 | if not is_native or not is_arm_linux_eabi(config.root.host_triple): 6 | config.unsupported = True 7 | -------------------------------------------------------------------------------- /test/native/arm-linux-eabi/ttype-encoding-00.pass.sh.s: -------------------------------------------------------------------------------- 1 | @ RUN: %cxx %flags %link_flags %s -o %t.exe 2 | @ RUN: %t.exe 3 | @ UNSUPPORTED: libcxxabi-no-exceptions 4 | 5 | @ PURPOSE: Check that 0x00 is a valid value for ttype encoding. LLVM and 6 | @ GCC 4.6 are generating 0x00 as ttype encoding. libc++abi should provide 7 | @ legacy support. 8 | 9 | @ NOTE: 10 | @ 11 | @ This file is generated from the following C++ source code: 12 | @ 13 | @ ``` 14 | @ int main() { 15 | @ try { 16 | @ throw 5; 17 | @ } catch (int i) { 18 | @ if (i != 5) 19 | @ abort(); 20 | @ return 0; 21 | @ } 22 | @ } 23 | @ ``` 24 | 25 | .syntax unified 26 | 27 | .text 28 | .globl main 29 | .p2align 2 30 | .type main,%function 31 | main: @ @main 32 | .Lfunc_begin0: 33 | .fnstart 34 | @ BB#0: @ %entry 35 | .save {r11, lr} 36 | push {r11, lr} 37 | .setfp r11, sp 38 | mov r11, sp 39 | mov r0, #4 40 | bl __cxa_allocate_exception 41 | mov r1, #5 42 | str r1, [r0] 43 | .Ltmp0: 44 | ldr r1, .LCPI0_0 45 | mov r2, #0 46 | bl __cxa_throw 47 | .Ltmp1: 48 | 49 | @ BB#2: @ %lpad 50 | .Ltmp2: 51 | bl __cxa_begin_catch 52 | ldr r0, [r0] 53 | cmp r0, #5 54 | bne .LBB0_4 55 | @ BB#3: @ %if.end 56 | bl __cxa_end_catch 57 | mov r0, #0 58 | pop {r11, lr} 59 | bx lr 60 | .LBB0_4: @ %if.then 61 | bl abort 62 | .p2align 2 63 | @ BB#5: 64 | .LCPI0_0: 65 | .long _ZTIi 66 | .Lfunc_end0: 67 | 68 | .size main, .Lfunc_end0-main 69 | .globl __gxx_personality_v0 70 | .personality __gxx_personality_v0 71 | .handlerdata 72 | .p2align 2 73 | GCC_except_table0: 74 | .Lexception0: 75 | .byte 255 @ @LPStart Encoding = omit 76 | .byte 0 @ @TType Encoding = absptr 77 | .asciz "\257\200" @ @TType base offset 78 | .byte 3 @ Call site Encoding = udata4 79 | .byte 39 @ Call site table length 80 | .long .Lfunc_begin0-.Lfunc_begin0 @ >> Call Site 1 << 81 | .long .Ltmp0-.Lfunc_begin0 @ Call between .Lfunc_begin0 and .Ltmp0 82 | .long 0 @ has no landing pad 83 | .byte 0 @ On action: cleanup 84 | .long .Ltmp0-.Lfunc_begin0 @ >> Call Site 2 << 85 | .long .Ltmp1-.Ltmp0 @ Call between .Ltmp0 and .Ltmp1 86 | .long .Ltmp2-.Lfunc_begin0 @ jumps to .Ltmp2 87 | .byte 1 @ On action: 1 88 | .long .Ltmp1-.Lfunc_begin0 @ >> Call Site 3 << 89 | .long .Lfunc_end0-.Ltmp1 @ Call between .Ltmp1 and .Lfunc_end0 90 | .long 0 @ has no landing pad 91 | .byte 0 @ On action: cleanup 92 | .byte 1 @ >> Action Record 1 << 93 | @ Catch TypeInfo 1 94 | .byte 0 @ No further actions 95 | @ >> Catch TypeInfos << 96 | .long _ZTIi(target2) @ TypeInfo 1 97 | .p2align 2 98 | .fnend 99 | -------------------------------------------------------------------------------- /test/native/arm-linux-eabi/ttype-encoding-90.pass.sh.s: -------------------------------------------------------------------------------- 1 | @ RUN: %cxx %flags %link_flags %s -o %t.exe 2 | @ RUN: %t.exe 3 | @ UNSUPPORTED: libcxxabi-no-exceptions 4 | 5 | @ PURPOSE: Check that 0x90 is a valid value for ttype encoding. 6 | 7 | @ NOTE: 8 | @ 9 | @ This file is generated from the following C++ source code and then change the 10 | @ `TType Encoding` to 0x90. 11 | @ 12 | @ ``` 13 | @ int main() { 14 | @ try { 15 | @ throw 5; 16 | @ } catch (int i) { 17 | @ if (i != 5) 18 | @ abort(); 19 | @ return 0; 20 | @ } 21 | @ } 22 | @ ``` 23 | 24 | .syntax unified 25 | 26 | .text 27 | .globl main 28 | .p2align 2 29 | .type main,%function 30 | main: @ @main 31 | .Lfunc_begin0: 32 | .fnstart 33 | @ BB#0: @ %entry 34 | .save {r11, lr} 35 | push {r11, lr} 36 | .setfp r11, sp 37 | mov r11, sp 38 | mov r0, #4 39 | bl __cxa_allocate_exception 40 | mov r1, #5 41 | str r1, [r0] 42 | .Ltmp0: 43 | ldr r1, .LCPI0_0 44 | mov r2, #0 45 | bl __cxa_throw 46 | .Ltmp1: 47 | 48 | @ BB#2: @ %lpad 49 | .Ltmp2: 50 | bl __cxa_begin_catch 51 | ldr r0, [r0] 52 | cmp r0, #5 53 | bne .LBB0_4 54 | @ BB#3: @ %if.end 55 | bl __cxa_end_catch 56 | mov r0, #0 57 | pop {r11, lr} 58 | bx lr 59 | .LBB0_4: @ %if.then 60 | bl abort 61 | .p2align 2 62 | @ BB#5: 63 | .LCPI0_0: 64 | .long _ZTIi 65 | .Lfunc_end0: 66 | 67 | .size main, .Lfunc_end0-main 68 | .globl __gxx_personality_v0 69 | .personality __gxx_personality_v0 70 | .handlerdata 71 | .p2align 2 72 | GCC_except_table0: 73 | .Lexception0: 74 | .byte 255 @ @LPStart Encoding = omit 75 | .byte 0x90 @ @TType Encoding = indirect | pcrel 76 | .asciz "\257\200" @ @TType base offset 77 | .byte 3 @ Call site Encoding = udata4 78 | .byte 39 @ Call site table length 79 | .long .Lfunc_begin0-.Lfunc_begin0 @ >> Call Site 1 << 80 | .long .Ltmp0-.Lfunc_begin0 @ Call between .Lfunc_begin0 and .Ltmp0 81 | .long 0 @ has no landing pad 82 | .byte 0 @ On action: cleanup 83 | .long .Ltmp0-.Lfunc_begin0 @ >> Call Site 2 << 84 | .long .Ltmp1-.Ltmp0 @ Call between .Ltmp0 and .Ltmp1 85 | .long .Ltmp2-.Lfunc_begin0 @ jumps to .Ltmp2 86 | .byte 1 @ On action: 1 87 | .long .Ltmp1-.Lfunc_begin0 @ >> Call Site 3 << 88 | .long .Lfunc_end0-.Ltmp1 @ Call between .Ltmp1 and .Lfunc_end0 89 | .long 0 @ has no landing pad 90 | .byte 0 @ On action: cleanup 91 | .byte 1 @ >> Action Record 1 << 92 | @ Catch TypeInfo 1 93 | .byte 0 @ No further actions 94 | @ >> Catch TypeInfos << 95 | .long _ZTIi(target2) @ TypeInfo 1 96 | .p2align 2 97 | .fnend 98 | -------------------------------------------------------------------------------- /test/noexception1.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- noexception1.pass.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03 10 | // REQUIRES: libcxxabi-no-exceptions 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // namespace __cxxabiv1 { 18 | // void __cxa_increment_exception_refcount(void *thrown_object) throw(); 19 | // } 20 | 21 | unsigned gCounter = 0; 22 | 23 | void my_terminate() { exit(0); } 24 | 25 | int main () 26 | { 27 | // should not call std::terminate() 28 | __cxxabiv1::__cxa_increment_exception_refcount(nullptr); 29 | 30 | std::set_terminate(my_terminate); 31 | 32 | // should call std::terminate() 33 | __cxxabiv1::__cxa_increment_exception_refcount((void*) &gCounter); 34 | assert(false); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/noexception2.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- noexception2.pass.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03 10 | // REQUIRES: libcxxabi-no-exceptions 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // namespace __cxxabiv1 { 18 | // void __cxa_decrement_exception_refcount(void *thrown_object) throw(); 19 | // } 20 | 21 | unsigned gCounter = 0; 22 | 23 | void my_terminate() { exit(0); } 24 | 25 | int main () 26 | { 27 | // should not call std::terminate() 28 | __cxxabiv1::__cxa_decrement_exception_refcount(nullptr); 29 | 30 | std::set_terminate(my_terminate); 31 | 32 | // should call std::terminate() 33 | __cxxabiv1::__cxa_decrement_exception_refcount((void*) &gCounter); 34 | assert(false); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/noexception3.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- noexception3.pass.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03 10 | // REQUIRES: libcxxabi-no-exceptions 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // namespace __cxxabiv1 { 18 | // void __cxa_rethrow_primary_exception(void* thrown_object); 19 | // } 20 | 21 | unsigned gCounter = 0; 22 | 23 | void my_terminate() { exit(0); } 24 | 25 | int main () 26 | { 27 | // should not call std::terminate() 28 | __cxxabiv1::__cxa_rethrow_primary_exception(nullptr); 29 | 30 | std::set_terminate(my_terminate); 31 | 32 | // should call std::terminate() 33 | __cxxabiv1::__cxa_rethrow_primary_exception((void*) &gCounter); 34 | assert(false); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/noexception4.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- noexception4.pass.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // REQUIRES: libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // namespace __cxxabiv1 { 16 | // void *__cxa_current_primary_exception() throw(); 17 | // extern bool __cxa_uncaught_exception () throw(); 18 | // extern unsigned int __cxa_uncaught_exceptions() throw(); 19 | // } 20 | 21 | int main () 22 | { 23 | // Trivially 24 | assert(nullptr == __cxxabiv1::__cxa_current_primary_exception()); 25 | assert(!__cxxabiv1::__cxa_uncaught_exception()); 26 | assert(0 == __cxxabiv1::__cxa_uncaught_exceptions()); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/support/timer.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===//// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===//// 8 | 9 | #ifndef TIMER_H 10 | #define TIMER_H 11 | 12 | // Define LIBCXXABI_NO_TIMER to disable testing with a timer. 13 | #ifndef LIBCXXABI_NO_TIMER 14 | 15 | #include 16 | #include 17 | 18 | class timer 19 | { 20 | typedef std::chrono::high_resolution_clock Clock; 21 | typedef Clock::time_point TimePoint; 22 | typedef std::chrono::microseconds MicroSeconds; 23 | public: 24 | timer() : m_start(Clock::now()) {} 25 | 26 | timer(timer const &) = delete; 27 | timer & operator=(timer const &) = delete; 28 | 29 | ~timer() 30 | { 31 | using std::chrono::duration_cast; 32 | TimePoint end = Clock::now(); 33 | MicroSeconds us = duration_cast(end - m_start); 34 | std::cout << us.count() << " microseconds\n"; 35 | } 36 | 37 | private: 38 | TimePoint m_start; 39 | }; 40 | 41 | #else /* LIBCXXABI_NO_TIMER */ 42 | 43 | class timer 44 | { 45 | public: 46 | timer() {} 47 | timer(timer const &) = delete; 48 | timer & operator=(timer const &) = delete; 49 | ~timer() {} 50 | }; 51 | 52 | #endif /* LIBCXXABI_NO_TIMER */ 53 | 54 | #endif /* TIMER_H */ 55 | -------------------------------------------------------------------------------- /test/test_aux_runtime.pass.cpp: -------------------------------------------------------------------------------- 1 | //===-------------------------- test_aux_runtime.cpp ----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | 14 | // Test taken from 5.2.8.2 15 | // When typeid is applied to a glvalue expression whose type is a polymorphic 16 | // class type, (10.3), the result refers to a std::type_info object 17 | // representing the type of the most derived object (1.8) (that is, the 18 | // dynamic type) to which the glvalue refers. If the glvalue expression is 19 | // obtained by applying the unary * operator to a pointer(68) and the pointer 20 | // is a null pointer value (4.10), the typeid expression throws the 21 | // std::bad_typeid exception (18.7.3). 22 | // 23 | // 68) If p is an expression of pointer type, then *p, (*p), *(p), 24 | // ((*p)), *((p)), and so on all meet this requirement. 25 | bool bad_typeid_test () { 26 | class A { virtual void f() {}}; 27 | class B { virtual void g() {}}; 28 | 29 | B *bp = NULL; 30 | try {bool b = typeid(*bp) == typeid (A); ((void)b); } 31 | catch ( const std::bad_typeid &) { return true; } 32 | return false; 33 | } 34 | 35 | 36 | // The value of a failed cast to pointer type is the null pointer value of 37 | // the required result type. A failed cast to reference type throws 38 | // std::bad_cast (18.7.2). 39 | bool bad_cast_test () { 40 | class A { virtual void f() {}}; 41 | class B { virtual void g() {}}; 42 | class D : public virtual A, private B {}; 43 | 44 | D d; 45 | B *bp = (B*)&d; // cast needed to break protection 46 | try { D &dr = dynamic_cast (*bp); ((void)dr); } 47 | catch ( const std::bad_cast & ) { return true; } 48 | return false; 49 | } 50 | 51 | int main ( ) { 52 | int ret_val = 0; 53 | 54 | if ( !bad_typeid_test ()) { 55 | std::cerr << "TypeID test failed!" << std::endl; 56 | ret_val = 1; 57 | } 58 | 59 | if ( !bad_cast_test ()) { 60 | std::cerr << "Bad cast test failed!" << std::endl; 61 | ret_val = 1; 62 | } 63 | 64 | return ret_val; 65 | } 66 | -------------------------------------------------------------------------------- /test/test_aux_runtime_op_array_new.pass.cpp: -------------------------------------------------------------------------------- 1 | //===-------------------------- test_aux_runtime_op_array_new.cpp ---------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | 14 | // If the expression passed to operator new[] would result in an overflow, the 15 | // allocation function is not called, and a std::bad_array_new_length exception 16 | // is thrown instead (5.3.4p7). 17 | bool bad_array_new_length_test() { 18 | try { 19 | // We test this directly because Clang does not currently codegen the 20 | // correct call to __cxa_bad_array_new_length, so this test would result 21 | // in passing -1 to ::operator new[], which would then throw a 22 | // std::bad_alloc, causing the test to fail. 23 | __cxxabiv1::__cxa_throw_bad_array_new_length(); 24 | } catch ( const std::bad_array_new_length &banl ) { 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | int main() { 31 | int ret_val = 0; 32 | 33 | if ( !bad_array_new_length_test ()) { 34 | std::cerr << "Bad array new length test failed!" << std::endl; 35 | ret_val = 1; 36 | } 37 | 38 | return ret_val; 39 | } 40 | -------------------------------------------------------------------------------- /test/test_exception_address_alignment.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | // UNSUPPORTED: c++98, c++03 11 | 12 | // The system unwind.h on OS X provides an incorrectly aligned _Unwind_Exception 13 | // type. That causes these tests to fail. This XFAIL is my best attempt at 14 | // working around this failure. 15 | // XFAIL: darwin && libcxxabi-has-system-unwinder 16 | 17 | // Test that the address of the exception object is properly aligned as required 18 | // by the relevant ABI 19 | 20 | #include 21 | #include 22 | #include <__cxxabi_config.h> 23 | 24 | #include 25 | 26 | struct __attribute__((aligned)) AlignedType {}; 27 | 28 | // EHABI : 8-byte aligned 29 | // Itanium: Largest supported alignment for the system 30 | #if defined(_LIBCXXABI_ARM_EHABI) 31 | # define EXPECTED_ALIGNMENT 8 32 | #else 33 | # define EXPECTED_ALIGNMENT alignof(AlignedType) 34 | #endif 35 | 36 | static_assert(alignof(_Unwind_Exception) == EXPECTED_ALIGNMENT, 37 | "_Unwind_Exception is incorrectly aligned. This test is expected to fail"); 38 | 39 | struct MinAligned { }; 40 | static_assert(alignof(MinAligned) == 1 && sizeof(MinAligned) == 1, ""); 41 | 42 | int main() { 43 | for (int i=0; i < 10; ++i) { 44 | try { 45 | throw MinAligned{}; 46 | } catch (MinAligned const& ref) { 47 | assert(reinterpret_cast(&ref) % EXPECTED_ALIGNMENT == 0); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/test_exception_storage.pass.cpp: -------------------------------------------------------------------------------- 1 | //===-------------------- test_exception_storage.cpp ----------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include 10 | #include 11 | #include 12 | #include <__threading_support> 13 | #include 14 | 15 | #include "../src/cxa_exception.h" 16 | 17 | typedef __cxxabiv1::__cxa_eh_globals globals_t ; 18 | 19 | void *thread_code (void *parm) { 20 | size_t *result = (size_t *) parm; 21 | globals_t *glob1, *glob2; 22 | 23 | glob1 = __cxxabiv1::__cxa_get_globals (); 24 | if ( NULL == glob1 ) 25 | std::cerr << "Got null result from __cxa_get_globals" << std::endl; 26 | 27 | glob2 = __cxxabiv1::__cxa_get_globals_fast (); 28 | if ( glob1 != glob2 ) 29 | std::cerr << "Got different globals!" << std::endl; 30 | 31 | *result = (size_t) glob1; 32 | sleep ( 1 ); 33 | return parm; 34 | } 35 | 36 | #ifndef _LIBCXXABI_HAS_NO_THREADS 37 | #define NUMTHREADS 10 38 | size_t thread_globals [ NUMTHREADS ] = { 0 }; 39 | std::__libcpp_thread_t threads [ NUMTHREADS ]; 40 | #endif 41 | 42 | int main () { 43 | int retVal = 0; 44 | 45 | #ifndef _LIBCXXABI_HAS_NO_THREADS 46 | // Make the threads, let them run, and wait for them to finish 47 | for ( int i = 0; i < NUMTHREADS; ++i ) 48 | std::__libcpp_thread_create ( threads + i, thread_code, (void *) (thread_globals + i)); 49 | for ( int i = 0; i < NUMTHREADS; ++i ) 50 | std::__libcpp_thread_join ( &threads [ i ] ); 51 | 52 | for ( int i = 0; i < NUMTHREADS; ++i ) 53 | if ( 0 == thread_globals [ i ] ) { 54 | std::cerr << "Thread #" << i << " had a zero global" << std::endl; 55 | retVal = 1; 56 | } 57 | 58 | std::sort ( thread_globals, thread_globals + NUMTHREADS ); 59 | for ( int i = 1; i < NUMTHREADS; ++i ) 60 | if ( thread_globals [ i - 1 ] == thread_globals [ i ] ) { 61 | std::cerr << "Duplicate thread globals (" << i-1 << " and " << i << ")" << std::endl; 62 | retVal = 2; 63 | } 64 | #else // _LIBCXXABI_HAS_NO_THREADS 65 | size_t thread_globals; 66 | // Check that __cxa_get_globals() is not NULL. 67 | if (thread_code(&thread_globals) == 0) { 68 | retVal = 1; 69 | } 70 | #endif // !_LIBCXXABI_HAS_NO_THREADS 71 | return retVal; 72 | } 73 | -------------------------------------------------------------------------------- /test/test_guard.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------- test_guard.cpp -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | #include "cxxabi.h" 10 | 11 | #include 12 | 13 | #ifndef _LIBCXXABI_HAS_NO_THREADS 14 | #include 15 | #endif 16 | 17 | // Ensure that we initialize each variable once and only once. 18 | namespace test1 { 19 | static int run_count = 0; 20 | int increment() { 21 | ++run_count; 22 | return 0; 23 | } 24 | void helper() { 25 | static int a = increment(); 26 | ((void)a); 27 | } 28 | void test() { 29 | static int a = increment(); ((void)a); 30 | assert(run_count == 1); 31 | static int b = increment(); ((void)b); 32 | assert(run_count == 2); 33 | helper(); 34 | assert(run_count == 3); 35 | helper(); 36 | assert(run_count == 3); 37 | } 38 | } 39 | 40 | // When initialization fails, ensure that we try to initialize it again next 41 | // time. 42 | namespace test2 { 43 | #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS 44 | static int run_count = 0; 45 | int increment() { 46 | ++run_count; 47 | throw 0; 48 | } 49 | void helper() { 50 | try { 51 | static int a = increment(); 52 | assert(false); 53 | ((void)a); 54 | } catch (...) {} 55 | } 56 | void test() { 57 | helper(); 58 | assert(run_count == 1); 59 | helper(); 60 | assert(run_count == 2); 61 | } 62 | #else 63 | void test() {} 64 | #endif 65 | } 66 | 67 | // Check that we can initialize a second value while initializing a first. 68 | namespace test3 { 69 | int zero() { 70 | return 0; 71 | } 72 | 73 | int one() { 74 | static int b = zero(); ((void)b); 75 | return 0; 76 | } 77 | 78 | void test() { 79 | static int a = one(); ((void)a); 80 | } 81 | } 82 | 83 | #ifndef _LIBCXXABI_HAS_NO_THREADS 84 | // A simple thread test of two threads racing to initialize a variable. This 85 | // isn't guaranteed to catch any particular threading problems. 86 | namespace test4 { 87 | static int run_count = 0; 88 | int increment() { 89 | ++run_count; 90 | return 0; 91 | } 92 | 93 | void helper() { 94 | static int a = increment(); ((void)a); 95 | } 96 | 97 | void test() { 98 | std::thread t1(helper), t2(helper); 99 | t1.join(); 100 | t2.join(); 101 | assert(run_count == 1); 102 | } 103 | } 104 | 105 | // Check that we don't re-initialize a static variable even when it's 106 | // encountered from two different threads. 107 | namespace test5 { 108 | static int run_count = 0; 109 | int zero() { 110 | ++run_count; 111 | return 0; 112 | } 113 | 114 | int one() { 115 | static int b = zero(); ((void)b); 116 | return 0; 117 | } 118 | 119 | void another_helper() { 120 | static int a = one(); ((void)a); 121 | } 122 | 123 | void helper() { 124 | static int a = one(); ((void)a); 125 | std::thread t(another_helper); 126 | t.join(); 127 | } 128 | 129 | void test() { 130 | std::thread t(helper); 131 | t.join(); 132 | assert(run_count == 1); 133 | } 134 | } 135 | #endif /* _LIBCXXABI_HAS_NO_THREADS */ 136 | 137 | int main() 138 | { 139 | test1::test(); 140 | test2::test(); 141 | test3::test(); 142 | #ifndef _LIBCXXABI_HAS_NO_THREADS 143 | test4::test(); 144 | test5::test(); 145 | #endif 146 | } 147 | -------------------------------------------------------------------------------- /test/test_vector2.pass.cpp: -------------------------------------------------------------------------------- 1 | //===--------------------------- test_vector2.cpp -------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include "cxxabi.h" 12 | 13 | #include 14 | #include 15 | 16 | void my_terminate () { exit ( 0 ); } 17 | 18 | // Wrapper routines 19 | void *my_alloc2 ( size_t sz ) { 20 | void *p = std::malloc ( sz ); 21 | // std::printf ( "Allocated %ld bytes at %lx\n", sz, (unsigned long) p ); 22 | return p; 23 | } 24 | 25 | void my_dealloc2 ( void *p ) { 26 | // std::printf ( "Freeing %lx\n", (unsigned long) p ); 27 | std::free ( p ); 28 | } 29 | 30 | void my_dealloc3 ( void *p, size_t ) { 31 | // std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz ); 32 | std::free ( p ); 33 | } 34 | 35 | void my_construct ( void *) { 36 | // std::printf ( "Constructing %lx\n", (unsigned long) p ); 37 | } 38 | 39 | void my_destruct ( void *) { 40 | // std::printf ( "Destructing %lx\n", (unsigned long) p ); 41 | } 42 | 43 | int gCounter; 44 | void count_construct ( void * ) { ++gCounter; } 45 | void count_destruct ( void * ) { --gCounter; } 46 | 47 | 48 | int gConstructorCounter; 49 | int gConstructorThrowTarget; 50 | int gDestructorCounter; 51 | int gDestructorThrowTarget; 52 | void throw_construct ( void * ) { if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; } 53 | void throw_destruct ( void * ) { if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; } 54 | 55 | struct vec_on_stack { 56 | void *storage; 57 | vec_on_stack () : storage ( __cxxabiv1::__cxa_vec_new ( 10, 40, 8, throw_construct, throw_destruct )) {} 58 | ~vec_on_stack () { __cxxabiv1::__cxa_vec_delete ( storage, 40, 8, throw_destruct ); } 59 | }; 60 | 61 | 62 | // Make sure the constructors and destructors are matched 63 | void test_exception_in_destructor ( ) { 64 | 65 | // Try throwing from a destructor while unwinding the stack -- should abort 66 | gConstructorCounter = gDestructorCounter = 0; 67 | gConstructorThrowTarget = -1; 68 | gDestructorThrowTarget = 5; 69 | try { 70 | vec_on_stack v; 71 | throw 3; 72 | } 73 | catch ( int i ) {} 74 | 75 | std::cerr << "should never get here" << std::endl; 76 | } 77 | 78 | 79 | 80 | int main () { 81 | std::set_terminate ( my_terminate ); 82 | test_exception_in_destructor (); 83 | return 1; // we failed if we get here 84 | } 85 | -------------------------------------------------------------------------------- /test/test_vector3.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- test_vector3.cpp ---------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include "cxxabi.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | // use dtors instead of try/catch 21 | namespace test1 { 22 | struct B { 23 | ~B() { 24 | printf("should not be run\n"); 25 | exit(10); 26 | } 27 | }; 28 | 29 | struct A { 30 | ~A() 31 | #if __has_feature(cxx_noexcept) 32 | noexcept(false) 33 | #endif 34 | { 35 | B b; 36 | throw 0; 37 | } 38 | }; 39 | } // test1 40 | 41 | void my_terminate() { exit(0); } 42 | 43 | template 44 | void destroy(void* v) 45 | { 46 | T* t = static_cast(v); 47 | t->~T(); 48 | } 49 | 50 | int main() 51 | { 52 | std::set_terminate(my_terminate); 53 | { 54 | typedef test1::A Array[10]; 55 | Array a[10]; // calls _cxa_vec_dtor 56 | __cxxabiv1::__cxa_vec_dtor(a, 10, sizeof(test1::A), destroy); 57 | assert(false); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/testit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #===------------------------------ testit ----------------------------------===# 3 | # 4 | # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 | # See https://llvm.org/LICENSE.txt for license information. 6 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 | # 8 | #===------------------------------------------------------------------------===# 9 | 10 | if [ -z "$CC" ] 11 | then 12 | CC=clang++ 13 | fi 14 | 15 | if [ -z "$OPTIONS" ] 16 | then 17 | OPTIONS="-std=c++0x -stdlib=libc++" 18 | fi 19 | 20 | case $TRIPLE in 21 | *-*-mingw* | *-*-cygwin* | *-*-win*) 22 | TEST_EXE=test.exe 23 | ;; 24 | *) 25 | TEST_EXE=a.out 26 | ;; 27 | esac 28 | 29 | FAIL=0 30 | PASS=0 31 | UNIMPLEMENTED=0 32 | IMPLEMENTED_FAIL=0 33 | IMPLEMENTED_PASS=0 34 | 35 | afunc() 36 | { 37 | fail=0 38 | pass=0 39 | if (ls *.fail.cpp > /dev/null 2>&1) 40 | then 41 | for FILE in $(ls *.fail.cpp); do 42 | if $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o ./$TEST_EXE > /dev/null 2>&1 43 | then 44 | rm ./$TEST_EXE 45 | echo "$FILE should not compile" 46 | fail=$(($fail + 1)) 47 | else 48 | pass=$(($pass + 1)) 49 | fi 50 | done 51 | fi 52 | 53 | if (ls *.cpp > /dev/null 2>&1) 54 | then 55 | for FILE in $(ls *.pass.cpp); do 56 | if $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o ./$TEST_EXE 57 | then 58 | if ./$TEST_EXE 59 | then 60 | rm ./$TEST_EXE 61 | pass=$(($pass + 1)) 62 | else 63 | echo "$FILE failed at run time" 64 | fail=$(($fail + 1)) 65 | rm ./$TEST_EXE 66 | fi 67 | else 68 | echo "$FILE failed to compile" 69 | fail=$(($fail + 1)) 70 | fi 71 | done 72 | fi 73 | 74 | if [ $fail -gt 0 ] 75 | then 76 | echo "failed $fail tests in `pwd`" 77 | IMPLEMENTED_FAIL=$(($IMPLEMENTED_FAIL + 1)) 78 | fi 79 | if [ $pass -gt 0 ] 80 | then 81 | echo "passed $pass tests in `pwd`" 82 | if [ $fail -eq 0 ] 83 | then 84 | IMPLEMENTED_PASS=$(($IMPLEMENTED_PASS + 1)) 85 | fi 86 | fi 87 | if [ $fail -eq 0 -a $pass -eq 0 ] 88 | then 89 | echo "not implemented: `pwd`" 90 | UNIMPLEMENTED=$(($UNIMPLEMENTED + 1)) 91 | fi 92 | 93 | FAIL=$(($FAIL + $fail)) 94 | PASS=$(($PASS + $pass)) 95 | 96 | for FILE in * 97 | do 98 | if [ -d "$FILE" ]; 99 | then 100 | cd $FILE 101 | afunc 102 | cd .. 103 | fi 104 | done 105 | } 106 | 107 | afunc 108 | 109 | echo "****************************************************" 110 | echo "Results for `pwd`:" 111 | echo "using `$CC --version`" 112 | echo "with $OPTIONS $HEADER_INCLUDE $SOURCE_LIB" 113 | echo "----------------------------------------------------" 114 | echo "sections without tests : $UNIMPLEMENTED" 115 | echo "sections with failures : $IMPLEMENTED_FAIL" 116 | echo "sections without failures: $IMPLEMENTED_PASS" 117 | echo " + ----" 118 | echo "total number of sections : $(($UNIMPLEMENTED+$IMPLEMENTED_FAIL+$IMPLEMENTED_PASS))" 119 | echo "----------------------------------------------------" 120 | echo "number of tests failed : $FAIL" 121 | echo "number of tests passed : $PASS" 122 | echo " + ----" 123 | echo "total number of tests : $(($FAIL+$PASS))" 124 | echo "****************************************************" 125 | 126 | exit $FAIL 127 | -------------------------------------------------------------------------------- /test/thread_local_destruction_order.pass.cpp: -------------------------------------------------------------------------------- 1 | //===-------------- thread_local_destruction_order.pass.cpp ---------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // Darwin TLV finalization routines fail when creating a thread-local variable 10 | // in the destructor for another thread-local variable: 11 | // http://lists.llvm.org/pipermail/cfe-dev/2016-November/051376.html 12 | // XFAIL: darwin 13 | // UNSUPPORTED: c++98, c++03 14 | // UNSUPPORTED: libcxxabi-no-threads 15 | 16 | #include 17 | #include 18 | 19 | int seq = 0; 20 | 21 | class OrderChecker { 22 | public: 23 | explicit OrderChecker(int n) : n_{n} { } 24 | 25 | ~OrderChecker() { 26 | assert(seq++ == n_); 27 | } 28 | 29 | private: 30 | int n_; 31 | }; 32 | 33 | template 34 | class CreatesThreadLocalInDestructor { 35 | public: 36 | ~CreatesThreadLocalInDestructor() { 37 | thread_local OrderChecker checker{ID}; 38 | } 39 | }; 40 | 41 | OrderChecker global{7}; 42 | 43 | void thread_fn() { 44 | static OrderChecker fn_static{5}; 45 | thread_local CreatesThreadLocalInDestructor<2> creates_tl2; 46 | thread_local OrderChecker fn_thread_local{1}; 47 | thread_local CreatesThreadLocalInDestructor<0> creates_tl0; 48 | } 49 | 50 | int main() { 51 | static OrderChecker fn_static{6}; 52 | 53 | std::thread{thread_fn}.join(); 54 | assert(seq == 3); 55 | 56 | thread_local OrderChecker fn_thread_local{4}; 57 | thread_local CreatesThreadLocalInDestructor<3> creates_tl; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /test/uncaught_exception.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------- uncaught_exceptions.pass.cpp ---------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | // This tests that libc++abi still provides __cxa_uncaught_exception() for 12 | // ABI compatibility, even though the Standard doesn't require it to. 13 | 14 | #include 15 | #include 16 | 17 | // namespace __cxxabiv1 { 18 | // extern bool __cxa_uncaught_exception () throw(); 19 | // } 20 | 21 | struct A { 22 | ~A() { assert( __cxxabiv1::__cxa_uncaught_exception()); } 23 | }; 24 | 25 | int main () { 26 | try { A a; throw 3; assert(false); } 27 | catch (int) {} 28 | } 29 | -------------------------------------------------------------------------------- /test/uncaught_exceptions.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------- uncaught_exceptions.pass.cpp ---------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | #include 13 | 14 | // namespace __cxxabiv1 { 15 | // extern unsigned int __cxa_uncaught_exceptions() throw(); 16 | // } 17 | 18 | struct A { 19 | A(unsigned cnt) : data_(cnt) {} 20 | ~A() { assert( data_ == __cxxabiv1::__cxa_uncaught_exceptions()); } 21 | unsigned data_; 22 | }; 23 | 24 | int main () { 25 | try { A a(1); throw 3; assert(false); } 26 | catch (int) {} 27 | } 28 | -------------------------------------------------------------------------------- /test/unittest_demangle.pass.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------- unittest_demangle.cpp ------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: c++98, c++03 10 | 11 | #include "../src/cxa_demangle.cpp" 12 | 13 | using namespace __cxxabiv1; 14 | 15 | void testPODSmallVector() { 16 | { // {push/pop}_back 17 | PODSmallVector PSV; 18 | PSV.push_back(0); 19 | PSV.push_back(1); 20 | PSV.push_back(2); 21 | PSV.push_back(3); 22 | for (int i = 0; i < 4; ++i) 23 | assert(PSV[i] == i); 24 | PSV.pop_back(); 25 | for (int i = 0; i < 3; ++i) 26 | assert(PSV[i] == i); 27 | PSV.pop_back(); 28 | PSV.pop_back(); 29 | assert(!PSV.empty() && PSV.size() == 1); 30 | PSV.pop_back(); 31 | assert(PSV.empty() && PSV.size() == 0); 32 | } 33 | 34 | { 35 | PODSmallVector PSV1; 36 | PSV1.push_back(1); 37 | PSV1.push_back(2); 38 | PSV1.push_back(3); 39 | 40 | PODSmallVector PSV2; 41 | std::swap(PSV1, PSV2); 42 | assert(PSV1.size() == 0); 43 | assert(PSV2.size() == 3); 44 | int i = 1; 45 | for (int x : PSV2) { 46 | assert(x == i); 47 | ++i; 48 | } 49 | assert(i == 4); 50 | std::swap(PSV1, PSV2); 51 | assert(PSV1.size() == 3); 52 | assert(PSV2.size() == 0); 53 | i = 1; 54 | for (int x : PSV1) { 55 | assert(x == i); 56 | ++i; 57 | } 58 | assert(i == 4); 59 | } 60 | 61 | { 62 | PODSmallVector PSV1; 63 | PODSmallVector PSV2; 64 | PSV1.push_back(0); 65 | PSV1.push_back(1); 66 | PSV1.push_back(2); 67 | assert(PSV1.size() == 3); 68 | assert(PSV2.size() == 0); 69 | std::swap(PSV1, PSV2); 70 | assert(PSV1.size() == 0); 71 | assert(PSV2.size() == 3); 72 | int i = 0; 73 | for (int x : PSV2) { 74 | assert(x == i); 75 | ++i; 76 | } 77 | for (int x : PSV1) { 78 | assert(false); 79 | (void)x; 80 | } 81 | } 82 | } 83 | 84 | int main() { 85 | testPODSmallVector(); 86 | } 87 | -------------------------------------------------------------------------------- /test/unwind_01.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- unwind_01.cpp ------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | 11 | #include 12 | 13 | #if defined(__GNUC__) 14 | #pragma GCC diagnostic ignored "-Wunreachable-code" 15 | #endif 16 | 17 | struct A 18 | { 19 | static int count; 20 | int id_; 21 | A() : id_(++count) {} 22 | ~A() {assert(id_ == count--);} 23 | 24 | private: 25 | A(const A&); 26 | A& operator=(const A&); 27 | }; 28 | 29 | int A::count = 0; 30 | 31 | struct B 32 | { 33 | static int count; 34 | int id_; 35 | B() : id_(++count) {} 36 | ~B() {assert(id_ == count--);} 37 | 38 | private: 39 | B(const B&); 40 | B& operator=(const B&); 41 | }; 42 | 43 | int B::count = 0; 44 | 45 | struct C 46 | { 47 | static int count; 48 | int id_; 49 | C() : id_(++count) {} 50 | ~C() {assert(id_ == count--);} 51 | 52 | private: 53 | C(const C&); 54 | C& operator=(const C&); 55 | }; 56 | 57 | int C::count = 0; 58 | 59 | void f2() 60 | { 61 | C c; 62 | A a; 63 | throw 55; 64 | B b; 65 | } 66 | 67 | void f1() 68 | { 69 | A a; 70 | B b; 71 | f2(); 72 | C c; 73 | } 74 | 75 | int main() 76 | { 77 | try 78 | { 79 | f1(); 80 | assert(false); 81 | } 82 | catch (int* i) 83 | { 84 | assert(false); 85 | } 86 | catch (long i) 87 | { 88 | assert(false); 89 | } 90 | catch (int i) 91 | { 92 | assert(i == 55); 93 | } 94 | catch (...) 95 | { 96 | assert(false); 97 | } 98 | assert(A::count == 0); 99 | assert(B::count == 0); 100 | assert(C::count == 0); 101 | } 102 | -------------------------------------------------------------------------------- /test/unwind_02.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- unwind_02.cpp ------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | // REQUIRES: c++98 || c++03 || c++11 || c++14 11 | 12 | #include 13 | 14 | #if defined(__GNUC__) 15 | #pragma GCC diagnostic ignored "-Wunreachable-code" 16 | #endif 17 | 18 | struct A 19 | { 20 | static int count; 21 | int id_; 22 | A() : id_(++count) {} 23 | ~A() {assert(id_ == count--);} 24 | 25 | private: 26 | A(const A&); 27 | A& operator=(const A&); 28 | }; 29 | 30 | int A::count = 0; 31 | 32 | struct B 33 | { 34 | static int count; 35 | int id_; 36 | B() : id_(++count) {} 37 | ~B() {assert(id_ == count--);} 38 | 39 | private: 40 | B(const B&); 41 | B& operator=(const B&); 42 | }; 43 | 44 | int B::count = 0; 45 | 46 | struct C 47 | { 48 | static int count; 49 | int id_; 50 | C() : id_(++count) {} 51 | ~C() {assert(id_ == count--);} 52 | 53 | private: 54 | C(const C&); 55 | C& operator=(const C&); 56 | }; 57 | 58 | int C::count = 0; 59 | 60 | void f2() 61 | { 62 | C c; 63 | A a; 64 | throw 55; 65 | B b; 66 | } 67 | 68 | void f1() throw (long, char, int, double) 69 | { 70 | A a; 71 | B b; 72 | f2(); 73 | C c; 74 | } 75 | 76 | int main() 77 | { 78 | try 79 | { 80 | f1(); 81 | assert(false); 82 | } 83 | catch (int* i) 84 | { 85 | assert(false); 86 | } 87 | catch (long i) 88 | { 89 | assert(false); 90 | } 91 | catch (int i) 92 | { 93 | assert(i == 55); 94 | } 95 | catch (...) 96 | { 97 | assert(false); 98 | } 99 | assert(A::count == 0); 100 | assert(B::count == 0); 101 | assert(C::count == 0); 102 | } 103 | -------------------------------------------------------------------------------- /test/unwind_03.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- unwind_03.cpp ------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | // REQUIRES: c++98 || c++03 || c++11 || c++14 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined(__GNUC__) 17 | #pragma GCC diagnostic ignored "-Wunreachable-code" 18 | #endif 19 | 20 | struct A 21 | { 22 | static int count; 23 | int id_; 24 | A() : id_(++count) {} 25 | ~A() {assert(id_ == count--);} 26 | 27 | private: 28 | A(const A&); 29 | A& operator=(const A&); 30 | }; 31 | 32 | int A::count = 0; 33 | 34 | struct B 35 | { 36 | static int count; 37 | int id_; 38 | B() : id_(++count) {} 39 | ~B() {assert(id_ == count--);} 40 | 41 | private: 42 | B(const B&); 43 | B& operator=(const B&); 44 | }; 45 | 46 | int B::count = 0; 47 | 48 | struct C 49 | { 50 | static int count; 51 | int id_; 52 | C() : id_(++count) {} 53 | ~C() {assert(id_ == count--);} 54 | 55 | private: 56 | C(const C&); 57 | C& operator=(const C&); 58 | }; 59 | 60 | int C::count = 0; 61 | 62 | void f2() 63 | { 64 | C c; 65 | A a; 66 | throw 55; 67 | B b; 68 | } 69 | 70 | void f1() throw (long, char, double) 71 | { 72 | A a; 73 | B b; 74 | f2(); 75 | C c; 76 | } 77 | 78 | void u_handler() 79 | { 80 | exit(0); 81 | } 82 | 83 | int main() 84 | { 85 | std::set_unexpected(u_handler); 86 | try 87 | { 88 | f1(); 89 | assert(false); 90 | } 91 | catch (int* i) 92 | { 93 | assert(false); 94 | } 95 | catch (long i) 96 | { 97 | assert(false); 98 | } 99 | catch (int i) 100 | { 101 | assert(i == 55); 102 | } 103 | catch (...) 104 | { 105 | assert(false); 106 | } 107 | assert(false); 108 | } 109 | -------------------------------------------------------------------------------- /test/unwind_04.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- unwind_04.cpp ------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | // REQUIRES: c++98 || c++03 || c++11 || c++14 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined(__GNUC__) 17 | #pragma GCC diagnostic ignored "-Wunreachable-code" 18 | #endif 19 | 20 | struct A 21 | { 22 | static int count; 23 | int id_; 24 | A() : id_(++count) {} 25 | ~A() {assert(id_ == count--);} 26 | 27 | private: 28 | A(const A&); 29 | A& operator=(const A&); 30 | }; 31 | 32 | int A::count = 0; 33 | 34 | struct B 35 | { 36 | static int count; 37 | int id_; 38 | B() : id_(++count) {} 39 | ~B() {assert(id_ == count--);} 40 | 41 | private: 42 | B(const B&); 43 | B& operator=(const B&); 44 | }; 45 | 46 | int B::count = 0; 47 | 48 | struct C 49 | { 50 | static int count; 51 | int id_; 52 | C() : id_(++count) {} 53 | ~C() {assert(id_ == count--);} 54 | 55 | private: 56 | C(const C&); 57 | C& operator=(const C&); 58 | }; 59 | 60 | int C::count = 0; 61 | 62 | void f2() 63 | { 64 | C c; 65 | A a; 66 | throw 55; 67 | B b; 68 | } 69 | 70 | void f1() throw (long, char, double) 71 | { 72 | A a; 73 | B b; 74 | f2(); 75 | C c; 76 | } 77 | 78 | void u_handler() 79 | { 80 | throw 'a'; 81 | } 82 | 83 | int main() 84 | { 85 | std::set_unexpected(u_handler); 86 | try 87 | { 88 | f1(); 89 | assert(false); 90 | } 91 | catch (int* i) 92 | { 93 | assert(false); 94 | } 95 | catch (long i) 96 | { 97 | assert(false); 98 | } 99 | catch (int i) 100 | { 101 | assert(false); 102 | } 103 | catch (char c) 104 | { 105 | assert(c == 'a'); 106 | } 107 | catch (...) 108 | { 109 | assert(false); 110 | } 111 | assert(A::count == 0); 112 | assert(B::count == 0); 113 | assert(C::count == 0); 114 | } 115 | -------------------------------------------------------------------------------- /test/unwind_05.pass.cpp: -------------------------------------------------------------------------------- 1 | //===------------------------- unwind_05.cpp ------------------------------===// 2 | // 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 | // See https://llvm.org/LICENSE.txt for license information. 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | // UNSUPPORTED: libcxxabi-no-exceptions 10 | // REQUIRES: c++98 || c++03 || c++11 || c++14 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined(__GNUC__) 17 | #pragma GCC diagnostic ignored "-Wunreachable-code" 18 | #endif 19 | 20 | struct A 21 | { 22 | static int count; 23 | int id_; 24 | A() : id_(++count) {} 25 | ~A() {assert(id_ == count--);} 26 | 27 | private: 28 | A(const A&); 29 | A& operator=(const A&); 30 | }; 31 | 32 | int A::count = 0; 33 | 34 | struct B 35 | { 36 | static int count; 37 | int id_; 38 | B() : id_(++count) {} 39 | ~B() {assert(id_ == count--);} 40 | 41 | private: 42 | B(const B&); 43 | B& operator=(const B&); 44 | }; 45 | 46 | int B::count = 0; 47 | 48 | struct C 49 | { 50 | static int count; 51 | int id_; 52 | C() : id_(++count) {} 53 | ~C() {assert(id_ == count--);} 54 | 55 | private: 56 | C(const C&); 57 | C& operator=(const C&); 58 | }; 59 | 60 | int C::count = 0; 61 | 62 | void f2() 63 | { 64 | C c; 65 | A a; 66 | throw 55; 67 | B b; 68 | } 69 | 70 | void f1() throw (long, char, double, std::bad_exception) 71 | { 72 | A a; 73 | B b; 74 | f2(); 75 | C c; 76 | } 77 | 78 | void u_handler() 79 | { 80 | throw; 81 | } 82 | 83 | int main() 84 | { 85 | std::set_unexpected(u_handler); 86 | try 87 | { 88 | f1(); 89 | assert(false); 90 | } 91 | catch (int* i) 92 | { 93 | assert(false); 94 | } 95 | catch (long i) 96 | { 97 | assert(false); 98 | } 99 | catch (int i) 100 | { 101 | assert(false); 102 | } 103 | catch (char c) 104 | { 105 | assert(false); 106 | } 107 | catch (const std::bad_exception& e) 108 | { 109 | assert(true); 110 | } 111 | catch (...) 112 | { 113 | assert(false); 114 | } 115 | assert(A::count == 0); 116 | assert(B::count == 0); 117 | assert(C::count == 0); 118 | } 119 | -------------------------------------------------------------------------------- /www/content.css: -------------------------------------------------------------------------------- 1 | html { margin: 0px; } body { margin: 8px; } 2 | 3 | html, body { 4 | padding:0px; 5 | font-size:small; font-family:"Lucida Grande", "Lucida Sans Unicode", Arial, Verdana, Helvetica, sans-serif; background-color: #fff; color: #222; 6 | line-height:1.5; 7 | } 8 | 9 | h1, h2, h3, tt { color: #000 } 10 | 11 | h1 { padding-top:0px; margin-top:0px;} 12 | h2 { color:#333333; padding-top:0.5em; } 13 | h3 { padding-top: 0.5em; margin-bottom: -0.25em; color:#2d58b7} 14 | li { padding-bottom: 0.5em; } 15 | ul { padding-left:1.5em; } 16 | 17 | /* Slides */ 18 | IMG.img_slide { 19 | display: block; 20 | margin-left: auto; 21 | margin-right: auto 22 | } 23 | 24 | .itemTitle { color:#2d58b7 } 25 | 26 | /* Tables */ 27 | tr { vertical-align:top } 28 | -------------------------------------------------------------------------------- /www/menu.css: -------------------------------------------------------------------------------- 1 | /***************/ 2 | /* page layout */ 3 | /***************/ 4 | 5 | [id=menu] { 6 | position:fixed; 7 | width:25ex; 8 | } 9 | [id=content] { 10 | /* ***** EDIT THIS VALUE IF CONTENT OVERLAPS MENU ***** */ 11 | position:absolute; 12 | left:29ex; 13 | padding-right:4ex; 14 | } 15 | 16 | /**************/ 17 | /* menu style */ 18 | /**************/ 19 | 20 | #menu .submenu { 21 | padding-top:1em; 22 | display:block; 23 | } 24 | 25 | #menu label { 26 | display:block; 27 | font-weight: bold; 28 | text-align: center; 29 | background-color: rgb(192,192,192); 30 | } 31 | #menu a { 32 | padding:0 .2em; 33 | display:block; 34 | text-align: center; 35 | background-color: rgb(235,235,235); 36 | } 37 | #menu a:visited { 38 | color:rgb(100,50,100); 39 | } 40 | --------------------------------------------------------------------------------