diff options
author | Dan Albert <danalbert@google.com> | 2017-01-31 23:33:25 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-01-31 23:33:25 +0000 |
commit | 72c474b3d4bb91253f767a8d4f13956e4f13c1e2 (patch) | |
tree | 43381406b927ad0b1e121d36fb50e30c47a1f5cb | |
parent | b53cf167f7e022ffa95f40cc22968beaefd6d15d (diff) | |
parent | 838ac37536c79c8e627b9dba862b341da8974136 (diff) | |
download | libcxxabi-72c474b3d4bb91253f767a8d4f13956e4f13c1e2.tar.gz |
Merge to upstream r293166. am: 467bf41d66 am: 444d5607de
am: 838ac37536
Change-Id: Ifad782f0eb70b3080b6c8e745339890a6c3f9b98
47 files changed, 356 insertions, 414 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5eb0109..8f23b7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,8 +49,20 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include") set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree") set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") - set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") set(LLVM_LIT_PATH "${LLVM_PATH}/utils/lit/lit.py") + + # --cmakedir is supported since llvm r291218 (4.0 release) + execute_process( + COMMAND ${LLVM_CONFIG_PATH} --cmakedir + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE CONFIG_OUTPUT + ERROR_QUIET) + if(NOT HAD_ERROR) + string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH) + else() + set(LLVM_CMAKE_PATH + "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") + endif() else() message(FATAL_ERROR "llvm-config not found and LLVM_MAIN_SRC_DIR not defined. " "Reconfigure with -DLLVM_CONFIG_PATH=path/to/llvm-config " @@ -66,10 +78,14 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) endif() set(PACKAGE_NAME libcxxabi) - set(PACKAGE_VERSION 4.0.0svn) + set(PACKAGE_VERSION 5.0.0svn) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") + if (NOT DEFINED LLVM_INCLUDE_TESTS) + set(LLVM_INCLUDE_TESTS ON) + endif() + if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) else() @@ -118,7 +134,14 @@ option(LIBCXXABI_USE_LLVM_UNWINDER "Build and use 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_EXTERNAL_THREAD_API + "Build libc++abi with an externalized threading API. + This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON." OFF) +option(LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY + "Build libc++abi with an externalized threading library. + This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON" OFF) option(LIBCXXABI_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_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.") @@ -347,18 +370,59 @@ if (NOT LIBCXXABI_ENABLE_SHARED) list(APPEND LIBCXXABI_COMPILE_FLAGS -D_LIBCPP_BUILD_STATIC) endif() +# Threading if (NOT LIBCXXABI_ENABLE_THREADS) if (LIBCXXABI_HAS_PTHREAD_API) message(FATAL_ERROR "LIBCXXABI_HAS_PTHREAD_API can only" " be set to ON when LIBCXXABI_ENABLE_THREADS" " is also set to ON.") endif() + if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) + message(FATAL_ERROR "LIBCXXABI_HAS_EXTERNAL_THREAD_API can only" + " be set to ON when LIBCXXABI_ENABLE_THREADS" + " is also set to ON.") + endif() + if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY) + message(FATAL_ERROR "LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY can only" + " be set to ON when LIBCXXABI_ENABLE_THREADS" + " is also set to ON.") + endif() add_definitions(-D_LIBCXXABI_HAS_NO_THREADS) endif() +if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) + if (LIBCXXABI_HAS_PTHREAD_API) + message(FATAL_ERROR "The options LIBCXXABI_HAS_EXTERNAL_THREAD_API" + " and LIBCXXABI_HAS_PTHREAD_API cannot be both" + " set to ON at the same time.") + endif() + if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY) + message(FATAL_ERROR "The options LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY" + " and LIBCXXABI_HAS_EXTERNAL_THREAD_API cannot be both" + " set to ON at the same time.") + endif() +endif() + +if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY AND LIBCXXABI_ENABLE_SHARED) + # Need to allow unresolved symbols if this is to work with shared library builds + if (APPLE) + add_link_flags("-undefined dynamic_lookup") + else() + # Relax this restriction from HandleLLVMOptions + string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + endif() +endif() + if (LIBCXXABI_HAS_PTHREAD_API) add_definitions(-D_LIBCPP_HAS_THREAD_API_PTHREAD) - add_definitions(-D_LIBCXXABI_USE_THREAD_API_PTHREAD) +endif() + +if (LIBCXXABI_HAS_EXTERNAL_THREAD_API) + add_definitions(-D_LIBCPP_HAS_THREAD_API_EXTERNAL) +endif() + +if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY) + add_definitions(-D_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) endif() if (MSVC) @@ -370,6 +434,10 @@ if (LIBCXXABI_USE_LLVM_UNWINDER) add_definitions(-DLIBCXXABI_USE_LLVM_UNWINDER=1) endif() +if (LIBCXXABI_SILENT_TERMINATE) + add_definitions(-DLIBCXXABI_SILENT_TERMINATE=1) +endif() + string(REPLACE ";" " " LIBCXXABI_CXX_FLAGS "${LIBCXXABI_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LIBCXXABI_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBCXXABI_C_FLAGS}") @@ -411,15 +479,19 @@ if (LIBCXXABI_USE_LLVM_UNWINDER OR LLVM_NATIVE_ARCH MATCHES ARM) set(LIBCXXABI_LIBUNWIND_SOURCES "") endif() - include_directories("${LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL}") - include_directories("${LIBCXXABI_LIBUNWIND_SOURCES}") + if (NOT LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL STREQUAL "LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL-NOTFOUND") + include_directories("${LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL}") + endif() + if (NOT LIBCXXABI_LIBUNWIND_SOURCES STREQUAL "") + include_directories("${LIBCXXABI_LIBUNWIND_SOURCES}") + endif() endif() # Add source code. This also contains all of the logic for deciding linker flags # soname, etc... add_subdirectory(src) -if (LIBCXXABI_STANDALONE_BUILD AND NOT LIBCXXABI_ENABLE_SHARED) +if (NOT LIBCXXABI_INCLUDE_TESTS OR (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- @@ -432,4 +504,5 @@ if (LIBCXXABI_STANDALONE_BUILD AND NOT LIBCXXABI_ENABLE_SHARED) "available!") else() add_subdirectory(test) + add_subdirectory(fuzz) endif() diff --git a/LICENSE.TXT b/LICENSE.TXT index 14fd39a..f333f1f 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -14,7 +14,7 @@ Full text of the relevant licenses is included below. University of Illinois/NCSA Open Source License -Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT +Copyright (c) 2009-2017 by the contributors listed in CREDITS.TXT All rights reserved. diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt new file mode 100644 index 0000000..017427e --- /dev/null +++ b/fuzz/CMakeLists.txt @@ -0,0 +1,11 @@ +# See http://llvm.org/docs/LibFuzzer.html +if( LLVM_USE_SANITIZE_COVERAGE ) + add_executable(cxa_demangle_fuzzer + cxa_demangle_fuzzer.cpp + ../src/cxa_demangle.cpp + ) + + target_link_libraries(cxa_demangle_fuzzer + LLVMFuzzer + ) +endif() diff --git a/fuzz/cxa_demangle_fuzzer.cpp b/fuzz/cxa_demangle_fuzzer.cpp new file mode 100644 index 0000000..cc9b193 --- /dev/null +++ b/fuzz/cxa_demangle_fuzzer.cpp @@ -0,0 +1,15 @@ +#include <stdint.h> +#include <stddef.h> +#include <string.h> +#include <stdlib.h> +extern "C" char * +__cxa_demangle(const char *mangled_name, char *buf, size_t *n, int *status); + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + char *str = new char[size+1]; + memcpy(str, data, size); + str[size] = 0; + free(__cxa_demangle(str, 0, 0, 0)); + delete [] str; + return 0; +} diff --git a/include/__cxxabi_config.h b/include/__cxxabi_config.h index 0e7106e..2c58a22 100644 --- a/include/__cxxabi_config.h +++ b/include/__cxxabi_config.h @@ -22,7 +22,7 @@ #endif #if defined(_WIN32) - #if defined(_LIBCXXABI_DISABLE_DLL_IMPORT_EXPORT) + #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) #define _LIBCXXABI_HIDDEN #define _LIBCXXABI_DATA_VIS #define _LIBCXXABI_FUNC_VIS @@ -39,13 +39,20 @@ #define _LIBCXXABI_TYPE_VIS __declspec(dllimport) #endif #else - #define _LIBCXXABI_HIDDEN __attribute__((__visibility__("hidden"))) - #define _LIBCXXABI_DATA_VIS __attribute__((__visibility__("default"))) - #define _LIBCXXABI_FUNC_VIS __attribute__((__visibility__("default"))) - #if __has_attribute(__type_visibility__) - #define _LIBCXXABI_TYPE_VIS __attribute__((__type_visibility__("default"))) + #if !defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) + #define _LIBCXXABI_HIDDEN __attribute__((__visibility__("hidden"))) + #define _LIBCXXABI_DATA_VIS __attribute__((__visibility__("default"))) + #define _LIBCXXABI_FUNC_VIS __attribute__((__visibility__("default"))) + #if __has_attribute(__type_visibility__) + #define _LIBCXXABI_TYPE_VIS __attribute__((__type_visibility__("default"))) + #else + #define _LIBCXXABI_TYPE_VIS __attribute__((__visibility__("default"))) + #endif #else - #define _LIBCXXABI_TYPE_VIS __attribute__((__visibility__("default"))) + #define _LIBCXXABI_HIDDEN + #define _LIBCXXABI_DATA_VIS + #define _LIBCXXABI_FUNC_VIS + #define _LIBCXXABI_TYPE_VIS #endif #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e6bd381..efbea67 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ # Get sources set(LIBCXXABI_SOURCES - abort_message.cpp + # C++ABI files cxa_aux_runtime.cpp cxa_default_handlers.cpp cxa_demangle.cpp @@ -11,11 +11,14 @@ set(LIBCXXABI_SOURCES cxa_unexpected.cpp cxa_vector.cpp cxa_virtual.cpp - exception.cpp + # C++ STL files + stdlib_exception.cpp + stdlib_stdexcept.cpp + stdlib_typeinfo.cpp + # Internal files + abort_message.cpp fallback_malloc.cpp private_typeinfo.cpp - stdexcept.cpp - typeinfo.cpp ) if (LIBCXXABI_ENABLE_EXCEPTIONS) diff --git a/src/config.h b/src/config.h index 625ad1b..72a05e0 100644 --- a/src/config.h +++ b/src/config.h @@ -16,40 +16,6 @@ #include <unistd.h> -#ifndef __has_attribute - #define __has_attribute(x) 0 -#endif - -// Configure inline visibility attributes -#if defined(_WIN32) - #if defined(_MSC_VER) && !defined(__clang__) - // Using Microsoft Visual C++ compiler - #define _LIBCXXABI_INLINE_VISIBILITY __forceinline - #else - #if __has_attribute(__internal_linkage__) - #define _LIBCXXABI_INLINE_VISIBILITY __attribute__ ((__internal_linkage__, __always_inline__)) - #else - #define _LIBCXXABI_INLINE_VISIBILITY __attribute__ ((__always_inline__)) - #endif - #endif -#else - #if __has_attribute(__internal_linkage__) - #define _LIBCXXABI_INLINE_VISIBILITY __attribute__ ((__internal_linkage__, __always_inline__)) - #else - #define _LIBCXXABI_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__)) - #endif -#endif - -// Try and deduce a threading api if one has not been explicitly set. -#if !defined(_LIBCXXABI_HAS_NO_THREADS) && \ - !defined(_LIBCXXABI_USE_THREAD_API_PTHREAD) - #if defined(_POSIX_THREADS) && _POSIX_THREADS >= 0 - #define _LIBCXXABI_USE_THREAD_API_PTHREAD - #else - #error "No thread API" - #endif -#endif - // Set this in the CXXFLAGS when you need it, because otherwise we'd have to // #if !defined(__linux__) && !defined(__APPLE__) && ... // and so-on for *every* platform. @@ -57,4 +23,11 @@ # define LIBCXXABI_BAREMETAL 0 #endif +// The default terminate handler attempts to demangle uncaught exceptions, which +// causes extra I/O and demangling code to be pulled in. +// Set this to make the terminate handler default to a silent alternative. +#ifndef LIBCXXABI_SILENT_TERMINATE +# define LIBCXXABI_SILENT_TERMINATE 0 +#endif + #endif // LIBCXXABI_CONFIG_H diff --git a/src/cxa_default_handlers.cpp b/src/cxa_default_handlers.cpp index 09350e7..a1ea296 100644 --- a/src/cxa_default_handlers.cpp +++ b/src/cxa_default_handlers.cpp @@ -12,6 +12,7 @@ #include <stdexcept> #include <new> #include <exception> +#include <cstdlib> #include "abort_message.h" #include "config.h" // For __sync_swap #include "cxxabi.h" @@ -22,7 +23,7 @@ static const char* cause = "uncaught"; __attribute__((noreturn)) -static void default_terminate_handler() +static void demangling_terminate_handler() { // If there might be an uncaught exception using namespace __cxxabiv1; @@ -78,12 +79,19 @@ static void default_terminate_handler() } __attribute__((noreturn)) -static void default_unexpected_handler() +static void demangling_unexpected_handler() { cause = "unexpected"; std::terminate(); } +#if !LIBCXXABI_SILENT_TERMINATE +static std::terminate_handler default_terminate_handler = demangling_terminate_handler; +static std::terminate_handler default_unexpected_handler = demangling_unexpected_handler; +#else +static std::terminate_handler default_terminate_handler = std::abort; +static std::terminate_handler default_unexpected_handler = std::abort; +#endif // // Global variables that hold the pointers to the current handler diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp index 4aeed1b..8f5cb30 100644 --- a/src/cxa_demangle.cpp +++ b/src/cxa_demangle.cpp @@ -1927,10 +1927,11 @@ parse_type(const char* first, const char* last, C& db) if (is_function) { size_t p = db.names[k].second.size(); - if (db.names[k].second[p-2] == '&') - p -= 3; - else if (db.names[k].second.back() == '&') + if (db.names[k].second[p - 2] == '&' && + db.names[k].second[p - 1] == '&') p -= 2; + else if (db.names[k].second.back() == '&') + p -= 1; if (cv & 1) { db.names[k].second.insert(p, " const"); @@ -3058,9 +3059,9 @@ parse_unnamed_type_name(const char* first, const char* last, C& db) } if (t0 == last || *t0 != 'E') { - if(!db.names.empty()) + if (!db.names.empty()) db.names.pop_back(); - return first; + return first; } ++t0; if (t0 == last) @@ -4952,13 +4953,13 @@ struct Db sub_type names; template_param_type subs; Vector<template_param_type> template_param; - unsigned cv; - unsigned ref; - unsigned encoding_depth; - bool parsed_ctor_dtor_cv; - bool tag_templates; - bool fix_forward_references; - bool try_to_parse_template_args; + unsigned cv = 0; + unsigned ref = 0; + unsigned encoding_depth = 0; + bool parsed_ctor_dtor_cv = false; + bool tag_templates = true; + bool fix_forward_references = false; + bool try_to_parse_template_args = true; template <size_t N> Db(arena<N>& ar) : @@ -4979,29 +4980,12 @@ __cxa_demangle(const char *mangled_name, char *buf, size_t *n, int *status) { return nullptr; } - size_t len = std::strlen(mangled_name); - if (len < 2 || strncmp(mangled_name, "_Z", 2)) - { - if (len < 4 || strncmp(mangled_name, "___Z", 4)) - { - if (status) - *status = invalid_mangled_name; - return nullptr; - } - } - size_t internal_size = buf != nullptr ? *n : 0; arena<bs> a; Db db(a); - db.cv = 0; - db.ref = 0; - db.encoding_depth = 0; - db.parsed_ctor_dtor_cv = false; - db.tag_templates = true; db.template_param.emplace_back(a); - db.fix_forward_references = false; - db.try_to_parse_template_args = true; int internal_status = success; + size_t len = std::strlen(mangled_name); demangle(mangled_name, mangled_name + len, db, internal_status); if (internal_status == success && db.fix_forward_references && diff --git a/src/cxa_exception.cpp b/src/cxa_exception.cpp index f84c0e8..757b3d4 100644 --- a/src/cxa_exception.cpp +++ b/src/cxa_exception.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "config.h" -#include "threading_support.h" #include "cxxabi.h" #include <exception> // for std::terminate diff --git a/src/cxa_exception_storage.cpp b/src/cxa_exception_storage.cpp index d18eb0f..549d747 100644 --- a/src/cxa_exception_storage.cpp +++ b/src/cxa_exception_storage.cpp @@ -14,7 +14,7 @@ #include "cxa_exception.hpp" #include "config.h" -#include "threading_support.h" +#include <__threading_support> #if defined(_LIBCXXABI_HAS_NO_THREADS) @@ -54,17 +54,17 @@ extern "C" { namespace __cxxabiv1 { namespace { - __libcxxabi_tls_key key_; - __libcxxabi_exec_once_flag flag_ = _LIBCXXABI_EXEC_ONCE_INITIALIZER; + std::__libcpp_tls_key key_; + std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER; void destruct_ (void *p) { __free_with_fallback ( p ); - if ( 0 != __libcxxabi_tls_set ( key_, NULL ) ) + if ( 0 != std::__libcpp_tls_set ( key_, NULL ) ) abort_message("cannot zero out thread value for __cxa_get_globals()"); } void construct_ () { - if ( 0 != __libcxxabi_tls_create ( &key_, destruct_ ) ) + if ( 0 != std::__libcpp_tls_create ( &key_, destruct_ ) ) abort_message("cannot create thread specific key for __cxa_get_globals()"); } } @@ -80,8 +80,8 @@ extern "C" { (__calloc_with_fallback (1, sizeof (__cxa_eh_globals))); if ( NULL == retVal ) abort_message("cannot allocate __cxa_eh_globals"); - if ( 0 != __libcxxabi_tls_set ( key_, retVal ) ) - abort_message("__libcxxabi_tls_set failure in __cxa_get_globals()"); + if ( 0 != std::__libcpp_tls_set ( key_, retVal ) ) + abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()"); } return retVal; } @@ -92,10 +92,10 @@ extern "C" { // libc++abi. __cxa_eh_globals * __cxa_get_globals_fast () { // First time through, create the key. - if (0 != __libcxxabi_execute_once(&flag_, construct_)) + if (0 != std::__libcpp_execute_once(&flag_, construct_)) abort_message("execute once failure in __cxa_get_globals_fast()"); // static int init = construct_(); - return static_cast<__cxa_eh_globals*>(__libcxxabi_tls_get(key_)); + return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_)); } } diff --git a/src/cxa_guard.cpp b/src/cxa_guard.cpp index 1c468ff..49f83ed 100644 --- a/src/cxa_guard.cpp +++ b/src/cxa_guard.cpp @@ -11,7 +11,7 @@ #include "abort_message.h" #include "config.h" -#include "threading_support.h" +#include <__threading_support> #include <stdint.h> @@ -20,8 +20,8 @@ which will turn around and try to call __cxa_guard_acquire reentrantly. For this reason, the headers of this file are as restricted as possible. Previous implementations of this code for __APPLE__ have used - __libcxxabi_mutex_lock and the abort_message utility without problem. This - implementation also uses __libcxxabi_condvar_wait which has tested + std::__libcpp_mutex_lock and the abort_message utility without problem. This + implementation also uses std::__libcpp_condvar_wait which has tested to not be a problem. */ @@ -67,8 +67,8 @@ bool is_initialized(guard_type* guard_object) { #endif #ifndef _LIBCXXABI_HAS_NO_THREADS -__libcxxabi_mutex_t guard_mut = _LIBCXXABI_MUTEX_INITIALIZER; -__libcxxabi_condvar_t guard_cv = _LIBCXXABI_CONDVAR_INITIALIZER; +std::__libcpp_mutex_t guard_mut = _LIBCPP_MUTEX_INITIALIZER; +std::__libcpp_condvar_t guard_cv = _LIBCPP_CONDVAR_INITIALIZER; #endif #if defined(__APPLE__) && !defined(__arm__) @@ -173,13 +173,25 @@ extern "C" #ifndef _LIBCXXABI_HAS_NO_THREADS _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type *guard_object) { char* initialized = (char*)guard_object; - if (__libcxxabi_mutex_lock(&guard_mut)) + if (std::__libcpp_mutex_lock(&guard_mut)) abort_message("__cxa_guard_acquire failed to acquire mutex"); int result = *initialized == 0; if (result) { #if defined(__APPLE__) && !defined(__arm__) - const lock_type id = __libcxxabi_thread_get_port(); + // This is a special-case pthread dependency for Mac. We can't pull this + // out into libcxx's threading API (__threading_support) because not all + // supported Mac environments provide this function (in pthread.h). To + // make it possible to build/use libcxx in those environments, we have to + // keep this pthread dependency local to libcxxabi. If there is some + // convenient way to detect precisely when pthread_mach_thread_np is + // available in a given Mac environment, it might still be possible to + // bury this dependency in __threading_support. + #ifdef _LIBCPP_HAS_THREAD_API_PTHREAD + const lock_type id = pthread_mach_thread_np(std::__libcpp_thread_get_current_id()); + #else + #error "How do I pthread_mach_thread_np()?" + #endif lock_type lock = get_lock(*guard_object); if (lock) { @@ -188,7 +200,7 @@ _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type *guard_object) { abort_message("__cxa_guard_acquire detected deadlock"); do { - if (__libcxxabi_condvar_wait(&guard_cv, &guard_mut)) + if (std::__libcpp_condvar_wait(&guard_cv, &guard_mut)) abort_message("__cxa_guard_acquire condition variable wait failed"); lock = get_lock(*guard_object); } while (lock); @@ -200,36 +212,36 @@ _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(guard_type *guard_object) { set_lock(*guard_object, id); #else // !__APPLE__ || __arm__ while (get_lock(*guard_object)) - if (__libcxxabi_condvar_wait(&guard_cv, &guard_mut)) + if (std::__libcpp_condvar_wait(&guard_cv, &guard_mut)) abort_message("__cxa_guard_acquire condition variable wait failed"); result = *initialized == 0; if (result) set_lock(*guard_object, true); #endif // !__APPLE__ || __arm__ } - if (__libcxxabi_mutex_unlock(&guard_mut)) + if (std::__libcpp_mutex_unlock(&guard_mut)) abort_message("__cxa_guard_acquire failed to release mutex"); return result; } _LIBCXXABI_FUNC_VIS void __cxa_guard_release(guard_type *guard_object) { - if (__libcxxabi_mutex_lock(&guard_mut)) + if (std::__libcpp_mutex_lock(&guard_mut)) abort_message("__cxa_guard_release failed to acquire mutex"); *guard_object = 0; set_initialized(guard_object); - if (__libcxxabi_mutex_unlock(&guard_mut)) + if (std::__libcpp_mutex_unlock(&guard_mut)) abort_message("__cxa_guard_release failed to release mutex"); - if (__libcxxabi_condvar_broadcast(&guard_cv)) + if (std::__libcpp_condvar_broadcast(&guard_cv)) abort_message("__cxa_guard_release failed to broadcast condition variable"); } _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *guard_object) { - if (__libcxxabi_mutex_lock(&guard_mut)) + if (std::__libcpp_mutex_lock(&guard_mut)) abort_message("__cxa_guard_abort failed to acquire mutex"); *guard_object = 0; - if (__libcxxabi_mutex_unlock(&guard_mut)) + if (std::__libcpp_mutex_unlock(&guard_mut)) abort_message("__cxa_guard_abort failed to release mutex"); - if (__libcxxabi_condvar_broadcast(&guard_cv)) + if (std::__libcpp_condvar_broadcast(&guard_cv)) abort_message("__cxa_guard_abort failed to broadcast condition variable"); } diff --git a/src/cxa_handlers.cpp b/src/cxa_handlers.cpp index 3f78131..ce2cfba 100644 --- a/src/cxa_handlers.cpp +++ b/src/cxa_handlers.cpp @@ -104,7 +104,9 @@ terminate() _NOEXCEPT // In the future this will become: // std::atomic<std::new_handler> __cxa_new_handler(0); -extern "C" _LIBCXXABI_DATA_VIS new_handler __cxa_new_handler = 0; +extern "C" { +_LIBCXXABI_DATA_VIS new_handler __cxa_new_handler = 0; +} new_handler set_new_handler(new_handler handler) _NOEXCEPT diff --git a/src/cxa_new_delete.cpp b/src/cxa_new_delete.cpp index 7a2c864..7609d76 100644 --- a/src/cxa_new_delete.cpp +++ b/src/cxa_new_delete.cpp @@ -14,6 +14,11 @@ #include <new> #include <cstdlib> +#if !defined(_THROW_BAD_ALLOC) || !defined(_NOEXCEPT) +#error _THROW_BAD_ALLOC and _NOEXCEPT libc++ macros must already be defined \ + by libc++. +#endif + /* [new.delete.single] @@ -33,10 +38,7 @@ */ __attribute__((__weak__, __visibility__("default"))) void * -operator new(std::size_t size) -#if !__has_feature(cxx_noexcept) - throw(std::bad_alloc) -#endif +operator new(std::size_t size) _THROW_BAD_ALLOC { if (size == 0) size = 1; @@ -70,12 +72,7 @@ that call. Otherwise, returns a null pointer. */ __attribute__((__weak__, __visibility__("default"))) void* -operator new(size_t size, const std::nothrow_t&) -#if __has_feature(cxx_noexcept) - noexcept -#else - throw() -#endif +operator new(size_t size, const std::nothrow_t&) _NOEXCEPT { void* p = 0; #ifndef _LIBCXXABI_NO_EXCEPTIONS @@ -99,10 +96,7 @@ Returns operator new(size). */ __attribute__((__weak__, __visibility__("default"))) void* -operator new[](size_t size) -#if !__has_feature(cxx_noexcept) - throw(std::bad_alloc) -#endif +operator new[](size_t size) _THROW_BAD_ALLOC { return ::operator new(size); } @@ -115,12 +109,7 @@ of that call. Otherwise, returns a null pointer. */ __attribute__((__weak__, __visibility__("default"))) void* -operator new[](size_t size, const std::nothrow_t&) -#if __has_feature(cxx_noexcept) - noexcept -#else - throw() -#endif +operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT { void* p = 0; #ifndef _LIBCXXABI_NO_EXCEPTIONS @@ -145,12 +134,7 @@ earlier call to operator new. */ __attribute__((__weak__, __visibility__("default"))) void -operator delete(void* ptr) -#if __has_feature(cxx_noexcept) - noexcept -#else - throw() -#endif +operator delete(void* ptr) _NOEXCEPT { if (ptr) std::free(ptr); @@ -163,12 +147,7 @@ calls operator delete(ptr) */ __attribute__((__weak__, __visibility__("default"))) void -operator delete(void* ptr, const std::nothrow_t&) -#if __has_feature(cxx_noexcept) - noexcept -#else - throw() -#endif +operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT { ::operator delete(ptr); } @@ -180,12 +159,7 @@ Calls operator delete(ptr) */ __attribute__((__weak__, __visibility__("default"))) void -operator delete[] (void* ptr) -#if __has_feature(cxx_noexcept) - noexcept -#else - throw() -#endif +operator delete[] (void* ptr) _NOEXCEPT { ::operator delete(ptr); } @@ -197,12 +171,7 @@ calls operator delete[](ptr) */ __attribute__((__weak__, __visibility__("default"))) void -operator delete[] (void* ptr, const std::nothrow_t&) -#if __has_feature(cxx_noexcept) - noexcept -#else - throw() -#endif +operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT { ::operator delete[](ptr); } diff --git a/src/cxa_thread_atexit.cpp b/src/cxa_thread_atexit.cpp index 3ddaf0c..748b0eb 100644 --- a/src/cxa_thread_atexit.cpp +++ b/src/cxa_thread_atexit.cpp @@ -9,7 +9,7 @@ #include "abort_message.h" #include "cxxabi.h" -#include "threading_support.h" +#include <__threading_support> #include <cstdlib> namespace __cxxabiv1 { @@ -39,7 +39,7 @@ namespace { // destructors of any objects with static storage duration. // // - thread_local destructors on non-main threads run on the first iteration - // through the __libcxxabi_tls_key destructors. + // through the __libccpp_tls_key destructors. // std::notify_all_at_thread_exit() and similar functions must be careful to // wait until the second iteration to provide their intended ordering // guarantees. @@ -66,7 +66,7 @@ namespace { // True if the destructors are currently scheduled to run on this thread __thread bool dtors_alive = false; // Used to trigger destructors on thread exit; value is ignored - __libcxxabi_tls_key dtors_key; + std::__libcpp_tls_key dtors_key; void run_dtors(void*) { while (auto head = dtors) { @@ -80,16 +80,16 @@ namespace { struct DtorsManager { DtorsManager() { - // There is intentionally no matching __libcxxabi_tls_delete call, as + // There is intentionally no matching std::__libcpp_tls_delete call, as // __cxa_thread_atexit() may be called arbitrarily late (for example, from // global destructors or atexit() handlers). - if (__libcxxabi_tls_create(&dtors_key, run_dtors) != 0) { - abort_message("__libcxxabi_tls_create() failed in __cxa_thread_atexit()"); + if (std::__libcpp_tls_create(&dtors_key, run_dtors) != 0) { + abort_message("std::__libcpp_tls_create() failed in __cxa_thread_atexit()"); } } ~DtorsManager() { - // __libcxxabi_tls_key destructors do not run on threads that call exit() + // std::__libcpp_tls_key destructors do not run on threads that call exit() // (including when the main thread returns from main()), so we explicitly // call the destructor here. This runs at exit time (potentially earlier // if libc++abi is dlclose()'d). Any thread_locals initialized after this @@ -110,12 +110,12 @@ extern "C" { if (__cxa_thread_atexit_impl) { return __cxa_thread_atexit_impl(dtor, obj, dso_symbol); } else { - // Initialize the dtors __libcxxabi_tls_key (uses __cxa_guard_*() for + // Initialize the dtors std::__libcpp_tls_key (uses __cxa_guard_*() for // one-time initialization and __cxa_atexit() for destruction) static DtorsManager manager; if (!dtors_alive) { - if (__libcxxabi_tls_set(dtors_key, &dtors_key) != 0) { + if (std::__libcpp_tls_set(dtors_key, &dtors_key) != 0) { return -1; } dtors_alive = true; diff --git a/src/fallback_malloc.cpp b/src/fallback_malloc.cpp index 5f52ece..3f8441e 100644 --- a/src/fallback_malloc.cpp +++ b/src/fallback_malloc.cpp @@ -10,7 +10,7 @@ #include "fallback_malloc.h" #include "config.h" -#include "threading_support.h" +#include <__threading_support> #include <cstdlib> // for malloc, calloc, free #include <cstring> // for memset @@ -29,7 +29,8 @@ namespace { // When POSIX threads are not available, make the mutex operations a nop #ifndef _LIBCXXABI_HAS_NO_THREADS -static __libcxxabi_mutex_t heap_mutex = _LIBCXXABI_MUTEX_INITIALIZER; +_LIBCPP_SAFE_STATIC +static std::__libcpp_mutex_t heap_mutex = _LIBCPP_MUTEX_INITIALIZER; #else static void * heap_mutex = 0; #endif @@ -37,8 +38,10 @@ static void * heap_mutex = 0; class mutexor { public: #ifndef _LIBCXXABI_HAS_NO_THREADS - mutexor ( __libcxxabi_mutex_t *m ) : mtx_(m) { __libcxxabi_mutex_lock ( mtx_ ); } - ~mutexor () { __libcxxabi_mutex_unlock ( mtx_ ); } + mutexor ( std::__libcpp_mutex_t *m ) : mtx_(m) { + std::__libcpp_mutex_lock ( mtx_ ); + } + ~mutexor () { std::__libcpp_mutex_unlock ( mtx_ ); } #else mutexor ( void * ) {} ~mutexor () {} @@ -47,9 +50,9 @@ private: mutexor ( const mutexor &rhs ); mutexor & operator = ( const mutexor &rhs ); #ifndef _LIBCXXABI_HAS_NO_THREADS - __libcxxabi_mutex_t *mtx_; + std::__libcpp_mutex_t *mtx_; #endif - }; +}; static const size_t HEAP_SIZE = 512; diff --git a/src/private_typeinfo.cpp b/src/private_typeinfo.cpp index 6112a1f..e7995ed 100644 --- a/src/private_typeinfo.cpp +++ b/src/private_typeinfo.cpp @@ -105,45 +105,6 @@ __function_type_info::~__function_type_info() { } -// __qualified_function_type_info - -__qualified_function_type_info::~__qualified_function_type_info() -{ -} - -// Determine if a function pointer conversion can convert a pointer (or pointer -// to member) to type x into a pointer (or pointer to member) to type y. -static bool is_function_pointer_conversion(const std::type_info* x, - const std::type_info* y) -{ - const unsigned int discardable_quals = - __qualified_function_type_info::__noexcept_mask | - __qualified_function_type_info::__transaction_safe_mask | - __qualified_function_type_info::__noreturn_mask; - - // If x has only discardable qualifiers and y is unqualified, then - // conversion is permitted. - const __qualified_function_type_info* qual_x = - dynamic_cast<const __qualified_function_type_info *>(x); - if (!qual_x) - return false; - if ((qual_x->__qualifiers & ~discardable_quals) == 0 && - is_equal(qual_x->__base_type, y, false)) - return true; - - // Otherwise, x's qualifiers must be the same as y's, plus some discardable - // ones. - const __qualified_function_type_info* qual_y = - dynamic_cast<const __qualified_function_type_info *>(y); - if (!qual_y) - return false; - if (qual_y->__qualifiers & ~qual_x->__qualifiers) - return false; - if (qual_x->__qualifiers & ~qual_y->__qualifiers & ~discardable_quals) - return false; - return is_equal(qual_x->__base_type, qual_y->__base_type, false); -} - // __enum_type_info __enum_type_info::~__enum_type_info() @@ -429,15 +390,13 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type, // Do the dereference adjustment if (adjustedPtr != NULL) adjustedPtr = *static_cast<void**>(adjustedPtr); - // bullet 3B - if (thrown_pointer_type->__flags & ~__flags) + // bullet 3B and 3C + if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask) + return false; + if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask) return false; if (is_equal(__pointee, thrown_pointer_type->__pointee, false)) return true; - // bullet 3C - if (is_function_pointer_conversion(thrown_pointer_type->__pointee, - __pointee)) - return true; // bullet 3A if (is_equal(__pointee, &typeid(void), false)) { // pointers to functions cannot be converted to void*. @@ -543,11 +502,11 @@ bool __pointer_to_member_type_info::can_catch( dynamic_cast<const __pointer_to_member_type_info*>(thrown_type); if (thrown_pointer_type == 0) return false; - if (thrown_pointer_type->__flags & ~__flags) + if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask) + return false; + if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask) return false; - if (!is_equal(__pointee, thrown_pointer_type->__pointee, false) && - !is_function_pointer_conversion(thrown_pointer_type->__pointee, - __pointee)) + if (!is_equal(__pointee, thrown_pointer_type->__pointee, false)) return false; if (is_equal(__context, thrown_pointer_type->__context, false)) return true; diff --git a/src/private_typeinfo.h b/src/private_typeinfo.h index fa6bd63..f3d3e1d 100644 --- a/src/private_typeinfo.h +++ b/src/private_typeinfo.h @@ -49,33 +49,6 @@ public: void *&) const; }; -// This implements the following proposal from cxx-abi-dev (not yet part of the -// ABI document): -// -// http://sourcerytools.com/pipermail/cxx-abi-dev/2016-October/002988.html -// -// This is necessary for support of http://wg21.link/p0012, which permits throwing -// noexcept function and member function pointers and catching them as non-noexcept -// pointers. -class _LIBCXXABI_TYPE_VIS __qualified_function_type_info : public __shim_type_info { -public: - const __function_type_info* __base_type; - unsigned int __qualifiers; - - enum __qualifiers_mask { - __const_mask = 0x01, - __volatile_mask = 0x02, - __restrict_mask = 0x04, - __lval_ref_mask = 0x08, - __rval_ref_mask = 0x10, - __noexcept_mask = 0x20, - __transaction_safe_mask = 0x40, - __noreturn_mask = 0x80 - }; - - _LIBCXXABI_HIDDEN virtual ~__qualified_function_type_info(); -}; - class _LIBCXXABI_TYPE_VIS __enum_type_info : public __shim_type_info { public: _LIBCXXABI_HIDDEN virtual ~__enum_type_info(); @@ -233,7 +206,22 @@ public: __volatile_mask = 0x2, __restrict_mask = 0x4, __incomplete_mask = 0x8, - __incomplete_class_mask = 0x10 + __incomplete_class_mask = 0x10, + __transaction_safe_mask = 0x20, + // This implements the following proposal from cxx-abi-dev (not yet part of + // the ABI document): + // + // http://sourcerytools.com/pipermail/cxx-abi-dev/2016-October/002986.html + // + // This is necessary for support of http://wg21.link/p0012, which permits + // throwing noexcept function and member function pointers and catching + // them as non-noexcept pointers. + __noexcept_mask = 0x40, + + // Flags that cannot be removed by a standard conversion. + __no_remove_flags_mask = __const_mask | __volatile_mask | __restrict_mask, + // Flags that cannot be added by a standard conversion. + __no_add_flags_mask = __transaction_safe_mask | __noexcept_mask }; _LIBCXXABI_HIDDEN virtual ~__pbase_type_info(); diff --git a/src/exception.cpp b/src/stdlib_exception.cpp index c47a9b7..c47a9b7 100644 --- a/src/exception.cpp +++ b/src/stdlib_exception.cpp diff --git a/src/stdexcept.cpp b/src/stdlib_stdexcept.cpp index bd6789e..bd6789e 100644 --- a/src/stdexcept.cpp +++ b/src/stdlib_stdexcept.cpp diff --git a/src/typeinfo.cpp b/src/stdlib_typeinfo.cpp index 9313be0..9313be0 100644 --- a/src/typeinfo.cpp +++ b/src/stdlib_typeinfo.cpp diff --git a/src/threading_support.h b/src/threading_support.h deleted file mode 100644 index 78a225f..0000000 --- a/src/threading_support.h +++ /dev/null @@ -1,107 +0,0 @@ -//===------------------------ threading_support.h -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCXXABI_THREADING_SUPPORT_H -#define _LIBCXXABI_THREADING_SUPPORT_H - -#include "__cxxabi_config.h" -#include "config.h" - -#ifndef _LIBCXXABI_HAS_NO_THREADS - -#if defined(_LIBCXXABI_USE_THREAD_API_PTHREAD) -#include <pthread.h> - -#define _LIBCXXABI_THREAD_ABI_VISIBILITY inline _LIBCXXABI_INLINE_VISIBILITY - -// Mutex -typedef pthread_mutex_t __libcxxabi_mutex_t; -#define _LIBCXXABI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_mutex_lock(__libcxxabi_mutex_t *mutex) { - return pthread_mutex_lock(mutex); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_mutex_unlock(__libcxxabi_mutex_t *mutex) { - return pthread_mutex_unlock(mutex); -} - -// Condition variable -typedef pthread_cond_t __libcxxabi_condvar_t; -#define _LIBCXXABI_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_condvar_wait(__libcxxabi_condvar_t *cv, - __libcxxabi_mutex_t *mutex) { - return pthread_cond_wait(cv, mutex); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_condvar_broadcast(__libcxxabi_condvar_t *cv) { - return pthread_cond_broadcast(cv); -} - -// Execute once -typedef pthread_once_t __libcxxabi_exec_once_flag; -#define _LIBCXXABI_EXEC_ONCE_INITIALIZER PTHREAD_ONCE_INIT - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_execute_once(__libcxxabi_exec_once_flag *flag, - void (*init_routine)(void)) { - return pthread_once(flag, init_routine); -} - -// Thread id -#if defined(__APPLE__) && !defined(__arm__) -_LIBCXXABI_THREAD_ABI_VISIBILITY -mach_port_t __libcxxabi_thread_get_port() -{ - return pthread_mach_thread_np(pthread_self()); -} -#endif - -// Thread -typedef pthread_t __libcxxabi_thread_t; - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_thread_create(__libcxxabi_thread_t* __t, - void* (*__func)(void*), void* __arg) -{ - return pthread_create(__t, 0, __func, __arg); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_thread_join(__libcxxabi_thread_t* __t) -{ - return pthread_join(*__t, 0); -} - -// TLS -typedef pthread_key_t __libcxxabi_tls_key; - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_tls_create(__libcxxabi_tls_key *key, - void (*destructor)(void *)) { - return pthread_key_create(key, destructor); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -void *__libcxxabi_tls_get(__libcxxabi_tls_key key) { - return pthread_getspecific(key); -} - -_LIBCXXABI_THREAD_ABI_VISIBILITY -int __libcxxabi_tls_set(__libcxxabi_tls_key key, void *value) { - return pthread_setspecific(key, value); -} -#endif // _LIBCXXABI_USE_THREAD_API_PTHREAD -#endif // !_LIBCXXABI_HAS_NO_THREADS -#endif // _LIBCXXABI_THREADING_SUPPORT_H diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 85c6f60..c1819d7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,6 +17,7 @@ pythonize_bool(LIBCXXABI_ENABLE_SHARED) pythonize_bool(LIBCXXABI_ENABLE_THREADS) pythonize_bool(LIBCXXABI_ENABLE_EXCEPTIONS) pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER) +pythonize_bool(LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY) set(LIBCXXABI_TARGET_INFO "libcxx.test.target_info.LocalTI" CACHE STRING "TargetInfo to use when setting up test environment.") set(LIBCXXABI_EXECUTOR "None" CACHE STRING @@ -34,6 +35,10 @@ else() set(LIBCXXABI_TEST_DEPS cxxabi_static) endif() +if (LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY) + list(APPEND LIBCXXABI_TEST_DEPS cxx_external_threads) +endif() + if (NOT LIBCXXABI_STANDALONE_BUILD) list(APPEND LIBCXXABI_TEST_DEPS cxx) if (LIBCXXABI_USE_LLVM_UNWINDER) diff --git a/test/backtrace_test.pass.cpp b/test/backtrace_test.pass.cpp index 80346c0..b9388ff 100644 --- a/test/backtrace_test.pass.cpp +++ b/test/backtrace_test.pass.cpp @@ -14,7 +14,7 @@ #include <unwind.h> extern "C" _Unwind_Reason_Code -trace_function(struct _Unwind_Context* context, void* ntraced) { +trace_function(struct _Unwind_Context*, void* ntraced) { (*reinterpret_cast<size_t*>(ntraced))++; // We should never have a call stack this deep... assert(*reinterpret_cast<size_t*>(ntraced) < 20); diff --git a/test/catch_function_03.pass.cpp b/test/catch_function_03.pass.cpp index 4118fde..bf817a9 100644 --- a/test/catch_function_03.pass.cpp +++ b/test/catch_function_03.pass.cpp @@ -8,8 +8,7 @@ //===----------------------------------------------------------------------===// // Can a noexcept function pointer be caught by a non-noexcept catch clause? -// UNSUPPORTED: c++98, c++03, c++11, c++14 -// UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-qualified-function-types +// UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-noexcept-function-type #include <cassert> diff --git a/test/catch_member_function_pointer_02.pass.cpp b/test/catch_member_function_pointer_02.pass.cpp index 860d8ed..5ce2359 100644 --- a/test/catch_member_function_pointer_02.pass.cpp +++ b/test/catch_member_function_pointer_02.pass.cpp @@ -9,8 +9,7 @@ // Can a noexcept member function pointer be caught by a non-noexcept catch // clause? -// UNSUPPORTED: c++98, c++03, c++11, c++14 -// UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-qualified-function-types +// UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-noexcept-function-type #include <cassert> diff --git a/test/catch_reference_nullptr.pass.cpp b/test/catch_reference_nullptr.pass.cpp index 3ab520f..82a49df 100644 --- a/test/catch_reference_nullptr.pass.cpp +++ b/test/catch_reference_nullptr.pass.cpp @@ -12,12 +12,6 @@ #include <cassert> #include <cstdlib> -// Clang emits a warning on converting an object of type nullptr_t to bool, -// even in generic code. Suppress it. -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wnull-conversion" -#endif - struct A {}; template<typename T, bool CanCatchNullptr> @@ -25,7 +19,7 @@ static void catch_nullptr_test() { try { throw nullptr; } catch (T &p) { - assert(CanCatchNullptr && !p); + assert(CanCatchNullptr && !static_cast<bool>(p)); } catch (...) { assert(!CanCatchNullptr); } diff --git a/test/cxa_bad_cast.pass.cpp b/test/cxa_bad_cast.pass.cpp index c863d6f..d2c3bf9 100644 --- a/test/cxa_bad_cast.pass.cpp +++ b/test/cxa_bad_cast.pass.cpp @@ -40,6 +40,7 @@ int main () #endif Derived &d = test_bad_cast(gB); assert(false); + ((void)d); #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS } catch (std::bad_cast) { // success diff --git a/test/libcxxabi/test/config.py b/test/libcxxabi/test/config.py index 7cb1e9b..e219961 100644 --- a/test/libcxxabi/test/config.py +++ b/test/libcxxabi/test/config.py @@ -33,12 +33,18 @@ class Configuration(LibcxxConfiguration): self.libcxxabi_obj_root = self.get_lit_conf('libcxxabi_obj_root') super(Configuration, self).configure_obj_root() + def has_cpp_feature(self, feature, required_value): + return int(self.cxx.dumpMacros().get('__cpp_' + feature, 0)) >= required_value + def configure_features(self): super(Configuration, self).configure_features() if not self.get_lit_bool('enable_exceptions', True): self.config.available_features.add('libcxxabi-no-exceptions') - if not self.cxx.addCompileFlagIfSupported(['-Xclang', '-mqualified-function-type-info']): - self.config.available_features.add("libcxxabi-no-qualified-function-types") + if not self.has_cpp_feature('noexcept_function_type', 201510): + self.config.available_features.add('libcxxabi-no-noexcept-function-type') + # test_exception_storage_nodynmem.pass.cpp fails under this specific configuration + if self.get_lit_bool('cxx_ext_threads', False) and self.get_lit_bool('libcxxabi_shared', False): + self.config.available_features.add('libcxxabi-shared-externally-threaded') def configure_compile_flags(self): self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER'] @@ -49,7 +55,7 @@ class Configuration(LibcxxConfiguration): if not self.get_lit_bool('enable_threads', True): self.cxx.compile_flags += ['-D_LIBCXXABI_HAS_NO_THREADS'] self.config.available_features.add('libcxxabi-no-threads') - super(Configuration, self).configure_compile_flags() + super(Configuration, self).configure_compile_flags() def configure_compile_flags_header_includes(self): self.configure_config_site_header() diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index b8fb35c..9c0fdf2 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -19,6 +19,7 @@ config.enable_exceptions = "@LIBCXXABI_ENABLE_EXCEPTIONS@" config.host_triple = "@LLVM_HOST_TRIPLE@" config.target_triple = "@TARGET_TRIPLE@" config.use_target = len("@LIBCXXABI_TARGET_TRIPLE@") > 0 +config.cxx_ext_threads = "@LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY@" # Let the main config do the real work. lit_config.load_config(config, "@LIBCXXABI_SOURCE_DIR@/test/lit.cfg") diff --git a/test/test_aux_runtime.pass.cpp b/test/test_aux_runtime.pass.cpp index a9f240e..0c9a8f2 100644 --- a/test/test_aux_runtime.pass.cpp +++ b/test/test_aux_runtime.pass.cpp @@ -28,8 +28,8 @@ bool bad_typeid_test () { class B { virtual void g() {}}; B *bp = NULL; - try {bool b = typeid(*bp) == typeid (A); } - catch ( const std::bad_typeid &bc ) { return true; } + try {bool b = typeid(*bp) == typeid (A); ((void)b); } + catch ( const std::bad_typeid &) { return true; } return false; } @@ -44,12 +44,12 @@ bool bad_cast_test () { D d; B *bp = (B*)&d; // cast needed to break protection - try { D &dr = dynamic_cast<D&> (*bp); } - catch ( const std::bad_cast &bc ) { return true; } + try { D &dr = dynamic_cast<D&> (*bp); ((void)dr); } + catch ( const std::bad_cast & ) { return true; } return false; } -int main ( int argc, char *argv [] ) { +int main ( ) { int ret_val = 0; if ( !bad_typeid_test ()) { diff --git a/test/test_aux_runtime_op_array_new.pass.cpp b/test/test_aux_runtime_op_array_new.pass.cpp index 701a457..d4a63d7 100644 --- a/test/test_aux_runtime_op_array_new.pass.cpp +++ b/test/test_aux_runtime_op_array_new.pass.cpp @@ -28,7 +28,7 @@ bool bad_array_new_length_test() { return false; } -int main(int argc, char *argv []) { +int main() { int ret_val = 0; if ( !bad_array_new_length_test ()) { diff --git a/test/test_demangle.pass.cpp b/test/test_demangle.pass.cpp index af16b56..4eb6a88 100644 --- a/test/test_demangle.pass.cpp +++ b/test/test_demangle.pass.cpp @@ -29594,6 +29594,14 @@ const char* cases[][2] = // NOTE: disable this test since it is a negative test case, you cannot demangle a non-mangled symbol // {"\x6D", nullptr}, // This use to crash with ASAN {"_ZTIU4_farrVKPi", "typeinfo for int* const volatile restrict _far"}, + + // mangled names can include type manglings too, which don't start with _Z: + {"i", "int"}, + + {"PKFvRiE", "void (*)(int&) const"}, + // FIXME(compnerd) pretty print this as void (*)(unsigned long &) volatile && + {"PVFvRmOE", "void (*)(unsigned long&) volatile&&"}, + {"PFvRmOE", "void (*)(unsigned long&) &&"}, }; const unsigned N = sizeof(cases) / sizeof(cases[0]); diff --git a/test/test_exception_storage.pass.cpp b/test/test_exception_storage.pass.cpp index d509227..67ab51d 100644 --- a/test/test_exception_storage.pass.cpp +++ b/test/test_exception_storage.pass.cpp @@ -12,7 +12,7 @@ #include <cstdlib> #include <algorithm> #include <iostream> -#include "../src/threading_support.h" +#include <__threading_support> #include <unistd.h> #include "../src/cxa_exception.hpp" @@ -39,18 +39,18 @@ void *thread_code (void *parm) { #ifndef _LIBCXXABI_HAS_NO_THREADS #define NUMTHREADS 10 size_t thread_globals [ NUMTHREADS ] = { 0 }; -__libcxxabi_thread_t threads [ NUMTHREADS ]; +std::__libcpp_thread_t threads [ NUMTHREADS ]; #endif -int main ( int argc, char *argv [] ) { +int main () { int retVal = 0; #ifndef _LIBCXXABI_HAS_NO_THREADS // Make the threads, let them run, and wait for them to finish for ( int i = 0; i < NUMTHREADS; ++i ) - __libcxxabi_thread_create ( threads + i, thread_code, (void *) (thread_globals + i)); + std::__libcpp_thread_create ( threads + i, thread_code, (void *) (thread_globals + i)); for ( int i = 0; i < NUMTHREADS; ++i ) - __libcxxabi_thread_join ( &threads [ i ] ); + std::__libcpp_thread_join ( &threads [ i ] ); for ( int i = 0; i < NUMTHREADS; ++i ) if ( 0 == thread_globals [ i ] ) { diff --git a/test/test_fallback_malloc.pass.cpp b/test/test_fallback_malloc.pass.cpp index 250a738..e29e128 100644 --- a/test/test_fallback_malloc.pass.cpp +++ b/test/test_fallback_malloc.pass.cpp @@ -10,7 +10,7 @@ #include <iostream> #include <deque> -#include "../src/threading_support.h" +#include <__threading_support> typedef std::deque<void *> container; @@ -165,7 +165,7 @@ void exhaustion_test3 () { } -int main ( int argc, char *argv [] ) { +int main () { print_free_list (); char *p = (char *) fallback_malloc ( 1024 ); // too big! diff --git a/test/test_guard.pass.cpp b/test/test_guard.pass.cpp index 2312b51..ef86717 100644 --- a/test/test_guard.pass.cpp +++ b/test/test_guard.pass.cpp @@ -25,11 +25,12 @@ namespace test1 { } void helper() { static int a = increment(); + ((void)a); } void test() { - static int a = increment(); + static int a = increment(); ((void)a); assert(run_count == 1); - static int b = increment(); + static int b = increment(); ((void)b); assert(run_count == 2); helper(); assert(run_count == 3); @@ -50,7 +51,8 @@ namespace test2 { void helper() { try { static int a = increment(); - assert(0); + assert(false); + ((void)a); } catch (...) {} } void test() { @@ -71,12 +73,12 @@ namespace test3 { } int one() { - static int b = zero(); + static int b = zero(); ((void)b); return 0; } void test() { - static int a = one(); + static int a = one(); ((void)a); } } @@ -91,7 +93,7 @@ namespace test4 { } void helper() { - static int a = increment(); + static int a = increment(); ((void)a); } void test() { @@ -112,16 +114,16 @@ namespace test5 { } int one() { - static int b = zero(); + static int b = zero(); ((void)b); return 0; } void another_helper() { - static int a = one(); + static int a = one(); ((void)a); } void helper() { - static int a = one(); + static int a = one(); ((void)a); std::thread t(another_helper); t.join(); } diff --git a/test/test_vector1.pass.cpp b/test/test_vector1.pass.cpp index 978ed3c..0f3acd2 100644 --- a/test/test_vector1.pass.cpp +++ b/test/test_vector1.pass.cpp @@ -25,36 +25,36 @@ void my_dealloc2 ( void *p ) { std::free ( p ); } -void my_dealloc3 ( void *p, size_t sz ) { +void my_dealloc3 ( void *p, size_t ) { // std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz ); std::free ( p ); } -void my_construct ( void *p ) { +void my_construct ( void * ) { // std::printf ( "Constructing %lx\n", (unsigned long) p ); } -void my_destruct ( void *p ) { +void my_destruct ( void * ) { // std::printf ( "Destructing %lx\n", (unsigned long) p ); } int gCounter; -void count_construct ( void *p ) { ++gCounter; } -void count_destruct ( void *p ) { --gCounter; } +void count_construct ( void * ) { ++gCounter; } +void count_destruct ( void * ) { --gCounter; } int gConstructorCounter; int gConstructorThrowTarget; int gDestructorCounter; int gDestructorThrowTarget; -void throw_construct ( void *p ) { +void throw_construct ( void * ) { #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; #endif } -void throw_destruct ( void *p ) { +void throw_destruct ( void * ) { #ifndef LIBCXXABI_HAS_NO_EXCEPTIONS if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; @@ -269,7 +269,7 @@ int test_exception_in_destructor ( ) { } #endif -int main ( int argc, char *argv [] ) { +int main () { int retVal = 0; retVal += test_empty (); retVal += test_counted (); diff --git a/test/test_vector2.pass.cpp b/test/test_vector2.pass.cpp index 4bc279d..5a5ff06 100644 --- a/test/test_vector2.pass.cpp +++ b/test/test_vector2.pass.cpp @@ -28,30 +28,30 @@ void my_dealloc2 ( void *p ) { std::free ( p ); } -void my_dealloc3 ( void *p, size_t sz ) { +void my_dealloc3 ( void *p, size_t ) { // std::printf ( "Freeing %lx (size %ld)\n", (unsigned long) p, sz ); std::free ( p ); } -void my_construct ( void *p ) { +void my_construct ( void *) { // std::printf ( "Constructing %lx\n", (unsigned long) p ); } -void my_destruct ( void *p ) { +void my_destruct ( void *) { // std::printf ( "Destructing %lx\n", (unsigned long) p ); } int gCounter; -void count_construct ( void *p ) { ++gCounter; } -void count_destruct ( void *p ) { --gCounter; } +void count_construct ( void * ) { ++gCounter; } +void count_destruct ( void * ) { --gCounter; } int gConstructorCounter; int gConstructorThrowTarget; int gDestructorCounter; int gDestructorThrowTarget; -void throw_construct ( void *p ) { if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; } -void throw_destruct ( void *p ) { if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; } +void throw_construct ( void * ) { if ( gConstructorCounter == gConstructorThrowTarget ) throw 1; ++gConstructorCounter; } +void throw_destruct ( void * ) { if ( ++gDestructorCounter == gDestructorThrowTarget ) throw 2; } struct vec_on_stack { void *storage; @@ -78,7 +78,7 @@ void test_exception_in_destructor ( ) { -int main ( int argc, char *argv [] ) { +int main () { std::set_terminate ( my_terminate ); test_exception_in_destructor (); return 1; // we failed if we get here diff --git a/test/test_vector3.pass.cpp b/test/test_vector3.pass.cpp index a817125..2f983ef 100644 --- a/test/test_vector3.pass.cpp +++ b/test/test_vector3.pass.cpp @@ -48,7 +48,7 @@ void destroy(void* v) t->~T(); } -int main( int argc, char *argv []) +int main() { std::set_terminate(my_terminate); { diff --git a/test/thread_local_destruction_order.pass.cpp b/test/thread_local_destruction_order.pass.cpp index 23a0fdb..0bb359e 100644 --- a/test/thread_local_destruction_order.pass.cpp +++ b/test/thread_local_destruction_order.pass.cpp @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +// Darwin TLV finalization routines fail when creating a thread-local variable +// in the destructor for another thread-local variable: +// http://lists.llvm.org/pipermail/cfe-dev/2016-November/051376.html +// XFAIL: darwin // UNSUPPORTED: c++98, c++03 // UNSUPPORTED: libcxxabi-no-threads diff --git a/test/uncaught_exceptions.pass.cpp b/test/uncaught_exceptions.pass.cpp index 0c64067..fe7374d 100644 --- a/test/uncaught_exceptions.pass.cpp +++ b/test/uncaught_exceptions.pass.cpp @@ -23,9 +23,9 @@ struct A { }; struct B { - B(int cnt) : data_(cnt) {} + B(unsigned cnt) : data_(cnt) {} ~B() { assert( data_ == __cxxabiv1::__cxa_uncaught_exceptions()); } - int data_; + unsigned data_; }; int main () diff --git a/test/unwind_01.pass.cpp b/test/unwind_01.pass.cpp index 1bf6cfd..2730fdd 100644 --- a/test/unwind_01.pass.cpp +++ b/test/unwind_01.pass.cpp @@ -11,6 +11,10 @@ #include <assert.h> +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif + struct A { static int count; diff --git a/test/unwind_02.pass.cpp b/test/unwind_02.pass.cpp index 90dc25a..2c6e1d6 100644 --- a/test/unwind_02.pass.cpp +++ b/test/unwind_02.pass.cpp @@ -8,9 +8,14 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: libcxxabi-no-exceptions +// REQUIRES: c++98 || c++03 || c++11 || c++14 #include <assert.h> +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif + struct A { static int count; diff --git a/test/unwind_03.pass.cpp b/test/unwind_03.pass.cpp index bda8c31..6bc16bd 100644 --- a/test/unwind_03.pass.cpp +++ b/test/unwind_03.pass.cpp @@ -8,11 +8,16 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: libcxxabi-no-exceptions +// REQUIRES: c++98 || c++03 || c++11 || c++14 #include <exception> #include <stdlib.h> #include <assert.h> +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif + struct A { static int count; diff --git a/test/unwind_04.pass.cpp b/test/unwind_04.pass.cpp index b5a08af..1b75994 100644 --- a/test/unwind_04.pass.cpp +++ b/test/unwind_04.pass.cpp @@ -8,11 +8,16 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: libcxxabi-no-exceptions +// REQUIRES: c++98 || c++03 || c++11 || c++14 #include <exception> #include <stdlib.h> #include <assert.h> +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif + struct A { static int count; diff --git a/test/unwind_05.pass.cpp b/test/unwind_05.pass.cpp index 3dea2aa..d1f5fcd 100644 --- a/test/unwind_05.pass.cpp +++ b/test/unwind_05.pass.cpp @@ -8,11 +8,16 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: libcxxabi-no-exceptions +// REQUIRES: c++98 || c++03 || c++11 || c++14 #include <exception> #include <stdlib.h> #include <assert.h> +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif + struct A { static int count; diff --git a/test/unwind_06.pass.cpp b/test/unwind_06.pass.cpp index a30efb1..e712566 100644 --- a/test/unwind_06.pass.cpp +++ b/test/unwind_06.pass.cpp @@ -101,9 +101,9 @@ double try7(bool v) { double g = get(0); double h = get(0); for (counter = 100; counter; --counter) - a += get(1) + b+c+d+e+f+g; + a += get(1) + b+c+d+e+f+g+h; if (v) throw 10; - return get(0)+a+b+c+d+e+f+g; + return get(0)+a+b+c+d+e+f+g+h; } double try8(bool v) { @@ -117,9 +117,9 @@ double try8(bool v) { double h = get(0); double i = get(0); for (counter = 100; counter; --counter) - a += get(1) + b+c+d+e+f+g+i; + a += get(1) + b+c+d+e+f+g+h+i; if (v) throw 10; - return get(0)+a+b+c+d+e+f+g+i; + return get(0)+a+b+c+d+e+f+g+h+i; } |