1 // RUN: %clang_cc1 -std=c++98 %s -Wno-parentheses -Wdeprecated -verify=expected,not-cxx20 -triple x86_64-linux-gnu
2 // RUN: %clang_cc1 -std=c++11 %s -Wno-parentheses -Wdeprecated -verify=expected,not-cxx20 -triple x86_64-linux-gnu
3 // RUN: %clang_cc1 -std=c++14 %s -Wno-parentheses -Wdeprecated -verify=expected,not-cxx20 -triple x86_64-linux-gnu
4 // RUN: %clang_cc1 -std=c++17 %s -Wno-parentheses -Wdeprecated -verify=expected,not-cxx20 -triple x86_64-linux-gnu
5 // RUN: %clang_cc1 -std=c++2a %s -Wno-parentheses -Wdeprecated -verify=expected,cxx20 -triple x86_64-linux-gnu
6 
7 // RUN: %clang_cc1 -std=c++14 %s -Wno-parentheses -Wdeprecated -verify=expected,not-cxx20 -triple x86_64-linux-gnu -Wno-deprecated-register -DNO_DEPRECATED_FLAGS
8 
9 #include "Inputs/register.h"
10 
11 namespace std {
12   struct type_info {};
13 }
14 
15 void g() throw();
16 void h() throw(int);
17 void i() throw(...);
18 #if __cplusplus > 201402L
19 // expected-warning@-4 {{dynamic exception specifications are deprecated}} expected-note@-4 {{use 'noexcept' instead}}
20 // expected-error@-4 {{ISO C++17 does not allow dynamic exception specifications}} expected-note@-4 {{use 'noexcept(false)' instead}}
21 // expected-error@-4 {{ISO C++17 does not allow dynamic exception specifications}} expected-note@-4 {{use 'noexcept(false)' instead}}
22 #elif __cplusplus >= 201103L
23 // expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept' instead}}
24 // expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept(false)' instead}}
25 // expected-warning@-8 {{dynamic exception specifications are deprecated}} expected-note@-8 {{use 'noexcept(false)' instead}}
26 #endif
27 
stuff(register int q)28 void stuff(register int q) {
29 #if __cplusplus > 201402L
30   // expected-error@-2 {{ISO C++17 does not allow 'register' storage class specifier}}
31 #elif __cplusplus >= 201103L && !defined(NO_DEPRECATED_FLAGS)
32   // expected-warning@-4 {{'register' storage class specifier is deprecated}}
33 #endif
34   register int n;
35 #if __cplusplus > 201402L
36   // expected-error@-2 {{ISO C++17 does not allow 'register' storage class specifier}}
37 #elif __cplusplus >= 201103L && !defined(NO_DEPRECATED_FLAGS)
38   // expected-warning@-4 {{'register' storage class specifier is deprecated}}
39 #endif
40 
41   register int m asm("rbx"); // no-warning
42 
43   int k = to_int(n); // no-warning
44   bool b;
45   ++b;
46 #if __cplusplus > 201402L
47   // expected-error@-2 {{ISO C++17 does not allow incrementing expression of type bool}}
48 #else
49   // expected-warning@-4 {{incrementing expression of type bool is deprecated}}
50 #endif
51 
52   b++;
53 #if __cplusplus > 201402L
54   // expected-error@-2 {{ISO C++17 does not allow incrementing expression of type bool}}
55 #else
56   // expected-warning@-4 {{incrementing expression of type bool is deprecated}}
57 #endif
58 
59   char *p = "foo";
60 #if __cplusplus < 201103L
61   // expected-warning@-2 {{conversion from string literal to 'char *' is deprecated}}
62 #else
63   // expected-warning@-4 {{ISO C++11 does not allow conversion from string literal to 'char *'}}
64 #endif
65 }
66 
67 struct S { int n; void operator+(int); };
68 struct T : private S {
69   S::n;
70 #if __cplusplus < 201103L
71   // expected-warning@-2 {{access declarations are deprecated; use using declarations instead}}
72 #else
73   // expected-error@-4 {{ISO C++11 does not allow access declarations; use using declarations instead}}
74 #endif
75   S::operator+;
76 #if __cplusplus < 201103L
77   // expected-warning@-2 {{access declarations are deprecated; use using declarations instead}}
78 #else
79   // expected-error@-4 {{ISO C++11 does not allow access declarations; use using declarations instead}}
80 #endif
81 };
82 
83 #if __cplusplus >= 201103L
84 namespace DeprecatedCopy {
85   struct Assign {
86     Assign &operator=(const Assign&); // expected-warning {{definition of implicit copy constructor for 'Assign' is deprecated because it has a user-provided copy assignment operator}}
87   };
88   Assign a1, a2(a1); // expected-note {{implicit copy constructor for 'DeprecatedCopy::Assign' first required here}}
89 
90   struct Ctor {
91     Ctor();
92     Ctor(const Ctor&); // expected-warning {{definition of implicit copy assignment operator for 'Ctor' is deprecated because it has a user-provided copy constructor}}
93   };
94   Ctor b1, b2;
f()95   void f() { b1 = b2; } // expected-note {{implicit copy assignment operator for 'DeprecatedCopy::Ctor' first required here}}
96 
97   struct Dtor {
98     ~Dtor();
99     // expected-warning@-1 {{definition of implicit copy constructor for 'Dtor' is deprecated because it has a user-provided destructor}}
100     // expected-warning@-2 {{definition of implicit copy assignment operator for 'Dtor' is deprecated because it has a user-provided destructor}}
101   };
102   Dtor c1, c2(c1); // expected-note {{implicit copy constructor for 'DeprecatedCopy::Dtor' first required here}}
g()103   void g() { c1 = c2; } // expected-note {{implicit copy assignment operator for 'DeprecatedCopy::Dtor' first required here}}
104 
105   struct DefaultedDtor {
106     ~DefaultedDtor() = default; // expected-warning {{definition of implicit copy constructor for 'DefaultedDtor' is deprecated because it has a user-declared destructor}}
107   };                            // expected-warning@-1 {{definition of implicit copy assignment operator for 'DefaultedDtor' is deprecated because it has a user-declared destructor}}
108   DefaultedDtor d1;
109   DefaultedDtor d2(d1);         // expected-note {{in implicit copy constructor for 'DeprecatedCopy::DefaultedDtor' first required here}}
h()110   void h() { d1 = d2; }         // expected-note {{in implicit copy assignment operator for 'DeprecatedCopy::DefaultedDtor' first required here}}
111 }
112 #endif
113 
114 struct X {
115   friend int operator,(X, X);
116   void operator[](int);
117 };
array_index_comma()118 void array_index_comma() {
119   int arr[123];
120   (void)arr[(void)1, 2];
121   (void)arr[X(), X()];
122   X()[(void)1, 2];
123   X()[X(), X()];
124 #if __cplusplus > 201703L
125   // expected-warning@-5 {{deprecated}}
126   // expected-warning@-5 {{deprecated}}
127   // expected-warning@-5 {{deprecated}}
128   // expected-warning@-5 {{deprecated}}
129 #endif
130 
131   (void)arr[((void)1, 2)];
132   (void)arr[(X(), X())];
133   (void)((void)1,2)[arr];
134   (void)(X(), X())[arr];
135   X()[((void)1, 2)];
136   X()[(X(), X())];
137 }
138 
139 namespace DeprecatedVolatile {
140   volatile int n = 1;
141   void use(int);
f()142   void f() {
143     // simple assignments are deprecated only if their value is used
144     n = 5; // ok
145 #if __cplusplus >= 201103L
146     decltype(n = 5) m = n; // ok expected-warning {{side effects}}
147     (void)noexcept(n = 5); // ok expected-warning {{side effects}}
148 #endif
149     (void)typeid(n = 5); // ok expected-warning {{side effects}}
150     (n = 5, 0); // ok
151     use(n = 5); // cxx20-warning {{use of result of assignment to object of volatile-qualified type 'volatile int' is deprecated}}
152     int q = n = 5; // cxx20-warning {{deprecated}}
153     q = n = 5; // cxx20-warning {{deprecated}}
154 #if __cplusplus >= 201103L
155     decltype(q = n = 5) m2 = q; // cxx20-warning {{deprecated}} expected-warning {{side effects}}
156     (void)noexcept(q = n = 5); // cxx20-warning {{deprecated}} expected-warning {{side effects}}
157 #endif
158     (void)sizeof(q = n = 5); // cxx20-warning {{deprecated}} expected-warning {{side effects}}
159     (void)typeid(use(n = 5)); // cxx20-warning {{deprecated}} expected-warning {{side effects}}
160     (void)__alignof(+(n = 5)); // cxx20-warning {{deprecated}} expected-warning {{side effects}}
161 
162     // FIXME: These cases are technically deprecated because the parens are
163     // part of the operand, but we choose to not diagnose for now.
164     (void)sizeof(n = 5); // expected-warning {{side effects}}
165     (void)__alignof(n = 5); // expected-warning {{side effects}}
166     // Similarly here.
167     (n = 5);
168 
169     volatile bool b = true;
170     if (b = true) {} // cxx20-warning {{deprecated}}
171     for (b = true;
172          b = true; // cxx20-warning {{deprecated}}
173          b = true) {}
174     for (volatile bool x = true;
175          volatile bool y = true; // ok despite volatile load from volatile initialization
176         ) {}
177 
178     // inc / dec / compound assignments are always deprecated
179     ++n; // cxx20-warning {{increment of object of volatile-qualified type 'volatile int' is deprecated}}
180     --n; // cxx20-warning {{decrement of object of volatile-qualified type 'volatile int' is deprecated}}
181     n++; // cxx20-warning {{increment of object of volatile-qualified type 'volatile int' is deprecated}}
182     n--; // cxx20-warning {{decrement of object of volatile-qualified type 'volatile int' is deprecated}}
183     n += 5; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
184     n *= 3; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
185     n /= 2; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
186     n %= 42; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
187     n &= 2; // undeprecated as a DR in C++23
188     n |= 2; // undeprecated as a DR in C++23
189     n ^= 2; // undeprecated as a DR in C++23
190 
191     (void)__is_trivially_assignable(volatile int&, int); // no warning
192 
193 #if __cplusplus >= 201703L
194     struct X { int a, b; };
195     volatile auto [x, y] = X{1, 2}; // cxx20-warning {{volatile qualifier in structured binding declaration is deprecated}}
196 
197     struct Y { volatile int a, b; };
198     auto [x2, y2] = Y{1, 2}; // ok
199 #endif
200   }
201   volatile int g( // cxx20-warning {{volatile-qualified return type 'volatile int' is deprecated}}
202       volatile int n, // cxx20-warning {{volatile-qualified parameter type 'volatile int' is deprecated}}
203       volatile int (*p)( // cxx20-warning {{volatile-qualified return type 'volatile int' is deprecated}}
204         volatile int m) // cxx20-warning {{volatile-qualified parameter type 'volatile int' is deprecated}}
205       );
206 #if __cplusplus >= 201103L
207   auto lambda = []( // cxx20-warning{{volatile-qualified return type 'volatile int' is deprecated}}
208       volatile int n) // cxx20-warning{{volatile-qualified parameter type 'volatile int' is deprecated}}
__anon7082f44c0102( volatile int n) 209     -> volatile int { return n; };
210 #endif
211 
212   template<typename T> T f(T v); // cxx20-warning 2{{deprecated}}
213   int use_f = f<volatile int>(0); // FIXME: Missing "in instantiation of" note.
214 
215   // OK, only the built-in operators are deprecated.
216   struct UDT {
217     UDT(volatile const UDT&);
218     UDT &operator=(const UDT&);
219     UDT &operator=(const UDT&) volatile;
220     UDT operator+=(const UDT&) volatile;
221   };
h(UDT a)222   void h(UDT a) {
223     volatile UDT b = a;
224     volatile UDT c = b;
225     a = c = a;
226     b += a;
227   }
228 }
229 
230 namespace ArithConv {
231   enum E { e } e2;
232   enum F { f };
233   bool b1 = e == e2;
234   bool b2 = e == f; // not-cxx20-warning-re {{different enumeration types ('ArithConv::E' and 'ArithConv::F'){{$}}}} cxx20-warning {{F') is deprecated}}
235   bool b3 = e == 0.0; // cxx20-warning {{comparison of enumeration type 'ArithConv::E' with floating-point type 'double' is deprecated}}
236   bool b4 = 0.0 == f; // cxx20-warning {{comparison of floating-point type 'double' with enumeration type 'ArithConv::F' is deprecated}}
237   int n1 = true ? e : f; // cxx20-warning {{conditional expression between different enumeration types ('ArithConv::E' and 'ArithConv::F') is deprecated}}
238   int n2 = true ? e : 0.0; // cxx20-warning {{conditional expression between enumeration type 'ArithConv::E' and floating-point type 'double' is deprecated}}
239 }
240 
241 namespace ArrayComp {
242   int arr1[3], arr2[4];
243   bool b1 = arr1 == arr2; // expected-warning {{array comparison always evaluates to false}} cxx20-warning {{comparison between two arrays is deprecated}}
244   bool b2 = arr1 < arr2; // expected-warning {{array comparison always evaluates to a constant}} cxx20-warning {{comparison between two arrays is deprecated}}
245   __attribute__((weak)) int arr3[3];
246   bool b3 = arr1 == arr3; // cxx20-warning {{comparison between two arrays is deprecated}}
247   bool b4 = arr1 < arr3; // cxx20-warning {{comparison between two arrays is deprecated}}
248 #if __cplusplus > 201703L
249   bool b5 = arr1 <=> arr2; // cxx20-error {{invalid operands}}
250 #endif
251 
252   int (&f())[3];
253   bool b6 = arr1 == f(); // cxx20-warning {{comparison between two arrays is deprecated}}
254   bool b7 = arr1 == +f();
255 }
256 
257 # 1 "/usr/include/system-header.h" 1 3
258 void system_header_function(void) throw();
259