Exceptions store the message as reference counted string for
compatibility to libstdc++. Move the implementation into a header for
easier sharing with libc++abi. Merge a number of improvements from that
version. Provide a POD definition for <stdexcept>'s public use to avoid
cast dances. Discussed with Marshall Clow.
llvm-svn: 207695
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: a1fbf3459fd1a2f480183615893065f0c2e9dae9
diff --git a/src/stdexcept.cpp b/src/stdexcept.cpp
index ec7f666..aff4b18 100644
--- a/src/stdexcept.cpp
+++ b/src/stdexcept.cpp
@@ -7,124 +7,42 @@
//
//===----------------------------------------------------------------------===//
+#include "__refstring"
#include "stdexcept"
#include "new"
#include "string"
-#include <cstdlib>
-#include <cstring>
-#include <cstdint>
-#include <cstddef>
#include "system_error"
#ifndef __has_include
#define __has_include(inc) 0
#endif
-#ifdef __APPLE__
-#include <cxxabi.h>
-#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
+/* For _LIBCPPABI_VERSION */
+#if __has_include(<cxxabi.h>) || defined(__APPLE_) || defined(LIBCXXRT)
#include <cxxabi.h>
#endif
-// Note: optimize for size
-
-#if ! defined(_LIBCPP_MSVC)
-#pragma GCC visibility push(hidden)
-#endif
-
-namespace
-{
-
-class __libcpp_nmstr
-{
-private:
- const char* str_;
-
- typedef std::size_t unused_t;
- typedef std::ptrdiff_t count_t;
-
- static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
- sizeof(count_t));
-
- count_t& count() const _NOEXCEPT {return *const_cast<count_t *>(reinterpret_cast<const count_t *>(str_ - sizeof(count_t)));}
-public:
- explicit __libcpp_nmstr(const char* msg);
- __libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT;
- __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _NOEXCEPT;
- ~__libcpp_nmstr();
- const char* c_str() const _NOEXCEPT {return str_;}
-};
-
-__libcpp_nmstr::__libcpp_nmstr(const char* msg)
-{
- std::size_t len = strlen(msg);
- str_ = new char[len + 1 + offset];
- unused_t* c = reinterpret_cast<unused_t*>(const_cast<char *>(str_));
- c[0] = c[1] = len;
- str_ += offset;
- count() = 0;
- std::memcpy(const_cast<char*>(c_str()), msg, len + 1);
-}
-
-inline
-__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT
- : str_(s.str_)
-{
- __sync_add_and_fetch(&count(), 1);
-}
-
-__libcpp_nmstr&
-__libcpp_nmstr::operator=(const __libcpp_nmstr& s) _NOEXCEPT
-{
- const char* p = str_;
- str_ = s.str_;
- __sync_add_and_fetch(&count(), 1);
- if (__sync_add_and_fetch(reinterpret_cast<count_t*>(const_cast<char*>(p)-sizeof(count_t)), count_t(-1)) < 0)
- delete [] (p-offset);
- return *this;
-}
-
-inline
-__libcpp_nmstr::~__libcpp_nmstr()
-{
- if (__sync_add_and_fetch(&count(), count_t(-1)) < 0)
- delete [] (str_ - offset);
-}
-
-}
-
-#if ! defined(_LIBCPP_MSVC)
-#pragma GCC visibility pop
-#endif
+static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), "");
namespace std // purposefully not using versioning namespace
{
-logic_error::logic_error(const string& msg)
+logic_error::logic_error(const string& msg) : __imp_(msg.c_str())
{
- __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- ::new(s) __libcpp_nmstr(msg.c_str());
}
-logic_error::logic_error(const char* msg)
+logic_error::logic_error(const char* msg) : __imp_(msg)
{
- __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- ::new(s) __libcpp_nmstr(msg);
}
-logic_error::logic_error(const logic_error& le) _NOEXCEPT
+logic_error::logic_error(const logic_error& le) _NOEXCEPT : __imp_(le.__imp_)
{
- __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- const __libcpp_nmstr *s2 = reinterpret_cast<const __libcpp_nmstr *>(&le.__imp_);
- ::new(s) __libcpp_nmstr(*s2);
}
logic_error&
logic_error::operator=(const logic_error& le) _NOEXCEPT
{
- __libcpp_nmstr *s1 = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- const __libcpp_nmstr *s2 = reinterpret_cast<const __libcpp_nmstr *>(&le.__imp_);
- *s1 = *s2;
+ __imp_ = le.__imp_;
return *this;
}
@@ -132,44 +50,33 @@
logic_error::~logic_error() _NOEXCEPT
{
- __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- s->~__libcpp_nmstr();
}
const char*
logic_error::what() const _NOEXCEPT
{
- const __libcpp_nmstr *s = reinterpret_cast<const __libcpp_nmstr *>(&__imp_);
- return s->c_str();
+ return __imp_.c_str();
}
#endif
-runtime_error::runtime_error(const string& msg)
+runtime_error::runtime_error(const string& msg) : __imp_(msg.c_str())
{
- __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- ::new(s) __libcpp_nmstr(msg.c_str());
}
-runtime_error::runtime_error(const char* msg)
+runtime_error::runtime_error(const char* msg) : __imp_(msg)
{
- __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- ::new(s) __libcpp_nmstr(msg);
}
runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
+ : __imp_(le.__imp_)
{
- __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- const __libcpp_nmstr *s2 = reinterpret_cast<const __libcpp_nmstr *>(&le.__imp_);
- ::new(s) __libcpp_nmstr(*s2);
}
runtime_error&
runtime_error::operator=(const runtime_error& le) _NOEXCEPT
{
- __libcpp_nmstr *s1 = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- const __libcpp_nmstr *s2 = reinterpret_cast<const __libcpp_nmstr *>(&le.__imp_);
- *s1 = *s2;
+ __imp_ = le.__imp_;
return *this;
}
@@ -177,15 +84,12 @@
runtime_error::~runtime_error() _NOEXCEPT
{
- __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
- s->~__libcpp_nmstr();
}
const char*
runtime_error::what() const _NOEXCEPT
{
- const __libcpp_nmstr *s = reinterpret_cast<const __libcpp_nmstr *>(&__imp_);
- return s->c_str();
+ return __imp_.c_str();
}
domain_error::~domain_error() _NOEXCEPT {}