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 
188     (void)__is_trivially_assignable(volatile int&, int); // no warning
189 
190 #if __cplusplus >= 201703L
191     struct X { int a, b; };
192     volatile auto [x, y] = X{1, 2}; // cxx20-warning {{volatile qualifier in structured binding declaration is deprecated}}
193 
194     struct Y { volatile int a, b; };
195     auto [x2, y2] = Y{1, 2}; // ok
196 #endif
197   }
198   volatile int g( // cxx20-warning {{volatile-qualified return type 'volatile int' is deprecated}}
199       volatile int n, // cxx20-warning {{volatile-qualified parameter type 'volatile int' is deprecated}}
200       volatile int (*p)( // cxx20-warning {{volatile-qualified return type 'volatile int' is deprecated}}
201         volatile int m) // cxx20-warning {{volatile-qualified parameter type 'volatile int' is deprecated}}
202       );
203 #if __cplusplus >= 201103L
204   auto lambda = []( // cxx20-warning{{volatile-qualified return type 'volatile int' is deprecated}}
205       volatile int n) // cxx20-warning{{volatile-qualified parameter type 'volatile int' is deprecated}}
__anon62963d150102( volatile int n) 206     -> volatile int { return n; };
207 #endif
208 
209   template<typename T> T f(T v); // cxx20-warning 2{{deprecated}}
210   int use_f = f<volatile int>(0); // FIXME: Missing "in instantiation of" note.
211 
212   // OK, only the built-in operators are deprecated.
213   struct UDT {
214     UDT(volatile const UDT&);
215     UDT &operator=(const UDT&);
216     UDT &operator=(const UDT&) volatile;
217     UDT operator+=(const UDT&) volatile;
218   };
h(UDT a)219   void h(UDT a) {
220     volatile UDT b = a;
221     volatile UDT c = b;
222     a = c = a;
223     b += a;
224   }
225 }
226 
227 namespace ArithConv {
228   enum E { e } e2;
229   enum F { f };
230   bool b1 = e == e2;
231   bool b2 = e == f; // not-cxx20-warning-re {{different enumeration types ('ArithConv::E' and 'ArithConv::F'){{$}}}} cxx20-warning {{F') is deprecated}}
232   bool b3 = e == 0.0; // cxx20-warning {{comparison of enumeration type 'ArithConv::E' with floating-point type 'double' is deprecated}}
233   bool b4 = 0.0 == f; // cxx20-warning {{comparison of floating-point type 'double' with enumeration type 'ArithConv::F' is deprecated}}
234   int n1 = true ? e : f; // cxx20-warning {{conditional expression between different enumeration types ('ArithConv::E' and 'ArithConv::F') is deprecated}}
235   int n2 = true ? e : 0.0; // cxx20-warning {{conditional expression between enumeration type 'ArithConv::E' and floating-point type 'double' is deprecated}}
236 }
237 
238 namespace ArrayComp {
239   int arr1[3], arr2[4];
240   bool b1 = arr1 == arr2; // expected-warning {{array comparison always evaluates to false}} cxx20-warning {{comparison between two arrays is deprecated}}
241   bool b2 = arr1 < arr2; // expected-warning {{array comparison always evaluates to a constant}} cxx20-warning {{comparison between two arrays is deprecated}}
242   __attribute__((weak)) int arr3[3];
243   bool b3 = arr1 == arr3; // cxx20-warning {{comparison between two arrays is deprecated}}
244   bool b4 = arr1 < arr3; // cxx20-warning {{comparison between two arrays is deprecated}}
245 #if __cplusplus > 201703L
246   bool b5 = arr1 <=> arr2; // cxx20-error {{invalid operands}}
247 #endif
248 
249   int (&f())[3];
250   bool b6 = arr1 == f(); // cxx20-warning {{comparison between two arrays is deprecated}}
251   bool b7 = arr1 == +f();
252 }
253 
254 # 1 "/usr/include/system-header.h" 1 3
255 void system_header_function(void) throw();
256