Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / SemaCXX / builtin-dump-struct.cpp
blobb3d2a2d808ce26744c8c28963372609d6d408295
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
163 // Check that PseudoObjectExprBitfields:NumSubExprs doesn't overflow. This
164 // would previously cause a crash.
165 struct t1 {
166 int v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16,
167 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
168 v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46,
169 v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61,
170 v62, v63, v64, v65, v66, v67, v68, v69, v70, v71, v72, v73, v74, v75, v76,
171 v77, v78, v79, v80, v81, v82, v83, v84, v85, v86, v87, v88, v89, v90, v91,
172 v92, v93, v94, v95, v96, v97, v98, v99;
175 struct t2 {
176 t1 v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16,
177 v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
178 v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46,
179 v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61,
180 v62, v63, v64, v65, v66, v67, v68, v69, v70, v71, v72, v73, v74, v75, v76,
181 v77, v78, v79, v80, v81, v82, v83, v84, v85, v86, v87, v88, v89, v90, v91,
182 v92, v93, v94, v95, v96, v97, v98, v99;
185 int printf(const char *, ...);
186 void f1(t2 w) { __builtin_dump_struct(&w, printf); }