diff options
Diffstat (limited to 'clang/test/SemaTemplate/GH164330.cpp')
-rw-r--r-- | clang/test/SemaTemplate/GH164330.cpp | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/clang/test/SemaTemplate/GH164330.cpp b/clang/test/SemaTemplate/GH164330.cpp new file mode 100644 index 0000000..767420d --- /dev/null +++ b/clang/test/SemaTemplate/GH164330.cpp @@ -0,0 +1,309 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s +// expected-no-diagnostics + +template <int __v> struct integral_constant { + static constexpr int value = __v; +}; +template <bool _Val> using _BoolConstant = integral_constant<_Val>; +template <int, class> struct tuple_element; +template <class...> class tuple; +template <int _Ip, class... _Tp> struct tuple_element<_Ip, tuple<_Tp...>> { + using type = __type_pack_element<_Ip, _Tp...>; +}; +template <class> struct tuple_size; +template <bool> using __enable_if_t = int; +template <template <class> class _BaseType, class _Tp, _Tp _SequenceSize> +using __make_integer_sequence_impl = + __make_integer_seq<_BaseType, _Tp, _SequenceSize>; +template <class _Tp, _Tp...> struct __integer_sequence; +template <int... _Indices> +using __index_sequence = __integer_sequence<int, _Indices...>; +template <int _SequenceSize> +using __make_index_sequence = + __make_integer_sequence_impl<__integer_sequence, int, _SequenceSize>; +template <class _Tp, _Tp...> struct integer_sequence {}; +template <int... _Ip> using index_sequence = integer_sequence<int, _Ip...>; +template <class _Tp, _Tp _Ep> +using make_integer_sequence = + __make_integer_sequence_impl<integer_sequence, _Tp, _Ep>; +template <int _Np> using make_index_sequence = make_integer_sequence<int, _Np>; +enum __element_count : int; +constexpr void __constexpr_memmove(char *__dest, const char *__src, + __element_count __n) { + __builtin_memmove(__dest, __src, __n); +} +template <class _Tp> using __underlying_type_t = __underlying_type(_Tp); +template <class _Tp> using underlying_type_t = __underlying_type_t<_Tp>; +template <class _Tp, class> using __enable_if_tuple_size_imp = _Tp; +template <class _Tp> +struct tuple_size<__enable_if_tuple_size_imp< + const _Tp, __enable_if_t<_BoolConstant<__is_volatile(int)>::value>>> + : integral_constant<tuple_size<_Tp>::value> {}; +template <class... _Tp> +struct tuple_size<tuple<_Tp...>> : integral_constant<sizeof...(_Tp)> {}; +template <class _Tp> constexpr int tuple_size_v = tuple_size<_Tp>::value; +template <class _T1, class _T2> struct pair { + _T1 first; + _T2 second; +}; +template <class _T1> constexpr pair<_T1, char *> make_pair(_T1, char *__t2) { + return pair(_T1(), __t2); +} +template <int, class _Hp> struct __tuple_leaf { + _Hp __value_; + constexpr const _Hp &get() const { return __value_; } +}; +template <class...> struct __tuple_impl; +template <int... _Indx, class... _Tp> +struct __tuple_impl<__index_sequence<_Indx...>, _Tp...> + : __tuple_leaf<_Indx, _Tp>... { + template <class... _Args> + constexpr __tuple_impl(int, _Args... __args) + : __tuple_leaf<_Indx, _Tp>(__args)... {} +}; +template <class... _Tp> struct tuple { + __tuple_impl<__make_index_sequence<sizeof...(_Tp)>, _Tp...> __base_; + template <class... _Up> constexpr tuple(_Up... __u) : __base_({}, __u...) {} +}; +template <int _Ip, class... _Tp> +constexpr const tuple_element<_Ip, tuple<_Tp...>>::type & +get(const tuple<_Tp...> &__t) noexcept { + return static_cast<const __tuple_leaf< + _Ip, typename tuple_element<_Ip, tuple<_Tp...>>::type> &>(__t.__base_) + .get(); +} +template <class... _Tp> constexpr tuple<_Tp...> make_tuple(_Tp... __t) { + return tuple<_Tp...>(__t...); +} +constexpr int __char_traits_length_checked(const char *__s) { + return __builtin_strlen(__s); +} +struct basic_string_view { + constexpr basic_string_view() {} + constexpr basic_string_view(const char *__s) + : __data_(__s), __size_(__char_traits_length_checked(__s)) {} + constexpr const char *begin() { return __data_; } + constexpr const char *end() { + return __data_ + __size_; + } + const char *__data_; + int __size_; +}; +template <class _Algorithm> +constexpr pair<const char *, char *> +__copy_move_unwrap_iters(const char *__first, const char *__last, + char *__out_first) { + pair<const char *, const char *> __range = {__first, __last}; + auto __result = _Algorithm()(__range.first, __range.second, __out_first); + return make_pair(__result.first, __result.second); +} +struct __copy_impl { + constexpr pair<const char *, char *> + operator()(const char *__first, const char *__last, char *__result) { + const int __n(__last - __first); + __constexpr_memmove(__result, __first, __element_count(__n)); + return make_pair(__last, __result); + } +}; +constexpr char *copy(const char *__first, const char *__last, char *__result) { + return __copy_move_unwrap_iters<__copy_impl>(__first, __last, __result).second; +} +constexpr char *copy_n(const char *__first, int __orig_n, char *__result) { + return copy(__first, __first + __orig_n, __result); +} +template <int _Size> struct array { + basic_string_view __elems_[_Size]; + constexpr basic_string_view &operator[](int __n) { return __elems_[__n]; } + constexpr basic_string_view operator[](int __n) const { + return __elems_[__n]; + } +}; + +template <typename> struct FieldId; + +template <FieldId field> constexpr auto FieldIdToInnerValue() { + return field.template ToInnerValue<field>(); +} +struct FieldNameEnum { + enum class type; +}; +template <int N> using FieldName = FieldNameEnum::type; +template <typename, auto> struct GetParentMessageAtIndexImpl; +template <typename, auto> struct FieldInfoHelper; +template <FieldId...> struct PathImpl; +template <int N> struct LongPathLiteral { + consteval LongPathLiteral(const char (&s)[N]) { + copy_n(s, N, long_path)[N] = field_count = long_path_size = 1; + } + consteval basic_string_view to_string_view() const { return long_path; } + char long_path[N + 1]; + int long_path_size; + int field_count; +}; +template <LongPathLiteral kLongPath> consteval auto get_field_components() { + basic_string_view long_path(kLongPath.to_string_view()); + array<kLongPath.field_count> ret; + for (int i = 0; i < kLongPath.field_count; ++i) + ret[i] = long_path; + return ret; +} +template <LongPathLiteral kLongPath> +constexpr auto kFieldComponents = get_field_components<kLongPath>(); +template <LongPathLiteral kLongPath> struct LongPathHelper { + template <int... I> + static PathImpl<kFieldComponents<kLongPath>[I]...> + PathForLongPath(index_sequence<I...>); + using type = + decltype(PathForLongPath(make_index_sequence<kLongPath.field_count>{})); +}; +template <typename T> struct PathFieldId { + template <typename Arg> constexpr PathFieldId(Arg &arg) : value(arg) {} + T value; +}; +template <PathFieldId...> constexpr auto PathImplHelper(); + +template <int N> using FieldName = FieldName<N>; +enum class FieldNumber; +template <PathFieldId... fields> +constexpr auto Path = PathImplHelper<fields...>(); +template <typename Proto, FieldId field> +using FieldInfo = + FieldInfoHelper<Proto, FieldIdToInnerValue<field>()>::type; +template <> struct FieldId<FieldNameEnum::type> { + constexpr FieldId(basic_string_view); + int size; + long hash; + template <auto field> static constexpr auto ToInnerValue() { + return static_cast<FieldNameEnum::type>(field.hash); + } +}; +FieldId(basic_string_view) -> FieldId<FieldNameEnum::type>; +template <typename Proto, FieldId field, int index> +using GetParentMessageAtIndex = GetParentMessageAtIndexImpl< + Proto, FieldIdToInnerValue<field>()>::type; + +template <typename T> +PathFieldId(T &t) -> PathFieldId<decltype(LongPathLiteral(t))>; +template <FieldId... fields1, FieldId... fields2> +constexpr PathImpl<fields1..., fields2...> *ConcatPath(PathImpl<fields1...> *, + PathImpl<fields2...> *) { + return nullptr; +} +template <LongPathLiteral long_path_literal> +constexpr LongPathHelper<long_path_literal>::type *SinglePath() { + return nullptr; +} +template <PathFieldId... fields> constexpr auto PathImplHelper() { + return ConcatPath(SinglePath<fields.value>()...); +} +template <auto hash_prime, auto offset_bias> +constexpr auto Fnv1a(basic_string_view str) { + auto hash = offset_bias; + for (char c : str) { + hash ^= c; + hash *= hash_prime; + } + return hash; +} +constexpr auto HashField(basic_string_view str) { + return Fnv1a<1099511628211u, 1039346656037>(str); +} +template <typename FI> struct FieldInfoValueTypeAlias : FI {}; +template <typename Proto, auto field> struct FieldInfoHelperBase { + static constexpr auto MaskFieldNameHash() { + using FieldEnum = decltype(field); + return FieldEnum{static_cast<underlying_type_t<FieldEnum>>(field) & 31}; + } + using internal_type = + Proto::template FieldInfoImpl<decltype(field), MaskFieldNameHash()>; +}; +template <typename Proto, auto field> struct FieldInfoHelper { + using type = FieldInfoValueTypeAlias< + typename FieldInfoHelperBase<Proto, field>::internal_type>; +}; + +template <auto... fields> +struct FieldId<const PathImpl<fields...> *> { + constexpr FieldId(PathImpl<fields...> *) : path() {} + template <auto field> static constexpr auto ToInnerValue() { + return field.path; + } + const PathImpl<fields...> *path; +}; +template <auto... fields> +FieldId(PathImpl<fields...> *) + -> FieldId<const PathImpl<fields...> *>; + +template <auto> struct UnpackedField { + static constexpr bool is_path = false; +}; +template <auto... fields, const PathImpl<fields...> *path> +struct UnpackedField<path> { + static constexpr auto value = make_tuple(fields...); + static constexpr bool is_path = true; +}; +template <typename Proto, FieldId... fields, const PathImpl<fields...> *path> +struct GetParentMessageAtIndexImpl<Proto, path> { + using type = Proto; +}; + +constexpr FieldId<FieldNameEnum::type>::FieldId(basic_string_view str) + : size(), hash(HashField(str)) {} +template <FieldId field> constexpr bool IsPath() { + return UnpackedField< + FieldIdToInnerValue<field>()>::is_path; +} +template <FieldId field> constexpr auto UnpackFieldToTuple() { + return UnpackedField<FieldIdToInnerValue<field>()>::value; +} +template <int> struct CompileTimeString { + consteval CompileTimeString(basic_string_view &v) : internal_view_(v) {} + basic_string_view &internal_view_; +}; +CompileTimeString(basic_string_view) -> CompileTimeString<0>; + +template <CompileTimeString... parts> struct NameJoiner { + template <CompileTimeString... after> + NameJoiner<parts...> operator+(NameJoiner<after...>); +}; +template <FieldId> struct FieldNameBuilder; +template <FieldId field> + requires(!IsPath<field>()) +struct FieldNameBuilder<field> { + template <typename Proto> static auto Get() { + return NameJoiner<FieldInfo<Proto, field>::name>(); + } +}; +template <FieldId field> + requires(IsPath<field>()) +struct FieldNameBuilder<field> { + static constexpr auto kTuple = UnpackFieldToTuple<field>(); + static constexpr int kTupleSize = tuple_size_v<decltype(kTuple)>; + template <typename Proto, int... Is> static void Get(index_sequence<Is...>) { + (FieldNameBuilder<get<Is>( + kTuple)>::template Get<GetParentMessageAtIndex<Proto, field, Is>>() + + ...); + } + template <typename Proto> static void Get() { + Get<Proto>(make_index_sequence<kTupleSize>()); + } +}; + +struct T { + template <typename FieldType, FieldType> struct FieldInfoImpl; +}; +void AddPathsToFieldMask() { + FieldNameBuilder<Path<"message_field", "int32_field">>::Get<T>(); +} +template <> struct T::FieldInfoImpl<FieldNumber, FieldNumber{1}> { + static basic_string_view name; +}; +template <> +struct T::FieldInfoImpl<FieldName<1>, FieldName<1>{12}> + : FieldInfoImpl<FieldNumber, FieldNumber{1}> {}; +template <> struct T::FieldInfoImpl<FieldNumber, FieldNumber{10}> { + static basic_string_view name; +}; +template <> +struct T::FieldInfoImpl<FieldName<3>, FieldName<3>{11}> + : FieldInfoImpl<FieldNumber, FieldNumber{10}> {}; |