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 
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-declared 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-declared copy constructor}}
93   };
94   Ctor b1, b2;
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-declared destructor}}
100     // expected-warning@-2 {{definition of implicit copy assignment operator for 'Dtor' is deprecated because it has a user-declared destructor}}
101   };
102   Dtor c1, c2(c1); // expected-note {{implicit copy constructor for 'DeprecatedCopy::Dtor' first required here}}
103   void g() { c1 = c2; } // expected-note {{implicit copy assignment operator for 'DeprecatedCopy::Dtor' first required here}}
104 
105   struct DefaultedDtor {
106     ~DefaultedDtor() = default;
107   };
108   DefaultedDtor d1, d2(d1);
109   void h() { d1 = d2; }
110 }
111 #endif
112 
113 struct X {
114   friend int operator,(X, X);
115   void operator[](int);
116 };
117 void array_index_comma() {
118   int arr[123];
119   (void)arr[(void)1, 2];
120   (void)arr[X(), X()];
121   X()[(void)1, 2];
122   X()[X(), X()];
123 #if __cplusplus > 201703L
124   // expected-warning@-5 {{deprecated}}
125   // expected-warning@-5 {{deprecated}}
126   // expected-warning@-5 {{deprecated}}
127   // expected-warning@-5 {{deprecated}}
128 #endif
129 
130   (void)arr[((void)1, 2)];
131   (void)arr[(X(), X())];
132   (void)((void)1,2)[arr];
133   (void)(X(), X())[arr];
134   X()[((void)1, 2)];
135   X()[(X(), X())];
136 }
137 
138 namespace DeprecatedVolatile {
139   volatile int n = 1;
140   void use(int);
141   void f() {
142     // simple assignments are deprecated only if their value is used
143     n = 5; // ok
144 #if __cplusplus >= 201103L
145     decltype(n = 5) m = n; // ok expected-warning {{side effects}}
146     (void)noexcept(n = 5); // ok expected-warning {{side effects}}
147 #endif
148     (void)typeid(n = 5); // ok expected-warning {{side effects}}
149     (n = 5, 0); // ok
150     use(n = 5); // cxx20-warning {{use of result of assignment to object of volatile-qualified type 'volatile int' is deprecated}}
151     int q = n = 5; // cxx20-warning {{deprecated}}
152     q = n = 5; // cxx20-warning {{deprecated}}
153 #if __cplusplus >= 201103L
154     decltype(q = n = 5) m2 = q; // cxx20-warning {{deprecated}} expected-warning {{side effects}}
155     (void)noexcept(q = n = 5); // cxx20-warning {{deprecated}} expected-warning {{side effects}}
156 #endif
157     (void)sizeof(q = n = 5); // cxx20-warning {{deprecated}} expected-warning {{side effects}}
158     (void)typeid(use(n = 5)); // cxx20-warning {{deprecated}} expected-warning {{side effects}}
159     (void)__alignof(+(n = 5)); // cxx20-warning {{deprecated}} expected-warning {{side effects}}
160 
161     // FIXME: These cases are technically deprecated because the parens are
162     // part of the operand, but we choose to not diagnose for now.
163     (void)sizeof(n = 5); // expected-warning {{side effects}}
164     (void)__alignof(n = 5); // expected-warning {{side effects}}
165     // Similarly here.
166     (n = 5);
167 
168     volatile bool b = true;
169     if (b = true) {} // cxx20-warning {{deprecated}}
170     for (b = true;
171          b = true; // cxx20-warning {{deprecated}}
172          b = true) {}
173     for (volatile bool x = true;
174          volatile bool y = true; // ok despite volatile load from volatile initialization
175         ) {}
176 
177     // inc / dec / compound assignments are always deprecated
178     ++n; // cxx20-warning {{increment of object of volatile-qualified type 'volatile int' is deprecated}}
179     --n; // cxx20-warning {{decrement of object of volatile-qualified type 'volatile int' is deprecated}}
180     n++; // cxx20-warning {{increment of object of volatile-qualified type 'volatile int' is deprecated}}
181     n--; // cxx20-warning {{decrement of object of volatile-qualified type 'volatile int' is deprecated}}
182     n += 5; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
183     n *= 3; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
184     n /= 2; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
185     n %= 42; // cxx20-warning {{compound assignment to object of volatile-qualified type 'volatile int' is deprecated}}
186 
187     (void)__is_trivially_assignable(volatile int&, int); // no warning
188 
189 #if __cplusplus >= 201703L
190     struct X { int a, b; };
191     volatile auto [x, y] = X{1, 2}; // cxx20-warning {{volatile qualifier in structured binding declaration is deprecated}}
192 
193     struct Y { volatile int a, b; };
194     auto [x2, y2] = Y{1, 2}; // ok
195 #endif
196   }
197   volatile int g( // cxx20-warning {{volatile-qualified return type 'volatile int' is deprecated}}
198       volatile int n, // cxx20-warning {{volatile-qualified parameter type 'volatile int' is deprecated}}
199       volatile int (*p)( // cxx20-warning {{volatile-qualified return type 'volatile int' is deprecated}}
200         volatile int m) // cxx20-warning {{volatile-qualified parameter type 'volatile int' is deprecated}}
201       );
202 #if __cplusplus >= 201103L
203   auto lambda = []( // cxx20-warning{{volatile-qualified return type 'volatile int' is deprecated}}
204       volatile int n) // cxx20-warning{{volatile-qualified parameter type 'volatile int' is deprecated}}
205     -> volatile int { return n; };
206 #endif
207 
208   template<typename T> T f(T v); // cxx20-warning 2{{deprecated}}
209   int use_f = f<volatile int>(0); // FIXME: Missing "in instantiation of" note.
210 
211   // OK, only the built-in operators are deprecated.
212   struct UDT {
213     UDT(volatile const UDT&);
214     UDT &operator=(const UDT&);
215     UDT &operator=(const UDT&) volatile;
216     UDT operator+=(const UDT&) volatile;
217   };
218   void h(UDT a) {
219     volatile UDT b = a;
220     volatile UDT c = b;
221     a = c = a;
222     b += a;
223   }
224 }
225 
226 namespace ArithConv {
227   enum E { e } e2;
228   enum F { f };
229   bool b1 = e == e2;
230   bool b2 = e == f; // not-cxx20-warning-re {{different enumeration types ('ArithConv::E' and 'ArithConv::F'){{$}}}} cxx20-warning {{F') is deprecated}}
231   bool b3 = e == 0.0; // cxx20-warning {{comparison of enumeration type 'ArithConv::E' with floating-point type 'double' is deprecated}}
232   bool b4 = 0.0 == f; // cxx20-warning {{comparison of floating-point type 'double' with enumeration type 'ArithConv::F' is deprecated}}
233   int n1 = true ? e : f; // cxx20-warning {{conditional expression between different enumeration types ('ArithConv::E' and 'ArithConv::F') is deprecated}}
234   int n2 = true ? e : 0.0; // cxx20-warning {{conditional expression between enumeration type 'ArithConv::E' and floating-point type 'double' is deprecated}}
235 }
236 
237 namespace ArrayComp {
238   int arr1[3], arr2[4];
239   bool b1 = arr1 == arr2; // expected-warning {{array comparison always evaluates to false}} cxx20-warning {{comparison between two arrays is deprecated}}
240   bool b2 = arr1 < arr2; // expected-warning {{array comparison always evaluates to a constant}} cxx20-warning {{comparison between two arrays is deprecated}}
241   __attribute__((weak)) int arr3[3];
242   bool b3 = arr1 == arr3; // cxx20-warning {{comparison between two arrays is deprecated}}
243   bool b4 = arr1 < arr3; // cxx20-warning {{comparison between two arrays is deprecated}}
244 #if __cplusplus > 201703L
245   bool b5 = arr1 <=> arr2; // cxx20-error {{invalid operands}}
246 #endif
247 
248   int (&f())[3];
249   bool b6 = arr1 == f(); // cxx20-warning {{comparison between two arrays is deprecated}}
250   bool b7 = arr1 == +f();
251 }
252 
253 # 1 "/usr/include/system-header.h" 1 3
254 void system_header_function(void) throw();
255