|
| 1 | +// RUN: %clang_cc1 -std=c++2c -verify=expected,both %s -fexperimental-new-constant-interpreter |
| 2 | +// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s |
| 3 | + |
| 4 | +template <int __v> struct integral_constant { |
| 5 | + static const int value = __v; |
| 6 | +}; |
| 7 | +template <bool _Val> using _BoolConstant = integral_constant<_Val>; |
| 8 | +template <class _From, class _To> |
| 9 | +constexpr bool is_convertible_v = __is_convertible(_From, _To); |
| 10 | +template <class _Tp> _Tp __declval(int); |
| 11 | +template <class _Tp> decltype(__declval<_Tp>(0)) declval(); |
| 12 | +template <class _Tp, class _Up> |
| 13 | +using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>; |
| 14 | +template <class _If> struct conditional { |
| 15 | + using type = _If; |
| 16 | +}; |
| 17 | +template <bool, class _IfRes, class> |
| 18 | +using conditional_t = conditional<_IfRes>::type; |
| 19 | +template <class _Tp, class> |
| 20 | +concept __weakly_equality_comparable_with = requires(_Tp __t) { __t; }; |
| 21 | +template <bool, class _Tp = void> using __enable_if_t = _Tp; |
| 22 | +template <template <class> class, class> |
| 23 | +integral_constant<true> __sfinae_test_impl(int); |
| 24 | +template <template <class> class _Templ, class... _Args> |
| 25 | +using _IsValidExpansion = decltype(__sfinae_test_impl<_Templ, _Args...>(0)); |
| 26 | +template <class _Tp> |
| 27 | +using __test_for_primary_template = |
| 28 | + __enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>; |
| 29 | +template <class _Tp> |
| 30 | +using __is_primary_template = |
| 31 | + _IsValidExpansion<__test_for_primary_template, _Tp>; |
| 32 | +template <class _Ip> |
| 33 | +using iter_difference_t = |
| 34 | + conditional_t<__is_primary_template<_Ip>::value, _Ip, _Ip>::difference_type; |
| 35 | +template <int> struct _OrImpl { |
| 36 | + template <class, class _First> |
| 37 | + using _Result = _OrImpl<!_First::value>::template _Result<_First>; |
| 38 | +}; |
| 39 | +template <> struct _OrImpl<false> { |
| 40 | + template <class _Res> using _Result = _Res; |
| 41 | +}; |
| 42 | +template <class... _Args> |
| 43 | +using _Or = _OrImpl<sizeof...(_Args)>::template _Result<_Args...>; |
| 44 | +struct input_iterator_tag {}; |
| 45 | +template <class _Dp, class _Bp> |
| 46 | +concept derived_from = is_convertible_v<_Dp, _Bp>; |
| 47 | +template <class _Ip> |
| 48 | +concept input_or_output_iterator = requires(_Ip __i) { __i; }; |
| 49 | +template <class _Sp, class _Ip> |
| 50 | +concept sentinel_for = __weakly_equality_comparable_with<_Sp, _Ip>; |
| 51 | +struct __iter_concept_category_test { |
| 52 | + template <class> using _Apply = input_iterator_tag; |
| 53 | +}; |
| 54 | +struct __test_iter_concept |
| 55 | + : _IsValidExpansion<__iter_concept_category_test::_Apply, int>, |
| 56 | + __iter_concept_category_test {}; |
| 57 | +struct __iter_concept_cache { |
| 58 | + using type = _Or<int, __test_iter_concept>; |
| 59 | +}; |
| 60 | +template <class _Iter> |
| 61 | +using _ITER_CONCEPT = __iter_concept_cache::type::_Apply<_Iter>; |
| 62 | +template <class _Ip> |
| 63 | +concept input_iterator = derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>; |
| 64 | +template <class _T1, class _T2> struct pair { |
| 65 | + _T1 first; |
| 66 | + _T2 second; |
| 67 | +}; |
| 68 | +struct { |
| 69 | + template <class _Tp> auto operator()(_Tp __t) { return __t.begin(); } |
| 70 | +} begin; |
| 71 | +template <class _Tp> using iterator_t = decltype(begin(declval<_Tp>())); |
| 72 | +template <class _Tp> |
| 73 | +concept __member_size = requires(_Tp __t) { __t; }; |
| 74 | +struct { |
| 75 | + template <__member_size _Tp> constexpr void operator()(_Tp &&__t) { |
| 76 | + __t.size(); // both-note 2{{in instantiation}} |
| 77 | + } |
| 78 | +} size; |
| 79 | +template <class _Tp> |
| 80 | +concept range = requires(_Tp __t) { __t; }; |
| 81 | +template <class _Tp> |
| 82 | +concept input_range = input_iterator<_Tp>; |
| 83 | +template <range _Rp> |
| 84 | +using range_difference_t = iter_difference_t<iterator_t<_Rp>>; |
| 85 | +struct { |
| 86 | + template <range _Rp> constexpr range_difference_t<_Rp> operator()(_Rp &&__r) { |
| 87 | + size(__r); // both-note 2{{in instantiation}} |
| 88 | + } // both-warning {{does not return a value}} |
| 89 | +} distance; |
| 90 | +template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> |
| 91 | +struct subrange { |
| 92 | + _Iter __begin_; |
| 93 | + _Sent __end_; |
| 94 | + _Iter begin(); |
| 95 | + constexpr _Iter size() { __end_ - __begin_; } // both-warning {{does not return a value}} \ |
| 96 | + // both-note {{in instantiation}} |
| 97 | +}; |
| 98 | +struct { |
| 99 | + template <input_range _Range1, input_range _Range2> |
| 100 | + void operator()(_Range1 &&__range1, _Range2) { |
| 101 | + (void)(distance(__range1) != 0); // both-note 3{{in instantiation}} |
| 102 | + } |
| 103 | +} equal; |
| 104 | +template <class _Owner> struct __key_value_iterator { |
| 105 | + using difference_type = _Owner::difference_type; |
| 106 | + constexpr friend difference_type operator-(__key_value_iterator, |
| 107 | + __key_value_iterator &) {} // both-warning {{does not return a value}} |
| 108 | +}; |
| 109 | +struct flat_multimap { |
| 110 | + template <bool> using __iterator = __key_value_iterator<flat_multimap>; |
| 111 | + using difference_type = |
| 112 | + decltype(static_cast<int *>(nullptr) - static_cast<int *>(nullptr)); |
| 113 | + pair<__iterator<true>, __iterator<true>> equal_range(const char *); |
| 114 | +} test_expected_range; |
| 115 | +void test() { |
| 116 | + flat_multimap m; |
| 117 | + auto test_found = [](auto map, auto expected_key, int) { |
| 118 | + auto [first, last] = map.equal_range(expected_key); |
| 119 | + equal(subrange(first, last), test_expected_range); // both-note 3{{in instantiation}} |
| 120 | + }; |
| 121 | + test_found(m, "", {}); |
| 122 | +} |
0 commit comments