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 @@
#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
......@@ -80,16 +87,28 @@
#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
......@@ -97,23 +116,30 @@
#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));
}
......
......@@ -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;
}
......
......@@ -30,7 +30,18 @@
#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"
......
......@@ -25,7 +25,16 @@
#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>
......
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