[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / test / SemaCXX / builtin-dump-struct.cpp
blobe057eac029463d3554796a5bf0274b4bcd8fbc30
1 // RUN: %clang_cc1 -std=c++20 -verify %s
3 namespace std {
4 typedef decltype(sizeof(int)) size_t;
6 template <class E> struct initializer_list {
7 const E *data;
8 size_t size;
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);
23 data[size] = '\0';
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) {
39 delete[] data;
40 data = o.data;
41 o.data = nullptr;
42 return *this;
44 constexpr ~ConstexprString() { delete[] data; }
45 char *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) {
51 return a = a + 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);
60 struct Arg {
61 template<typename T, int (*)[__is_integral(T) ? 1 : -1] = nullptr>
62 constexpr Arg(T value) {
63 bool negative = false;
64 if (value < 0) {
65 value = -value;
66 negative = true;
68 while (value > 0) {
69 char str[2] = {char('0' + value % 10), '\0'};
70 s = ConstexprString(str) + s;
71 value /= 10;
73 if (negative)
74 s = "-" + 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) {}
84 ConstexprString s;
87 template<typename... T> constexpr void Format(ConstexprString &out, const char *fmt, T... args) { // #Format
88 Arg formatted_args[] = {args...};
89 int i = 0;
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.
97 fmt = percent;
98 while (!__builtin_strchr("diouxXeEfFgGcsp", *fmt)) ++fmt;
99 // Skip the conversion specifier too. TODO: Check it's the right one.
100 ++fmt;
102 out += ConstexprString(fmt);
105 template<typename T> constexpr ConstexprString ToString(const T &t) { return Arg(t).s; }
107 struct A {
108 int x, y, z : 3;
109 int : 4;
110 ConstexprString s;
112 struct B : A {
113 int p, q;
114 struct {
115 int anon1, anon2;
117 union {
118 int anon3;
120 struct {
121 int m;
122 } c;
123 int &&r;
126 #if PRINT_OUTPUT
127 #include <stdio.h>
128 int main() {
129 puts(ToString(B{1, 2, 3, "hello", 4, 5, 6, 7, 8, 9, 10}).data);
131 #else
132 static_assert(ToString(B{1, 2, 3, "hello", 4, 5, 6, 7, 8, 9, 10}) == &R"(
135 int x = 1
136 int y = 2
137 int z : 3 = 3
138 ConstexprString s = "hello"
140 int p = 4
141 int q = 5
142 int anon1 = 6
143 int anon2 = 7
144 int anon3 = 8
145 struct (unnamed) c = {
146 int m = 9
148 int && r = reference to 10
150 )"[1]);
152 void errors(B b) {
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}}
161 #endif