xref: /llvm-project/clang/test/SemaCXX/cxx11-default-member-initializers.cpp (revision 060137038ab9246b377e190ae3c6f272fa57cbfc)
1 // RUN: %clang_cc1 -std=c++11 -verify %s -pedantic
2 // RUN: %clang_cc1 -std=c++11 -verify %s -pedantic -fexperimental-new-constant-interpreter
3 // RUN: %clang_cc1 -std=c++20 -verify %s -pedantic
4 // RUN: %clang_cc1 -std=c++20 -verify %s -pedantic -fexperimental-new-constant-interpreter
5 
6 
7 namespace PR31692 {
8   struct A {
9     struct X { int n = 0; } x;
10     // Trigger construction of X() from a SFINAE context. This must not mark
11     // any part of X as invalid.
12     static_assert(!__is_constructible(X), "");
13     // Check that X::n is not marked invalid.
14     double &r = x.n; // expected-error {{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}}
15   };
16   // A::X can now be default-constructed.
17   static_assert(__is_constructible(A::X), "");
18 }
19 
20 
21 struct S {
22 } constexpr s;
23 struct C {
24   C(S);
25 };
26 class MemInit {
27   C m = s;
28 };
29 
30 namespace std {
31 typedef decltype(sizeof(int)) size_t;
32 
33 // libc++'s implementation
34 template <class _E> class initializer_list {
35   const _E *__begin_;
36   size_t __size_;
37 
38   initializer_list(const _E *__b, size_t __s) : __begin_(__b), __size_(__s) {}
39 
40 public:
41   typedef _E value_type;
42   typedef const _E &reference;
43   typedef const _E &const_reference;
44   typedef size_t size_type;
45 
46   typedef const _E *iterator;
47   typedef const _E *const_iterator;
48 
49   initializer_list() : __begin_(nullptr), __size_(0) {}
50 
51   size_t size() const { return __size_; }
52   const _E *begin() const { return __begin_; }
53   const _E *end() const { return __begin_ + __size_; }
54 };
55 } // namespace std
56 
57 #if __cplusplus >= 201703L
58 
59 // Test CXXDefaultInitExpr rebuild issue in
60 // https://github.com/llvm/llvm-project/pull/87933
61 namespace test_rebuild {
62 template <typename T, int> class C {
63 public:
64   C(std::initializer_list<T>);
65 };
66 
67 template <typename T> using Ptr = __remove_pointer(T) *;
68 template <typename T> C(T) -> C<Ptr<T>, sizeof(T)>;
69 
70 class A {
71 public:
72   template <typename T1, typename T2> T1 *some_func(T2 &&);
73 };
74 
75 struct B : A {
76   int *ar = some_func<int>(C{some_func<int>(0)});
77   B() {}
78 };
79 
80 int TestBody_got;
81 template <int> class Vector {
82 public:
83   Vector(std::initializer_list<int>);
84 };
85 template <typename... Ts> Vector(Ts...) -> Vector<sizeof...(Ts)>;
86 class ProgramBuilder {
87 public:
88   template <typename T, typename ARGS> int *create(ARGS);
89 };
90 
91 struct TypeTest : ProgramBuilder {
92   int *str_f16 = create<int>(Vector{0});
93   TypeTest() {}
94 };
95 class TypeTest_Element_Test : TypeTest {
96   void TestBody();
97 };
98 void TypeTest_Element_Test::TestBody() {
99   int *expect = str_f16;
100   &TestBody_got != expect; // expected-warning {{inequality comparison result unused}}
101 }
102 } //  namespace test_rebuild
103 
104 // Test CXXDefaultInitExpr rebuild issue in
105 // https://github.com/llvm/llvm-project/pull/92527
106 namespace test_rebuild2 {
107 struct F {
108   int g;
109 };
110 struct H {};
111 struct I {
112   I(const F &);
113   I(H);
114 };
115 struct L {
116   I i = I({.g = 0});
117 };
118 struct N : L {};
119 
120 void f() {
121   delete new L; // Ok
122   delete new N; // Ok
123 }
124 } // namespace test_rebuild2
125 #endif // __cplusplus >= 201703L
126 
127 #if __cplusplus >= 202002L
128 // This test ensures cleanup expressions are correctly produced
129 // in the presence of default member initializers.
130 namespace PR136554 {
131 struct string {
132   constexpr string(const char*) {};
133   constexpr ~string();
134 };
135 struct S;
136 struct optional {
137     template <typename U = S>
138     constexpr optional(U &&) {}
139 };
140 struct S {
141     string a;
142     optional b;
143     int defaulted = 0;
144 } test {
145     "", {
146         { "", 0 }
147     }
148 };
149 
150 // Ensure that the this pointer is
151 // transformed without crashing
152 consteval int immediate() { return 0;}
153 struct StructWithThisInInitializer {
154   int member() const {
155       return 0;
156   }
157   int m = member() + immediate();
158   int m2 = this->member() + immediate();
159 };
160 
161 template <typename T>
162 struct StructWithThisInInitializerTPL {
163   template <typename U>
164   int member() const {
165       return 0;
166   }
167   int m = member<int>() + immediate();
168   int m2 = this->member<int>() + immediate();
169 };
170 
171 void test_this() {
172   (void)StructWithThisInInitializer{};
173   (void)StructWithThisInInitializerTPL<int>{};
174 }
175 
176 struct ReferenceToNestedMembers {
177   int m;
178   int a = ((void)immediate(), m); // ensure g is found in the correct scope
179   int b = ((void)immediate(), this->m); // ensure g is found in the correct scope
180 };
181 struct ReferenceToNestedMembersTest {
182  void* m = nullptr;
183  ReferenceToNestedMembers j{0};
184 } test_reference_to_nested_members;
185 
186 }
187 
188 
189 namespace odr_in_unevaluated_context {
190 template <typename e, bool = __is_constructible(e)> struct f {
191     using type = bool;
192 };
193 
194 template <class k, f<k>::type = false> int l;
195 int m;
196 struct p {
197   // This used to crash because m is first marked odr used
198   // during parsing, but subsequently used in an unevaluated context
199   // without being transformed.
200   int o = m;
201   p() {}
202 };
203 
204 int i = l<p>;
205 }
206 
207 #endif
208