--- /dev/null
+BasedOnStyle: LLVM
+
+---
+Language: Cpp
+
+AlwaysBreakTemplateDeclarations: true
+PointerAlignment: Left
+
+# Disable formatting options which may break tests.
+SortIncludes: false
+ReflowComments: false
+---
# See www/CMake.html for instructions on how to build libcxxabi with CMake.
+if (NOT IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/../libcxx")
+ message(FATAL_ERROR "libc++abi now requires being built in a monorepo layout with libcxx available")
+endif()
+
#===============================================================================
# Setup Project
#===============================================================================
project(libcxxabi CXX C)
set(PACKAGE_NAME libcxxabi)
- set(PACKAGE_VERSION 10.0.1)
+ set(PACKAGE_VERSION 11.1.0)
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org")
option(LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY
"Build libc++abi with an externalized threading library.
This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON" OFF)
+option(LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST
+"Make dynamic_cast more forgiving when type_info's mistakenly have hidden \
+visibility, and thus multiple type_infos can exist for a single type. \
+When the dynamic_cast would normally fail, this option will cause the \
+library to try comparing the type_info names to see if they are equal \
+instead." OFF)
# 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)
option(LIBCXXABI_ENABLE_SHARED "Build libc++abi as a shared library." ON)
option(LIBCXXABI_ENABLE_STATIC "Build libc++abi as a static library." ON)
-option(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI
- "Whether the libc++abi tests should link with the shared libc++abi library"
- ${LIBCXXABI_ENABLE_SHARED})
-
-option(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX
- "Whether the libc++abi tests should link with the shared libc++ library"
- ${LIBCXX_ENABLE_SHARED})
-
cmake_dependent_option(LIBCXXABI_INSTALL_STATIC_LIBRARY
"Install the static libc++abi library." ON
"LIBCXXABI_ENABLE_STATIC;LIBCXXABI_INSTALL_LIBRARY" OFF)
message(FATAL_ERROR "libc++abi must be built as either a shared or static library.")
endif()
-if(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI AND NOT LIBCXXABI_ENABLE_SHARED)
- message(FATAL_ERROR "LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI being ON requires LIBCXXABI_ENABLE_SHARED to be ON")
-endif()
-
-if(NOT LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI AND NOT LIBCXXABI_ENABLE_STATIC)
- message(FATAL_ERROR "LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXXABI being OFF requires LIBCXXABI_ENABLE_STATIC to be ON")
-endif()
-
-if(DEFINED LIBCXX_ENABLE_SHARED
- AND LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX
- AND NOT LIBCXX_ENABLE_SHARED)
- message(FATAL_ERROR "LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX being ON requires LIBCXX_ENABLE_SHARED to be ON")
-endif()
-
-if(DEFINED LIBCXX_ENABLE_STATIC
- AND NOT LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX
- AND NOT LIBCXX_ENABLE_STATIC)
- message(FATAL_ERROR "LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX being OFF requires LIBCXX_ENABLE_STATIC to be ON")
-endif()
-
-if (LLVM_EXTERNAL_LIBCXX_SOURCE_DIR)
- set(LIBCXXABI_LIBCXX_SRC_DIRS ${LLVM_EXTERNAL_LIBCXX_SOURCE_DIR})
-else()
- set(LIBCXXABI_LIBCXX_SRC_DIRS
- "${LLVM_MAIN_SRC_DIR}/projects/libcxx"
- "${LLVM_MAIN_SRC_DIR}/runtimes/libcxx"
- "${LLVM_MAIN_SRC_DIR}/../libcxx"
- )
-endif()
-
-set(LIBCXXABI_LIBCXX_INCLUDE_DIRS "")
-foreach(dir ${LIBCXXABI_LIBCXX_SRC_DIRS})
- list(APPEND LIBCXXABI_LIBCXX_INCLUDE_DIRS "${dir}/include")
-endforeach()
-
-find_path(
- LIBCXXABI_LIBCXX_INCLUDES
- __config
- PATHS ${LIBCXXABI_LIBCXX_INCLUDES}
- ${LIBCXXABI_LIBCXX_PATH}/include
- ${CMAKE_BINARY_DIR}/${LIBCXXABI_LIBCXX_INCLUDES}
- ${LIBCXXABI_LIBCXX_INCLUDE_DIRS}
- ${LLVM_INCLUDE_DIR}/c++/v1
- NO_DEFAULT_PATH
- NO_CMAKE_FIND_ROOT_PATH
- )
-
-set(LIBCXXABI_LIBCXX_INCLUDES "${LIBCXXABI_LIBCXX_INCLUDES}" CACHE PATH
- "Specify path to libc++ includes." FORCE)
-
-find_path(
- LIBCXXABI_LIBCXX_PATH
- utils/libcxx/test/__init__.py
- PATHS ${LIBCXXABI_LIBCXX_PATH}
- ${LIBCXXABI_LIBCXX_INCLUDES}/../
- ${LIBCXXABI_LIBCXX_SRC_DIRS}
- NO_DEFAULT_PATH
- NO_CMAKE_FIND_ROOT_PATH
- )
-
-if (LIBCXXABI_LIBCXX_PATH STREQUAL "LIBCXXABI_LIBCXX_PATH-NOTFOUND")
- message(WARNING "LIBCXXABI_LIBCXX_PATH was not specified and couldn't be infered.")
- set(LIBCXXABI_LIBCXX_PATH "")
-endif()
-
-set(LIBCXXABI_LIBCXX_PATH "${LIBCXXABI_LIBCXX_PATH}" CACHE PATH
- "Specify path to libc++ source." FORCE)
+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
+ "Specify path to libc++ includes.")
+message(STATUS "Libc++abi will be using libc++ includes from ${LIBCXXABI_LIBCXX_INCLUDES}")
option(LIBCXXABI_HERMETIC_STATIC_LIBRARY
"Do not export any symbols from the static library." OFF)
+set(LIBCXXABI_TEST_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/test/lit.site.cfg.in" CACHE STRING
+ "The Lit testing configuration to use when running the tests.")
+set(LIBCXXABI_TEST_PARAMS "" CACHE STRING
+ "A list of parameters to run the Lit test suite with.")
+
#===============================================================================
# Configure System
#===============================================================================
# Do we really need to be run through the C compiler ?
add_c_compile_flags_if_supported(-funwind-tables)
else()
- add_definitions(-D_LIBCXXABI_NO_EXCEPTIONS)
add_compile_flags_if_supported(-fno-exceptions)
add_compile_flags_if_supported(-EHs-)
add_compile_flags_if_supported(-EHa-)
check_library_exists(c fopen "" LIBCXXABI_HAS_C_LIB)
if (NOT LIBCXXABI_USE_COMPILER_RT)
- check_library_exists(gcc_s __gcc_personality_v0 "" LIBCXXABI_HAS_GCC_S_LIB)
- check_library_exists(gcc __aeabi_uldivmod "" LIBCXXABI_HAS_GCC_LIB)
+ if (ANDROID)
+ check_library_exists(gcc __gcc_personality_v0 "" LIBCXXABI_HAS_GCC_LIB)
+ else ()
+ check_library_exists(gcc_s __gcc_personality_v0 "" LIBCXXABI_HAS_GCC_S_LIB)
+ check_library_exists(gcc __aeabi_uldivmod "" LIBCXXABI_HAS_GCC_LIB)
+ endif ()
endif ()
# libc++abi is built with -nodefaultlibs, so we want all our checks to also
# define _LIBCXXABI_GUARD_ABI_ARM
#endif
+#if defined(_LIBCXXABI_COMPILER_CLANG)
+# if !__has_feature(cxx_exceptions)
+# define _LIBCXXABI_NO_EXCEPTIONS
+# endif
+#elif defined(_LIBCXXABI_COMPILER_GCC) && !__EXCEPTIONS
+# define _LIBCXXABI_NO_EXCEPTIONS
+#endif
+
#endif // ____CXXABI_CONFIG_H
--- /dev/null
+___cxa_allocate_dependent_exception
+___cxa_allocate_exception
+___cxa_begin_catch
+___cxa_call_unexpected
+___cxa_current_exception_type
+___cxa_end_catch
+___cxa_free_dependent_exception
+___cxa_free_exception
+___cxa_get_exception_ptr
+___cxa_rethrow
+___cxa_throw
__ZTVSt9exception
__ZTVSt9type_info
-# Itanium C++ ABI requirements
-___cxa_allocate_dependent_exception
-___cxa_allocate_exception
+# Itanium C++ ABI requirements (minus most exception support)
___cxa_bad_cast
___cxa_bad_typeid
-___cxa_begin_catch
-___cxa_call_unexpected
-___cxa_current_exception_type
___cxa_current_primary_exception
___cxa_decrement_exception_refcount
___cxa_deleted_virtual
___cxa_demangle
-___cxa_end_catch
-___cxa_free_dependent_exception
-___cxa_free_exception
-___cxa_get_exception_ptr
___cxa_get_globals
___cxa_get_globals_fast
___cxa_guard_abort
___cxa_guard_release
___cxa_increment_exception_refcount
___cxa_pure_virtual
-___cxa_rethrow
___cxa_rethrow_primary_exception
-___cxa_throw
___cxa_throw_bad_array_new_length
___cxa_uncaught_exception
___cxa_uncaught_exceptions
cxa_exception_storage.cpp
cxa_guard.cpp
cxa_handlers.cpp
- cxa_unexpected.cpp
cxa_vector.cpp
cxa_virtual.cpp
# C++ STL files
add_definitions(-DHAVE___CXA_THREAD_ATEXIT_IMPL)
endif()
+if (LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST)
+ add_definitions(-D_LIBCXXABI_FORGIVING_DYNAMIC_CAST)
+endif()
+
if (APPLE)
add_library_flags_if(LIBCXXABI_HAS_SYSTEM_LIB System)
else()
# MINGW_LIBRARIES is defined in config-ix.cmake
list(APPEND LIBCXXABI_LIBRARIES ${MINGW_LIBRARIES})
endif()
+if (ANDROID AND ANDROID_PLATFORM_LEVEL LESS 21)
+ list(APPEND LIBCXXABI_LIBRARIES android_support)
+endif()
if (NOT LIBCXXABI_USE_COMPILER_RT)
add_library_flags_if(LIBCXXABI_HAS_GCC_LIB gcc)
add_link_flags("-Wl,-rpath,${LIBDIR}")
endif()
endif()
+
+ # Make sure we link in CrashReporterClient if we find it -- it's used by
+ # abort() on Apple platforms when building the system dylib.
+ find_library(CrashReporterClient NAMES libCrashReporterClient.a
+ PATHS "${CMAKE_OSX_SYSROOT}/usr/local/lib")
+ if (CrashReporterClient)
+ message(STATUS "Linking with CrashReporterClient at ${CrashReporterClient}")
+ add_library_flags("${CrashReporterClient}")
+ else()
+ message(STATUS "Could not find CrashReporterClient, not linking against it")
+ endif()
endif()
split_list(LIBCXXABI_COMPILE_FLAGS)
message(STATUS "Could not find ParallelSTL, libc++abi will not attempt to use it but the build may fail if the libc++ in use needs it to be available.")
endif()
-if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(armv6|armv7|armv7s)$")
- set(LIBCXXABI_USE_SJLJ_EXCEPTIONS ON)
-else()
- set(LIBCXXABI_USE_SJLJ_EXCEPTIONS OFF)
-endif()
-
# Build the shared library.
if (LIBCXXABI_ENABLE_SHARED)
add_library(cxxabi_shared SHARED ${LIBCXXABI_SOURCES} ${LIBCXXABI_HEADERS})
target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/new-delete.exp")
endif()
- if (LIBCXXABI_USE_SJLJ_EXCEPTIONS)
- target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-sjlj.exp")
- else()
- target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-v0.exp")
+ if (LIBCXXABI_ENABLE_EXCEPTIONS)
+ target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${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")
+ else()
+ target_link_libraries(cxxabi_shared PRIVATE "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/../lib/personality-v0.exp")
+ endif()
endif()
endif()
endif()
set(MERGE_ARCHIVES_LIBTOOL "--use-libtool" "--libtool" "${CMAKE_LIBTOOL}")
endif()
- # Merge the the libc++abi.a and libunwind.a into one.
+ # Merge the libc++abi.a and libunwind.a into one.
if(LIBCXXABI_USE_LLVM_UNWINDER AND LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY)
add_custom_command(TARGET cxxabi_static POST_BUILD
COMMAND ${PYTHON_EXECUTABLE} ${LIBCXXABI_LIBCXX_PATH}/utils/merge_archives.py
-DCMAKE_INSTALL_COMPONENT=cxxabi
-DCMAKE_INSTALL_DO_STRIP=1
-P "${LIBCXXABI_BINARY_DIR}/cmake_install.cmake")
-
- # TODO: This is a legacy target name and should be removed at some point.
- add_custom_target(install-libcxxabi DEPENDS install-cxxabi)
endif()
#include "abort_message.h"
#ifdef __BIONIC__
-#include <android/api-level.h>
-#if __ANDROID_API__ >= 21
-#include <syslog.h>
-extern "C" void android_set_abort_message(const char* msg);
-#else
-#include <assert.h>
-#endif // __ANDROID_API__ >= 21
+# include <android/api-level.h>
+# if __ANDROID_API__ >= 21
+# include <syslog.h>
+ extern "C" void android_set_abort_message(const char* msg);
+# else
+# include <assert.h>
+# endif // __ANDROID_API__ >= 21
#endif // __BIONIC__
-#ifdef __APPLE__
-# if defined(__has_include) && __has_include(<CrashReporterClient.h>)
-# define HAVE_CRASHREPORTERCLIENT_H
-# include <CrashReporterClient.h>
-# endif
+#if defined(__APPLE__) && __has_include(<CrashReporterClient.h>)
+# include <CrashReporterClient.h>
+# define _LIBCXXABI_USE_CRASHREPORTER_CLIENT
#endif
void abort_message(const char* format, ...)
{
- // write message to stderr
+ // Write message to stderr. We do this before formatting into a
+ // variable-size buffer so that we still get some information if
+ // formatting into the variable-sized buffer fails.
#if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL)
-#ifdef __APPLE__
- fprintf(stderr, "libc++abi.dylib: ");
+ {
+ fprintf(stderr, "libc++abi: ");
+ va_list list;
+ va_start(list, format);
+ vfprintf(stderr, format, list);
+ va_end(list);
+ fprintf(stderr, "\n");
+ }
#endif
+
+ // Format the arguments into an allocated buffer. We leak the buffer on
+ // purpose, since we're about to abort() anyway.
+#if defined(_LIBCXXABI_USE_CRASHREPORTER_CLIENT)
+ char* buffer;
va_list list;
va_start(list, format);
- vfprintf(stderr, format, list);
+ vasprintf(&buffer, format, list);
va_end(list);
- fprintf(stderr, "\n");
-#endif
-#if defined(__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
- // record message in crash report
- char* buffer;
- va_list list2;
- va_start(list2, format);
- vasprintf(&buffer, format, list2);
- va_end(list2);
CRSetCrashLogMessage(buffer);
#elif defined(__BIONIC__)
char* buffer;
- va_list list2;
- va_start(list2, format);
- vasprintf(&buffer, format, list2);
- va_end(list2);
+ va_list list;
+ va_start(list, format);
+ vasprintf(&buffer, format, list);
+ va_end(list);
-#if __ANDROID_API__ >= 21
+# if __ANDROID_API__ >= 21
// Show error in tombstone.
android_set_abort_message(buffer);
openlog("libc++abi", 0, 0);
syslog(LOG_CRIT, "%s", buffer);
closelog();
-#else
+# else
// The good error reporting wasn't available in Android until L. Since we're
// about to abort anyway, just call __assert2, which will log _somewhere_
// (tombstone and/or logcat) in older releases.
__assert2(__FILE__, __LINE__, __func__, buffer);
-#endif // __ANDROID_API__ >= 21
+# endif // __ANDROID_API__ >= 21
#endif // __BIONIC__
abort();
#include "cxxabi.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-_LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
+extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
abort_message(const char *format, ...) __attribute__((format(printf, 1, 2)));
-#ifdef __cplusplus
-}
#endif
-
-#endif
-
#include "__cxxabi_config.h"
#include "include/atomic_support.h"
#include <unistd.h>
-#include <sys/types.h>
#if defined(__has_include)
# if __has_include(<sys/syscall.h>)
# include <sys/syscall.h>
bool is_init = false;
};
+template <class IntType>
+class AtomicInt {
+public:
+ using MemoryOrder = std::__libcpp_atomic_order;
+
+ explicit AtomicInt(IntType *b) : b(b) {}
+ AtomicInt(AtomicInt const&) = delete;
+ AtomicInt& operator=(AtomicInt const&) = delete;
+
+ IntType load(MemoryOrder ord) {
+ return std::__libcpp_atomic_load(b, ord);
+ }
+ void store(IntType val, MemoryOrder ord) {
+ std::__libcpp_atomic_store(b, val, ord);
+ }
+ IntType exchange(IntType new_val, MemoryOrder ord) {
+ return std::__libcpp_atomic_exchange(b, new_val, ord);
+ }
+ bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
+ return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
+ }
+
+private:
+ IntType *b;
+};
+
//===----------------------------------------------------------------------===//
// PlatformGetThreadID
//===----------------------------------------------------------------------===//
public:
/// base_address - the address of the original guard object.
void* const base_address;
- /// The address of the guord byte at offset 0.
+ /// The address of the guard byte at offset 0.
uint8_t* const guard_byte_address;
/// The address of the byte used by the implementation during initialization.
uint8_t* const init_byte_address;
#ifndef _CXA_HANDLERS_H
#define _CXA_HANDLERS_H
-#include <__cxxabi_config.h>
+#include "__cxxabi_config.h"
#include <exception>
namespace __cxxabiv1 {
-#if 0
-#pragma mark --Helper routines and classes --
-#endif
+//
+// Helper routines and classes
+//
namespace {
inline static size_t __get_element_count ( void *p ) {
};
}
-#if 0
-#pragma mark --Externally visible routines--
-#endif
+//
+// Externally visible routines
+//
namespace {
_LIBCXXABI_NORETURN
--- /dev/null
+BasedOnStyle: LLVM
+
X(BoolExpr) \
X(StringLiteral) \
X(LambdaExpr) \
- X(IntegerCastExpr) \
+ X(EnumLiteral) \
X(IntegerLiteral) \
X(FloatLiteral) \
X(DoubleLiteral) \
}
};
-class IntegerCastExpr : public Node {
+class EnumLiteral : public Node {
// ty(integer)
const Node *Ty;
StringView Integer;
public:
- IntegerCastExpr(const Node *Ty_, StringView Integer_)
- : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {}
+ EnumLiteral(const Node *Ty_, StringView Integer_)
+ : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
void printLeft(OutputStream &S) const override {
- S += "(";
+ S << "(";
Ty->print(S);
- S += ")";
- S += Integer;
+ S << ")";
+
+ if (Integer[0] == 'n')
+ S << "-" << Integer.dropFront(1);
+ else
+ S << Integer;
}
};
// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
+// ::= fpT # 'this' expression (not part of standard?)
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
+ if (consumeIf("fpT"))
+ return make<NameType>("this");
if (consumeIf("fp")) {
parseCVQualifiers();
StringView Num = parseNumber();
return getDerived().template parseFloatingLiteral<double>();
case 'e':
++First;
+#if defined(__powerpc__) || defined(__s390__)
+ // Handle cases where long doubles encoded with e have the same size
+ // and representation as doubles.
+ return getDerived().template parseFloatingLiteral<double>();
+#else
return getDerived().template parseFloatingLiteral<long double>();
+#endif
case '_':
if (consumeIf("_Z")) {
Node *R = getDerived().parseEncoding();
Node *T = getDerived().parseType();
if (T == nullptr)
return nullptr;
- StringView N = parseNumber();
+ StringView N = parseNumber(/*AllowNegative=*/true);
if (N.empty())
return nullptr;
if (!consumeIf('E'))
return nullptr;
- return make<IntegerCastExpr>(T, N);
+ return make<EnumLiteral>(T, N);
}
}
}
// ::= <special-name>
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
+ // The template parameters of an encoding are unrelated to those of the
+ // enclosing context.
+ class SaveTemplateParams {
+ AbstractManglingParser *Parser;
+ decltype(TemplateParams) OldParams;
+
+ public:
+ SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) {
+ OldParams = std::move(Parser->TemplateParams);
+ Parser->TemplateParams.clear();
+ }
+ ~SaveTemplateParams() {
+ Parser->TemplateParams = std::move(OldParams);
+ }
+ } SaveTemplateParams(this);
+
if (look() == 'G' || look() == 'T')
return getDerived().parseSpecialName();
_LIBCPP_END_NAMESPACE_STD
-namespace {
-
-template <class IntType>
-class AtomicInt {
-public:
- using MemoryOrder = std::__libcpp_atomic_order;
-
- explicit AtomicInt(IntType *b) : b(b) {}
- AtomicInt(AtomicInt const&) = delete;
- AtomicInt& operator=(AtomicInt const&) = delete;
-
- IntType load(MemoryOrder ord) {
- return std::__libcpp_atomic_load(b, ord);
- }
- void store(IntType val, MemoryOrder ord) {
- std::__libcpp_atomic_store(b, val, ord);
- }
- IntType exchange(IntType new_val, MemoryOrder ord) {
- return std::__libcpp_atomic_exchange(b, new_val, ord);
- }
- bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
- return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
- }
-
-private:
- IntType *b;
-};
-
-} // end namespace
-
#endif // ATOMIC_SUPPORT_H
#include "private_typeinfo.h"
-// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more
-// forgiving when type_info's mistakenly have hidden visibility and thus
-// multiple type_infos can exist for a single type.
+// The flag _LIBCXXABI_FORGIVING_DYNAMIC_CAST is used to make dynamic_cast
+// more forgiving when type_info's mistakenly have hidden visibility and
+// thus multiple type_infos can exist for a single type.
//
-// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where
+// When _LIBCXXABI_FORGIVING_DYNAMIC_CAST is defined, and only in the case where
// there is a detected inconsistency in the type_info hierarchy during a
// dynamic_cast, then the equality operation will fall back to using strcmp
// on type_info names to determine type_info equality.
// algorithm and an inconsistency is still detected, dynamic_cast will call
// abort with an appropriate message.
//
-// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a
+// The current implementation of _LIBCXXABI_FORGIVING_DYNAMIC_CAST requires a
// printf-like function called syslog:
//
// void syslog(int facility_priority, const char* format, ...);
// If you want this functionality but your platform doesn't have syslog,
// just implement it in terms of fprintf(stderr, ...).
//
-// _LIBCXX_DYNAMIC_FALLBACK is currently off by default.
+// _LIBCXXABI_FORGIVING_DYNAMIC_CAST is currently off by default.
// On Windows, typeids are different between DLLs and EXEs, so comparing
// type_info* will work for typeids from the same compiled file but fail
// for typeids from a DLL and an executable. Among other things, exceptions
// are not caught by handlers since can_catch() returns false.
//
-// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls
+// Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST does not help since can_catch() calls
// is_equal() with use_strcmp=false so the string names are not compared.
#include <string.h>
-#ifdef _LIBCXX_DYNAMIC_FALLBACK
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
#include "abort_message.h"
#include <sys/syslog.h>
+#include <atomic>
#endif
static inline
info.number_of_dst_type = 1;
// Do the search
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
-#ifdef _LIBCXX_DYNAMIC_FALLBACK
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should definitely
// find (static_ptr, static_type), either on a public or private path
if (info.path_dst_ptr_to_static_ptr == unknown)
{
// We get here only if there is some kind of visibility problem
// in client code.
- syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
- "should have public visibility. At least one of them is hidden. %s"
- ", %s.\n", static_type->name(), dynamic_type->name());
+ static std::atomic<size_t> error_count(0);
+ size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
+ if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
+ syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
+ "should have public visibility. At least one of them is hidden. %s"
+ ", %s.\n", static_type->name(), dynamic_type->name());
// Redo the search comparing type_info's using strcmp
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
info.number_of_dst_type = 1;
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
}
-#endif // _LIBCXX_DYNAMIC_FALLBACK
+#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// Query the search.
if (info.path_dst_ptr_to_static_ptr == public_path)
dst_ptr = dynamic_ptr;
{
// Not using giant short cut. Do the search
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
- #ifdef _LIBCXX_DYNAMIC_FALLBACK
+ #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should definitely
// find (static_ptr, static_type), either on a public or private path
if (info.path_dst_ptr_to_static_ptr == unknown &&
info.path_dynamic_ptr_to_static_ptr == unknown)
{
- syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
- "has hidden visibility or is defined in more than one translation "
- "unit. They should all have public visibility. "
- "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
- dst_type->name());
+ static std::atomic<size_t> error_count(0);
+ size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
+ if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
+ syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
+ "has hidden visibility or is defined in more than one translation "
+ "unit. They should all have public visibility. "
+ "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
+ dst_type->name());
// Redo the search comparing type_info's using strcmp
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
}
-#endif // _LIBCXX_DYNAMIC_FALLBACK
+#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// Query the search.
switch (info.number_to_static_ptr)
{