--- /dev/null
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# vim swap files
+.*.sw?
+.sw?
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+#lib/ # We actually have things checked in to lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.cache
+nosetests.xml
+coverage.xml
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
# Setup Project
#===============================================================================
-cmake_minimum_required(VERSION 3.4.3)
-
-if(POLICY CMP0042)
- cmake_policy(SET CMP0042 NEW) # Set MACOSX_RPATH=YES by default
-endif()
+cmake_minimum_required(VERSION 3.13.4)
# Add path for custom modules
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
)
+set(CMAKE_FOLDER "libc++")
+
+set(LIBCXXABI_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(LIBCXXABI_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+set(LIBCXXABI_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
+ "Specify path to libc++ source.")
+
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXXABI_STANDALONE_BUILD)
project(libcxxabi CXX C)
set(PACKAGE_NAME libcxxabi)
- set(PACKAGE_VERSION 11.1.0)
+ set(PACKAGE_VERSION 11.0.0git)
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
+ # Add the CMake module path of libcxx so we can reuse HandleOutOfTreeLLVM.cmake
+ set(LIBCXXABI_LIBCXX_CMAKE_PATH "${LIBCXXABI_LIBCXX_PATH}/cmake/Modules")
+ list(APPEND CMAKE_MODULE_PATH "${LIBCXXABI_LIBCXX_CMAKE_PATH}")
+
+ # In a standalone build, we don't have llvm to automatically generate the
+ # llvm-lit script for us. So we need to provide an explicit directory that
+ # the configurator should write the script into.
+ set(LIBCXXABI_STANDALONE_BUILD 1)
+ set(LLVM_LIT_OUTPUT_DIR "${LIBCXXABI_BINARY_DIR}/bin")
+
# Find the LLVM sources and simulate LLVM CMake options.
include(HandleOutOfTreeLLVM)
endif()
+if (LIBCXXABI_STANDALONE_BUILD)
+ find_package(Python3 COMPONENTS Interpreter)
+ if(NOT Python3_Interpreter_FOUND)
+ message(WARNING "Python3 not found, using python2 as a fallback")
+ find_package(Python2 COMPONENTS Interpreter REQUIRED)
+ if(Python2_VERSION VERSION_LESS 2.7)
+ message(SEND_ERROR "Python 2.7 or newer is required")
+ endif()
+
+ # Treat python2 as python3
+ add_executable(Python3::Interpreter IMPORTED)
+ set_target_properties(Python3::Interpreter PROPERTIES
+ IMPORTED_LOCATION ${Python2_EXECUTABLE})
+ set(Python3_EXECUTABLE ${Python2_EXECUTABLE})
+ endif()
+endif()
+
# Require out of source build.
include(MacroEnsureOutOfSourceBuild)
MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
When disabled, libc++abi does not support stack unwinding and other exceptions-related features." ON)
option(LIBCXXABI_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON)
option(LIBCXXABI_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
-option(LIBCXXABI_ENABLE_PIC "Build Position-Independent Code, even in static library" ON)
option(LIBCXXABI_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
option(LIBCXXABI_USE_LLVM_UNWINDER "Build and use the LLVM unwinder." OFF)
option(LIBCXXABI_ENABLE_STATIC_UNWINDER "Statically link the LLVM unwinder." OFF)
option(LIBCXXABI_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF)
option(LIBCXXABI_ENABLE_THREADS "Build with threads enabled" ON)
option(LIBCXXABI_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF)
+option(LIBCXXABI_HAS_WIN32_THREAD_API "Ignore auto-detection and force use of win32 thread API" OFF)
option(LIBCXXABI_HAS_EXTERNAL_THREAD_API
"Build libc++abi with an externalized threading API.
This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON." OFF)
library to try comparing the type_info names to see if they are equal \
instead." OFF)
-# FIXME: This option should default to off. Unfortunatly GCC 4.9 fails to link
-# programs to due undefined references to new/delete in libc++abi. Once this
-# has been fixed or worked around the default value should be changed.
-# See https://reviews.llvm.org/D68269 for more details.
option(LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS
- "Build libc++abi with definitions for operator new/delete. Normally libc++
- provides these definitions" ON)
+ "Build libc++abi with definitions for operator new/delete. These are normally
+ defined in libc++abi, but it is also possible to define them in libc++, in
+ which case the definition in libc++abi should be turned off." ON)
option(LIBCXXABI_BUILD_32_BITS "Build 32 bit libc++abi." ${LLVM_BUILD_32_BITS})
option(LIBCXXABI_INCLUDE_TESTS "Generate build targets for the libc++abi unit tests." ${LLVM_INCLUDE_TESTS})
set(LIBCXXABI_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
"Define suffix of library directory name (32/64)")
option(LIBCXXABI_INSTALL_LIBRARY "Install the libc++abi library." ON)
-set(LIBCXXABI_TARGET_TRIPLE "" CACHE STRING "Target triple for cross compiling.")
+set(LIBCXXABI_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" CACHE STRING "Target triple for cross compiling.")
set(LIBCXXABI_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.")
set(LIBCXXABI_SYSROOT "" CACHE PATH "Sysroot for cross compiling.")
set(LIBCXXABI_LIBCXX_LIBRARY_PATH "" CACHE PATH "The path to libc++ library.")
# The default terminate handler attempts to demangle uncaught exceptions, which
# causes extra I/O and demangling code to be pulled in.
option(LIBCXXABI_SILENT_TERMINATE "Set this to make the terminate handler default to a silent alternative" OFF)
+option(LIBCXXABI_NON_DEMANGLING_TERMINATE "Set this to make the terminate handler
+avoid demangling" OFF)
if (NOT LIBCXXABI_ENABLE_SHARED AND NOT LIBCXXABI_ENABLE_STATIC)
message(FATAL_ERROR "libc++abi must be built as either a shared or static library.")
endif()
-set(LIBCXXABI_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
- "Specify path to libc++ source.")
-set(LIBCXXABI_LIBCXX_INCLUDES "${LIBCXXABI_LIBCXX_PATH}/include" CACHE PATH
+# TODO: This is a workaround for the fact that Standalone builds can't use
+# targets from the other runtimes (so the cxx-headers target doesn't exist).
+set(LIBCXXABI_LIBCXX_INCLUDES "" CACHE PATH
"Specify path to libc++ includes.")
-message(STATUS "Libc++abi will be using libc++ includes from ${LIBCXXABI_LIBCXX_INCLUDES}")
+if (LIBCXXABI_STANDALONE_BUILD)
+ if (NOT IS_DIRECTORY ${LIBCXXABI_LIBCXX_INCLUDES})
+ message(FATAL_ERROR
+ "LIBCXXABI_LIBCXX_INCLUDES=${LIBCXXABI_LIBCXX_INCLUDES} is not a valid directory. "
+ "Please provide the path to where the libc++ headers have been installed.")
+ endif()
+ add_library(cxx-headers INTERFACE)
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC")
+ target_compile_options(cxx-headers INTERFACE /I "${LIBCXXABI_LIBCXX_INCLUDES}")
+ else()
+ target_compile_options(cxx-headers INTERFACE -I "${LIBCXXABI_LIBCXX_INCLUDES}")
+ endif()
+endif()
option(LIBCXXABI_HERMETIC_STATIC_LIBRARY
"Do not export any symbols from the static library." OFF)
${CMAKE_MODULE_PATH}
)
-set(LIBCXXABI_COMPILER ${CMAKE_CXX_COMPILER})
-set(LIBCXXABI_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
-set(LIBCXXABI_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
-
-string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION
- ${PACKAGE_VERSION})
-
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
- set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
- set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
+ set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
+ set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
+ set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
+ "Path where built libc++abi libraries should be installed.")
if(LIBCXX_LIBDIR_SUBDIR)
string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
string(APPEND LIBCXXABI_INSTALL_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
endif()
elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
+ set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
- set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX})
+ set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
+ "Path where built libc++abi libraries should be installed.")
else()
+ set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR})
set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
- set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX})
+ set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
+ "Path where built libc++abi libraries should be installed.")
endif()
-set(LIBCXXABI_INSTALL_PREFIX "" CACHE STRING "Define libc++abi destination prefix.")
-
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXXABI_LIBRARY_DIR})
add_target_flags_if(LIBCXXABI_BUILD_32_BITS "-m32")
if(LIBCXXABI_TARGET_TRIPLE)
- add_target_flags("--target=${LIBCXXABI_TARGET_TRIPLE}")
+ add_target_flags_if_supported("--target=${LIBCXXABI_TARGET_TRIPLE}")
elseif(CMAKE_CXX_COMPILER_TARGET)
set(LIBCXXABI_TARGET_TRIPLE "${CMAKE_CXX_COMPILER_TARGET}")
endif()
if(LIBCXX_GCC_TOOLCHAIN)
- add_target_flags("--gcc-toolchain=${LIBCXXABI_GCC_TOOLCHAIN}")
+ add_target_flags_if_supported("--gcc-toolchain=${LIBCXXABI_GCC_TOOLCHAIN}")
elseif(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN)
set(LIBCXXABI_GCC_TOOLCHAIN "${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN}")
endif()
if(LIBCXXABI_SYSROOT)
- add_target_flags("--sysroot=${LIBCXXABI_SYSROOT}")
+ add_target_flags_if_supported("--sysroot=${LIBCXXABI_SYSROOT}")
elseif(CMAKE_SYSROOT)
set(LIBCXXABI_SYSROOT "${CMAKE_SYSROOT}")
endif()
-if (LIBCXXABI_TARGET_TRIPLE)
- set(TARGET_TRIPLE "${LIBCXXABI_TARGET_TRIPLE}")
-endif()
-
# Configure compiler. Must happen after setting the target flags.
include(config-ix)
# See: https://gitlab.kitware.com/cmake/cmake/issues/19227
set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "")
# Remove -stdlib flags to prevent them from causing an unused flag warning.
+ string(REPLACE "--stdlib=libc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ string(REPLACE "--stdlib=libstdc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "-stdlib=libc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "-stdlib=libstdc++" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
# library.
add_definitions(-D_LIBCXXABI_BUILDING_LIBRARY)
+# libcxxabi needs to, for various reasons, include the libcpp headers as if
+# it is being built as part of libcxx.
+add_definitions(-D_LIBCPP_BUILDING_LIBRARY)
+
# Disable DLL annotations on Windows for static builds.
if (WIN32 AND LIBCXXABI_ENABLE_STATIC AND NOT LIBCXXABI_ENABLE_SHARED)
- add_definitions(-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
+ if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_STATIC_ABI_LIBRARY)
+ # Building libcxxabi statically, but intending for it to be statically
+ # linked into a shared libcxx; keep dllexport enabled within libcxxabi,
+ # as the symbols will need to be exported from libcxx.
+ else()
+ # Regular static build; disable dllexports.
+ add_definitions(-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
+ endif()
endif()
add_compile_flags_if_supported(-Werror=return-type)
add_compile_flags_if_supported(-Wwrite-strings)
add_compile_flags_if_supported(-Wundef)
+add_compile_flags_if_supported(-Wno-suggest-override)
+
if (LIBCXXABI_ENABLE_WERROR)
add_compile_flags_if_supported(-Werror)
add_compile_flags_if_supported(-WX)
list(APPEND LIBCXXABI_COMPILE_FLAGS -DNDEBUG)
endif()
endif()
-# Static library
-if (NOT LIBCXXABI_ENABLE_SHARED)
- list(APPEND LIBCXXABI_COMPILE_FLAGS -D_LIBCPP_BUILD_STATIC)
-endif()
# Threading
if (NOT LIBCXXABI_ENABLE_THREADS)
" be set to ON when LIBCXXABI_ENABLE_THREADS"
" is also set to ON.")
endif()
+ if (LIBCXXABI_HAS_WIN32_THREAD_API)
+ message(FATAL_ERROR "LIBCXXABI_HAS_WIN32_THREAD_API can only"
+ " be set to ON when LIBCXXABI_ENABLE_THREADS"
+ " is also set to ON.")
+ endif()
if (LIBCXXABI_HAS_EXTERNAL_THREAD_API)
message(FATAL_ERROR "LIBCXXABI_HAS_EXTERNAL_THREAD_API can only"
" be set to ON when LIBCXXABI_ENABLE_THREADS"
" is also set to ON.")
endif()
add_definitions(-D_LIBCXXABI_HAS_NO_THREADS)
+ add_definitions(-D_LIBCPP_HAS_NO_THREADS)
endif()
if (LIBCXXABI_HAS_EXTERNAL_THREAD_API)
" and LIBCXXABI_HAS_PTHREAD_API cannot be both"
" set to ON at the same time.")
endif()
+ if (LIBCXXABI_HAS_WIN32_THREAD_API)
+ message(FATAL_ERROR "The options LIBCXXABI_HAS_EXTERNAL_THREAD_API"
+ " and LIBCXXABI_HAS_WIN32_THREAD_API cannot be both"
+ " set to ON at the same time.")
+ endif()
if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY)
message(FATAL_ERROR "The options LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY"
" and LIBCXXABI_HAS_EXTERNAL_THREAD_API cannot be both"
endif()
endif()
+if (LIBCXXABI_HAS_PTHREAD_API)
+ if (LIBCXXABI_HAS_WIN32_THREAD_API)
+ message(FATAL_ERROR "The options LIBCXXABI_HAS_PTHREAD_API"
+ "and LIBCXXABI_HAS_WIN32_THREAD_API cannot be both"
+ "set to ON at the same time.")
+ endif()
+endif()
+
if (LLVM_ENABLE_MODULES)
# Ignore that the rest of the modules flags are now unused.
add_compile_flags_if_supported(-Wno-unused-command-line-argument)
add_definitions(-D_LIBCPP_HAS_THREAD_API_PTHREAD)
endif()
+if (LIBCXXABI_HAS_WIN32_THREAD_API)
+ add_definitions(-D_LIBCPP_HAS_THREAD_API_WIN32)
+endif()
+
if (LIBCXXABI_HAS_EXTERNAL_THREAD_API)
add_definitions(-D_LIBCPP_HAS_THREAD_API_EXTERNAL)
endif()
# Prevent libc++abi from having library dependencies on libc++
add_definitions(-D_LIBCPP_DISABLE_EXTERN_TEMPLATE)
-# Bring back `std::unexpected`, which is removed in C++17, to support
-# pre-C++17.
-add_definitions(-D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS)
-
if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
add_definitions(-DLIBCXXABI_SILENT_TERMINATE)
endif()
+if (LIBCXXABI_NON_DEMANGLING_TERMINATE)
+ add_definitions(-DLIBCXXABI_NON_DEMANGLING_TERMINATE)
+endif()
+
if (LIBCXXABI_BAREMETAL)
add_definitions(-DLIBCXXABI_BAREMETAL)
endif()
add_subdirectory(src)
if (LIBCXXABI_INCLUDE_TESTS)
- if (LIBCXXABI_STANDALONE_BUILD AND NOT LIBCXXABI_ENABLE_SHARED)
- # We can't reasonably test the system C++ library with a static
- # libc++abi. We either need to be able to replace libc++abi at
- # run time (with a shared libc++abi), or we need to be able to
- # replace the C++ runtime (with a non- standalone build).
- message(WARNING "The libc++abi tests aren't valid when libc++abi "
- "is built standalone (i.e. outside of "
- "llvm/projects/libcxxabi ) and is built without "
- "a shared library. Either build a shared "
- "library, build libc++abi at the same time as "
- "you build libc++, or do without testing. No "
- "check target will be available!")
- else()
- add_subdirectory(test)
- add_subdirectory(fuzz)
- endif()
+ add_subdirectory(test)
+ add_subdirectory(fuzz)
endif()
endif()
endmacro()
+# Add all the flags supported by the compiler to all of
+# 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBCXXABI_COMPILE_FLAGS'
+# and 'LIBCXXABI_LINK_FLAGS'.
+macro(add_target_flags_if_supported)
+ foreach(flag ${ARGN})
+ mangle_name("${flag}" flagname)
+ check_cxx_compiler_flag("${flag}" "LIBCXXABI_SUPPORTS_${flagname}_FLAG")
+ add_target_flags_if(LIBCXXABI_SUPPORTS_${flagname}_FLAG ${flag})
+ endforeach()
+endmacro()
+
# Add a specified list of flags to both 'LIBCXXABI_COMPILE_FLAGS' and
# 'LIBCXXABI_LINK_FLAGS'.
macro(add_flags)
endif ()
endif ()
-# libc++abi is built with -nodefaultlibs, so we want all our checks to also
-# use this option, otherwise we may end up with an inconsistency between
+# libc++abi is using -nostdlib++ at the link step when available,
+# otherwise -nodefaultlibs is used. We want all our checks to also
+# use one of these options, otherwise we may end up with an inconsistency between
# the flags we think we require during configuration (if the checks are
# performed without -nodefaultlibs) and the flags that are actually
# required during compilation (which has the -nodefaultlibs). libc is
# required for the link to go through. We remove sanitizers from the
# configuration checks to avoid spurious link errors.
-check_c_compiler_flag(-nodefaultlibs LIBCXXABI_HAS_NODEFAULTLIBS_FLAG)
-if (LIBCXXABI_HAS_NODEFAULTLIBS_FLAG)
- set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
+
+check_c_compiler_flag(-nostdlib++ LIBCXXABI_SUPPORTS_NOSTDLIBXX_FLAG)
+if (LIBCXXABI_SUPPORTS_NOSTDLIBXX_FLAG)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nostdlib++")
+else()
+ check_c_compiler_flag(-nodefaultlibs LIBCXXABI_SUPPORTS_NODEFAULTLIBS_FLAG)
+ if (LIBCXXABI_SUPPORTS_NODEFAULTLIBS_FLAG)
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs")
+ endif()
+endif()
+
+if (LIBCXXABI_SUPPORTS_NOSTDLIBXX_FLAG OR LIBCXXABI_SUPPORTS_NODEFAULTLIBS_FLAG)
if (LIBCXXABI_HAS_C_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES c)
endif ()
#define __has_attribute(_attribute_) 0
#endif
+#if defined(__clang__)
+# define _LIBCXXABI_COMPILER_CLANG
+# ifndef __apple_build_version__
+# define _LIBCXXABI_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
+# endif
+#elif defined(__GNUC__)
+# define _LIBCXXABI_COMPILER_GCC
+#elif defined(_MSC_VER)
+# define _LIBCXXABI_COMPILER_MSVC
+#elif defined(__IBMCPP__)
+# define _LIBCXXABI_COMPILER_IBM
+#endif
+
#if defined(_WIN32)
#if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
#define _LIBCXXABI_HIDDEN
#endif
#endif
-#if defined(_WIN32)
+#if defined(_LIBCXXABI_COMPILER_MSVC)
#define _LIBCXXABI_WEAK
#else
#define _LIBCXXABI_WEAK __attribute__((__weak__))
#endif
// wasm32 follows the arm32 ABI convention of using 32-bit guard.
-#if defined(__arm__) || defined(__wasm32__)
+#if defined(__arm__) || defined(__wasm32__) || defined(__ARM64_ARCH_8_32__)
# define _LIBCXXABI_GUARD_ABI_ARM
#endif
#define _LIBCPPABI_VERSION 1002
#define _LIBCXXABI_NORETURN __attribute__((noreturn))
+#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold))
#ifdef __cplusplus
// 3.3.2 One-time Construction API
#if defined(_LIBCXXABI_GUARD_ABI_ARM)
-extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint32_t *);
-extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint32_t *);
-extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint32_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *);
#else
-extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint64_t *);
-extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint64_t *);
-extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint64_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *);
+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *);
#endif
// 3.3.3 Array Construction and Destruction API
void (*destructor)(void *));
// 3.3.5.3 Runtime API
-extern _LIBCXXABI_FUNC_VIS int __cxa_atexit(void (*f)(void *), void *p,
- void *d);
-extern _LIBCXXABI_FUNC_VIS int __cxa_finalize(void *);
+// These functions are part of the C++ ABI, but they are not defined in libc++abi:
+// int __cxa_atexit(void (*)(void *), void *, void *);
+// void __cxa_finalize(void *);
// 3.4 Demangler API
extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name,
)
if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS)
- list(APPEND LIBCXXABI_SOURCES stdlib_new_delete.cpp)
+ list(APPEND LIBCXXABI_SOURCES
+ stdlib_new_delete.cpp
+ )
endif()
if (LIBCXXABI_ENABLE_EXCEPTIONS)
)
endif()
-if (LIBCXXABI_ENABLE_THREADS AND (UNIX OR FUCHSIA) AND NOT (APPLE OR CYGWIN))
+if (LIBCXXABI_ENABLE_THREADS AND (UNIX OR FUCHSIA) AND NOT (APPLE OR CYGWIN)
+ AND NOT (${CMAKE_SYSTEM_NAME} MATCHES "AIX"))
list(APPEND LIBCXXABI_SOURCES
cxa_thread_atexit.cpp
)
endif()
endif()
-include_directories("${LIBCXXABI_LIBCXX_INCLUDES}")
+# stdlib_stdexcept.cpp depends on libc++ internals.
+include_directories("${LIBCXXABI_LIBCXX_PATH}")
if (LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL)
add_definitions(-DHAVE___CXA_THREAD_ATEXIT_IMPL)
add_library_flags_if(LIBCXXABI_HAS_C_LIB c)
endif()
+if (LIBCXXABI_USE_COMPILER_RT)
+ find_compiler_rt_library(builtins LIBCXXABI_BUILTINS_LIBRARY)
+ list(APPEND LIBCXXABI_SHARED_LIBRARIES "${LIBCXXABI_BUILTINS_LIBRARY}")
+endif ()
+
if (LIBCXXABI_USE_LLVM_UNWINDER)
# Prefer using the in-tree version of libunwind, either shared or static. If
# none are found fall back to using -lunwind.
endif ()
# Setup flags.
-add_link_flags_if_supported(-nodefaultlibs)
+if (LIBCXXABI_SUPPORTS_NOSTDLIBXX_FLAG)
+ add_link_flags_if_supported(-nostdlib++)
+else()
+ add_link_flags_if_supported(-nodefaultlibs)
+endif()
if ( APPLE )
if (LLVM_USE_SANITIZER)
# Build the shared library.
if (LIBCXXABI_ENABLE_SHARED)
add_library(cxxabi_shared SHARED ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS})
- if(COMMAND llvm_setup_rpath)
- llvm_setup_rpath(cxxabi_shared)
- endif()
- target_link_libraries(cxxabi_shared PRIVATE ${LIBCXXABI_SHARED_LIBRARIES} ${LIBCXXABI_LIBRARIES})
+ target_link_libraries(cxxabi_shared PRIVATE cxx-headers ${LIBCXXABI_SHARED_LIBRARIES} ${LIBCXXABI_LIBRARIES})
if (TARGET pstl::ParallelSTL)
target_link_libraries(cxxabi_shared PUBLIC pstl::ParallelSTL)
endif()
set_target_properties(cxxabi_shared
- PROPERTIES
- CXX_EXTENSIONS
- OFF
- CXX_STANDARD
- 11
- CXX_STANDARD_REQUIRED
- ON
- COMPILE_FLAGS
- "${LIBCXXABI_COMPILE_FLAGS}"
- LINK_FLAGS
- "${LIBCXXABI_LINK_FLAGS}"
- OUTPUT_NAME
- "c++abi"
- SOVERSION
- "1"
- VERSION
- "${LIBCXXABI_LIBRARY_VERSION}"
- DEFINE_SYMBOL
- "")
-
- if(LIBCXXABI_ENABLE_PIC)
- set_target_properties(cxxabi_shared PROPERTIES POSITION_INDEPENDENT_CODE ON)
- endif()
+ PROPERTIES
+ CXX_EXTENSIONS OFF
+ CXX_STANDARD 20
+ CXX_STANDARD_REQUIRED OFF
+ COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
+ LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}"
+ OUTPUT_NAME "c++abi"
+ SOVERSION "1"
+ VERSION "${LIBCXXABI_LIBRARY_VERSION}"
+ DEFINE_SYMBOL ""
+ POSITION_INDEPENDENT_CODE ON
+ )
list(APPEND LIBCXXABI_BUILD_TARGETS "cxxabi_shared")
if (LIBCXXABI_INSTALL_SHARED_LIBRARY)
list(APPEND LIBCXXABI_INSTALL_TARGETS "cxxabi_shared")
endif()
+ add_library(cxxabi-reexports INTERFACE)
+
# -exported_symbols_list is only available on Apple platforms
if (APPLE)
- target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/itanium-base.exp")
+ function(export_symbols file)
+ target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${file}")
+ endfunction()
+ function(reexport_symbols file)
+ export_symbols("${file}")
+ target_link_libraries(cxxabi-reexports INTERFACE "-Wl,-reexported_symbols_list,${file}")
+ endfunction()
+
+ export_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/itanium-base.exp")
if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS)
- target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/new-delete.exp")
+ reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/new-delete.exp")
endif()
if (LIBCXXABI_ENABLE_EXCEPTIONS)
- target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/exceptions.exp")
+ reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/exceptions.exp")
if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(armv6|armv7|armv7s)$")
- target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-sjlj.exp")
+ reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-sjlj.exp")
else()
- target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-v0.exp")
+ reexport_symbols("${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-v0.exp")
endif()
endif()
endif()
# Build the static library.
if (LIBCXXABI_ENABLE_STATIC)
add_library(cxxabi_static STATIC ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS})
- target_link_libraries(cxxabi_static PRIVATE ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
+ target_link_libraries(cxxabi_static PRIVATE cxx-headers ${LIBCXXABI_STATIC_LIBRARIES} ${LIBCXXABI_LIBRARIES})
if (TARGET pstl::ParallelSTL)
target_link_libraries(cxxabi_static PUBLIC pstl::ParallelSTL)
endif()
set_target_properties(cxxabi_static
- PROPERTIES
- CXX_EXTENSIONS
- OFF
- CXX_STANDARD
- 11
- CXX_STANDARD_REQUIRED
- ON
- COMPILE_FLAGS
- "${LIBCXXABI_COMPILE_FLAGS}"
- LINK_FLAGS
- "${LIBCXXABI_LINK_FLAGS}"
- OUTPUT_NAME
- "c++abi")
-
- if(LIBCXXABI_ENABLE_PIC)
- set_target_properties(cxxabi_static PROPERTIES POSITION_INDEPENDENT_CODE ON)
- endif()
+ PROPERTIES
+ CXX_EXTENSIONS OFF
+ CXX_STANDARD 20
+ CXX_STANDARD_REQUIRED OFF
+ COMPILE_FLAGS "${LIBCXXABI_COMPILE_FLAGS}"
+ LINK_FLAGS "${LIBCXXABI_LINK_FLAGS}"
+ OUTPUT_NAME "c++abi"
+ POSITION_INDEPENDENT_CODE ON
+ )
if(LIBCXXABI_HERMETIC_STATIC_LIBRARY)
append_flags_if_supported(CXXABI_STATIC_LIBRARY_FLAGS -fvisibility=hidden)
# Merge the libc++abi.a and libunwind.a into one.
if(LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
add_custom_command(TARGET cxxabi_static POST_BUILD
- COMMAND ${PYTHON_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/merge_archives.py
+ COMMAND ${Python3_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/merge_archives.py
ARGS
-o "$<TARGET_LINKER_FILE:cxxabi_static>"
--ar "${CMAKE_AR}"
"$<TARGET_LINKER_FILE:cxxabi_static>"
"$<TARGET_LINKER_FILE:unwind_static>"
WORKING_DIRECTORY ${LIBCXXABI_BUILD_DIR}
+ DEPENDS unwind_static
)
endif()
endif()
if (LIBCXXABI_INSTALL_LIBRARY)
install(TARGETS ${LIBCXXABI_INSTALL_TARGETS}
- LIBRARY DESTINATION ${LIBCXXABI_INSTALL_PREFIX}${LIBCXXABI_INSTALL_LIBRARY_DIR} COMPONENT cxxabi
- ARCHIVE DESTINATION ${LIBCXXABI_INSTALL_PREFIX}${LIBCXXABI_INSTALL_LIBRARY_DIR} COMPONENT cxxabi
+ LIBRARY DESTINATION ${LIBCXXABI_INSTALL_LIBRARY_DIR} COMPONENT cxxabi
+ ARCHIVE DESTINATION ${LIBCXXABI_INSTALL_LIBRARY_DIR} COMPONENT cxxabi
)
endif()
exception_header + 1;
const __shim_type_info* thrown_type =
static_cast<const __shim_type_info*>(exception_header->exceptionType);
+#if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE)
// Try to get demangled name of thrown_type
int status;
char buf[1024];
const char* name = __cxa_demangle(thrown_type->name(), buf, &len, &status);
if (status != 0)
name = thrown_type->name();
+#else
+ const char* name = thrown_type->name();
+#endif
// If the uncaught exception can be caught with std::exception&
const __shim_type_info* catch_type =
static_cast<const __shim_type_info*>(&typeid(std::exception));
{
unexpected_handler
-set_unexpected(unexpected_handler func) _NOEXCEPT
+set_unexpected(unexpected_handler func) noexcept
{
if (func == 0)
func = default_unexpected_handler;
}
terminate_handler
-set_terminate(terminate_handler func) _NOEXCEPT
+set_terminate(terminate_handler func) noexcept
{
if (func == 0)
func = default_terminate_handler;
#include "include/atomic_support.h"
#if __has_feature(address_sanitizer)
-extern "C" void __asan_handle_no_return(void);
+#include <sanitizer/asan_interface.h>
#endif
// +---------------------------+-----------------------------+---------------+
" bl abort\n"
" .popsection"
);
-#endif // defined(_LIBCXXABI_ARM_EHABI)
+#endif // defined(_LIBCXXABI_ARM_EHABI)
/*
This routine can catch foreign or native exceptions. If native, the exception
} // namespace __cxxabiv1
-#endif // _CXA_EXCEPTION_H
+#endif // _CXA_EXCEPTION_H
#endif
#endif
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+#elif defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Waddress"
+#endif
+
// To make testing possible, this header is included from both cxa_guard.cpp
// and a number of tests.
//
public:
using MemoryOrder = std::__libcpp_atomic_order;
- explicit AtomicInt(IntType *b) : b(b) {}
+ explicit AtomicInt(IntType *b) : b_(b) {}
AtomicInt(AtomicInt const&) = delete;
AtomicInt& operator=(AtomicInt const&) = delete;
IntType load(MemoryOrder ord) {
- return std::__libcpp_atomic_load(b, ord);
+ return std::__libcpp_atomic_load(b_, ord);
}
void store(IntType val, MemoryOrder ord) {
- std::__libcpp_atomic_store(b, val, ord);
+ std::__libcpp_atomic_store(b_, val, ord);
}
IntType exchange(IntType new_val, MemoryOrder ord) {
- return std::__libcpp_atomic_exchange(b, new_val, ord);
+ return std::__libcpp_atomic_exchange(b_, new_val, ord);
}
bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
- return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
+ return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure);
}
private:
- IntType *b;
+ IntType *b_;
};
//===----------------------------------------------------------------------===//
constexpr bool PlatformSupportsThreadID() {
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
-#endif
return +PlatformThreadID != nullptr;
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
}
//===----------------------------------------------------------------------===//
LockGuard& operator=(LockGuard const&) = delete;
explicit LockGuard(const char* calling_func)
- : calling_func(calling_func) {
+ : calling_func_(calling_func) {
if (global_mutex.lock())
- ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func);
+ ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_);
}
~LockGuard() {
if (global_mutex.unlock())
- ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func);
+ ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func_);
}
private:
- const char* const calling_func;
+ const char* const calling_func_;
};
};
#endif
constexpr bool PlatformSupportsFutex() {
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
-#endif
return +PlatformFutexWait != nullptr;
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
}
/// InitByteFutex - Manages initialization using atomics and the futex syscall
} // end namespace
} // end namespace __cxxabiv1
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#elif defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
+
#endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H
{
unexpected_handler
-get_unexpected() _NOEXCEPT
+get_unexpected() noexcept
{
return __libcpp_atomic_load(&__cxa_unexpected_handler, _AO_Acquire);
}
}
terminate_handler
-get_terminate() _NOEXCEPT
+get_terminate() noexcept
{
return __libcpp_atomic_load(&__cxa_terminate_handler, _AO_Acquire);
}
void
-__terminate(terminate_handler func) _NOEXCEPT
+__terminate(terminate_handler func) noexcept
{
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
func();
// handler should not return
abort_message("terminate_handler unexpectedly returned");
// handler should not throw exception
abort_message("terminate_handler unexpectedly threw an exception");
}
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
}
__attribute__((noreturn))
void
-terminate() _NOEXCEPT
+terminate() noexcept
{
#ifndef _LIBCXXABI_NO_EXCEPTIONS
// If there might be an uncaught exception
}
new_handler
-set_new_handler(new_handler handler) _NOEXCEPT
+set_new_handler(new_handler handler) noexcept
{
return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
}
new_handler
-get_new_handler() _NOEXCEPT
+get_new_handler() noexcept
{
return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire);
}
_LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN
void
-__terminate(terminate_handler func) _NOEXCEPT;
+__terminate(terminate_handler func) noexcept;
} // std
} // extern "C"
-#endif // _CXA_HANDLERS_H
+#endif // _CXA_HANDLERS_H
| +-------------+---------------------------------+------------------------------+ |
| ... |
+----------------------------------------------------------------------------------+
-#endif // __USING_SJLJ_EXCEPTIONS__
+#endif // __USING_SJLJ_EXCEPTIONS__
+---------------------------------------------------------------------+
| Beginning of Action Table ttypeIndex == 0 : cleanup |
| ... ttypeIndex > 0 : catch |
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
/// @param data reference variable holding memory pointer to decode from
/// @param encoding dwarf encoding type
+/// @param base for adding relative offset, default to 0
/// @returns decoded value
static
uintptr_t
-readEncodedPointer(const uint8_t** data, uint8_t encoding)
+readEncodedPointer(const uint8_t** data, uint8_t encoding, uintptr_t base = 0)
{
uintptr_t result = 0;
if (encoding == DW_EH_PE_omit)
if (result)
result += (uintptr_t)(*data);
break;
- case DW_EH_PE_textrel:
case DW_EH_PE_datarel:
+ assert((base != 0) && "DW_EH_PE_datarel is invalid with a base of 0");
+ if (result)
+ result += base;
+ break;
+ case DW_EH_PE_textrel:
case DW_EH_PE_funcrel:
case DW_EH_PE_aligned:
default:
static const __shim_type_info*
get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
uint8_t ttypeEncoding, bool native_exception,
- _Unwind_Exception* unwind_exception)
+ _Unwind_Exception* unwind_exception, uintptr_t /*base*/ = 0)
{
if (classInfo == 0)
{
const __shim_type_info*
get_shim_type_info(uint64_t ttypeIndex, const uint8_t* classInfo,
uint8_t ttypeEncoding, bool native_exception,
- _Unwind_Exception* unwind_exception)
+ _Unwind_Exception* unwind_exception, uintptr_t base = 0)
{
if (classInfo == 0)
{
call_terminate(native_exception, unwind_exception);
}
classInfo -= ttypeIndex;
- return (const __shim_type_info*)readEncodedPointer(&classInfo, ttypeEncoding);
+ return (const __shim_type_info*)readEncodedPointer(&classInfo,
+ ttypeEncoding, base);
}
#endif // !defined(_LIBCXXABI_ARM_EHABI)
bool
exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
uint8_t ttypeEncoding, const __shim_type_info* excpType,
- void* adjustedPtr, _Unwind_Exception* unwind_exception)
+ void* adjustedPtr, _Unwind_Exception* unwind_exception,
+ uintptr_t /*base*/ = 0)
{
if (classInfo == 0)
{
bool
exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo,
uint8_t ttypeEncoding, const __shim_type_info* excpType,
- void* adjustedPtr, _Unwind_Exception* unwind_exception)
+ void* adjustedPtr, _Unwind_Exception* unwind_exception,
+ uintptr_t base = 0)
{
if (classInfo == 0)
{
classInfo,
ttypeEncoding,
true,
- unwind_exception);
+ unwind_exception,
+ base);
void* tempPtr = adjustedPtr;
if (catchType->can_catch(excpType, tempPtr))
return false;
{
#if defined(__USING_SJLJ_EXCEPTIONS__)
#define __builtin_eh_return_data_regno(regno) regno
+#elif defined(__ibmxl__)
+// IBM xlclang++ compiler does not support __builtin_eh_return_data_regno.
+#define __builtin_eh_return_data_regno(regno) regno + 3
#endif
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
reinterpret_cast<uintptr_t>(unwind_exception));
return;
}
results.languageSpecificData = lsda;
+#if defined(_AIX)
+ uintptr_t base = _Unwind_GetDataRelBase(context);
+#else
+ uintptr_t base = 0;
+#endif
// Get the current instruction pointer and offset it before next
// instruction in the current frame which threw the exception.
uintptr_t ip = _Unwind_GetIP(context) - 1;
// ip is 1-based index into call site table
#else // !__USING_SJLJ_EXCEPTIONS__
uintptr_t ipOffset = ip - funcStart;
-#endif // !defined(_USING_SLJL_EXCEPTIONS__)
+#endif // !defined(_USING_SLJL_EXCEPTIONS__)
const uint8_t* classInfo = NULL;
// Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
// dwarf emission
// Parse LSDA header.
uint8_t lpStartEncoding = *lsda++;
- const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
+ const uint8_t* lpStart =
+ (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
if (lpStart == 0)
lpStart = (const uint8_t*)funcStart;
uint8_t ttypeEncoding = *lsda++;
uintptr_t landingPad = readULEB128(&callSitePtr);
uintptr_t actionEntry = readULEB128(&callSitePtr);
if (--ip == 0)
-#endif // __USING_SJLJ_EXCEPTIONS__
+#endif // __USING_SJLJ_EXCEPTIONS__
{
// Found the call site containing ip.
#ifndef __USING_SJLJ_EXCEPTIONS__
landingPad = (uintptr_t)lpStart + landingPad;
#else // __USING_SJLJ_EXCEPTIONS__
++landingPad;
-#endif // __USING_SJLJ_EXCEPTIONS__
+#endif // __USING_SJLJ_EXCEPTIONS__
+ results.landingPad = landingPad;
if (actionEntry == 0)
{
// Found a cleanup
- // If this is a type 1 or type 2 search, there are no handlers
- // If this is a type 3 search, you want to install the cleanup.
- if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
- {
- results.ttypeIndex = 0; // Redundant but clarifying
- results.landingPad = landingPad;
- results.reason = _URC_HANDLER_FOUND;
- return;
- }
- // No handler here
- results.reason = _URC_CONTINUE_UNWIND;
+ results.reason = actions & _UA_SEARCH_PHASE
+ ? _URC_CONTINUE_UNWIND
+ : _URC_HANDLER_FOUND;
return;
}
// Convert 1-based byte offset into
const uint8_t* action = actionTableStart + (actionEntry - 1);
+ bool hasCleanup = false;
// Scan action entries until you find a matching handler, cleanup, or the end of action list
while (true)
{
const __shim_type_info* catchType =
get_shim_type_info(static_cast<uint64_t>(ttypeIndex),
classInfo, ttypeEncoding,
- native_exception, unwind_exception);
+ native_exception, unwind_exception,
+ base);
if (catchType == 0)
{
- // Found catch (...) catches everything, including foreign exceptions
- // If this is a type 1 search save state and return _URC_HANDLER_FOUND
- // If this is a type 2 search save state and return _URC_HANDLER_FOUND
- // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
- // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
- if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
- {
- // Save state and return _URC_HANDLER_FOUND
- results.ttypeIndex = ttypeIndex;
- results.actionRecord = actionRecord;
- results.landingPad = landingPad;
- results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
- results.reason = _URC_HANDLER_FOUND;
- return;
- }
- else if (!(actions & _UA_FORCE_UNWIND))
- {
- // It looks like the exception table has changed
- // on us. Likely stack corruption!
- call_terminate(native_exception, unwind_exception);
- }
+ // Found catch (...) catches everything, including
+ // foreign exceptions. This is search phase, cleanup
+ // phase with foreign exception, or forced unwinding.
+ assert(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME |
+ _UA_FORCE_UNWIND));
+ results.ttypeIndex = ttypeIndex;
+ results.actionRecord = actionRecord;
+ results.adjustedPtr =
+ get_thrown_object_ptr(unwind_exception);
+ results.reason = _URC_HANDLER_FOUND;
+ return;
}
// Else this is a catch (T) clause and will never
// catch a foreign exception
}
if (catchType->can_catch(excpType, adjustedPtr))
{
- // Found a matching handler
- // If this is a type 1 search save state and return _URC_HANDLER_FOUND
- // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1!
- // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan
- if (actions & _UA_SEARCH_PHASE)
- {
- // Save state and return _URC_HANDLER_FOUND
- results.ttypeIndex = ttypeIndex;
- results.actionRecord = actionRecord;
- results.landingPad = landingPad;
- results.adjustedPtr = adjustedPtr;
- results.reason = _URC_HANDLER_FOUND;
- return;
- }
- else if (!(actions & _UA_FORCE_UNWIND))
- {
- // It looks like the exception table has changed
- // on us. Likely stack corruption!
- call_terminate(native_exception, unwind_exception);
- }
+ // Found a matching handler. This is either search
+ // phase or forced unwinding.
+ assert(actions &
+ (_UA_SEARCH_PHASE | _UA_FORCE_UNWIND));
+ results.ttypeIndex = ttypeIndex;
+ results.actionRecord = actionRecord;
+ results.adjustedPtr = adjustedPtr;
+ results.reason = _URC_HANDLER_FOUND;
+ return;
}
}
// Scan next action ...
}
else if (ttypeIndex < 0)
{
- // Found an exception spec. If this is a foreign exception,
- // it is always caught.
- if (native_exception)
- {
+ // Found an exception specification.
+ if (actions & _UA_FORCE_UNWIND) {
+ // Skip if forced unwinding.
+ } else if (native_exception) {
// Does the exception spec catch this native exception?
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
void* adjustedPtr = get_thrown_object_ptr(unwind_exception);
}
if (exception_spec_can_catch(ttypeIndex, classInfo,
ttypeEncoding, excpType,
- adjustedPtr, unwind_exception))
+ adjustedPtr,
+ unwind_exception, base))
{
- // native exception caught by exception spec
- // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
- // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
- // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
- if (actions & _UA_SEARCH_PHASE)
- {
- // Save state and return _URC_HANDLER_FOUND
- results.ttypeIndex = ttypeIndex;
- results.actionRecord = actionRecord;
- results.landingPad = landingPad;
- results.adjustedPtr = adjustedPtr;
- results.reason = _URC_HANDLER_FOUND;
- return;
- }
- else if (!(actions & _UA_FORCE_UNWIND))
- {
- // It looks like the exception table has changed
- // on us. Likely stack corruption!
- call_terminate(native_exception, unwind_exception);
- }
- }
- }
- else
- {
- // foreign exception caught by exception spec
- // If this is a type 1 search, save state and return _URC_HANDLER_FOUND
- // If this is a type 2 search, save state and return _URC_HANDLER_FOUND
- // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1!
- // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan
- if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME))
- {
- // Save state and return _URC_HANDLER_FOUND
+ // Native exception caught by exception
+ // specification.
+ assert(actions & _UA_SEARCH_PHASE);
results.ttypeIndex = ttypeIndex;
results.actionRecord = actionRecord;
- results.landingPad = landingPad;
- results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
+ results.adjustedPtr = adjustedPtr;
results.reason = _URC_HANDLER_FOUND;
return;
}
- else if (!(actions & _UA_FORCE_UNWIND))
- {
- // It looks like the exception table has changed
- // on us. Likely stack corruption!
- call_terminate(native_exception, unwind_exception);
- }
- }
- // Scan next action ...
- }
- else // ttypeIndex == 0
- {
- // Found a cleanup
- // If this is a type 1 search, ignore it and continue scan
- // If this is a type 2 search, ignore it and continue scan
- // If this is a type 3 search, save state and return _URC_HANDLER_FOUND
- if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME))
- {
- // Save state and return _URC_HANDLER_FOUND
+ } else {
+ // foreign exception caught by exception spec
results.ttypeIndex = ttypeIndex;
results.actionRecord = actionRecord;
- results.landingPad = landingPad;
- results.adjustedPtr = get_thrown_object_ptr(unwind_exception);
+ results.adjustedPtr =
+ get_thrown_object_ptr(unwind_exception);
results.reason = _URC_HANDLER_FOUND;
return;
}
+ // Scan next action ...
+ } else {
+ hasCleanup = true;
}
const uint8_t* temp = action;
int64_t actionOffset = readSLEB128(&temp);
if (actionOffset == 0)
{
- // End of action list, no matching handler or cleanup found
- results.reason = _URC_CONTINUE_UNWIND;
+ // End of action list. If this is phase 2 and we have found
+ // a cleanup (ttypeIndex=0), return _URC_HANDLER_FOUND;
+ // otherwise return _URC_CONTINUE_UNWIND.
+ results.reason = hasCleanup && actions & _UA_CLEANUP_PHASE
+ ? _URC_HANDLER_FOUND
+ : _URC_CONTINUE_UNWIND;
return;
}
// Go to next action
// Possible stack corruption.
call_terminate(native_exception, unwind_exception);
}
-#endif // !__USING_SJLJ_EXCEPTIONS__
+#endif // !__USING_SJLJ_EXCEPTIONS__
} // there might be some tricky cases which break out of this loop
// It is possible that no eh table entry specify how to handle
bool native_exception = (exceptionClass & get_vendor_and_language) ==
(kOurExceptionClass & get_vendor_and_language);
scan_results results;
+ // Process a catch handler for a native exception first.
+ if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME) &&
+ native_exception) {
+ // Reload the results from the phase 1 cache.
+ __cxa_exception* exception_header =
+ (__cxa_exception*)(unwind_exception + 1) - 1;
+ results.ttypeIndex = exception_header->handlerSwitchValue;
+ results.actionRecord = exception_header->actionRecord;
+ results.languageSpecificData = exception_header->languageSpecificData;
+ results.landingPad =
+ reinterpret_cast<uintptr_t>(exception_header->catchTemp);
+ results.adjustedPtr = exception_header->adjustedPtr;
+
+ // Jump to the handler.
+ set_registers(unwind_exception, context, results);
+ // Cache base for calculating the address of ttype in
+ // __cxa_call_unexpected.
+ if (results.ttypeIndex < 0) {
+#if defined(_AIX)
+ exception_header->catchTemp = (void *)_Unwind_GetDataRelBase(context);
+#else
+ exception_header->catchTemp = 0;
+#endif
+ }
+ return _URC_INSTALL_CONTEXT;
+ }
+
+ // In other cases we need to scan LSDA.
+ scan_eh_tab(results, actions, native_exception, unwind_exception, context);
+ if (results.reason == _URC_CONTINUE_UNWIND ||
+ results.reason == _URC_FATAL_PHASE1_ERROR)
+ return results.reason;
+
if (actions & _UA_SEARCH_PHASE)
{
// Phase 1 search: All we're looking for in phase 1 is a handler that
// halts unwinding
- scan_eh_tab(results, actions, native_exception, unwind_exception, context);
- if (results.reason == _URC_HANDLER_FOUND)
- {
- // Found one. Can we cache the results somewhere to optimize phase 2?
- if (native_exception)
- {
- __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
- exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
- exception_header->actionRecord = results.actionRecord;
- exception_header->languageSpecificData = results.languageSpecificData;
- exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad);
- exception_header->adjustedPtr = results.adjustedPtr;
- }
- return _URC_HANDLER_FOUND;
+ assert(results.reason == _URC_HANDLER_FOUND);
+ if (native_exception) {
+ // For a native exception, cache the LSDA result.
+ __cxa_exception* exc = (__cxa_exception*)(unwind_exception + 1) - 1;
+ exc->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
+ exc->actionRecord = results.actionRecord;
+ exc->languageSpecificData = results.languageSpecificData;
+ exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
+ exc->adjustedPtr = results.adjustedPtr;
}
- // Did not find a catching-handler. Return the results of the scan
- // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR
- // if we were called improperly).
- return results.reason;
+ return _URC_HANDLER_FOUND;
}
- if (actions & _UA_CLEANUP_PHASE)
- {
- // Phase 2 search:
- // Did we find a catching handler in phase 1?
- if (actions & _UA_HANDLER_FRAME)
- {
- // Yes, phase 1 said we have a catching handler here.
- // Did we cache the results of the scan?
- if (native_exception)
- {
- // Yes, reload the results from the cache.
- __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
- results.ttypeIndex = exception_header->handlerSwitchValue;
- results.actionRecord = exception_header->actionRecord;
- results.languageSpecificData = exception_header->languageSpecificData;
- results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp);
- results.adjustedPtr = exception_header->adjustedPtr;
- }
- else
- {
- // No, do the scan again to reload the results.
- scan_eh_tab(results, actions, native_exception, unwind_exception, context);
- // Phase 1 told us we would find a handler. Now in Phase 2 we
- // didn't find a handler. The eh table should not be changing!
- if (results.reason != _URC_HANDLER_FOUND)
- call_terminate(native_exception, unwind_exception);
- }
- // Jump to the handler
- set_registers(unwind_exception, context, results);
- return _URC_INSTALL_CONTEXT;
- }
- // Either we didn't do a phase 1 search (due to forced unwinding), or
- // phase 1 reported no catching-handlers.
- // Search for a (non-catching) cleanup
- scan_eh_tab(results, actions, native_exception, unwind_exception, context);
- if (results.reason == _URC_HANDLER_FOUND)
- {
- // Found a non-catching handler. Jump to it:
- set_registers(unwind_exception, context, results);
- return _URC_INSTALL_CONTEXT;
- }
- // Did not find a cleanup. Return the results of the scan
- // (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR
- // if we were called improperly).
- return results.reason;
+
+ assert(actions & _UA_CLEANUP_PHASE);
+ assert(results.reason == _URC_HANDLER_FOUND);
+ set_registers(unwind_exception, context, results);
+ // Cache base for calculating the address of ttype in __cxa_call_unexpected.
+ if (results.ttypeIndex < 0) {
+ __cxa_exception* exception_header =
+ (__cxa_exception*)(unwind_exception + 1) - 1;
+#if defined(_AIX)
+ exception_header->catchTemp = (void *)_Unwind_GetDataRelBase(context);
+#else
+ exception_header->catchTemp = 0;
+#endif
}
- // We were called improperly: neither a phase 1 or phase 2 search
- return _URC_FATAL_PHASE1_ERROR;
+ return _URC_INSTALL_CONTEXT;
}
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
__cxa_exception* old_exception_header = 0;
int64_t ttypeIndex;
const uint8_t* lsda;
+ uintptr_t base = 0;
+
if (native_old_exception)
{
old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
#else
ttypeIndex = old_exception_header->handlerSwitchValue;
lsda = old_exception_header->languageSpecificData;
+ base = (uintptr_t)old_exception_header->catchTemp;
#endif
}
else
// Have:
// old_exception_header->languageSpecificData
// old_exception_header->actionRecord
+ // old_exception_header->catchTemp, base for calculating ttype
// Need
// const uint8_t* classInfo
// uint8_t ttypeEncoding
uint8_t lpStartEncoding = *lsda++;
- const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding);
+ const uint8_t* lpStart =
+ (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
(void)lpStart; // purposefully unused. Just needed to increment lsda.
uint8_t ttypeEncoding = *lsda++;
if (ttypeEncoding == DW_EH_PE_omit)
((__cxa_dependent_exception*)new_exception_header)->primaryException :
new_exception_header + 1;
if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
- excpType, adjustedPtr, unwind_exception))
+ excpType, adjustedPtr,
+ unwind_exception, base))
{
// We need to __cxa_end_catch, but for the old exception,
// not the new one. This is a little tricky ...
std::bad_exception be;
adjustedPtr = &be;
if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding,
- excpType, adjustedPtr, unwind_exception))
+ excpType, adjustedPtr,
+ unwind_exception, base))
{
// We need to __cxa_end_catch for both the old exception and the
// new exception. Technically we should do it in that order.
std::__terminate(t_handler);
}
+#if defined(_AIX)
+// Personality routine for EH using the range table. Make it an alias of
+// __gxx_personality_v0().
+_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(
+ int version, _Unwind_Action actions, uint64_t exceptionClass,
+ _Unwind_Exception* unwind_exception, _Unwind_Context* context)
+ __attribute__((__alias__("__gxx_personality_v0")));
+#endif
+
} // extern "C"
} // __cxxabiv1
X(PostfixExpr) \
X(ConditionalExpr) \
X(MemberExpr) \
+ X(SubobjectExpr) \
X(EnclosingExpr) \
X(CastExpr) \
X(SizeofParamPackExpr) \
X(PrefixExpr) \
X(FunctionParam) \
X(ConversionExpr) \
+ X(PointerToMemberConversionExpr) \
X(InitListExpr) \
X(FoldExpr) \
X(ThrowExpr) \
- X(UUIDOfExpr) \
X(BoolExpr) \
X(StringLiteral) \
X(LambdaExpr) \
class VendorExtQualType final : public Node {
const Node *Ty;
StringView Ext;
+ const Node *TA;
public:
- VendorExtQualType(const Node *Ty_, StringView Ext_)
- : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}
+ VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
+ : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
- template<typename Fn> void match(Fn F) const { F(Ty, Ext); }
+ template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
void printLeft(OutputStream &S) const override {
Ty->print(S);
S += " ";
S += Ext;
+ if (TA != nullptr)
+ TA->print(S);
}
};
}
};
+class SubobjectExpr : public Node {
+ const Node *Type;
+ const Node *SubExpr;
+ StringView Offset;
+ NodeArray UnionSelectors;
+ bool OnePastTheEnd;
+
+public:
+ SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
+ NodeArray UnionSelectors_, bool OnePastTheEnd_)
+ : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
+ UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
+
+ template<typename Fn> void match(Fn F) const {
+ F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
+ }
+
+ void printLeft(OutputStream &S) const override {
+ SubExpr->print(S);
+ S += ".<";
+ Type->print(S);
+ S += " at offset ";
+ if (Offset.empty()) {
+ S += "0";
+ } else if (Offset[0] == 'n') {
+ S += "-";
+ S += Offset.dropFront();
+ } else {
+ S += Offset;
+ }
+ S += ">";
+ }
+};
+
class EnclosingExpr : public Node {
const StringView Prefix;
const Node *Infix;
}
};
+class PointerToMemberConversionExpr : public Node {
+ const Node *Type;
+ const Node *SubExpr;
+ StringView Offset;
+
+public:
+ PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
+ StringView Offset_)
+ : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_),
+ Offset(Offset_) {}
+
+ template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
+
+ void printLeft(OutputStream &S) const override {
+ S += "(";
+ Type->print(S);
+ S += ")(";
+ SubExpr->print(S);
+ S += ")";
+ }
+};
+
class InitListExpr : public Node {
const Node *Ty;
NodeArray Inits;
}
};
-// MSVC __uuidof extension, generated by clang in -fms-extensions mode.
-class UUIDOfExpr : public Node {
- Node *Operand;
-public:
- UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {}
-
- template<typename Fn> void match(Fn F) const { F(Operand); }
-
- void printLeft(OutputStream &S) const override {
- S << "__uuidof(";
- Operand->print(S);
- S << ")";
- }
-};
-
class BoolExpr : public Node {
bool Value;
TemplateParamList Params;
public:
- ScopedTemplateParamList(AbstractManglingParser *Parser)
- : Parser(Parser),
- OldNumTemplateParamLists(Parser->TemplateParams.size()) {
+ ScopedTemplateParamList(AbstractManglingParser *TheParser)
+ : Parser(TheParser),
+ OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Parser->TemplateParams.push_back(&Params);
}
~ScopedTemplateParamList() {
Node *parseConversionExpr();
Node *parseBracedExpr();
Node *parseFoldExpr();
+ Node *parsePointerToMemberConversionExpr();
+ Node *parseSubobjectExpr();
/// Parse the <type> production.
Node *parseType();
if (Qual.empty())
return nullptr;
- // FIXME parse the optional <template-args> here!
-
// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
if (Qual.startsWith("objcproto")) {
StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
return make<ObjCProtoName>(Child, Proto);
}
+ Node *TA = nullptr;
+ if (look() == 'I') {
+ TA = getDerived().parseTemplateArgs();
+ if (TA == nullptr)
+ return nullptr;
+ }
+
Node *Child = getDerived().parseQualifiedType();
if (Child == nullptr)
return nullptr;
- return make<VendorExtQualType>(Child, Qual);
+ return make<VendorExtQualType>(Child, Qual, TA);
}
Qualifiers Quals = parseCVQualifiers();
// ::= Dh # IEEE 754r half-precision floating point (16 bits)
case 'h':
First += 2;
- return make<NameType>("decimal16");
+ return make<NameType>("half");
// ::= Di # char32_t
case 'i':
First += 2;
return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
}
+// <expression> ::= mc <parameter type> <expr> [<offset number>] E
+//
+// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() {
+ Node *Ty = getDerived().parseType();
+ if (!Ty)
+ return nullptr;
+ Node *Expr = getDerived().parseExpr();
+ if (!Expr)
+ return nullptr;
+ StringView Offset = getDerived().parseNumber(true);
+ if (!consumeIf('E'))
+ return nullptr;
+ return make<PointerToMemberConversionExpr>(Ty, Expr, Offset);
+}
+
+// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
+// <union-selector> ::= _ [<number>]
+//
+// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
+ Node *Ty = getDerived().parseType();
+ if (!Ty)
+ return nullptr;
+ Node *Expr = getDerived().parseExpr();
+ if (!Expr)
+ return nullptr;
+ StringView Offset = getDerived().parseNumber(true);
+ size_t SelectorsBegin = Names.size();
+ while (consumeIf('_')) {
+ Node *Selector = make<NameType>(parseNumber());
+ if (!Selector)
+ return nullptr;
+ Names.push_back(Selector);
+ }
+ bool OnePastTheEnd = consumeIf('p');
+ if (!consumeIf('E'))
+ return nullptr;
+ return make<SubobjectExpr>(
+ Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
+}
+
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
// ::= <ternary operator-name> <expression> <expression> <expression>
return nullptr;
case 'm':
switch (First[1]) {
+ case 'c':
+ First += 2;
+ return parsePointerToMemberConversionExpr();
case 'i':
First += 2;
return getDerived().parseBinaryExpr("-");
return Ex;
return make<CastExpr>("static_cast", T, Ex);
}
+ case 'o':
+ First += 2;
+ return parseSubobjectExpr();
case 'p': {
First += 2;
Node *Child = getDerived().parseExpr();
}
}
return nullptr;
+ case 'u': {
+ ++First;
+ Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
+ if (!Name)
+ return nullptr;
+ // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
+ // standard encoding expects a <template-arg>, and would be otherwise be
+ // interpreted as <type> node 'short' or 'ellipsis'. However, neither
+ // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
+ // actual conflict here.
+ if (Name->getBaseName() == "__uuidof") {
+ if (numLeft() < 2)
+ return nullptr;
+ if (*First == 't') {
+ ++First;
+ Node *Ty = getDerived().parseType();
+ if (!Ty)
+ return nullptr;
+ return make<CallExpr>(Name, makeNodeArray(&Ty, &Ty + 1));
+ }
+ if (*First == 'z') {
+ ++First;
+ Node *Ex = getDerived().parseExpr();
+ if (!Ex)
+ return nullptr;
+ return make<CallExpr>(Name, makeNodeArray(&Ex, &Ex + 1));
+ }
+ }
+ size_t ExprsBegin = Names.size();
+ while (!consumeIf('E')) {
+ Node *E = getDerived().parseTemplateArg();
+ if (E == nullptr)
+ return E;
+ Names.push_back(E);
+ }
+ return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin));
+ }
case '1':
case '2':
case '3':
case '9':
return getDerived().parseUnresolvedName();
}
-
- if (consumeIf("u8__uuidoft")) {
- Node *Ty = getDerived().parseType();
- if (!Ty)
- return nullptr;
- return make<UUIDOfExpr>(Ty);
- }
-
- if (consumeIf("u8__uuidofz")) {
- Node *Ex = getDerived().parseExpr();
- if (!Ex)
- return nullptr;
- return make<UUIDOfExpr>(Ex);
- }
-
return nullptr;
}
switch (look()) {
case 'T':
switch (look(1)) {
+ // TA <template-arg> # template parameter object
+ //
+ // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
+ case 'A': {
+ First += 2;
+ Node *Arg = getDerived().parseTemplateArg();
+ if (Arg == nullptr)
+ return nullptr;
+ return make<SpecialName>("template parameter object for ", Arg);
+ }
// TV <type> # virtual table
case 'V': {
First += 2;
class SaveTemplateParams {
AbstractManglingParser *Parser;
decltype(TemplateParams) OldParams;
+ decltype(OuterTemplateParams) OldOuterParams;
public:
- SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) {
+ SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
OldParams = std::move(Parser->TemplateParams);
+ OldOuterParams = std::move(Parser->OuterTemplateParams);
Parser->TemplateParams.clear();
+ Parser->OuterTemplateParams.clear();
}
~SaveTemplateParams() {
Parser->TemplateParams = std::move(OldParams);
+ Parser->OuterTemplateParams = std::move(OldOuterParams);
}
} SaveTemplateParams(this);
#else
static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
#endif
- static const size_t max_demangled_size = 40;
+ // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
+ // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
+ // Negatives are one character longer than positives.
+ // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
+ // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
+ static const size_t max_demangled_size = 42;
static constexpr const char *spec = "%LaL";
};
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
StringView() : First(nullptr), Last(nullptr) {}
- StringView substr(size_t From) const {
- return StringView(begin() + From, size() - From);
+ StringView substr(size_t Pos, size_t Len = npos) const {
+ assert(Pos <= size());
+ return StringView(begin() + Pos, std::min(Len, size() - Pos));
}
size_t find(char C, size_t From = 0) const {
return npos;
}
- StringView substr(size_t From, size_t To) const {
- if (To >= size())
- To = size() - 1;
- if (From >= size())
- From = size() - 1;
- return StringView(First + From, First + To);
- }
-
StringView dropFront(size_t N = 1) const {
if (N >= size())
N = size();
char *TempPtr = std::end(Temp);
while (N) {
- *--TempPtr = '0' + char(N % 10);
+ *--TempPtr = char('0' + N % 10);
N /= 10;
}
//
//===----------------------------------------------------------------------===//
-// Define _LIBCPP_BUILDING_LIBRARY to ensure _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
-// is only defined when libc aligned allocation is not available.
-#define _LIBCPP_BUILDING_LIBRARY
#include "fallback_malloc.h"
#include <__threading_support>
#include <stdlib.h> // for malloc, calloc, free
#include <string.h> // for memset
+#include <new> // for std::__libcpp_aligned_{alloc,free}
// A small, simple heap manager based (loosely) on
// the startup heap manager from FreeBSD, optimized for space.
mutexor mtx(&heap_mutex);
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << "Freeing item at " << offset_from_node(cp) << " of size "
- << cp->len << std::endl;
+ std::printf("Freeing item at %d of size %d\n", offset_from_node(cp), cp->len);
#endif
for (p = freelist, prev = 0; p && p != list_end;
prev = p, p = node_from_offset(p->next_node)) {
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << " p, cp, after (p), after(cp) " << offset_from_node(p) << ' '
- << offset_from_node(cp) << ' ' << offset_from_node(after(p))
- << ' ' << offset_from_node(after(cp)) << std::endl;
+ std::printf(" p=%d, cp=%d, after(p)=%d, after(cp)=%d\n",
+ offset_from_node(p), offset_from_node(cp),
+ offset_from_node(after(p)), offset_from_node(after(cp)));
#endif
if (after(p) == cp) {
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << " Appending onto chunk at " << offset_from_node(p)
- << std::endl;
+ std::printf(" Appending onto chunk at %d\n", offset_from_node(p));
#endif
p->len = static_cast<heap_size>(
p->len + cp->len); // make the free heap_node larger
return;
} else if (after(cp) == p) { // there's a free heap_node right after
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << " Appending free chunk at " << offset_from_node(p)
- << std::endl;
+ std::printf(" Appending free chunk at %d\n", offset_from_node(p));
#endif
cp->len = static_cast<heap_size>(cp->len + p->len);
if (prev == 0) {
}
// Nothing to merge with, add it to the start of the free list
#ifdef DEBUG_FALLBACK_MALLOC
- std::cout << " Making new free list entry " << offset_from_node(cp)
- << std::endl;
+ std::printf(" Making new free list entry %d\n", offset_from_node(cp));
#endif
cp->next_node = offset_from_node(freelist);
freelist = cp;
for (p = freelist, prev = 0; p && p != list_end;
prev = p, p = node_from_offset(p->next_node)) {
- std::cout << (prev == 0 ? "" : " ") << "Offset: " << offset_from_node(p)
- << "\tsize: " << p->len << " Next: " << p->next_node << std::endl;
+ std::printf("%sOffset: %d\tsize: %d Next: %d\n",
+ (prev == 0 ? "" : " "), offset_from_node(p), p->len, p->next_node);
total_free += p->len;
}
- std::cout << "Total Free space: " << total_free << std::endl;
+ std::printf("Total Free space: %d\n", total_free);
return total_free;
}
#endif
void* __aligned_malloc_with_fallback(size_t size) {
#if defined(_WIN32)
- if (void* dest = _aligned_malloc(size, alignof(__aligned_type)))
+ if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size))
return dest;
#elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
if (void* dest = ::malloc(size))
#else
if (size == 0)
size = 1;
- void* dest;
- if (::posix_memalign(&dest, __alignof(__aligned_type), size) == 0)
+ if (void* dest = std::__libcpp_aligned_alloc(__alignof(__aligned_type), size))
return dest;
#endif
return fallback_malloc(size);
if (is_fallback_ptr(ptr))
fallback_free(ptr);
else {
-#if defined(_WIN32)
- ::_aligned_free(ptr);
-#else
+#if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
::free(ptr);
+#else
+ std::__libcpp_aligned_free(ptr);
#endif
}
}
return x == y || strcmp(x->name(), y->name()) == 0;
}
+static inline ptrdiff_t update_offset_to_base(const char* vtable,
+ ptrdiff_t offset_to_base) {
+#if __has_feature(cxx_abi_relative_vtable)
+ // VTable components are 32 bits in the relative vtables ABI.
+ return *reinterpret_cast<const int32_t*>(vtable + offset_to_base);
+#else
+ return *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+#endif
+}
+
namespace __cxxabiv1
{
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(adjustedPtr);
- offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+ offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
}
__base_type->has_unambiguous_public_base(
// Possible future optimization: Take advantage of src2dst_offset
// Get (dynamic_ptr, dynamic_type) from static_ptr
+#if __has_feature(cxx_abi_relative_vtable)
+ // The vtable address will point to the first virtual function, which is 8
+ // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component).
+ const int32_t* vtable =
+ *reinterpret_cast<const int32_t* const*>(static_ptr);
+ int32_t offset_to_derived = vtable[-2];
+ const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
+
+ // The typeinfo component is now a relative offset to a proxy.
+ int32_t offset_to_ti_proxy = vtable[-1];
+ const uint8_t* ptr_to_ti_proxy =
+ reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
+ const __class_type_info* dynamic_type =
+ *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
+#else
void **vtable = *static_cast<void ** const *>(static_ptr);
ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
+#endif
// Initialize answer to nullptr. This will be changed from the search
// results if a non-null answer is found. Regardless, this is what will
{
// We get here only if there is some kind of visibility problem
// in client code.
+ static_assert(std::atomic<size_t>::is_always_lock_free, "");
static std::atomic<size_t> error_count(0);
size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
info.number_of_dst_type = 1;
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
}
-#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// Query the search.
if (info.path_dst_ptr_to_static_ptr == public_path)
dst_ptr = dynamic_ptr;
if (info.path_dst_ptr_to_static_ptr == unknown &&
info.path_dynamic_ptr_to_static_ptr == unknown)
{
+ static_assert(std::atomic<size_t>::is_always_lock_free, "");
static std::atomic<size_t> error_count(0);
size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
}
-#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// Query the search.
switch (info.number_to_static_ptr)
{
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(current_ptr);
- offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+ offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
__base_type->search_above_dst(info, dst_ptr,
static_cast<const char*>(current_ptr) + offset_to_base,
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(current_ptr);
- offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base);
+ offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
__base_type->search_below_dst(info,
static_cast<const char*>(current_ptr) + offset_to_base,
} // __cxxabiv1
-#endif // __PRIVATE_TYPEINFO_H_
+#endif // __PRIVATE_TYPEINFO_H_
//
//===----------------------------------------------------------------------===//
-#define _LIBCPP_BUILDING_LIBRARY
#include <new>
#include <exception>
// exception
-exception::~exception() _NOEXCEPT
+exception::~exception() noexcept
{
}
-const char* exception::what() const _NOEXCEPT
+const char* exception::what() const noexcept
{
return "std::exception";
}
// bad_exception
-bad_exception::~bad_exception() _NOEXCEPT
+bad_exception::~bad_exception() noexcept
{
}
-const char* bad_exception::what() const _NOEXCEPT
+const char* bad_exception::what() const noexcept
{
return "std::bad_exception";
}
// bad_alloc
-bad_alloc::bad_alloc() _NOEXCEPT
+bad_alloc::bad_alloc() noexcept
{
}
-bad_alloc::~bad_alloc() _NOEXCEPT
+bad_alloc::~bad_alloc() noexcept
{
}
const char*
-bad_alloc::what() const _NOEXCEPT
+bad_alloc::what() const noexcept
{
return "std::bad_alloc";
}
// bad_array_new_length
-bad_array_new_length::bad_array_new_length() _NOEXCEPT
+bad_array_new_length::bad_array_new_length() noexcept
{
}
-bad_array_new_length::~bad_array_new_length() _NOEXCEPT
+bad_array_new_length::~bad_array_new_length() noexcept
{
}
const char*
-bad_array_new_length::what() const _NOEXCEPT
+bad_array_new_length::what() const noexcept
{
return "bad_array_new_length";
}
// This file implements the new and delete operators.
//===----------------------------------------------------------------------===//
-#define _LIBCPP_BUILDING_LIBRARY
#include "__cxxabi_config.h"
#include <new>
#include <cstdlib>
-#if !defined(_THROW_BAD_ALLOC) || !defined(_NOEXCEPT) || !defined(_LIBCXXABI_WEAK)
-#error The _THROW_BAD_ALLOC, _NOEXCEPT, and _LIBCXXABI_WEAK libc++ macros must \
+#if !defined(_THROW_BAD_ALLOC) || !defined(_LIBCXXABI_WEAK)
+#error The _THROW_BAD_ALLOC and _LIBCXXABI_WEAK libc++ macros must \
already be defined by libc++.
#endif
// Implement all new and delete operators as weak definitions
if (size == 0)
size = 1;
void* p;
- while ((p = ::malloc(size)) == 0)
+ while ((p = ::malloc(size)) == nullptr)
{
// If malloc fails and there is a new_handler,
// call it to try free up memory.
_LIBCXXABI_WEAK
void*
-operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
+operator new(size_t size, const std::nothrow_t&) noexcept
{
- void* p = 0;
+ void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
p = ::operator new(size);
#ifndef _LIBCXXABI_NO_EXCEPTIONS
}
catch (...)
{
}
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
return p;
}
_LIBCXXABI_WEAK
void*
-operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
+operator new[](size_t size, const std::nothrow_t&) noexcept
{
- void* p = 0;
+ void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
p = ::operator new[](size);
#ifndef _LIBCXXABI_NO_EXCEPTIONS
}
catch (...)
{
}
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
return p;
}
_LIBCXXABI_WEAK
void
-operator delete(void* ptr) _NOEXCEPT
+operator delete(void* ptr) noexcept
{
- if (ptr)
- ::free(ptr);
+ ::free(ptr);
}
_LIBCXXABI_WEAK
void
-operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
+operator delete(void* ptr, const std::nothrow_t&) noexcept
{
::operator delete(ptr);
}
_LIBCXXABI_WEAK
void
-operator delete(void* ptr, size_t) _NOEXCEPT
+operator delete(void* ptr, size_t) noexcept
{
::operator delete(ptr);
}
_LIBCXXABI_WEAK
void
-operator delete[] (void* ptr) _NOEXCEPT
+operator delete[] (void* ptr) noexcept
{
::operator delete(ptr);
}
_LIBCXXABI_WEAK
void
-operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
+operator delete[] (void* ptr, const std::nothrow_t&) noexcept
{
::operator delete[](ptr);
}
_LIBCXXABI_WEAK
void
-operator delete[] (void* ptr, size_t) _NOEXCEPT
+operator delete[] (void* ptr, size_t) noexcept
{
::operator delete[](ptr);
}
size = 1;
if (static_cast<size_t>(alignment) < sizeof(void*))
alignment = std::align_val_t(sizeof(void*));
+
+ // Try allocating memory. If allocation fails and there is a new_handler,
+ // call it to try free up memory, and try again until it succeeds, or until
+ // the new_handler decides to terminate.
+ //
+ // If allocation fails and there is no new_handler, we throw bad_alloc
+ // (or return nullptr if exceptions are disabled).
void* p;
-#if defined(_LIBCPP_WIN32API)
- while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
-#else
- while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
-#endif
+ while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr)
{
- // If posix_memalign fails and there is a new_handler,
- // call it to try free up memory.
std::new_handler nh = std::get_new_handler();
if (nh)
nh();
#ifndef _LIBCXXABI_NO_EXCEPTIONS
throw std::bad_alloc();
#else
- p = nullptr; // posix_memalign doesn't initialize 'p' on failure
break;
#endif
}
_LIBCXXABI_WEAK
void*
-operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
{
- void* p = 0;
+ void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
p = ::operator new(size, alignment);
#ifndef _LIBCXXABI_NO_EXCEPTIONS
}
catch (...)
{
}
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
return p;
}
_LIBCXXABI_WEAK
void*
-operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
{
- void* p = 0;
+ void* p = nullptr;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
p = ::operator new[](size, alignment);
#ifndef _LIBCXXABI_NO_EXCEPTIONS
}
catch (...)
{
}
-#endif // _LIBCXXABI_NO_EXCEPTIONS
+#endif // _LIBCXXABI_NO_EXCEPTIONS
return p;
}
_LIBCXXABI_WEAK
void
-operator delete(void* ptr, std::align_val_t) _NOEXCEPT
+operator delete(void* ptr, std::align_val_t) noexcept
{
- if (ptr)
-#if defined(_LIBCPP_WIN32API)
- ::_aligned_free(ptr);
-#else
- ::free(ptr);
-#endif
+ std::__libcpp_aligned_free(ptr);
}
_LIBCXXABI_WEAK
void
-operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
{
::operator delete(ptr, alignment);
}
_LIBCXXABI_WEAK
void
-operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
+operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept
{
::operator delete(ptr, alignment);
}
_LIBCXXABI_WEAK
void
-operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT
+operator delete[] (void* ptr, std::align_val_t alignment) noexcept
{
::operator delete(ptr, alignment);
}
_LIBCXXABI_WEAK
void
-operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
+operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
{
::operator delete[](ptr, alignment);
}
_LIBCXXABI_WEAK
void
-operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
+operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept
{
::operator delete[](ptr, alignment);
}
//
//===----------------------------------------------------------------------===//
-#include "include/refstring.h"
#include "stdexcept"
#include "new"
#include <cstdlib>
#include <cstdint>
#include <cstddef>
+// This includes an implementation file from libc++.
+#include "src/include/refstring.h"
+
static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), "");
namespace std // purposefully not using versioning namespace
{
-logic_error::~logic_error() _NOEXCEPT {}
+logic_error::~logic_error() noexcept {}
const char*
-logic_error::what() const _NOEXCEPT
+logic_error::what() const noexcept
{
return __imp_.c_str();
}
-runtime_error::~runtime_error() _NOEXCEPT {}
+runtime_error::~runtime_error() noexcept {}
const char*
-runtime_error::what() const _NOEXCEPT
+runtime_error::what() const noexcept
{
return __imp_.c_str();
}
-domain_error::~domain_error() _NOEXCEPT {}
-invalid_argument::~invalid_argument() _NOEXCEPT {}
-length_error::~length_error() _NOEXCEPT {}
-out_of_range::~out_of_range() _NOEXCEPT {}
+domain_error::~domain_error() noexcept {}
+invalid_argument::~invalid_argument() noexcept {}
+length_error::~length_error() noexcept {}
+out_of_range::~out_of_range() noexcept {}
-range_error::~range_error() _NOEXCEPT {}
-overflow_error::~overflow_error() _NOEXCEPT {}
-underflow_error::~underflow_error() _NOEXCEPT {}
+range_error::~range_error() noexcept {}
+overflow_error::~overflow_error() noexcept {}
+underflow_error::~underflow_error() noexcept {}
} // std
// bad_cast
-bad_cast::bad_cast() _NOEXCEPT
+bad_cast::bad_cast() noexcept
{
}
-bad_cast::~bad_cast() _NOEXCEPT
+bad_cast::~bad_cast() noexcept
{
}
const char*
-bad_cast::what() const _NOEXCEPT
+bad_cast::what() const noexcept
{
return "std::bad_cast";
}
// bad_typeid
-bad_typeid::bad_typeid() _NOEXCEPT
+bad_typeid::bad_typeid() noexcept
{
}
-bad_typeid::~bad_typeid() _NOEXCEPT
+bad_typeid::~bad_typeid() noexcept
{
}
const char*
-bad_typeid::what() const _NOEXCEPT
+bad_typeid::what() const noexcept
{
return "std::bad_typeid";
}