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 {}