1 // RUN: %clang_cc1 -std=c++20 -verify %s
4 typedef decltype(sizeof(int)) size_t;
6 template <class E
> struct initializer_list
{
10 constexpr initializer_list(const E
*data
, size_t size
)
11 : data(data
), size(size
) {}
12 constexpr initializer_list() : data(), size() {}
14 constexpr const E
*begin() const { return data
; }
15 constexpr const E
*end() const { return data
+ size
; }
19 struct ConstexprString
{
20 constexpr ConstexprString() : ConstexprString("") {}
21 constexpr ConstexprString(const char *p
, std::size_t size
) : data(new char[size
+1]) {
22 __builtin_memcpy(data
, p
, size
);
25 constexpr ConstexprString(const char *p
) : ConstexprString(p
, __builtin_strlen(p
)) {}
26 constexpr explicit ConstexprString(const char *p
, const char *q
) : data(nullptr) {
27 auto p_size
= __builtin_strlen(p
);
28 auto q_size
= __builtin_strlen(q
);
29 data
= new char[p_size
+ q_size
+ 1];
30 __builtin_memcpy(data
, p
, p_size
);
31 __builtin_memcpy(data
+ p_size
, q
, q_size
+ 1);
33 constexpr ConstexprString(const ConstexprString
&o
) : ConstexprString(o
.data
) {}
34 constexpr ConstexprString(ConstexprString
&&o
) : data(o
.data
) { o
.data
= nullptr; }
35 constexpr ConstexprString
&operator=(const ConstexprString
&o
) {
36 return *this = ConstexprString(o
);
38 constexpr ConstexprString
&operator=(ConstexprString
&&o
) {
44 constexpr ~ConstexprString() { delete[] data
; }
47 friend constexpr ConstexprString
operator+(const ConstexprString
&a
, const ConstexprString
&b
) {
48 return ConstexprString(a
.data
, b
.data
);
50 friend constexpr ConstexprString
&operator+=(ConstexprString
&a
, const ConstexprString
&b
) {
53 friend constexpr bool operator==(const ConstexprString
&a
, const ConstexprString
&b
) {
54 return __builtin_strcmp(a
.data
, b
.data
) == 0;
58 template<typename
... T
> constexpr void Format(ConstexprString
&out
, const char *fmt
, T
... args
);
61 template<typename T
, int (*)[__is_integral(T
) ? 1 : -1] = nullptr>
62 constexpr Arg(T value
) {
63 bool negative
= false;
69 char str
[2] = {char('0' + value
% 10), '\0'};
70 s
= ConstexprString(str
) + s
;
76 template<typename T
, int (*)[__is_class(T
) ? 1 : -1] = nullptr>
77 constexpr Arg(const T
&value
) {
78 __builtin_dump_struct(&value
, Format
, s
);
80 constexpr Arg(const char *s
) : s(s
) {}
81 constexpr Arg(const ConstexprString
*s
) : s("\"" + *s
+ "\"") {}
82 template<typename T
, int (*)[__is_integral(T
) ? 1 : -1] = nullptr>
83 constexpr Arg(const T
*p
) : s("reference to " + Arg(*p
).s
) {}
87 template<typename
... T
> constexpr void Format(ConstexprString
&out
, const char *fmt
, T
... args
) { // #Format
88 Arg formatted_args
[] = {args
...};
90 while (const char *percent
= __builtin_strchr(fmt
, '%')) {
91 if (percent
[1] == '%') continue;
92 if (percent
!= fmt
&& percent
[-1] == '*') --percent
;
93 out
+= ConstexprString(fmt
, percent
- fmt
);
94 out
+= formatted_args
[i
++].s
;
96 // Skip past format specifier until we hit a conversion specifier.
98 while (!__builtin_strchr("diouxXeEfFgGcsp", *fmt
)) ++fmt
;
99 // Skip the conversion specifier too. TODO: Check it's the right one.
102 out
+= ConstexprString(fmt
);
105 template<typename T
> constexpr ConstexprString
ToString(const T
&t
) { return Arg(t
).s
; }
129 puts(ToString(B
{1, 2, 3, "hello", 4, 5, 6, 7, 8, 9, 10}).data
);
132 static_assert(ToString(B
{1, 2, 3, "hello", 4, 5, 6, 7, 8, 9, 10}) == &R
"(
138 ConstexprString s = "hello
"
145 struct (unnamed) c = {
148 int && r = reference to 10
153 __builtin_dump_struct(); // expected-error {{too few arguments to function call, expected 2, have 0}}
154 __builtin_dump_struct(1); // expected-error {{too few arguments to function call, expected 2, have 1}}
155 __builtin_dump_struct(1, 2); // expected-error {{expected pointer to struct as 1st argument to '__builtin_dump_struct', found 'int'}}
156 __builtin_dump_struct(&b
, 2); // expected-error {{expected a callable expression as 2nd argument to '__builtin_dump_struct', found 'int'}}
157 __builtin_dump_struct(&b
, Format
, 0); // expected-error {{no matching function for call to 'Format'}}
158 // expected-note@-1 {{in call to printing function with arguments '(0, "%s", "B")' while dumping struct}}
159 // expected-note@#Format {{no known conversion from 'int' to 'ConstexprString &' for 1st argument}}