1 // RUN: %clang_cc1 -DNO_DTORS -DNO_EXCEPTIONS -fno-c++-static-destructors -verify %s
2 // RUN: %clang_cc1 -DNO_EXCEPTIONS -verify %s
3 // RUN: %clang_cc1 -DNO_DTORS -fexceptions -fno-c++-static-destructors -verify %s
4 // RUN: %clang_cc1 -fexceptions -verify %s
5 
6 struct SecretDestructor {
7 #ifndef NO_DTORS
8   // expected-note@+2 4 {{private}}
9 #endif
10 private: ~SecretDestructor(); // expected-note + {{private}}
11 };
12 
13 SecretDestructor sd1;
14 thread_local SecretDestructor sd2;
locals()15 void locals() {
16   static SecretDestructor sd3;
17   thread_local SecretDestructor sd4;
18 }
19 
20 #ifndef NO_DTORS
21 // SecretDestructor sd1;                  // expected-error@-8 {{private}}
22 // thread_local SecretDestructor sd2;     // expected-error@-8 {{private}}
23 // void locals() {
24 //   static SecretDestructor sd3;         // expected-error@-8 {{private}}
25 //   thread_local SecretDestructor sd4;   // expected-error@-8 {{private}}
26 // }
27 #endif
28 
29 [[clang::always_destroy]] SecretDestructor sd6; // expected-error{{private}}
30 [[clang::always_destroy]] thread_local SecretDestructor sd7; // expected-error{{private}}
31 
32 [[clang::no_destroy]] SecretDestructor sd8;
33 
main()34 int main() {
35   [[clang::no_destroy]] int p; // expected-error{{no_destroy attribute can only be applied to a variable with static or thread storage duration}}
36   [[clang::always_destroy]] int p2; // expected-error{{always_destroy attribute can only be applied to a variable with static or thread storage duration}}
37   [[clang::no_destroy]] static int p3;
38   [[clang::always_destroy]] static int p4;
39 }
40 
41 [[clang::always_destroy]] [[clang::no_destroy]] int p; // expected-error{{'no_destroy' and 'always_destroy' attributes are not compatible}} // expected-note{{here}}
42 [[clang::no_destroy]] [[clang::always_destroy]] int p2; // expected-error{{'always_destroy' and 'no_destroy' attributes are not compatible}} // expected-note{{here}}
43 
f()44 [[clang::always_destroy]] void f() {} // expected-warning{{'always_destroy' attribute only applies to variables}}
45 struct [[clang::no_destroy]] DoesntApply {};  // expected-warning{{'no_destroy' attribute only applies to variables}}
46 
47 [[clang::no_destroy(0)]] int no_args; // expected-error{{'no_destroy' attribute takes no arguments}}
48 [[clang::always_destroy(0)]] int no_args2; // expected-error{{'always_destroy' attribute takes no arguments}}
49 
50 // expected-error@+1 {{temporary of type 'SecretDestructor' has private destructor}}
51 SecretDestructor arr[10];
52 
local_arrays()53 void local_arrays() {
54   // expected-error@+1 {{temporary of type 'SecretDestructor' has private destructor}}
55   static SecretDestructor arr2[10];
56   // expected-error@+1 {{temporary of type 'SecretDestructor' has private destructor}}
57   thread_local SecretDestructor arr3[10];
58 }
59 
60 struct Base {
61   ~Base();
62 };
63 struct Derived1 {
64   Derived1(int);
65   Base b;
66 };
67 struct Derived2 {
68   Derived1 b;
69 };
70 
dontcrash()71 void dontcrash() {
72   [[clang::no_destroy]] static Derived2 d2[] = {0, 0};
73 }
74 
75 [[clang::no_destroy]] Derived2 d2[] = {0, 0};
76