Fix concepts#58
Closed
cor3ntin wants to merge 42 commits intocor3ntin:corentin/concept_normalization2from
Closed
Conversation
In the standard, constraint satisfaction checking is done on the normalized form of a constraint. Clang instead substitute on the non-normalized form, which cause us to report substitution failures in template arguments or concept ids, which is non-conforming but unavoidable witjout a parameter mapping This patch normalizes before satisfaction checking. However, we preserve concept-id nodes in the normalized form, solely for diagnostics purposes. This is a very incomplete attempt at addressing llvm#61811 and related concepts related conformance bugs, ideally to make the implementation of concept template parameters easier There is stil ~20 failing test files, mostly caused by poor adjustement of the template depth.
clang/test/SemaTemplate/alias-template-with-lambdas.cpp
AST/ByteCode/libcxx/deref-to-array.cpp now compiles But there are more tests getting regressed now, as I have disabled ShouldPreserveTemplateArgumentsPacks, which caused bugs for deref-to-array.cpp Failed Tests (13): Clang :: AST/ByteCode/libcxx/minmax.cpp Clang :: AST/ByteCode/libcxx/primitive-temporary.cpp Clang :: CXX/drs/cwg25xx.cpp Clang :: CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp Clang :: CXX/temp/temp.constr/temp.constr.normal/p1.cpp Clang :: CXX/temp/temp.param/p10-2a.cpp Clang :: CodeGenCXX/mangle-concept.cpp Clang :: Modules/pr62943.cppm Clang :: SemaCXX/cxx2c-fold-exprs.cpp Clang :: SemaTemplate/concepts-recursive-inst.cpp Clang :: SemaTemplate/concepts.cpp Clang :: SemaTemplate/instantiate-template-argument.cpp Clang :: SemaTemplate/temp_arg_nontype_cxx2c.cpp
Only 5 tests left now: Failed Tests (5): Clang :: CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp Clang :: Modules/pr62943.cppm Clang :: SemaCXX/cxx2c-fold-exprs.cpp Clang :: SemaTemplate/concepts-recursive-inst.cpp Clang :: SemaTemplate/instantiate-template-argument.cpp
Inspired by llvm@72ac907
the expressions don't subsume because they have different parameter mappings
This helps reduce the time cost of time_zone.cpp from 44s -> 14s It still needs improvements, as previous clang only takes 3s.
There are 6 tests failing now! Failed Tests (6): Clang :: AST/ByteCode/libcxx/deref-to-array.cpp Clang :: AST/ByteCode/libcxx/primitive-temporary.cpp Clang :: CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp Clang :: CXX/temp/temp.constr/temp.constr.normal/p1.cpp Clang :: Modules/GH60336.cpp Clang :: SemaTemplate/concepts-recursive-inst.cpp
Failed Tests (3): Clang :: CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp Clang :: CXX/temp/temp.constr/temp.constr.normal/p1.cpp Clang :: SemaTemplate/concepts-recursive-inst.cpp
* Remove unused headers * checkpoint
* Checkpoint Failed Tests (12): Clang :: CXX/drs/cwg25xx.cpp Clang :: CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp Clang :: CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp Clang :: CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp Clang :: CXX/temp/temp.constr/temp.constr.normal/p1.cpp Clang :: SemaCXX/concept-crash-on-diagnostic.cpp Clang :: SemaCXX/cxx23-assume.cpp Clang :: SemaCXX/cxx2c-fold-exprs.cpp Clang :: SemaCXX/invalid-requirement-requires-expr.cpp Clang :: SemaTemplate/concepts-recursive-inst.cpp Clang :: SemaTemplate/concepts.cpp Clang :: SemaTemplate/cxx2a-constraint-exprs.cpp * Fix more tests in error handling Remaining Failed Tests (7): Clang :: AST/ByteCode/libcxx/primitive-temporary.cpp Clang :: CXX/drs/cwg25xx.cpp Clang :: CXX/temp/temp.constr/temp.constr.normal/p1.cpp Clang :: SemaCXX/cxx2c-fold-exprs.cpp Clang :: SemaTemplate/alias-template-with-lambdas.cpp Clang :: SemaTemplate/concepts-recursive-inst.cpp Clang :: SemaTemplate/instantiate-abbreviated-template.cpp * Fix one more test * save * Fix more tests * Do not set ContainsError on substitution failure That would completely break overload resolution; see llvm@684a789#diff-b7090bd1c9146da9ed3ff99bef9fa52903cf7034e9bca340446ffa0ab3549d04 ```cpp template <class _Tp, class _Up> concept same_as = __is_same(_Up, _Tp); template <class> using type_identity_t = int; enum __arg_t {}; template <class _Context, same_as<typename _Context::char_type>> void __determine_arg_t(); template <class, class> __arg_t __determine_arg_t(); struct array { int data; }; struct __compile_time_basic_format_context; template <class, class... _Args> struct basic_format_string { template <class _Tp> basic_format_string(_Tp __str) {} array __types_{ __determine_arg_t<__compile_time_basic_format_context, _Args>()...}; }; template <class... _Args> using format_string = basic_format_string<char, type_identity_t<_Args>...>; template <class... _Args> void format(format_string<_Args...>, _Args...); void __format() { format("", char()); } ``` * Reapply 7483711: Instantiate concepts with sugared template arguments The sugared arguments of concepts are necessary to compile the following case, thanks to a Profile bug of DependentDecltypeType: namespace { template <int __v> struct integral_constant { static const int value = __v; }; template <class _Tp> _Tp forward; struct _IfImpl { template <class _IfRes, class> using _Select = _IfRes; }; template <bool, class _IfRes, class _ElseRes> using _If = _IfImpl::_Select<_IfRes, _ElseRes>; template <class _If> struct conditional { using type = _If; }; template <bool, class _If, class> using __conditional_t = conditional<_If>::type; template <class _Tp> struct enable_if { typedef _Tp type; }; template <class _Tp> _Tp __declval(long); template <class _Tp> decltype(__declval<_Tp>(0)) declval(); template <class _Fp, class... _Args> decltype(_Fp()(declval<_Args>()...)) __invoke(_Fp, _Args...); template <class, class _Fp, class... _Args> struct __invokable_r { template <class _XFp, class... _XArgs> static decltype(__invoke(_XFp(), declval<_XArgs>()...)) __try_call(int); using _Result = decltype(__try_call<_Fp, _Args...>(0)); }; template <class _Func, class... _Args> struct __invoke_result : enable_if<typename __invokable_r<void, _Func, _Args...>::_Result> {}; template <class _Fn, class... _Args> using invoke_result_t = __invoke_result<_Fn, _Args...>::type; template <class _From, class _To> constexpr bool is_convertible_v = __is_convertible(_From, _To); template <class _From, class> concept convertible_to = requires { _From(); }; template <class _Tp> concept move_constructible = convertible_to<_Tp, _Tp>; template <class _Tp> constexpr bool is_object_v = __is_object(_Tp); template <class _Dp, class _Bp> concept derived_from = is_convertible_v<_Dp, _Bp>; template <class _Tp> concept __boolean_testable = requires { forward<_Tp>; }; template <class _Fn, class... _Args> invoke_result_t<_Fn, _Args...> invoke(_Fn, _Args...); template <class _Fn, class... _Args> concept invocable = requires(_Fn __fn, _Args... __args) { invoke(__fn, __args...); }; template <class _Fn, class... _Args> concept regular_invocable = invocable<_Fn, _Args...>; template <class _Fn, class... _Args> concept predicate = __boolean_testable<invoke_result_t<_Fn, _Args...>>; template <class> using iter_difference_t = decltype(static_cast<int *>(nullptr) - static_cast<int *>(nullptr)); template <decltype(sizeof(int)), class> struct tuple_element; template <class...> struct tuple {}; template <decltype(sizeof(int)) _Ip, class... _Tp> tuple_element<_Ip, tuple<_Tp...>>::type get(tuple<_Tp...>); template <class _Tp, _Tp...> struct integer_sequence; template <decltype(sizeof(int))... _Ip> using index_sequence = integer_sequence<decltype(sizeof(int)), _Ip...>; template <class _Tp, _Tp _Ep> using make_integer_sequence = __make_integer_seq<integer_sequence, _Tp, _Ep>; template <decltype(sizeof(int)) _Np> using make_index_sequence = make_integer_sequence<decltype(sizeof(int)), _Np>; template <class... _Tp> using index_sequence_for = make_index_sequence<sizeof...(_Tp)>; template <class...> struct __tuple_types; template <decltype(sizeof(int)) _Ip, class... _Types> struct tuple_element<_Ip, __tuple_types<_Types...>> { using type = __type_pack_element<_Ip, _Types...>; }; template <class _Tp> concept __dereferenceable = requires(_Tp __t) { __t; }; template <__dereferenceable _Tp> using iter_reference_t = decltype(*_Tp()); struct input_iterator_tag {}; struct forward_iterator_tag : input_iterator_tag {}; struct bidirectional_iterator_tag : forward_iterator_tag {}; struct contiguous_iterator_tag : bidirectional_iterator_tag {}; auto to_address(0); template <class _Ip> concept input_or_output_iterator = requires(_Ip __i) { __i; }; template <class _Sp, class _Ip> concept sized_sentinel_for = requires(_Ip __i, _Sp __s) { __i - __s; }; template <class _Ip> concept input_iterator = derived_from<typename _Ip::iterator_concept, input_iterator_tag>; template <class _Ip> concept forward_iterator = derived_from<typename _Ip::iterator_concept, forward_iterator_tag>; template <class> concept bidirectional_iterator = requires { to_address; }; template <class _Fp, class _It> concept indirect_unary_predicate = predicate<_Fp, iter_reference_t<_It>>; namespace ranges { struct { template <class _Tp> auto operator()(_Tp __t) { return __t.begin(); } } begin; template <class _Tp> using iterator_t = decltype(begin(declval<_Tp>())); template <class> constexpr bool enable_view = requires { nullptr; }; template <class _Tp> concept __difference = requires(_Tp __t) { { begin(__t) } -> sized_sentinel_for<decltype(begin(declval<_Tp>()))>; // { begin(__t) } -> sized_sentinel_for<decltype(begin(_Tp()))>; }; struct { template <__difference _Tp> auto operator()(_Tp __t) { auto __trans_tmp_1(__t); 0 - __trans_tmp_1; } } size; template <class _Tp> concept range = requires(_Tp __t) { __t; }; template <class _Tp> concept input_range = input_iterator<iterator_t<_Tp>>; template <range _Rp> using range_difference_t = iter_difference_t<_Rp>; template <range _Rp> using range_reference_t = iter_reference_t<iterator_t<_Rp>>; template <class _Tp> concept sized_range = requires(_Tp __t) { size(__t); }; template <class _Tp> concept forward_range = forward_iterator<iterator_t<_Tp>>; template <class _Tp> concept bidirectional_range = bidirectional_iterator<_Tp>; } // namespace ranges template <class> struct tuple_size; template <class... _Tp> struct tuple_size<tuple<_Tp...>> : integral_constant<sizeof...(_Tp)> {}; template <class _Tp> constexpr decltype(sizeof(int)) tuple_size_v = tuple_size<_Tp>::value; namespace ranges { template <class _Derived> struct view_interface { template <class _D2 = _Derived> void front() requires forward_range<_D2>; }; } // namespace ranges struct __rule {}; struct basic_string {}; template <decltype(sizeof(int)) _Ip, class... _Tp> struct tuple_element<_Ip, tuple<_Tp...>> { using type = tuple_element<_Ip, __tuple_types<_Tp...>>::type; }; template <bool _Const, class _Tp> using __maybe_const = __conditional_t<_Const, _Tp, _Tp>; template <class...> struct __perfect_forward_impl; template <class _Op, decltype(sizeof(int))... _Idx, class... _BoundArgs> struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> { tuple<_BoundArgs...> __bound_args_; template <class... _Args> auto operator()(_Args... __args) -> decltype(_Op()(get<_Idx>(__bound_args_)..., __args...)); }; template <class _Op, class... _Args> using __perfect_forward = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; struct __wrap_iter { typedef contiguous_iterator_tag iterator_concept; __rule operator*(); }; struct vector { __wrap_iter begin(); }; namespace ranges { template <class> concept _RangeAdaptorClosure = requires { nullptr; }; template <range _Range, _RangeAdaptorClosure _Closure> auto operator|(_Range __range, _Closure __closure) { return invoke(__closure, __range); } } // namespace ranges template <input_or_output_iterator _Iter> struct counted_iterator : _Iter { counted_iterator(_Iter, iter_difference_t<_Iter>); }; template <decltype(sizeof(int)) _NBound, class = make_index_sequence<_NBound>> struct __bind_back_op; template <decltype(sizeof(int)) _NBound, decltype(sizeof(int))... _Ip> struct __bind_back_op<_NBound, index_sequence<_Ip...>> { template <class _Fn, class _BoundArgs, class... _Args> auto operator()(_Fn __f, _BoundArgs __bound_args, _Args... __args) -> decltype(invoke(__f, __args..., get<_Ip>(__bound_args)...)); }; template <class _Fn, class _BoundArgs> struct __bind_back_t : __perfect_forward<__bind_back_op<tuple_size_v<_BoundArgs>>, _Fn, _BoundArgs> {}; template <class _Fn, class... _Args> auto __bind_back(_Fn, _Args...) -> decltype(__bind_back_t<_Fn, tuple<_Args...>>()); namespace ranges { struct __empty_cache; template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires is_object_v<_Pred> class filter_view { class __iterator; public: filter_view(_View, _Pred); __iterator begin(); }; template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred> requires is_object_v<_Pred> class filter_view<_View, _Pred>::__iterator { public: using iterator_concept = _If<bidirectional_range<_View>, bidirectional_iterator_tag, _If<forward_range<_View>, forward_iterator_tag, input_iterator_tag>>; range_reference_t<_View> operator*(); }; struct { template <class _Range, class _Pred> auto operator()(_Range __range, _Pred __pred) -> decltype(filter_view(__range, __pred)); template <class _Pred> auto operator()(_Pred __pred) { return __bind_back(*this, __pred); } } filter; template <input_range _View> struct lazy_split_view { template <int _Const> struct __outer_iterator { using _Base = __maybe_const<_Const, _View>; _If<forward_range<_View>, iterator_t<_Base>, __empty_cache>; }; }; template <class _View> struct take_view : view_interface<take_view<_View>> { _View __base_; range_difference_t<_View> __count_; take_view(_View, range_difference_t<_View>); auto begin() { sized_range<_View>; return counted_iterator(ranges::begin(__base_), __count_); } }; struct { template <class _Range, convertible_to<_Range> _Np> auto operator()(_Range __range, _Np __n) -> decltype(take_view(__range, __n)); auto operator()(int __n) { return __bind_back(*this, __n); } } take; template <class _View, class _Fn> concept __transform_view_constraints = regular_invocable<_Fn, invoke_result_t<_Fn, range_reference_t<_View>>>; template <class _View, class _Fn> struct transform_view { template <bool> class __iterator; transform_view(_View, _Fn); __iterator<false> begin(); }; template <class> struct __transform_view_iterator_concept { using type = forward_iterator_tag; }; template <class _View, class _Fn> template <bool _Const> class transform_view<_View, _Fn>::__iterator { using _Base = __maybe_const<_Const, _View>; public: using iterator_concept = __transform_view_iterator_concept<_View>::type; _Base friend operator-(__iterator, __iterator) // iterator_t<_Base> was canonicalized to the type of the one written on line 221 iterator_t<_Base>. requires sized_sentinel_for<_Base, iterator_t<_Base>> {} }; struct { template <class _Range, class _Fn> auto operator()(_Range __range, _Fn __f) -> decltype(transform_view(__range, __f)); template <class _Fn> auto operator()(_Fn __f) { return __bind_back(*this, __f); } } transform; } // namespace ranges namespace views = ranges; vector __letters_before_first_rule___rules; basic_string __letters_before_first_rule() { auto __letters = __letters_before_first_rule___rules | views::filter([](__rule) { return 0; }) | views::transform([](__rule __rule) { return __rule; }) | views::take(1); __letters.front(); } } // namespace
* Do not normalize empty FoldExprs? * Refactor substituteParameterMappings. NFC * Establish a mapping on fold exprs * Remove unused return * Fix another crash where we accidentally transformed the requires expression where we shouldn't We might be evaluating a constraint when establishing parameter mappings * Do not expand too much packs within a FoldExpr * Revert "Do not expand too much packs within a FoldExpr" This reverts commit 542eb27. * Reapply "Do not expand too much packs within a FoldExpr" This reverts commit 11c2ce0. * Fix another assertion * Avoid extra expansions by not building PackExpansionTypes * [do not merge] debugging * Revert "[do not merge] debugging" This reverts commit 03d9aba. * Cache? * Atomic concept cache? * Avoid computing cache with SubstitutionInTemplateArguments That is a heavy operation!
template <int __v> struct integral_constant {
static const bool value = __v;
};
template <bool _Val> using _BoolConstant = integral_constant<_Val>;
using size_t = decltype(sizeof(int));
template <class _Tp>
concept default_initializable = requires { _Tp{}; };
template <class _Tp, class _Up>
using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
template <class _Tp, class _Up>
concept __same_as_impl = _IsSame<_Tp, _Up>::value;
template <class _Tp, class _Up>
concept same_as = __same_as_impl<_Up, _Tp>;
template <bool, class _IfRes, class> using conditional_t = _IfRes;
template <bool, class _If, class> using __conditional_t = _If;
template <class> using remove_cvref_t = struct common_reference;
template <class...> using common_reference_t = common_reference;
template <class, class>
concept common_reference_with =
same_as<common_reference_t<>, common_reference_t<>>;
struct enable_if;
template <bool> using __enable_if_t = enable_if;
template <template <class> class, class>
integral_constant<false> __sfinae_test_impl();
template <template <class> class _Templ, class... _Args>
using _IsValidExpansion = decltype(__sfinae_test_impl<_Templ, _Args...>());
template <class _Tp>
using __test_for_primary_template =
__enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>;
template <class _Tp>
using __is_primary_template =
_IsValidExpansion<__test_for_primary_template, _Tp>;
template <class _Tp> using make_signed_t = _Tp;
template <class> struct incrementable_traits;
template <class _Tp>
concept __has_integral_minus = requires(_Tp __y) { __y; };
template <__has_integral_minus _Tp> struct incrementable_traits<_Tp> {
using difference_type = make_signed_t<decltype(_Tp() - _Tp())>;
};
template <class _Ip>
using iter_difference_t =
conditional_t<__is_primary_template<_Ip>::value, incrementable_traits<_Ip>,
_Ip>::difference_type;
template <class _Tp>
concept __dereferenceable = requires(_Tp __t) { __t; };
template <__dereferenceable _Tp> using iter_reference_t = decltype(_Tp());
template <class _Tp>
concept semiregular = default_initializable<_Tp>;
template <class _In>
concept __indirectly_readable_impl = common_reference_with<_In, _In>;
template <class _In>
concept indirectly_readable = __indirectly_readable_impl<_In>;
template <class _Ip>
concept input_iterator = indirectly_readable<_Ip>;
template <class, class _Tp>
concept output_iterator = requires(_Tp __t) { __t; };
template <class _Ip>
concept random_access_iterator =
requires(_Ip __j, iter_difference_t<_Ip> __n) { __j[__n]; };
template <class _Ip>
concept contiguous_iterator = random_access_iterator<_Ip>;
template <class> struct numeric_limits {
int type;
static const int digits = sizeof(type);
};
namespace std {
inline namespace __1 {
int begin;
template <class> using iterator_t = decltype(begin);
int end;
namespace ranges {
template <class>
concept range = requires { end; };
template <class _Tp>
concept input_range = input_iterator<_Tp>;
template <range _Rp>
using range_reference_t = iter_reference_t<iterator_t<_Rp>>;
} // namespace ranges
using string = struct __wrap_iter {
int operator*();
void operator++();
};
template <class _Iter1, class _Iter2> bool operator==(_Iter1, _Iter2);
template <class _OutIt, class _CharT>
requires output_iterator<_OutIt, const _CharT &>
class basic_format_context;
template <class, class> struct formatter;
template <class _CharT>
concept __fmt_char_type = same_as<_CharT, char>;
template <class, class _Context, class _Formatter = _Context::formatter_type>
concept __formattable_with = semiregular<_Formatter>;
template <class _Tp, class _CharT>
concept __formattable =
__formattable_with<_Tp, basic_format_context<_CharT, _CharT>>;
template <class _Tp, class _CharT>
concept formattable = __formattable<_Tp, _CharT>;
namespace __format {
template <__fmt_char_type> struct __retarget_buffer {
struct __iterator {
__retarget_buffer *__buffer_;
};
template <contiguous_iterator _Iterator, class _UnaryOperation>
void __transform(_Iterator, _Iterator, _UnaryOperation);
};
} // namespace __format
enum range_format { sequence };
template <class> constexpr range_format format_kind = [] { return sequence; }();
struct __format_arg_store {};
template <class> struct basic_format_args {
basic_format_args(__format_arg_store);
};
struct locale {};
template <class _Facet> _Facet use_facet(locale);
template <class> class numpunct;
template <> struct numpunct<char> {
char thousands_sep();
};
template <class _OutIt, class _CharT>
requires output_iterator<_OutIt, const _CharT &>
struct basic_format_context {
using iterator = __format::__retarget_buffer<_CharT>::__iterator;
iterator out();
};
namespace __format_spec {
template <class> struct __parsed_specifications {};
template <class _CharT> struct __parser {
__parsed_specifications<_CharT> __get_parsed_std_specifications(auto);
};
} // namespace __format_spec
template <contiguous_iterator _Iterator, class _UnaryOperation>
void __transform(_Iterator __first, _Iterator __last, auto __out_it,
_UnaryOperation __operation) {
__out_it.__buffer_->__transform(__first, __last, __operation);
}
template <class, class _CharT> struct range_formatter {
template <ranges::input_range _Rp, class _FormatContext>
void format(_Rp __range, _FormatContext __ctx) {
for (auto __e : __range)
__underlying_.format(__e, __ctx);
}
formatter<int, _CharT> __underlying_;
};
template <class _Rp, class _CharT>
concept __const_formattable_range =
formattable<ranges::range_reference_t<_Rp>, _CharT>;
template <class _Rp, class _CharT>
using __fmt_maybe_const =
conditional_t<__const_formattable_range<_Rp, _CharT>, _Rp, _Rp>;
template <range_format, ranges::input_range, class>
struct __range_default_formatter;
template <ranges::input_range _Rp, class _CharT>
struct __range_default_formatter<sequence, _Rp, _CharT> {
using __maybe_const_r = __fmt_maybe_const<_Rp, _CharT>;
range_formatter<remove_cvref_t<ranges::range_reference_t<__maybe_const_r>>,
_CharT>
__underlying_;
template <class _FormatContext>
void format(__maybe_const_r __range, _FormatContext __ctx) {
__underlying_.format(__range, __ctx);
}
};
template <ranges::input_range _Rp, class _CharT>
struct formatter<_Rp, _CharT>
: __range_default_formatter<format_kind<_Rp>, _Rp, _CharT> {};
struct vector {
vector(int);
__wrap_iter begin();
__wrap_iter end();
};
void __hex_to_upper();
template <class, int> struct array {
int *begin();
int *end();
};
namespace __formatter {
template <class _Tp, size_t> consteval size_t __buffer_size() {
return numeric_limits<_Tp>::digits;
}
template <class _OutIt, contiguous_iterator _Iterator, class _CharT>
void __write_using_decimal_separators(
_OutIt __out_it, _Iterator, _Iterator __first, _Iterator __last, string,
_CharT, __format_spec::__parsed_specifications<_CharT>) {
__transform(__first, __last, __out_it, __hex_to_upper);
}
template <class _Tp, contiguous_iterator _Iterator, class _CharT,
class _FormatContext>
_FormatContext
__format_integer(_Tp, _FormatContext __ctx,
__format_spec::__parsed_specifications<_CharT> __specs, bool,
_Iterator __begin, _Iterator, char *, int) {
_Iterator __first;
_Iterator __last;
auto __np = use_facet<numpunct<_CharT>>(locale());
string __grouping;
__write_using_decimal_separators(__ctx.out(), __begin, __first, __last,
__grouping, __np.thousands_sep(), __specs);
}
template <class _Tp, class _CharT, class _FormatContext>
void __format_integer(_Tp __value, _FormatContext __ctx,
__format_spec::__parsed_specifications<_CharT> __specs,
bool __negative = false) {
array<char, __buffer_size<decltype(__value), 6>()> __array;
__format_integer(__value, __ctx, __specs, __negative, __array.begin(),
__array.end(), "", 6);
}
} // namespace __formatter
template <__fmt_char_type _CharT> struct __formatter_integer {
template <class _Tp, class _FormatContext>
void format(_Tp, _FormatContext __ctx) {
__format_spec::__parsed_specifications __specs =
__parser_.__get_parsed_std_specifications(__ctx);
using _Type = unsigned;
__formatter::__format_integer(_Type(), __ctx, __specs);
}
__format_spec::__parser<_CharT> __parser_;
};
template <__fmt_char_type _CharT>
struct formatter<int, _CharT> : __formatter_integer<_CharT> {};
} // namespace __1
} // namespace std
template <class OutIt, class CharT>
std::basic_format_context<OutIt, CharT> test_format_context_create(
OutIt, std::basic_format_args<std::basic_format_context<OutIt, CharT>>);
std::formatter<std::vector, char> test_setter_formatter;
int test_setter_out;
void test_setter() {
std::__format_arg_store __trans_tmp_1;
std::basic_format_context format_ctx =
test_format_context_create<int, char>(test_setter_out, __trans_tmp_1);
test_setter_formatter.format(2, format_ctx);
}
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.