Skip to content

Commit 11dd881

Browse files
authored
[libc++][format] Fixes nested concept evaluation. (llvm#85548)
Before the __formattable concept depended on itself in a contrieved example. By using the underlying concept directly the cycle is broken. Fixes llvm#81590
1 parent 4462bb5 commit 11dd881

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

libcxx/include/__format/format_arg_store.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ consteval __arg_t __determine_arg_t() {
151151
// The overload for not formattable types allows triggering the static
152152
// assertion below.
153153
template <class _Context, class _Tp>
154-
requires(!__formattable<_Tp, typename _Context::char_type>)
154+
requires(!__formattable_with<_Tp, _Context>)
155155
consteval __arg_t __determine_arg_t() {
156156
return __arg_t::__none;
157157
}
@@ -165,7 +165,6 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __valu
165165
using _Dp = remove_const_t<_Tp>;
166166
constexpr __arg_t __arg = __determine_arg_t<_Context, _Dp>();
167167
static_assert(__arg != __arg_t::__none, "the supplied type is not formattable");
168-
169168
static_assert(__formattable_with<_Tp, _Context>);
170169

171170
// Not all types can be used to directly initialize the
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===----------------------------------------------------------------------===//
2+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
//===----------------------------------------------------------------------===//
7+
8+
// UNSUPPORTED: c++03, c++11, c++14, c++17
9+
10+
// XFAIL: availability-fp_to_chars-missing
11+
12+
// The sample code is based on the bug report
13+
// https://github.com/llvm/llvm-project/issues/81590
14+
//
15+
// Tests whether this formatter does not fail to compile due to nested concept
16+
// evaluation.
17+
18+
#include <format>
19+
#include <variant>
20+
21+
struct X : std::variant<X*> {
22+
X* p = nullptr;
23+
constexpr const std::variant<X*>& decay() const noexcept { return *this; }
24+
};
25+
26+
template <>
27+
struct std::formatter<X, char> : std::formatter<std::string, char> {
28+
static constexpr auto format(const X& x, auto ctx) {
29+
if (!x.p)
30+
return ctx.out();
31+
auto m = [&](const X* t) { return std::format_to(ctx.out(), "{}", *t); };
32+
return std::visit(m, x.decay());
33+
}
34+
};
35+
36+
void bug_81590() { (void)std::format("{}", X{}); }

0 commit comments

Comments
 (0)