Handle lack of <bits/c++config.h> and <bits/functexcept.h>
authorPeter Griess <pgriess@fb.com>
Wed, 25 Sep 2013 23:49:10 +0000 (18:49 -0500)
committerPeter Griess <pgriess@fb.com>
Tue, 26 Nov 2013 15:05:18 +0000 (07:05 -0800)
Summary:
- Clang's libc++ doesn't provide these header files. Detect libc++ via
the _LIBCPP_VERSION symbol (pulling it in by sourcing some header
files earlier if necessary) and avoid using these files.

Test Plan:
- fbconfig -r folly && fbmake runtests
- ./configure && make check on Ubuntu/FC/Mac

Reviewed By: andrewjcg@fb.com

FB internal diff: D998595

folly/FBString.h
folly/Malloc.h
folly/Range.h
folly/Traits.h

index 6f5ea13194978aad661e2227f6fcc34e90ba8d26..6912e0c751e05d0d2aa8f1d56e2eaedba14aa1ac 100644 (file)
 #endif
 #endif
 
+#include <atomic>
+#include <limits>
+#include <type_traits>
+
+// libc++ doesn't provide this header
+#ifndef _LIBCPP_VERSION
 // This file appears in two locations: inside fbcode and in the
 // libstdc++ source code (when embedding fbstring as std::string).
 // To aid in this schizophrenic use, two macros are defined in
@@ -65,6 +71,7 @@
 //   _LIBSTDCXX_FBSTRING - Set inside libstdc++.  This is useful to
 //      gate use inside fbcode v. libstdc++
 #include <bits/c++config.h>
+#endif
 
 #ifdef _LIBSTDCXX_FBSTRING
 
 #undef FOLLY_MALLOC_H_
 #endif
 
+// FBString cannot use throw when replacing std::string, though it may still
+// use std::__throw_*
+#define throw FOLLY_FBSTRING_MAY_NOT_USE_THROW
+#define THROW_LENGTH_ERROR    std::__throw_length_error
+#define THROW_LOGIC_ERROR     std::__throw_logic_error
+#define THROW_OUT_OF_RANGE    std::__throw_out_of_range
+
 #else // !_LIBSTDCXX_FBSTRING
 
 #include <string>
 #include <cstring>
 #include <cassert>
+#include <stdexcept>
 
 #include "folly/Traits.h"
 #include "folly/Malloc.h"
 #include "folly/Hash.h"
 
+#define THROW_LENGTH_ERROR    ::folly::throw_length_error
+#define THROW_LOGIC_ERROR     ::folly::throw_logic_error
+#define THROW_OUT_OF_RANGE    ::folly::throw_out_of_range
+
 #endif
 
 // We defined these here rather than including Likely.h to avoid
 #define FBSTRING_LIKELY(x)   (__builtin_expect((x), 1))
 #define FBSTRING_UNLIKELY(x) (__builtin_expect((x), 0))
 
-#include <atomic>
-#include <limits>
-#include <type_traits>
-
 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wshadow"
 
-// FBString cannot use throw when replacing std::string, though it may still
-// use std::__throw_*
-#define throw FOLLY_FBSTRING_MAY_NOT_USE_THROW
-
 #ifdef _LIBSTDCXX_FBSTRING
 namespace std _GLIBCXX_VISIBILITY(default) {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #else
 namespace folly {
+namespace {
+
+void throw_length_error(const char* msg) {
+  throw std::length_error(msg);
+}
+
+void throw_logic_error(const char* msg) {
+  throw std::logic_error(msg);
+}
+
+void throw_out_of_range(const char* msg) {
+  throw std::out_of_range(msg);
+}
+
+} // namespace fbstring_detail
 #endif
 
 // Different versions of gcc/clang support different versions of
@@ -1048,7 +1074,7 @@ public:
       : store_(s, s ? traits_type::length(s) : ({
           basic_fbstring<char> err = __PRETTY_FUNCTION__;
           err += ": null pointer initializer not valid";
-          std::__throw_logic_error(err.c_str());
+          THROW_LOGIC_ERROR(err.c_str());
           0;
       })) {
   }
@@ -1261,7 +1287,7 @@ public:
   size_type capacity() const { return store_.capacity(); }
 
   void reserve(size_type res_arg = 0) {
-    enforce(res_arg <= max_size(), std::__throw_length_error, "");
+    enforce(res_arg <= max_size(), THROW_LENGTH_ERROR, "");
     store_.reserve(res_arg);
   }
 
@@ -1291,12 +1317,12 @@ public:
   }
 
   const_reference at(size_type n) const {
-    enforce(n <= size(), std::__throw_out_of_range, "");
+    enforce(n <= size(), THROW_OUT_OF_RANGE, "");
     return (*this)[n];
   }
 
   reference at(size_type n) {
-    enforce(n < size(), std::__throw_out_of_range, "");
+    enforce(n < size(), THROW_OUT_OF_RANGE, "");
     return (*this)[n];
   }
 
@@ -1331,7 +1357,7 @@ public:
   basic_fbstring& append(const basic_fbstring& str, const size_type pos,
                          size_type n) {
     const size_type sz = str.size();
-    enforce(pos <= sz, std::__throw_out_of_range, "");
+    enforce(pos <= sz, THROW_OUT_OF_RANGE, "");
     procrustes(n, sz - pos);
     return append(str.data() + pos, n);
   }
@@ -1408,7 +1434,7 @@ public:
   basic_fbstring& assign(const basic_fbstring& str, const size_type pos,
                          size_type n) {
     const size_type sz = str.size();
-    enforce(pos <= sz, std::__throw_out_of_range, "");
+    enforce(pos <= sz, THROW_OUT_OF_RANGE, "");
     procrustes(n, sz - pos);
     return assign(str.data() + pos, n);
   }
@@ -1450,13 +1476,13 @@ public:
 
   basic_fbstring& insert(size_type pos1, const basic_fbstring& str,
                          size_type pos2, size_type n) {
-    enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
+    enforce(pos2 <= str.length(), THROW_OUT_OF_RANGE, "");
     procrustes(n, str.length() - pos2);
     return insert(pos1, str.data() + pos2, n);
   }
 
   basic_fbstring& insert(size_type pos, const value_type* s, size_type n) {
-    enforce(pos <= length(), std::__throw_out_of_range, "");
+    enforce(pos <= length(), THROW_OUT_OF_RANGE, "");
     insert(begin() + pos, s, s + n);
     return *this;
   }
@@ -1466,7 +1492,7 @@ public:
   }
 
   basic_fbstring& insert(size_type pos, size_type n, value_type c) {
-    enforce(pos <= length(), std::__throw_out_of_range, "");
+    enforce(pos <= length(), THROW_OUT_OF_RANGE, "");
     insert(begin() + pos, n, c);
     return *this;
   }
@@ -1586,7 +1612,7 @@ public:
   basic_fbstring& erase(size_type pos = 0, size_type n = npos) {
     Invariant checker(*this);
     (void) checker;
-    enforce(pos <= length(), std::__throw_out_of_range, "");
+    enforce(pos <= length(), THROW_OUT_OF_RANGE, "");
     procrustes(n, length() - pos);
     std::copy(begin() + pos + n, end(), begin() + pos);
     resize(length() - n);
@@ -1595,7 +1621,7 @@ public:
 
   iterator erase(iterator position) {
     const size_type pos(position - begin());
-    enforce(pos <= size(), std::__throw_out_of_range, "");
+    enforce(pos <= size(), THROW_OUT_OF_RANGE, "");
     erase(pos, 1);
     return begin() + pos;
   }
@@ -1618,7 +1644,7 @@ public:
   basic_fbstring& replace(size_type pos1, size_type n1,
                           const basic_fbstring& str,
                           size_type pos2, size_type n2) {
-    enforce(pos2 <= str.length(), std::__throw_out_of_range, "");
+    enforce(pos2 <= str.length(), THROW_OUT_OF_RANGE, "");
     return replace(pos1, n1, str.data() + pos2,
                    std::min(n2, str.size() - pos2));
   }
@@ -1640,7 +1666,7 @@ public:
                           StrOrLength s_or_n2, NumOrChar n_or_c) {
     Invariant checker(*this);
     (void) checker;
-    enforce(pos <= size(), std::__throw_out_of_range, "");
+    enforce(pos <= size(), THROW_OUT_OF_RANGE, "");
     procrustes(n1, length() - pos);
     const iterator b = begin() + pos;
     return replace(b, b + n1, s_or_n2, n_or_c);
@@ -1762,7 +1788,7 @@ public:
   }
 
   size_type copy(value_type* s, size_type n, size_type pos = 0) const {
-    enforce(pos <= size(), std::__throw_out_of_range, "");
+    enforce(pos <= size(), THROW_OUT_OF_RANGE, "");
     procrustes(n, size() - pos);
 
     fbstring_detail::pod_copy(
@@ -1994,7 +2020,7 @@ public:
   }
 
   basic_fbstring substr(size_type pos = 0, size_type n = npos) const {
-    enforce(pos <= size(), std::__throw_out_of_range, "");
+    enforce(pos <= size(), THROW_OUT_OF_RANGE, "");
     return basic_fbstring(data() + pos, std::min(n, size() - pos));
   }
 
@@ -2015,7 +2041,7 @@ public:
 
   int compare(size_type pos1, size_type n1,
               const value_type* s, size_type n2) const {
-    enforce(pos1 <= size(), std::__throw_out_of_range, "");
+    enforce(pos1 <= size(), THROW_OUT_OF_RANGE, "");
     procrustes(n1, size() - pos1);
     // The line below fixed by Jean-Francois Bastien, 04-23-2007. Thanks!
     const int r = traits_type::compare(pos1 + data(), s, std::min(n1, n2));
@@ -2025,7 +2051,7 @@ public:
   int compare(size_type pos1, size_type n1,
               const basic_fbstring& str,
               size_type pos2, size_type n2) const {
-    enforce(pos2 <= str.size(), std::__throw_out_of_range, "");
+    enforce(pos2 <= str.size(), THROW_OUT_OF_RANGE, "");
     return compare(pos1, n1, str.data() + pos2,
                    std::min(n2, str.size() - pos2));
   }
index f7c94ca1896f79cb707c04501db606134dd0e5cd..8310a9aafddac67b7d2bd789701dbbd71b9183fb 100644 (file)
@@ -41,9 +41,11 @@ namespace folly {
 
 #ifdef _LIBSTDCXX_FBSTRING
 #pragma GCC system_header
+#include <bits/functexcept.h>
 #define FOLLY_HAVE_MALLOC_H 1
 #else
 #include "folly/Portability.h"
+#include <stdexcept>
 #endif
 
 // for malloc_usable_size
@@ -62,8 +64,6 @@ namespace folly {
 
 #include <new>
 
-#include <bits/functexcept.h>
-
 /**
  * Define various ALLOCM_* macros normally provided by jemalloc.  We define
  * them so that we don't have to include jemalloc.h, in case the program is
@@ -157,19 +157,31 @@ static const size_t jemallocMinInPlaceExpandable = 4096;
  */
 inline void* checkedMalloc(size_t size) {
   void* p = malloc(size);
+#ifdef _LIBSTDCXX_FBSTRING
   if (!p) std::__throw_bad_alloc();
+#else
+  if (!p) throw std::bad_alloc();
+#endif
   return p;
 }
 
 inline void* checkedCalloc(size_t n, size_t size) {
   void* p = calloc(n, size);
+#ifdef _LIBSTDCXX_FBSTRING
   if (!p) std::__throw_bad_alloc();
+#else
+  if (!p) throw std::bad_alloc();
+#endif
   return p;
 }
 
 inline void* checkedRealloc(void* ptr, size_t size) {
   void* p = realloc(ptr, size);
+#ifdef _LIBSTDCXX_FBSTRING
   if (!p) std::__throw_bad_alloc();
+#else
+  if (!p) throw std::bad_alloc();
+#endif
   return p;
 }
 
index 2041d29b38134422afdcfacc2c25cefef4636dbc..487bc4edf5ca1f85e2faddda771dc41832cee0e3 100644 (file)
 #include <stdexcept>
 #include <type_traits>
 #include <boost/operators.hpp>
+
+// libc++ doesn't provide this header
+#if !FOLLY_USE_LIBCPP
+// This file appears in two locations: inside fbcode and in the
+// libstdc++ source code (when embedding fbstring as std::string).
+// To aid in this schizophrenic use, two macros are defined in
+// c++config.h:
+//   _LIBSTDCXX_FBSTRING - Set inside libstdc++.  This is useful to
+//      gate use inside fbcode v. libstdc++
 #include <bits/c++config.h>
+#endif
+
 #include "folly/CpuId.h"
 #include "folly/Traits.h"
 #include "folly/Likely.h"
index f5fe5816cf0e2f456aa665788a2795ec289345a1..4d6deeb5628799cc4a61d0964411588586ba8589 100644 (file)
 
 #include "folly/Portability.h"
 
+// libc++ doesn't provide this header
+#if !FOLLY_USE_LIBCPP
+// This file appears in two locations: inside fbcode and in the
+// libstdc++ source code (when embedding fbstring as std::string).
+// To aid in this schizophrenic use, two macros are defined in
+// c++config.h:
+//   _LIBSTDCXX_FBSTRING - Set inside libstdc++.  This is useful to
+//      gate use inside fbcode v. libstdc++
 #include <bits/c++config.h>
+#endif
 
 #include <boost/type_traits.hpp>
 #include <boost/mpl/and.hpp>