Commit 758e4c77 authored by Peter Griess's avatar Peter Griess

Handle lack of <bits/c++config.h> and <bits/functexcept.h>

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
parent 23123a01
...@@ -58,6 +58,12 @@ ...@@ -58,6 +58,12 @@
#endif #endif
#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 // This file appears in two locations: inside fbcode and in the
// libstdc++ source code (when embedding fbstring as std::string). // libstdc++ source code (when embedding fbstring as std::string).
// To aid in this schizophrenic use, two macros are defined in // To aid in this schizophrenic use, two macros are defined in
...@@ -65,6 +71,7 @@ ...@@ -65,6 +71,7 @@
// _LIBSTDCXX_FBSTRING - Set inside libstdc++. This is useful to // _LIBSTDCXX_FBSTRING - Set inside libstdc++. This is useful to
// gate use inside fbcode v. libstdc++ // gate use inside fbcode v. libstdc++
#include <bits/c++config.h> #include <bits/c++config.h>
#endif
#ifdef _LIBSTDCXX_FBSTRING #ifdef _LIBSTDCXX_FBSTRING
...@@ -80,16 +87,28 @@ ...@@ -80,16 +87,28 @@
#undef FOLLY_MALLOC_H_ #undef FOLLY_MALLOC_H_
#endif #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 #else // !_LIBSTDCXX_FBSTRING
#include <string> #include <string>
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
#include <stdexcept>
#include "folly/Traits.h" #include "folly/Traits.h"
#include "folly/Malloc.h" #include "folly/Malloc.h"
#include "folly/Hash.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 #endif
// We defined these here rather than including Likely.h to avoid // We defined these here rather than including Likely.h to avoid
...@@ -97,23 +116,30 @@ ...@@ -97,23 +116,30 @@
#define FBSTRING_LIKELY(x) (__builtin_expect((x), 1)) #define FBSTRING_LIKELY(x) (__builtin_expect((x), 1))
#define FBSTRING_UNLIKELY(x) (__builtin_expect((x), 0)) #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. // Ignore shadowing warnings within this file, so includers can use -Wshadow.
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow" #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 #ifdef _LIBSTDCXX_FBSTRING
namespace std _GLIBCXX_VISIBILITY(default) { namespace std _GLIBCXX_VISIBILITY(default) {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
#else #else
namespace folly { 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 #endif
// Different versions of gcc/clang support different versions of // Different versions of gcc/clang support different versions of
...@@ -1048,7 +1074,7 @@ public: ...@@ -1048,7 +1074,7 @@ public:
: store_(s, s ? traits_type::length(s) : ({ : store_(s, s ? traits_type::length(s) : ({
basic_fbstring<char> err = __PRETTY_FUNCTION__; basic_fbstring<char> err = __PRETTY_FUNCTION__;
err += ": null pointer initializer not valid"; err += ": null pointer initializer not valid";
std::__throw_logic_error(err.c_str()); THROW_LOGIC_ERROR(err.c_str());
0; 0;
})) { })) {
} }
...@@ -1261,7 +1287,7 @@ public: ...@@ -1261,7 +1287,7 @@ public:
size_type capacity() const { return store_.capacity(); } size_type capacity() const { return store_.capacity(); }
void reserve(size_type res_arg = 0) { 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); store_.reserve(res_arg);
} }
...@@ -1291,12 +1317,12 @@ public: ...@@ -1291,12 +1317,12 @@ public:
} }
const_reference at(size_type n) const { 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]; return (*this)[n];
} }
reference at(size_type n) { reference at(size_type n) {
enforce(n < size(), std::__throw_out_of_range, ""); enforce(n < size(), THROW_OUT_OF_RANGE, "");
return (*this)[n]; return (*this)[n];
} }
...@@ -1331,7 +1357,7 @@ public: ...@@ -1331,7 +1357,7 @@ public:
basic_fbstring& append(const basic_fbstring& str, const size_type pos, basic_fbstring& append(const basic_fbstring& str, const size_type pos,
size_type n) { size_type n) {
const size_type sz = str.size(); 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); procrustes(n, sz - pos);
return append(str.data() + pos, n); return append(str.data() + pos, n);
} }
...@@ -1408,7 +1434,7 @@ public: ...@@ -1408,7 +1434,7 @@ public:
basic_fbstring& assign(const basic_fbstring& str, const size_type pos, basic_fbstring& assign(const basic_fbstring& str, const size_type pos,
size_type n) { size_type n) {
const size_type sz = str.size(); 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); procrustes(n, sz - pos);
return assign(str.data() + pos, n); return assign(str.data() + pos, n);
} }
...@@ -1450,13 +1476,13 @@ public: ...@@ -1450,13 +1476,13 @@ public:
basic_fbstring& insert(size_type pos1, const basic_fbstring& str, basic_fbstring& insert(size_type pos1, const basic_fbstring& str,
size_type pos2, size_type n) { 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); procrustes(n, str.length() - pos2);
return insert(pos1, str.data() + pos2, n); return insert(pos1, str.data() + pos2, n);
} }
basic_fbstring& insert(size_type pos, const value_type* s, size_type 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); insert(begin() + pos, s, s + n);
return *this; return *this;
} }
...@@ -1466,7 +1492,7 @@ public: ...@@ -1466,7 +1492,7 @@ public:
} }
basic_fbstring& insert(size_type pos, size_type n, value_type c) { 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); insert(begin() + pos, n, c);
return *this; return *this;
} }
...@@ -1586,7 +1612,7 @@ public: ...@@ -1586,7 +1612,7 @@ public:
basic_fbstring& erase(size_type pos = 0, size_type n = npos) { basic_fbstring& erase(size_type pos = 0, size_type n = npos) {
Invariant checker(*this); Invariant checker(*this);
(void) checker; (void) checker;
enforce(pos <= length(), std::__throw_out_of_range, ""); enforce(pos <= length(), THROW_OUT_OF_RANGE, "");
procrustes(n, length() - pos); procrustes(n, length() - pos);
std::copy(begin() + pos + n, end(), begin() + pos); std::copy(begin() + pos + n, end(), begin() + pos);
resize(length() - n); resize(length() - n);
...@@ -1595,7 +1621,7 @@ public: ...@@ -1595,7 +1621,7 @@ public:
iterator erase(iterator position) { iterator erase(iterator position) {
const size_type pos(position - begin()); const size_type pos(position - begin());
enforce(pos <= size(), std::__throw_out_of_range, ""); enforce(pos <= size(), THROW_OUT_OF_RANGE, "");
erase(pos, 1); erase(pos, 1);
return begin() + pos; return begin() + pos;
} }
...@@ -1618,7 +1644,7 @@ public: ...@@ -1618,7 +1644,7 @@ public:
basic_fbstring& replace(size_type pos1, size_type n1, basic_fbstring& replace(size_type pos1, size_type n1,
const basic_fbstring& str, const basic_fbstring& str,
size_type pos2, size_type n2) { 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, return replace(pos1, n1, str.data() + pos2,
std::min(n2, str.size() - pos2)); std::min(n2, str.size() - pos2));
} }
...@@ -1640,7 +1666,7 @@ public: ...@@ -1640,7 +1666,7 @@ public:
StrOrLength s_or_n2, NumOrChar n_or_c) { StrOrLength s_or_n2, NumOrChar n_or_c) {
Invariant checker(*this); Invariant checker(*this);
(void) checker; (void) checker;
enforce(pos <= size(), std::__throw_out_of_range, ""); enforce(pos <= size(), THROW_OUT_OF_RANGE, "");
procrustes(n1, length() - pos); procrustes(n1, length() - pos);
const iterator b = begin() + pos; const iterator b = begin() + pos;
return replace(b, b + n1, s_or_n2, n_or_c); return replace(b, b + n1, s_or_n2, n_or_c);
...@@ -1762,7 +1788,7 @@ public: ...@@ -1762,7 +1788,7 @@ public:
} }
size_type copy(value_type* s, size_type n, size_type pos = 0) const { 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); procrustes(n, size() - pos);
fbstring_detail::pod_copy( fbstring_detail::pod_copy(
...@@ -1994,7 +2020,7 @@ public: ...@@ -1994,7 +2020,7 @@ public:
} }
basic_fbstring substr(size_type pos = 0, size_type n = npos) const { 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)); return basic_fbstring(data() + pos, std::min(n, size() - pos));
} }
...@@ -2015,7 +2041,7 @@ public: ...@@ -2015,7 +2041,7 @@ public:
int compare(size_type pos1, size_type n1, int compare(size_type pos1, size_type n1,
const value_type* s, size_type n2) const { 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); procrustes(n1, size() - pos1);
// The line below fixed by Jean-Francois Bastien, 04-23-2007. Thanks! // 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)); const int r = traits_type::compare(pos1 + data(), s, std::min(n1, n2));
...@@ -2025,7 +2051,7 @@ public: ...@@ -2025,7 +2051,7 @@ public:
int compare(size_type pos1, size_type n1, int compare(size_type pos1, size_type n1,
const basic_fbstring& str, const basic_fbstring& str,
size_type pos2, size_type n2) const { 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, return compare(pos1, n1, str.data() + pos2,
std::min(n2, str.size() - pos2)); std::min(n2, str.size() - pos2));
} }
......
...@@ -41,9 +41,11 @@ namespace folly { ...@@ -41,9 +41,11 @@ namespace folly {
#ifdef _LIBSTDCXX_FBSTRING #ifdef _LIBSTDCXX_FBSTRING
#pragma GCC system_header #pragma GCC system_header
#include <bits/functexcept.h>
#define FOLLY_HAVE_MALLOC_H 1 #define FOLLY_HAVE_MALLOC_H 1
#else #else
#include "folly/Portability.h" #include "folly/Portability.h"
#include <stdexcept>
#endif #endif
// for malloc_usable_size // for malloc_usable_size
...@@ -62,8 +64,6 @@ namespace folly { ...@@ -62,8 +64,6 @@ namespace folly {
#include <new> #include <new>
#include <bits/functexcept.h>
/** /**
* Define various ALLOCM_* macros normally provided by jemalloc. We define * 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 * 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; ...@@ -157,19 +157,31 @@ static const size_t jemallocMinInPlaceExpandable = 4096;
*/ */
inline void* checkedMalloc(size_t size) { inline void* checkedMalloc(size_t size) {
void* p = malloc(size); void* p = malloc(size);
#ifdef _LIBSTDCXX_FBSTRING
if (!p) std::__throw_bad_alloc(); if (!p) std::__throw_bad_alloc();
#else
if (!p) throw std::bad_alloc();
#endif
return p; return p;
} }
inline void* checkedCalloc(size_t n, size_t size) { inline void* checkedCalloc(size_t n, size_t size) {
void* p = calloc(n, size); void* p = calloc(n, size);
#ifdef _LIBSTDCXX_FBSTRING
if (!p) std::__throw_bad_alloc(); if (!p) std::__throw_bad_alloc();
#else
if (!p) throw std::bad_alloc();
#endif
return p; return p;
} }
inline void* checkedRealloc(void* ptr, size_t size) { inline void* checkedRealloc(void* ptr, size_t size) {
void* p = realloc(ptr, size); void* p = realloc(ptr, size);
#ifdef _LIBSTDCXX_FBSTRING
if (!p) std::__throw_bad_alloc(); if (!p) std::__throw_bad_alloc();
#else
if (!p) throw std::bad_alloc();
#endif
return p; return p;
} }
......
...@@ -30,7 +30,18 @@ ...@@ -30,7 +30,18 @@
#include <stdexcept> #include <stdexcept>
#include <type_traits> #include <type_traits>
#include <boost/operators.hpp> #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> #include <bits/c++config.h>
#endif
#include "folly/CpuId.h" #include "folly/CpuId.h"
#include "folly/Traits.h" #include "folly/Traits.h"
#include "folly/Likely.h" #include "folly/Likely.h"
......
...@@ -25,7 +25,16 @@ ...@@ -25,7 +25,16 @@
#include "folly/Portability.h" #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> #include <bits/c++config.h>
#endif
#include <boost/type_traits.hpp> #include <boost/type_traits.hpp>
#include <boost/mpl/and.hpp> #include <boost/mpl/and.hpp>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment