Open
Description
When using libc++, clang (trunk 20230914) fails to compile code using std::format with user-defined formatter
specialisation.
Minimal example, flags -std=c++20 -fexperimental-library -stdlib=libc++
#include <iostream>
#include <format>
struct Type {};
template <>
struct std::formatter<Type> : std::formatter<std::string> {
auto format(Type p, format_context& ctx) const {
return formatter<string>::format("test", ctx);
}
};
int main() {
std::cout << std::format("{}", Type{}) << std::endl;
}
- compiler explorer clang (trunk), libc++, fail
- compiler explorer clang (trunk), libstdc++, success
- compiler explorer gcc (trunk), libstdc++, success
Error
<source>:14:30: error: call to consteval function 'std::basic_format_string<char, Type>::basic_format_string<char[3]>' is not a constant expression
14 | std::cout << std::format("{}", Type{}) << std::endl;
| ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:268:7: note: non-constexpr function '__throw_format_error' cannot be used in a constant expression
268 | std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
| ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:315:13: note: in call to '__handle_replacement_field<const char *, std::basic_format_parse_context<char>, std::__format::__compile_time_basic_format_context<char>>(&"{}"[1], &"{}"[2], basic_format_parse_context<char>{this->__str_, sizeof...(_Args)}, _Context{__types_.data(), __handles_.data(), sizeof...(_Args)})'
315 | __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:346:5: note: in call to '__vformat_to<std::basic_format_parse_context<char>, std::__format::__compile_time_basic_format_context<char>>(basic_format_parse_context<char>{this->__str_, sizeof...(_Args)}, _Context{__types_.data(), __handles_.data(), sizeof...(_Args)})'
346 | __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
347 | _Context{__types_.data(), __handles_.data(), sizeof...(_Args)});
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:14:30: note: in call to 'basic_format_string<char[3]>("{}")'
14 | std::cout << std::format("{}", Type{}) << std::endl;
| ^~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_error.h:41:1: note: declared here
41 | __throw_format_error(const char* __s) {
| ^
In file included from <source>:2:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/format:176:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/container_adaptor.h:20:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/range_default_formatter.h:23:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/range_formatter.h:23:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_context.h:18:
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:167:17: error: static assertion failed due to requirement '__arg != __arg_t::__none': the supplied type is not formattable
167 | static_assert(__arg != __arg_t::__none, "the supplied type is not formattable");
| ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:210:54: note: in instantiation of function template specialization 'std::__format::__create_format_arg<std::format_context, Type>' requested here
210 | basic_format_arg<_Context> __arg = __format::__create_format_arg<_Context>(__args);
| ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:246:19: note: in instantiation of function template specialization 'std::__format::__create_packed_storage<std::format_context, Type &>' requested here
246 | __format::__create_packed_storage(__storage.__types_, __storage.__values_, __args...);
| ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:67:10: note: in instantiation of member function 'std::__format_arg_store<std::format_context, Type &>::__format_arg_store' requested here
67 | return _VSTD::__format_arg_store<_Context, _Args...>(__args...);
| ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__config:784:17: note: expanded from macro '_VSTD'
784 | # define _VSTD std
| ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:454:45: note: in instantiation of function template specialization 'std::make_format_args<std::format_context, Type &>' requested here
454 | return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...));
| ^
<source>:14:23: note: in instantiation of function template specialization 'std::format<Type>' requested here
14 | std::cout << std::format("{}", Type{}) << std::endl;
| ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:167:23: note: expression evaluates to '0 != 0'
167 | static_assert(__arg != __arg_t::__none, "the supplied type is not formattable");
| ~~~~~~^~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:201:12: error: no matching constructor for initialization of 'basic_format_arg<format_context>'
201 | return basic_format_arg<_Context>{__arg, __value};
| ^ ~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg.h:252:34: note: candidate constructor not viable: no known conversion from 'Type' to '__basic_format_arg_value<format_context>' for 2nd argument
252 | _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(__format::__arg_t __type,
| ^
253 | __basic_format_arg_value<_Context> __value) noexcept
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg.h:223:28: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
223 | class _LIBCPP_TEMPLATE_VIS basic_format_arg {
| ^~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg.h:223:28: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
223 | class _LIBCPP_TEMPLATE_VIS basic_format_arg {
| ^~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg.h:227:25: note: candidate constructor not viable: requires 0 arguments, but 2 were provided
227 | _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept
| ^
3 errors generated.
Compiler returned: 1