1 | // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s |
2 | // RUN: %clang_cc1 -fsyntax-only -std=c++14 -Wc++98-compat -verify %s -DCXX14COMPAT |
3 | |
4 | namespace std { |
5 | struct type_info; |
6 | using size_t = decltype(sizeof(0)); // expected-warning {{decltype}} expected-warning {{alias}} |
7 | template<typename T> struct initializer_list { |
8 | initializer_list(T*, size_t); |
9 | T *p; |
10 | size_t n; |
11 | T *begin(); |
12 | T *end(); |
13 | }; |
14 | } |
15 | |
16 | template<typename ...T> // expected-warning {{variadic templates are incompatible with C++98}} |
17 | class Variadic1 {}; |
18 | |
19 | template<template<typename> class ...T> // expected-warning {{variadic templates are incompatible with C++98}} |
20 | class Variadic2 {}; |
21 | |
22 | template<int ...I> // expected-warning {{variadic templates are incompatible with C++98}} |
23 | class Variadic3 {}; |
24 | |
25 | alignas(8) int with_alignas; // expected-warning {{'alignas' is incompatible with C++98}} |
26 | int with_attribute [[ ]]; // expected-warning {{C++11 attribute syntax is incompatible with C++98}} |
27 | |
28 | void Literals() { |
29 | (void)u8"str"; // expected-warning {{unicode literals are incompatible with C++98}} |
30 | (void)u"str"; // expected-warning {{unicode literals are incompatible with C++98}} |
31 | (void)U"str"; // expected-warning {{unicode literals are incompatible with C++98}} |
32 | (void)u'x'; // expected-warning {{unicode literals are incompatible with C++98}} |
33 | (void)U'x'; // expected-warning {{unicode literals are incompatible with C++98}} |
34 | |
35 | (void)u8R"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} |
36 | (void)uR"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} |
37 | (void)UR"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} |
38 | (void)R"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} |
39 | (void)LR"X(str)X"; // expected-warning {{raw string literals are incompatible with C++98}} |
40 | } |
41 | |
42 | template<typename T> struct S {}; |
43 | namespace TemplateParsing { |
44 | S<::S<void> > s; // expected-warning {{'<::' is treated as digraph '<:' (aka '[') followed by ':' in C++98}} |
45 | S< ::S<void>> t; // expected-warning {{consecutive right angle brackets are incompatible with C++98 (use '> >')}} |
46 | } |
47 | |
48 | void Lambda() { |
49 | []{}(); // expected-warning {{lambda expressions are incompatible with C++98}} |
50 | // Don't warn about implicit "-> auto" here. |
51 | [](){}(); // expected-warning {{lambda expressions are incompatible with C++98}} |
52 | } |
53 | |
54 | struct Ctor { |
55 | Ctor(int, char); |
56 | Ctor(double, long); |
57 | }; |
58 | struct InitListCtor { |
59 | InitListCtor(std::initializer_list<bool>); |
60 | }; |
61 | |
62 | int InitList(int i = {}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} \ |
63 | // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} |
64 | (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \ |
65 | // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} |
66 | (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \ |
67 | // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} |
68 | int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} |
69 | S<int> s = {}; // ok, aggregate |
70 | s = {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} |
71 | std::initializer_list<int> xs = { 1, 2, 3 }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}} |
72 | auto ys = { 1, 2, 3 }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}} \ |
73 | // expected-warning {{'auto' type specifier is incompatible with C++98}} |
74 | Ctor c1 = { 1, 2 }; // expected-warning {{constructor call from initializer list is incompatible with C++98}} |
75 | Ctor c2 = { 3.0, 4l }; // expected-warning {{constructor call from initializer list is incompatible with C++98}} |
76 | InitListCtor ilc = { true, false }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}} |
77 | const int &r = { 0 }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}} |
78 | struct { int a; const int &r; } rr = { 0, {0} }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}} |
79 | return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}} expected-warning {{scalar}} |
80 | } |
81 | struct DelayedDefaultArgumentParseInitList { |
82 | void f(int i = {1}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} expected-warning {{scalar}} |
83 | } |
84 | }; |
85 | |
86 | int operator"" _hello(const char *); // expected-warning {{literal operators are incompatible with C++98}} |
87 | |
88 | enum EnumFixed : int { // expected-warning {{enumeration types with a fixed underlying type are incompatible with C++98}} |
89 | }; |
90 | |
91 | enum class EnumScoped { // expected-warning {{scoped enumerations are incompatible with C++98}} |
92 | }; |
93 | |
94 | void Deleted() = delete; // expected-warning {{deleted function definitions are incompatible with C++98}} |
95 | struct Defaulted { |
96 | Defaulted() = default; // expected-warning {{defaulted function definitions are incompatible with C++98}} |
97 | }; |
98 | |
99 | int &&RvalueReference = 0; // expected-warning {{rvalue references are incompatible with C++98}} |
100 | struct RefQualifier { |
101 | void f() &; // expected-warning {{reference qualifiers on functions are incompatible with C++98}} |
102 | }; |
103 | |
104 | auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}} |
105 | #ifdef CXX14COMPAT |
106 | auto ff() { return 5; } // expected-warning {{'auto' type specifier is incompatible with C++98}} |
107 | // expected-warning@-1 {{return type deduction is incompatible with C++ standards before C++14}} |
108 | #endif |
109 | |
110 | void RangeFor() { |
111 | int xs[] = {1, 2, 3}; |
112 | for (int &a : xs) { // expected-warning {{range-based for loop is incompatible with C++98}} |
113 | } |
114 | for (auto &b : {1, 2, 3}) { |
115 | // expected-warning@-1 {{range-based for loop is incompatible with C++98}} |
116 | // expected-warning@-2 {{'auto' type specifier is incompatible with C++98}} |
117 | // expected-warning@-3 {{initialization of initializer_list object is incompatible with C++98}} |
118 | // expected-warning@-4 {{reference initialized from initializer list is incompatible with C++98}} |
119 | } |
120 | struct Agg { int a, b; } const &agg = { 1, 2 }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}} |
121 | } |
122 | |
123 | struct InClassInit { |
124 | int n = 0; // expected-warning {{in-class initialization of non-static data members is incompatible with C++98}} |
125 | }; |
126 | |
127 | struct OverrideControlBase { |
128 | virtual void f(); |
129 | virtual void g(); |
130 | }; |
131 | struct OverrideControl final : OverrideControlBase { // expected-warning {{'final' keyword is incompatible with C++98}} |
132 | virtual void f() override; // expected-warning {{'override' keyword is incompatible with C++98}} |
133 | virtual void g() final; // expected-warning {{'final' keyword is incompatible with C++98}} |
134 | }; |
135 | |
136 | using AliasDecl = int; // expected-warning {{alias declarations are incompatible with C++98}} |
137 | template<typename T> using AliasTemplate = T; // expected-warning {{alias declarations are incompatible with C++98}} |
138 | |
139 | inline namespace InlineNS { // expected-warning {{inline namespaces are incompatible with C++98}} |
140 | } |
141 | |
142 | auto auto_deduction = 0; // expected-warning {{'auto' type specifier is incompatible with C++98}} |
143 | int *p = new auto(0); // expected-warning {{'auto' type specifier is incompatible with C++98}} |
144 | |
145 | const int align_of = alignof(int); // expected-warning {{alignof expressions are incompatible with C++98}} |
146 | char16_t c16 = 0; // expected-warning {{'char16_t' type specifier is incompatible with C++98}} |
147 | char32_t c32 = 0; // expected-warning {{'char32_t' type specifier is incompatible with C++98}} |
148 | constexpr int const_expr = 0; // expected-warning {{'constexpr' specifier is incompatible with C++98}} |
149 | decltype(const_expr) decl_type = 0; // expected-warning {{'decltype' type specifier is incompatible with C++98}} |
150 | __decltype(const_expr) decl_type2 = 0; // ok |
151 | void no_except() noexcept; // expected-warning {{noexcept specifications are incompatible with C++98}} |
152 | bool no_except_expr = noexcept(1 + 1); // expected-warning {{noexcept expressions are incompatible with C++98}} |
153 | void *null = nullptr; // expected-warning {{'nullptr' is incompatible with C++98}} |
154 | static_assert(true, "!"); // expected-warning {{static_assert declarations are incompatible with C++98}} |
155 | |
156 | struct InhCtorBase { |
157 | InhCtorBase(int); |
158 | }; |
159 | struct InhCtorDerived : InhCtorBase { |
160 | using InhCtorBase::InhCtorBase; // expected-warning {{inheriting constructors are incompatible with C++98}} |
161 | }; |
162 | |
163 | struct FriendMember { |
164 | static void MemberFn(); |
165 | friend void FriendMember::MemberFn(); // expected-warning {{friend declaration naming a member of the declaring class is incompatible with C++98}} |
166 | }; |
167 | |
168 | struct DelegCtor { |
169 | DelegCtor(int) : DelegCtor() {} // expected-warning {{delegating constructors are incompatible with C++98}} |
170 | DelegCtor(); |
171 | }; |
172 | |
173 | template<int n = 0> void DefaultFuncTemplateArg(); // expected-warning {{default template arguments for a function template are incompatible with C++98}} |
174 | |
175 | template<typename T> int TemplateFn(T) { return 0; } |
176 | void LocalTemplateArg() { |
177 | struct S {}; |
178 | TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}} |
179 | } |
180 | struct {} obj_of_unnamed_type; // expected-note {{here}} |
181 | int UnnamedTemplateArg = TemplateFn(obj_of_unnamed_type); // expected-warning {{unnamed type as template argument is incompatible with C++98}} |
182 | |
183 | namespace RedundantParensInAddressTemplateParam { |
184 | int n; |
185 | template<int*p> struct S {}; |
186 | S<(&n)> s; // expected-warning {{redundant parentheses surrounding address non-type template argument are incompatible with C++98}} |
187 | S<(((&n)))> t; // expected-warning {{redundant parentheses surrounding address non-type template argument are incompatible with C++98}} |
188 | } |
189 | |
190 | namespace TemplateSpecOutOfScopeNs { |
191 | template<typename T> struct S {}; |
192 | } |
193 | template<> struct TemplateSpecOutOfScopeNs::S<char> {}; |
194 | |
195 | struct Typename { |
196 | template<typename T> struct Inner {}; |
197 | }; |
198 | typename ::Typename TypenameOutsideTemplate(); // expected-warning {{use of 'typename' outside of a template is incompatible with C++98}} |
199 | Typename::template Inner<int> TemplateOutsideTemplate(); // expected-warning {{use of 'template' keyword outside of a template is incompatible with C++98}} |
200 | |
201 | struct TrivialButNonPOD { |
202 | int f(int); |
203 | private: |
204 | int k; |
205 | }; |
206 | void Ellipsis(int n, ...); |
207 | void TrivialButNonPODThroughEllipsis() { |
208 | Ellipsis(1, TrivialButNonPOD()); // expected-warning {{passing object of trivial but non-POD type 'TrivialButNonPOD' through variadic function is incompatible with C++98}} |
209 | } |
210 | |
211 | struct HasExplicitConversion { |
212 | explicit operator bool(); // expected-warning {{explicit conversion functions are incompatible with C++98}} |
213 | }; |
214 | |
215 | struct Struct {}; |
216 | enum Enum { enum_val = 0 }; |
217 | struct BadFriends { |
218 | friend enum ::Enum; // expected-warning {{befriending enumeration type 'enum ::Enum' is incompatible with C++98}} |
219 | friend int; // expected-warning {{non-class friend type 'int' is incompatible with C++98}} |
220 | friend Struct; // expected-warning {{befriending 'Struct' without 'struct' keyword is incompatible with C++98}} |
221 | }; |
222 | |
223 | int n = {}; // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}} |
224 | |
225 | class PrivateMember { |
226 | struct ImPrivate {}; |
227 | }; |
228 | template<typename T> typename T::ImPrivate SFINAEAccessControl(T t) { // expected-warning {{substitution failure due to access control is incompatible with C++98}} |
229 | return typename T::ImPrivate(); |
230 | } |
231 | int SFINAEAccessControl(...) { return 0; } |
232 | int CheckSFINAEAccessControl = SFINAEAccessControl(PrivateMember()); // expected-note {{while substituting deduced template arguments into function template 'SFINAEAccessControl' [with T = PrivateMember]}} |
233 | |
234 | namespace UnionOrAnonStructMembers { |
235 | struct NonTrivCtor { |
236 | NonTrivCtor(); // expected-note 2{{user-provided default constructor}} |
237 | }; |
238 | struct NonTrivCopy { |
239 | NonTrivCopy(const NonTrivCopy&); // expected-note 2{{user-provided copy constructor}} |
240 | }; |
241 | struct NonTrivDtor { |
242 | ~NonTrivDtor(); // expected-note 2{{user-provided destructor}} |
243 | }; |
244 | union BadUnion { |
245 | NonTrivCtor ntc; // expected-warning {{union member 'ntc' with a non-trivial default constructor is incompatible with C++98}} |
246 | NonTrivCopy ntcp; // expected-warning {{union member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}} |
247 | NonTrivDtor ntd; // expected-warning {{union member 'ntd' with a non-trivial destructor is incompatible with C++98}} |
248 | }; |
249 | struct Wrap { |
250 | struct { |
251 | NonTrivCtor ntc; // expected-warning {{anonymous struct member 'ntc' with a non-trivial default constructor is incompatible with C++98}} |
252 | NonTrivCopy ntcp; // expected-warning {{anonymous struct member 'ntcp' with a non-trivial copy constructor is incompatible with C++98}} |
253 | NonTrivDtor ntd; // expected-warning {{anonymous struct member 'ntd' with a non-trivial destructor is incompatible with C++98}} |
254 | }; |
255 | }; |
256 | union WithStaticDataMember { |
257 | static constexpr double d = 0.0; // expected-warning {{static data member 'd' in union is incompatible with C++98}} expected-warning {{'constexpr' specifier is incompatible with C++98}} |
258 | static const int n = 0; // expected-warning {{static data member 'n' in union is incompatible with C++98}} |
259 | static int k; // expected-warning {{static data member 'k' in union is incompatible with C++98}} |
260 | }; |
261 | } |
262 | |
263 | int EnumNNS = Enum::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}} |
264 | template<typename T> void EnumNNSFn() { |
265 | int k = T::enum_val; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}} |
266 | }; |
267 | template void EnumNNSFn<Enum>(); // expected-note {{in instantiation}} |
268 | |
269 | void JumpDiagnostics(int n) { |
270 | goto DirectJump; // expected-warning {{jump from this goto statement to its label is incompatible with C++98}} |
271 | TrivialButNonPOD tnp1; // expected-note {{jump bypasses initialization of non-POD variable}} |
272 | |
273 | DirectJump: |
274 | void *Table[] = {&&DirectJump, &&Later}; |
275 | goto *Table[n]; // expected-warning {{jump from this indirect goto statement to one of its possible targets is incompatible with C++98}} |
276 | |
277 | TrivialButNonPOD tnp2; // expected-note {{jump bypasses initialization of non-POD variable}} |
278 | Later: // expected-note {{possible target of indirect goto statement}} |
279 | switch (n) { |
280 | TrivialButNonPOD tnp3; // expected-note {{jump bypasses initialization of non-POD variable}} |
281 | default: // expected-warning {{jump from switch statement to this case label is incompatible with C++98}} |
282 | return; |
283 | } |
284 | } |
285 | |
286 | namespace UnevaluatedMemberAccess { |
287 | struct S { |
288 | int n; |
289 | int f() { return sizeof(S::n); } // ok |
290 | }; |
291 | int k = sizeof(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}} |
292 | const std::type_info &ti = typeid(S::n); // expected-warning {{use of non-static data member 'n' in an unevaluated context is incompatible with C++98}} |
293 | } |
294 | |
295 | namespace LiteralUCNs { |
296 | char c1 = '\u001e'; // expected-warning {{universal character name referring to a control character is incompatible with C++98}} |
297 | wchar_t c2 = L'\u0041'; // expected-warning {{specifying character 'A' with a universal character name is incompatible with C++98}} |
298 | const char *s1 = "foo\u0031"; // expected-warning {{specifying character '1' with a universal character name is incompatible with C++98}} |
299 | const wchar_t *s2 = L"bar\u0085"; // expected-warning {{universal character name referring to a control character is incompatible with C++98}} |
300 | } |
301 | |
302 | namespace NonTypeTemplateArgs { |
303 | template<typename T, T v> struct S {}; |
304 | const int k = 5; // expected-note {{here}} |
305 | static void f() {} // expected-note {{here}} |
306 | S<const int&, k> s1; // expected-warning {{non-type template argument referring to object 'k' with internal linkage is incompatible with C++98}} |
307 | S<void(&)(), f> s2; // expected-warning {{non-type template argument referring to function 'f' with internal linkage is incompatible with C++98}} |
308 | } |
309 | |
310 | namespace NullPointerTemplateArg { |
311 | struct A {}; |
312 | template<int*> struct X {}; |
313 | template<int A::*> struct Y {}; |
314 | X<(int*)0> x; // expected-warning {{use of null pointer as non-type template argument is incompatible with C++98}} |
315 | Y<(int A::*)0> y; // expected-warning {{use of null pointer as non-type template argument is incompatible with C++98}} |
316 | } |
317 | |
318 | namespace PR13480 { |
319 | struct basic_iterator { |
320 | basic_iterator(const basic_iterator &it) {} // expected-note {{because type 'PR13480::basic_iterator' has a user-provided copy constructor}} |
321 | basic_iterator(basic_iterator &it) {} |
322 | }; |
323 | |
324 | union test { |
325 | basic_iterator it; // expected-warning {{union member 'it' with a non-trivial copy constructor is incompatible with C++98}} |
326 | }; |
327 | } |
328 | |
329 | namespace AssignOpUnion { |
330 | struct a { |
331 | void operator=(const a &it) {} // expected-note {{because type 'AssignOpUnion::a' has a user-provided copy assignment operator}} |
332 | void operator=(a &it) {} |
333 | }; |
334 | |
335 | struct b { |
336 | void operator=(const b &it) {} // expected-note {{because type 'AssignOpUnion::b' has a user-provided copy assignment operator}} |
337 | }; |
338 | |
339 | union test1 { |
340 | a x; // expected-warning {{union member 'x' with a non-trivial copy assignment operator is incompatible with C++98}} |
341 | b y; // expected-warning {{union member 'y' with a non-trivial copy assignment operator is incompatible with C++98}} |
342 | }; |
343 | } |
344 | |
345 | namespace rdar11736429 { |
346 | struct X { // expected-note {{because type 'rdar11736429::X' has no default constructor}} |
347 | X(const X&) = delete; // expected-warning{{deleted function definitions are incompatible with C++98}} \ |
348 | // expected-note {{implicit default constructor suppressed by user-declared constructor}} |
349 | }; |
350 | |
351 | union S { |
352 | X x; // expected-warning{{union member 'x' with a non-trivial default constructor is incompatible with C++98}} |
353 | }; |
354 | } |
355 | |
356 | template<typename T> T var = T(10); |
357 | #ifdef CXX14COMPAT |
358 | // expected-warning@-2 {{variable templates are incompatible with C++ standards before C++14}} |
359 | #else |
360 | // expected-warning@-4 {{variable templates are a C++14 extension}} |
361 | #endif |
362 | |
363 | // No diagnostic for specializations of variable templates; we will have |
364 | // diagnosed the primary template. |
365 | template<typename T> T* var<T*> = new T(); |
366 | template<> int var<int> = 10; |
367 | template char var<char>; |
368 | float fvar = var<float>; |
369 | |
370 | class A { |
371 | template<typename T> static T var = T(10); |
372 | #ifdef CXX14COMPAT |
373 | // expected-warning@-2 {{variable templates are incompatible with C++ standards before C++14}} |
374 | #else |
375 | // expected-warning@-4 {{variable templates are a C++14 extension}} |
376 | #endif |
377 | |
378 | template<typename T> static T* var<T*> = new T(); |
379 | }; |
380 | |
381 | struct B { template<typename T> static T v; }; |
382 | #ifdef CXX14COMPAT |
383 | // expected-warning@-2 {{variable templates are incompatible with C++ standards before C++14}} |
384 | #else |
385 | // expected-warning@-4 {{variable templates are a C++14 extension}} |
386 | #endif |
387 | |
388 | template<typename T> T B::v = T(); |
389 | #ifdef CXX14COMPAT |
390 | // expected-warning@-2 {{variable templates are incompatible with C++ standards before C++14}} |
391 | #else |
392 | // expected-warning@-4 {{variable templates are a C++14 extension}} |
393 | #endif |
394 | |
395 | template<typename T> T* B::v<T*> = new T(); |
396 | template<> int B::v<int> = 10; |
397 | template char B::v<char>; |
398 | float fsvar = B::v<float>; |
399 | |
400 | #ifdef CXX14COMPAT |
401 | int digit_seps = 123'456; // expected-warning {{digit separators are incompatible with C++ standards before C++14}} |
402 | #endif |
403 | |