blob: c36d80b9a65d60a101bb9e02c73a252422a38bdf [file] [log] [blame] [edit]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef FUZZTEST_FUZZTEST_INTERNAL_META_H_
#define FUZZTEST_FUZZTEST_INTERNAL_META_H_
#include <array>
#include <complex>
#include <cstdlib>
#include <memory>
#include <optional>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include <vector>
#include "absl/numeric/int128.h"
namespace google::protobuf {
template <typename T>
struct is_proto_enum;
} // namespace google::protobuf
namespace fuzztest::internal {
template <size_t... I, typename F>
constexpr auto ApplyIndexImpl(F f, std::index_sequence<I...>) {
return f(std::integral_constant<size_t, I>{}...);
}
// Invoke `f(std::integral_constant<size_t, 0>{}, ...,
// std::integral_constant<size_t, N - 1>{});
//
// Useful with a generic lambda like:
// ApplyIndex<N>([&](auto... I) {
// (std::get<I>(....), ...);
// }
// This allows users to expand an N without needing their own helper
// function/specialization generally required when working with
// std::index_sequence.
template <size_t N, typename F>
constexpr auto ApplyIndex(F f) {
return ApplyIndexImpl(f, std::make_index_sequence<N>{});
}
// Calls f(std::integral_constant<size_t, i>{}).
// Requires `0 <= i && i < Max`
// This function raises a runtime int into a static int. Useful for dealing with
// tuples, variants, etc.
template <size_t Max, typename F>
decltype(auto) Switch(size_t i, F f) {
using Call = decltype(f(std::integral_constant<size_t, 0>())) (*)(F&);
return ApplyIndex<Max>([](auto... I) {
static constexpr Call kFuncs[] = {
[](F& f) { return std::move(f)(decltype(I){}); }...};
return kFuncs;
})[i](f);
}
// Type dependent "true"/"false".
// Useful for SFINAE and static_asserts where we need a type dependent
// expression that happens to be constant.
template <typename T>
constexpr std::false_type always_false = {};
template <typename T>
constexpr std::true_type always_true = {};
// "backport" of C++20's `requires` expression.
// It can be used as:
// if constexpr (Requires<T>([](auto x) -> decltype(x.foo()) {})) {
// with similar behavior as C++20's
// if constexpr (requires{ t.foo(); }) {
// Much more verbose than `requires`, but still much more compact than the
// SFINAE alternative.
template <typename... T, typename F>
constexpr bool Requires(F) {
return std::is_invocable_v<F, T...>;
}
// Simple typeid implementation that does not require RTTI.
// Only supports comparisons for equality.
using TypeId = const void*;
template <typename T>
inline constexpr TypeId type_id = &type_id<T>;
// Some simple type traits
template <typename T>
inline constexpr bool is_monostate_v = std::is_class_v<T>&& std::is_empty_v<T>&&
std::is_default_constructible_v<T>;
template <typename T>
inline constexpr bool is_variant_v = false;
template <typename... T>
inline constexpr bool is_variant_v<std::variant<T...>> = true;
template <typename T>
inline constexpr bool is_pair_v = false;
template <typename T, typename U>
inline constexpr bool is_pair_v<std::pair<T, U>> = true;
template <typename... T>
inline constexpr bool is_tuple_v = false;
template <typename... T>
inline constexpr bool is_tuple_v<std::tuple<T...>> = true;
template <typename T>
inline constexpr bool is_array_v = false;
template <typename T, size_t N>
inline constexpr bool is_array_v<std::array<T, N>> = true;
template <typename T>
inline constexpr bool is_bitvector_v = false;
template <>
inline constexpr bool is_bitvector_v<std::vector<bool>> = true;
template <typename T>
inline constexpr bool is_vector_v = false;
template <typename T>
inline constexpr bool is_vector_v<std::vector<T>> = true;
template <typename T>
inline constexpr bool is_unique_ptr_v = false;
template <typename T>
inline constexpr bool is_unique_ptr_v<std::unique_ptr<T>> = true;
template <typename T>
inline constexpr bool is_shared_ptr_v = false;
template <typename T>
inline constexpr bool is_shared_ptr_v<std::shared_ptr<T>> = true;
template <typename T>
inline constexpr bool is_std_complex_v = false;
template <typename T>
inline constexpr bool is_std_complex_v<std::complex<T>> = true;
template <typename T>
using MakeUnsignedT = typename std::conditional_t<
std::is_same_v<T, absl::int128> || std::is_same_v<T, absl::uint128>,
std::enable_if<true, absl::uint128>, std::make_unsigned<T>>::type;
// Protocol buffers are handled through duck typing to avoid a strong dependency
// on the library.
template <typename T>
constexpr bool IsProtocolBufferImpl(typename T::Message*) {
// Check the basics:
// - There is a base class called Message.
// - It has GetReflection/GetDescriptor methods.
// - They interact as we expect with each other.
//
// We can add more specifics if this is still too ambiguous.
using Message = typename T::Message;
return std::is_base_of_v<Message, T> &&
std::is_convertible_v<const T*, const Message*> &&
Requires<const Message*>(
[](auto* f) -> decltype(f->GetReflection()->HasField(
*f, f->GetDescriptor()->field(0))) {});
}
template <typename T>
constexpr bool IsProtocolBufferImpl(...) {
return false;
}
template <typename T>
inline constexpr bool is_protocol_buffer_v = IsProtocolBufferImpl<T>(nullptr);
template <typename T>
constexpr bool IsProtocolBufferEnumImpl(
std::enable_if_t<google::protobuf::is_proto_enum<T>::value, bool>) {
return true;
}
template <typename T, typename = void>
constexpr bool IsProtocolBufferEnumImpl(...) {
return false;
}
template <typename T>
inline constexpr bool is_protocol_buffer_enum_v =
IsProtocolBufferEnumImpl<T>(true);
template <typename, typename = void>
inline constexpr bool is_flatbuffers_table_v = false;
// Flatbuffers tables generated structs do not have a public base class, so we
// check for a few specific methods:
// - T is a struct.
// - T has a `Builder` type.
// - T has a `BinarySchema` type with a static method `data()` (only available
// when passing `--bfbs-gen-embed` to the flatbuffer compiler).
// - T has a static method called `GetFullyQualifiedName` (only available when
// passing `--gen-name-strings` to the flatbuffer compiler).
template <typename T>
inline constexpr bool is_flatbuffers_table_v<
T, std::void_t<typename T::Builder, decltype(T::BinarySchema::data()),
decltype(T::GetFullyQualifiedName())>> = true;
template <typename T>
inline constexpr bool has_size_v =
Requires<T>([](auto v) -> decltype(v.size()) {});
template <typename T>
inline constexpr bool is_dynamic_container_v =
Requires<T>([](auto v) -> decltype(v.insert(v.end(), *v.begin())) {});
template <typename T>
inline constexpr bool is_associative_container_v = is_dynamic_container_v<T>&&
Requires<T>([](auto v) -> decltype(v.find(
std::declval<typename decltype(v)::key_type>())) {});
template <typename T, typename = void>
struct is_memory_dictionary_compatible : std::false_type {};
template <typename T>
struct is_memory_dictionary_compatible<
T, std::enable_if_t<T::is_memory_dictionary_compatible_v>>
: std::true_type {};
// `BindAggregate` uses structured bindings to create a tuple of references to
// the fields on the input object.
// It has to be provided with the number of fields contained in the structure.
// We special case `0` because we can't do structured bindings there, and it is
// unnecessary anyway.
template <typename T>
auto BindAggregate(T&, std::integral_constant<int, 0>) {
return std::tie();
}
// Implement the overloads from 1 to 80.
// There is no "variadic" way of doing this.
#define FUZZTEST_INTERNAL_BIND_AGGREGATE_(n, ...) \
template <typename T> \
auto BindAggregate(T& value, std::integral_constant<int, n>) { \
auto& [__VA_ARGS__] = value; \
return std::tie(__VA_ARGS__); \
}
FUZZTEST_INTERNAL_BIND_AGGREGATE_(1, x1)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(2, x1, x2)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(3, x1, x2, x3)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(4, x1, x2, x3, x4)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(5, x1, x2, x3, x4, x5)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(6, x1, x2, x3, x4, x5, x6)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(7, x1, x2, x3, x4, x5, x6, x7)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(8, x1, x2, x3, x4, x5, x6, x7, x8)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(9, x1, x2, x3, x4, x5, x6, x7, x8, x9)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(10, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(11, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(12, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(13, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(14, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(15, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(16, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(17, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(18, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(19, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(20, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(21, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(22, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(23, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(24, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(25, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(26, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(27, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(28, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(29, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(30, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(31, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(32, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(33, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(34, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(35, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(36, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(37, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(38, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(39, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(40, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(41, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(42, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(43, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(44, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(45, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(46, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(47, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(48, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(49, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(50, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(51, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(52, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(53, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(54, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(55, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(56, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(57, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(58, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(59, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(60, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(61, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(62, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(63, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(64, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(65, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(66, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(67, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(68, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(69, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(70, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69, x70)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(71, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69, x70, x71)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(72, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69, x70, x71, x72)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(73, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69, x70, x71, x72, x73)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(
74, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16,
x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31,
x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61,
x62, x63, x64, x65, x66, x67, x68, x69, x70, x71, x72, x73, x74)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(
75, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16,
x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31,
x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61,
x62, x63, x64, x65, x66, x67, x68, x69, x70, x71, x72, x73, x74, x75)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(
76, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16,
x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31,
x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61,
x62, x63, x64, x65, x66, x67, x68, x69, x70, x71, x72, x73, x74, x75, x76)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(77, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69, x70, x71, x72, x73,
x74, x75, x76, x77)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(78, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69, x70, x71, x72, x73,
x74, x75, x76, x77, x78)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(79, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69, x70, x71, x72, x73,
x74, x75, x76, x77, x78, x79)
FUZZTEST_INTERNAL_BIND_AGGREGATE_(80, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
x11, x12, x13, x14, x15, x16, x17, x18, x19,
x20, x21, x22, x23, x24, x25, x26, x27, x28,
x29, x30, x31, x32, x33, x34, x35, x36, x37,
x38, x39, x40, x41, x42, x43, x44, x45, x46,
x47, x48, x49, x50, x51, x52, x53, x54, x55,
x56, x57, x58, x59, x60, x61, x62, x63, x64,
x65, x66, x67, x68, x69, x70, x71, x72, x73,
x74, x75, x76, x77, x78, x79, x80)
#undef FUZZTEST_INTERNAL_BIND_AGGREGATE_
// For N > 80, use std::get<I>.
// Some aggregate types like std::tuple provide this protocol, but so can user
// defined types.
template <typename T, int N>
auto BindAggregate(T& value, std::integral_constant<int, N>) {
static_assert(N > 80);
if constexpr (std::is_aggregate_v<T> &&
!Requires<T>([](auto v) -> decltype(std::get<0>(v)) {})) {
static_assert(always_false<T>,
"Aggregate types are only supported up to 80 fields.");
}
// For the rest use the tuple API
return ApplyIndex<N>(
[&](auto... I) { return std::tie(std::get<I>(value)...); });
}
// We disable `T` because `{T&&}` would work for non aggregates as a move
// construction.
template <typename T>
struct AnythingBut {
template <typename U, std::enable_if_t<!std::is_same_v<U, T>, int> = 0>
operator U&&() const {
std::abort();
}
};
// Try to call ApplyIndex from I all the way down to 0.
template <size_t I, typename F>
constexpr std::optional<int> ApplyIndexFor(F f) {
if constexpr (ApplyIndex<I>(f)) {
return I;
}
if constexpr (I == 0) {
return std::nullopt;
} else {
return ApplyIndexFor<I - 1>(f);
}
}
// Try applying aggregate initialization to `T` with different number of
// arguments. We start at 80 and go down until one works.
template <typename T>
constexpr std::optional<int> DetectBraceInitCount() {
constexpr auto can_init_impl =
[](auto... I) -> decltype(T{(I, AnythingBut<T>{})...}) {};
constexpr auto can_init = [](auto... I) {
return std::is_invocable_v<decltype(can_init_impl), decltype(I)...>;
};
if constexpr (!std::is_aggregate_v<T>) {
return std::nullopt;
}
return ApplyIndexFor<80>(can_init);
}
// This allows us to determine whether T has a base class. If it does, it is
// initialized with a one more field than we can bind to it.
template <typename T>
struct AnythingButBaseOf {
template <typename U, std::enable_if_t<!std::is_base_of_v<U, T>, int> = 0>
operator U&&() const {
std::abort();
}
};
// Detect the number of fields bindable with `auto& [...] = t;`.
// This can be less than the number of fields used to initialize `T` if `T`
// inherits from an empty base class. Multiple inheritance is not supported.
template <typename T>
constexpr std::optional<int> DetectBindableFieldCount() {
// Classes which inherit from a base are initialized with an extra first field
// corresponding to the base class. We know from DetectBraceInitCount() that
// `T` is initializable with N fields which are not a `T`. If `T` is not
// initializable when we insist that the first field is not a base of `T`,
// then we know that T has a base class and needs to be adjusted accordingly.
// We don't worry about whether the potential base classes of T are empty: if
// they are not, then binding will fail later anyways with a good error
// message, and there is no way around this.
constexpr std::optional<int> brace_init_count_opt = DetectBraceInitCount<T>();
constexpr int brace_init_count = brace_init_count_opt.value_or(0);
// Detect if the first initialization field is a base class.
constexpr auto no_base_impl = [](auto... I)
-> decltype(T{AnythingButBaseOf<T>{}, (I, AnythingBut<T>{})...}) {};
constexpr auto no_base = [](auto... I) {
return std::is_invocable_v<decltype(no_base_impl), decltype(I)...>;
};
if constexpr (brace_init_count < 1) {
return brace_init_count_opt;
} else if constexpr (ApplyIndex<brace_init_count - 1>(no_base)) {
return brace_init_count;
}
// Detect if the second initialization field is a base class.
constexpr auto no_two_bases_impl =
[](auto... I) -> decltype(T{AnythingBut<T>{}, AnythingButBaseOf<T>{},
(I, AnythingBut<T>{})...}) {};
constexpr auto no_two_bases = [](auto... I) {
return std::is_invocable_v<decltype(no_two_bases_impl), decltype(I)...>;
};
// Check for multiple inheritance. This condition also triggers if we have a
// struct whose first field is its base class. The latter case should be
// somewhat rare, because:
// - We don't currently support structs with a non-empty parent class
// (these cannot be decomposed in `BindAggregate()`).
// - It is rare to have a struct with a member that is an empty class, as
// would be the case if the parent were empty.
if constexpr (brace_init_count >= 2) {
static_assert(ApplyIndex<brace_init_count - 2>(no_two_bases),
"Multiple inheritance is not currently supported, nor are "
"structs whose first fields are their base class.");
}
// We have exactly one base class.
return brace_init_count - 1;
}
template <typename T>
constexpr std::optional<int> DetectAggregateSize() {
if constexpr (is_pair_v<T> || is_tuple_v<T> || is_array_v<T>) {
return std::tuple_size_v<T>;
} else {
return DetectBindableFieldCount<T>();
}
}
// Detect the number and types of the fields.
template <typename T, int N = *DetectAggregateSize<std::remove_cv_t<T>>()>
auto DetectBindAggregate(T& v) {
return BindAggregate(v, std::integral_constant<int, N>{});
}
template <typename T>
inline constexpr bool is_bindable_aggregate_v =
Requires<T&>([](auto& v) -> decltype(DetectBindAggregate(v)) {});
template <int I, typename T>
struct ExtractTemplateParameterImpl;
template <int I, template <typename...> class C, typename... T>
struct ExtractTemplateParameterImpl<I, C<T...>> {
using type = std::tuple_element_t<I, std::tuple<T...>>;
};
// Evaluates to the Ith template parameter of the class template
// instantiation `T`. Eg:
// `ExtractTemplateParameter<1, Foo<int, double, char>>`
// evaluates to `double`.
template <int I, typename T>
using ExtractTemplateParameter =
typename ExtractTemplateParameterImpl<I, T>::type;
template <typename T>
struct DropConstImpl {
using type = std::remove_const_t<T>;
};
template <template <typename...> class C, typename... T>
struct DropConstImpl<C<T...>> {
using type = C<typename DropConstImpl<T>::type...>;
};
// Drop `const` recursively from class templates.
// Eg:
// `DropConst<std::vector<std::pair<const K, std::tuple<const int>>>`
// evaluates to
// `std::vector<std::pair<K, std::tuple<int>>>`
template <typename T>
using DropConst = typename DropConstImpl<T>::type;
// MakeDependentType<T, U...> evaluates to `T` but makes the declaration type
// dependent on templates `U...`.
// This allows delaying name lookup for the second phase when the types involved
// are fully defined.
// See https://en.cppreference.com/w/cpp/language/two-phase_lookup
template <typename T, typename... Dependent>
using MakeDependentType = std::enable_if_t<(always_true<Dependent> && ...), T>;
// We use this to get a nice compiler error when `T` and `U` don't match instead
// of just "false".
template <typename T, typename U>
constexpr void CheckIsSame() {
static_assert(std::is_same_v<T, U>);
}
template <typename Domain>
using value_type_t = typename Domain::value_type;
template <typename Domain>
using corpus_type_t = typename Domain::corpus_type;
} // namespace fuzztest::internal
#endif // FUZZTEST_FUZZTEST_INTERNAL_META_H_