Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into fuzz
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldreik committed Jun 1, 2019
2 parents ca9596d + f57227a commit 1c25840
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 102 deletions.
3 changes: 2 additions & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,9 @@ The library is highly portable and relies only on a small set of C++11 features:
* decltype
* trailing return types
* deleted functions
* alias templates

These are available since GCC 4.4, Clang 2.9 and MSVC 18.0 (2013). For older
These are available since GCC 4.8, Clang 3.0 and MSVC 19.0 (2015). For older
compilers use fmt `version 4.x
<https://github.com/fmtlib/fmt/releases/tag/4.1.0>`_ which continues to be
maintained and only requires C++98.
Expand Down
86 changes: 41 additions & 45 deletions include/fmt/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,36 +192,38 @@
(__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
# include <string_view>
# define FMT_STRING_VIEW std::basic_string_view
#elif FMT_HAS_INCLUDE(<experimental / string_view>) && __cplusplus >= 201402L
# define FMT_USE_STRING_VIEW
#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L
# include <experimental/string_view>
# define FMT_STRING_VIEW std::experimental::basic_string_view
# define FMT_USE_EXPERIMENTAL_STRING_VIEW
#endif

// An enable_if helper to be used in template parameters. enable_if in template
// parameters results in much shorter symbols: https://godbolt.org/z/sWw4vP.
#define FMT_ENABLE_IF_T(...) typename std::enable_if<(__VA_ARGS__), int>::type
#define FMT_ENABLE_IF(...) FMT_ENABLE_IF_T(__VA_ARGS__) = 0

FMT_BEGIN_NAMESPACE
namespace internal {

// An implementation of declval for pre-C++11 compilers such as gcc 4.
template <typename T>
typename std::add_rvalue_reference<T>::type declval() FMT_NOEXCEPT;
#if defined(FMT_USE_STRING_VIEW)
template <typename Char> using std_string_view = std::basic_string_view<Char>;
#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
template <typename Char>
using std_string_view = std::experimental::basic_string_view<Char>;
#else
template <typename T> struct std_string_view {};
#endif

template <typename> struct result_of;
// An enable_if helper to be used in template parameters. enable_if in template
// parameters results in much shorter symbols: https://godbolt.org/z/sWw4vP.
template <bool B> using enable_if_t = typename std::enable_if<B, int>::type;
#define FMT_ENABLE_IF(...) internal::enable_if_t<__VA_ARGS__> = 0

#if (__cplusplus >= 201703L || \
(defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) && \
__cpp_lib_is_invocable >= 201703L
template <typename F, typename... Args>
struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
using invoke_result_t = std::invoke_result_t<F, Args...>;
#else
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
// An implementation of invoke_result for pre-C++17.
template <typename F, typename... Args>
struct result_of<F(Args...)>
: std::result_of<typename std::remove_reference<F>::type(Args...)> {};
using invoke_result_t = typename std::result_of<F(Args...)>::type;
#endif

// Casts nonnegative integer to unsigned.
Expand Down Expand Up @@ -350,7 +352,8 @@ typedef char yes[1];
typedef char no[2];

template <typename T, typename V> struct is_constructible {
template <typename U> static yes& test(int (*)[sizeof(new U(declval<V>()))]);
template <typename U>
static yes& test(int (*)[sizeof(new U(std::declval<V>()))]);
template <typename U> static no& test(...);
enum { value = sizeof(test<T>(nullptr)) == sizeof(yes) };
};
Expand Down Expand Up @@ -399,11 +402,11 @@ template <typename Char> class basic_string_view {
FMT_NOEXCEPT : data_(s.data()),
size_(s.size()) {}

#ifdef FMT_STRING_VIEW
FMT_CONSTEXPR basic_string_view(FMT_STRING_VIEW<Char> s) FMT_NOEXCEPT
: data_(s.data()),
size_(s.size()) {}
#endif
template <
typename S,
FMT_ENABLE_IF(std::is_same<S, internal::std_string_view<Char>>::value)>
FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()),
size_(s.size()) {}

/** Returns a pointer to the string data. */
FMT_CONSTEXPR const Char* data() const { return data_; }
Expand Down Expand Up @@ -489,12 +492,12 @@ inline basic_string_view<Char> to_string_view(const Char* s) {
return s;
}

#ifdef FMT_STRING_VIEW
template <typename Char>
inline basic_string_view<Char> to_string_view(FMT_STRING_VIEW<Char> s) {
template <typename Char,
FMT_ENABLE_IF(!std::is_empty<internal::std_string_view<Char>>::value)>
inline basic_string_view<Char> to_string_view(
internal::std_string_view<Char> s) {
return s;
}
#endif

// A base class for compile-time strings. It is defined in the fmt namespace to
// make formatting functions visible via ADL, e.g. format(fmt("{}"), 42).
Expand Down Expand Up @@ -602,16 +605,16 @@ using fmt::v5::to_string_view;
template <typename S>
struct is_string
: std::integral_constant<
bool, !std::is_same<dummy_string_view,
decltype(to_string_view(declval<S>()))>::value> {
};
bool,
!std::is_same<dummy_string_view,
decltype(to_string_view(std::declval<S>()))>::value> {};

// Forward declare FILE* specialization defined in color.h
template <> struct is_string<std::FILE*>;
template <> struct is_string<const std::FILE*>;

template <typename S> struct char_t {
typedef decltype(to_string_view(declval<S>())) result;
typedef decltype(to_string_view(std::declval<S>())) result;
typedef typename result::char_type type;
};

Expand Down Expand Up @@ -900,8 +903,8 @@ template <typename Context> class basic_format_arg {
const T& value);

template <typename Visitor, typename Ctx>
friend FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
visit_format_arg(Visitor&& vis, const basic_format_arg<Ctx>& arg);
friend FMT_CONSTEXPR internal::invoke_result_t<Visitor, int> visit_format_arg(
Visitor&& vis, const basic_format_arg<Ctx>& arg);

friend class basic_format_args<Context>;
friend class internal::arg_map<Context>;
Expand Down Expand Up @@ -943,7 +946,7 @@ struct monostate {};
\endrst
*/
template <typename Visitor, typename Context>
FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type visit_format_arg(
FMT_CONSTEXPR internal::invoke_result_t<Visitor, int> visit_format_arg(
Visitor&& vis, const basic_format_arg<Context>& arg) {
typedef typename Context::char_type char_type;
switch (arg.type_) {
Expand Down Expand Up @@ -982,8 +985,8 @@ FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type visit_format_arg(
}

template <typename Visitor, typename Context>
FMT_DEPRECATED FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
visit(Visitor&& vis, const basic_format_arg<Context>& arg) {
FMT_DEPRECATED FMT_CONSTEXPR internal::invoke_result_t<Visitor, int> visit(
Visitor&& vis, const basic_format_arg<Context>& arg) {
return visit_format_arg(std::forward<Visitor>(vis), arg);
}

Expand Down Expand Up @@ -1038,8 +1041,8 @@ class locale_ref {
};

template <typename Context, typename T> struct get_type {
typedef decltype(
make_value<Context>(declval<typename std::decay<T>::type&>())) value_type;
typedef decltype(make_value<Context>(
std::declval<typename std::decay<T>::type&>())) value_type;
static const type value = value_type::type_tag;
};

Expand Down Expand Up @@ -1303,16 +1306,9 @@ struct wformat_args : basic_format_args<wformat_context> {
: basic_format_args<wformat_context>(std::forward<Args>(arg)...) {}
};

#ifndef FMT_USE_ALIAS_TEMPLATES
# define FMT_USE_ALIAS_TEMPLATES FMT_HAS_FEATURE(cxx_alias_templates)
#endif
#if FMT_USE_ALIAS_TEMPLATES
/** String's character type. */
template <typename S> using char_t = typename internal::char_t<S>::type;
# define FMT_CHAR(S) fmt::char_t<S>
#else
# define FMT_CHAR(S) typename internal::char_t<S>::type
#endif
#define FMT_CHAR(S) fmt::char_t<S>

namespace internal {
template <typename Context>
Expand Down
4 changes: 2 additions & 2 deletions include/fmt/format-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ template <typename Locale> Locale locale_ref::get() const {
}

template <typename Char> FMT_FUNC Char thousands_sep_impl(locale_ref loc) {
return std::use_facet<std::numpunct<Char> >(loc.get<std::locale>())
return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
.thousands_sep();
}
} // namespace internal
Expand Down Expand Up @@ -683,7 +683,7 @@ template <int GRISU_VERSION> struct grisu_shortest_handler {
}
};

template <typename Double, FMT_ENABLE_IF_T(sizeof(Double) == sizeof(uint64_t))>
template <typename Double, enable_if_t<sizeof(Double) == sizeof(uint64_t)>>
FMT_API bool grisu_format(Double value, buffer<char>& buf, int precision,
unsigned options, int& exp) {
FMT_ASSERT(value >= 0, "value is negative");
Expand Down
10 changes: 5 additions & 5 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ FMT_CONSTEXPR T* end(T (&array)[N]) FMT_NOEXCEPT {

// An implementation of iterator_t for pre-C++20 compilers such as gcc 4.
template <typename T> struct iterator_t {
typedef decltype(internal::begin(internal::declval<const T&>())) type;
typedef decltype(internal::begin(std::declval<const T&>())) type;
};

// For std::result_of in gcc 4.4.
Expand Down Expand Up @@ -1404,7 +1404,7 @@ template <typename Range, typename ErrorHandler = internal::error_handler>
class arg_formatter_base {
public:
typedef typename Range::value_type char_type;
typedef decltype(internal::declval<Range>().begin()) iterator;
typedef decltype(std::declval<Range>().begin()) iterator;
typedef basic_format_specs<char_type> format_specs;

private:
Expand Down Expand Up @@ -2249,7 +2249,7 @@ FMT_CONSTEXPR bool do_check_format_string(basic_string_view<Char> s,
}

template <typename... Args, typename S,
FMT_ENABLE_IF_T(is_compile_string<S>::value)>
internal::enable_if_t<is_compile_string<S>::value>>
void check_format_string(S format_str) {
typedef typename S::char_type char_t;
FMT_CONSTEXPR_DECL bool invalid_format =
Expand Down Expand Up @@ -2399,7 +2399,7 @@ FMT_API void format_system_error(internal::buffer<char>& out, int error_code,
template <typename Range> class basic_writer {
public:
typedef typename Range::value_type char_type;
typedef decltype(internal::declval<Range>().begin()) iterator;
typedef decltype(std::declval<Range>().begin()) iterator;
typedef basic_format_specs<char_type> format_specs;

private:
Expand Down Expand Up @@ -3438,7 +3438,7 @@ template <typename It> class is_output_iterator {
// The compiler reveals this property only at the point of *actually
// dereferencing* the iterator!
template <typename U>
static decltype(*(internal::declval<U>())) test(std::input_iterator_tag);
static decltype(*(std::declval<U>())) test(std::input_iterator_tag);
template <typename U> static char& test(std::output_iterator_tag);
template <typename U> static const char& test(...);

Expand Down
4 changes: 2 additions & 2 deletions include/fmt/ostream.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ template <typename Char> struct test_stream : std::basic_ostream<Char> {
template <typename T, typename Char> class is_streamable {
private:
template <typename U>
static decltype((void)(internal::declval<test_stream<Char>&>()
<< internal::declval<U>()),
static decltype((void)(std::declval<test_stream<Char>&>()
<< std::declval<U>()),
std::true_type())
test(int);

Expand Down
20 changes: 10 additions & 10 deletions include/fmt/prepare.h
Original file line number Diff line number Diff line change
Expand Up @@ -539,14 +539,14 @@ struct parts_container_concept_check : std::true_type {
template <typename T> static std::false_type has_add_check(check_second);
template <typename T>
static decltype(
(void)declval<T>().add(declval<typename T::format_part_type>()),
(void)std::declval<T>().add(std::declval<typename T::format_part_type>()),
std::true_type()) has_add_check(check_first);
typedef decltype(has_add_check<PartsContainer>(check_first())) has_add;
static_assert(has_add::value, "PartsContainer doesn't provide add() method");

template <typename T> static std::false_type has_last_check(check_second);
template <typename T>
static decltype((void)declval<T>().last(),
static decltype((void)std::declval<T>().last(),
std::true_type()) has_last_check(check_first);
typedef decltype(has_last_check<PartsContainer>(check_first())) has_last;
static_assert(has_last::value,
Expand All @@ -555,8 +555,8 @@ struct parts_container_concept_check : std::true_type {
template <typename T>
static std::false_type has_substitute_last_check(check_second);
template <typename T>
static decltype((void)declval<T>().substitute_last(
declval<typename T::format_part_type>()),
static decltype((void)std::declval<T>().substitute_last(
std::declval<typename T::format_part_type>()),
std::true_type()) has_substitute_last_check(check_first);
typedef decltype(has_substitute_last_check<PartsContainer>(
check_first())) has_substitute_last;
Expand All @@ -565,15 +565,15 @@ struct parts_container_concept_check : std::true_type {

template <typename T> static std::false_type has_begin_check(check_second);
template <typename T>
static decltype((void)declval<T>().begin(),
static decltype((void)std::declval<T>().begin(),
std::true_type()) has_begin_check(check_first);
typedef decltype(has_begin_check<PartsContainer>(check_first())) has_begin;
static_assert(has_begin::value,
"PartsContainer doesn't provide begin() method");

template <typename T> static std::false_type has_end_check(check_second);
template <typename T>
static decltype((void)declval<T>().end(),
static decltype((void)std::declval<T>().end(),
std::true_type()) has_end_check(check_first);
typedef decltype(has_end_check<PartsContainer>(check_first())) has_end;
static_assert(has_end::value, "PartsContainer doesn't provide end() method");
Expand Down Expand Up @@ -626,19 +626,19 @@ class parts_container {

format_part_type last() { return parts_.back(); }

auto begin() -> decltype(internal::declval<Container>().begin()) {
auto begin() -> decltype(std::declval<Container>().begin()) {
return parts_.begin();
}

auto begin() const -> decltype(internal::declval<const Container>().begin()) {
auto begin() const -> decltype(std::declval<const Container>().begin()) {
return parts_.begin();
}

auto end() -> decltype(internal::declval<Container>().end()) {
auto end() -> decltype(std::declval<Container>().end()) {
return parts_.end();
}

auto end() const -> decltype(internal::declval<const Container>().end()) {
auto end() const -> decltype(std::declval<const Container>().end()) {
return parts_.end();
}

Expand Down
2 changes: 1 addition & 1 deletion include/fmt/printf.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class printf_arg_formatter
typename internal::arg_formatter_base<Range>::iterator>,
public internal::arg_formatter_base<Range> {
public:
typedef decltype(internal::declval<Range>().begin()) iterator;
typedef decltype(std::declval<Range>().begin()) iterator;

private:
typedef typename Range::value_type char_type;
Expand Down
19 changes: 9 additions & 10 deletions include/fmt/ranges.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,20 @@ template <typename T, typename _ = void> struct is_range_ : std::false_type {};

#if !FMT_MSC_VER || FMT_MSC_VER > 1800
template <typename T>
struct is_range_<
T, typename std::conditional<
false,
conditional_helper<decltype(internal::declval<T>().begin()),
decltype(internal::declval<T>().end())>,
void>::type> : std::true_type {};
struct is_range_<T, typename std::conditional<
false,
conditional_helper<decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())>,
void>::type> : std::true_type {};
#endif

/// tuple_size and tuple_element check.
template <typename T> class is_tuple_like_ {
template <typename U>
static auto check(U* p) -> decltype(
std::tuple_size<U>::value,
(void)internal::declval<typename std::tuple_element<0, U>::type>(),
int());
static auto check(U* p)
-> decltype(std::tuple_size<U>::value,
(void)std::declval<typename std::tuple_element<0, U>::type>(),
int());
template <typename> static void check(...);

public:
Expand Down
1 change: 0 additions & 1 deletion support/appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ platform:
- x64

image:
- Visual Studio 2013
- Visual Studio 2015
- Visual Studio 2017

Expand Down
Loading

0 comments on commit 1c25840

Please sign in to comment.