Reimplement the type sorter to avoid a ICE in gcc 4.8.2.

Thanks to @sbenzaquen for this fix.
pull/9570/head
Adam Cozzette 3 years ago
parent 1c51f9fb39
commit 5faa6123d1
  1. 78
      src/google/protobuf/descriptor.cc

@ -162,47 +162,45 @@ constexpr size_t EffectiveAlignof() {
return std::is_same<T, char>::value ? 8 : alignof(T);
}
template <int align, typename U, typename... T>
using AppendIfAlign =
typename std::conditional<EffectiveAlignof<U>() == align, void (*)(T..., U),
void (*)(T...)>::type;
// Metafunction to sort types in descending order of alignment.
// Useful for the flat allocator to ensure proper alignment of all elements
// without having to add padding.
// Instead of implementing a proper sort metafunction we just do a
// filter+merge, which is much simpler to write as a metafunction.
// We have a fixed set of alignments we can filter on.
// For simplicity we use a function pointer as a type list.
struct TypeListSorter {
template <int align, typename U, typename... T>
static auto AppendIfAlign(void (*)(T...)) ->
typename std::conditional<EffectiveAlignof<U>() == align,
void (*)(T..., U), void (*)(T...)>::type {
return nullptr;
}
template <typename... T16, typename... T8, typename... T4, typename... T2,
typename... T1>
static auto SortImpl(void (*)(), void (*)(T16...), void (*)(T8...),
void (*)(T4...), void (*)(T2...), void (*)(T1...))
-> void (*)(T16..., T8..., T4..., T2..., T1...) {
return nullptr;
}
template <typename T, typename... Ts, typename T16, typename T8, typename T4,
typename T2, typename T1, typename Self = TypeListSorter>
static auto SortImpl(void (*)(T, Ts...), T16 p16, T8 p8, T4 p4, T2 p2, T1 p1)
-> decltype(Self::template SortImpl(
static_cast<void (*)(Ts...)>(nullptr), AppendIfAlign<16, T>(p16),
AppendIfAlign<8, T>(p8), AppendIfAlign<4, T>(p4),
AppendIfAlign<2, T>(p2), AppendIfAlign<1, T>(p1))) {
return nullptr;
}
template <typename In, typename T16, typename T8, typename T4, typename T2,
typename T1>
struct TypeListSortImpl;
template <typename... T16, typename... T8, typename... T4, typename... T2,
typename... T1>
struct TypeListSortImpl<void (*)(), void (*)(T16...), void (*)(T8...),
void (*)(T4...), void (*)(T2...), void (*)(T1...)> {
using type = void (*)(T16..., T8..., T4..., T2..., T1...);
};
// Instead of implementing a proper sort metafunction we just do a
// filter+merge, which is much simpler to write as a metafunction.
// We have a fixed set of alignments we can filter on.
template <typename... T>
static auto SortByAlignment(void (*p)() = nullptr)
-> decltype(SortImpl(static_cast<void (*)(T...)>(nullptr), p, p, p, p,
p)) {
return nullptr;
}
template <typename First, typename... Rest, typename... T16, typename... T8,
typename... T4, typename... T2, typename... T1>
struct TypeListSortImpl<void (*)(First, Rest...), void (*)(T16...),
void (*)(T8...), void (*)(T4...), void (*)(T2...),
void (*)(T1...)> {
using type = typename TypeListSortImpl<
void (*)(Rest...), AppendIfAlign<16, First, T16...>,
AppendIfAlign<8, First, T8...>, AppendIfAlign<4, First, T4...>,
AppendIfAlign<2, First, T2...>, AppendIfAlign<1, First, T1...>>::type;
};
template <typename... T>
using SortByAlignment =
typename TypeListSortImpl<void (*)(T...), void (*)(), void (*)(),
void (*)(), void (*)(), void (*)()>::type;
template <template <typename...> class C, typename... T>
auto ApplyTypeList(void (*)(T...)) -> C<T...>;
@ -1239,12 +1237,12 @@ namespace internal {
// necessarily in the same order.
class FlatAllocator
: public decltype(ApplyTypeList<FlatAllocatorImpl>(
TypeListSorter::SortByAlignment<
char, std::string, SourceCodeInfo, FileDescriptorTables,
// Option types
MessageOptions, FieldOptions, EnumOptions, EnumValueOptions,
ExtensionRangeOptions, OneofOptions, ServiceOptions,
MethodOptions, FileOptions>())) {};
SortByAlignment<char, std::string, SourceCodeInfo,
FileDescriptorTables,
// Option types
MessageOptions, FieldOptions, EnumOptions,
EnumValueOptions, ExtensionRangeOptions, OneofOptions,
ServiceOptions, MethodOptions, FileOptions>())) {};
} // namespace internal

Loading…
Cancel
Save