xref: /llvm-project/clang/test/SemaCXX/attr-trivial-abi.cpp (revision 0342bbf223fa12701a0570a23f9eac433b8b341c)
1 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
2 
3 void __attribute__((trivial_abi)) foo(); // expected-warning {{'trivial_abi' attribute only applies to classes}}
4 
5 // Should not crash.
6 template <class>
7 class __attribute__((trivial_abi)) a { a(a &&); };
8 #if defined(_WIN64) && !defined(__MINGW32__)
9 // On Windows/MSVC, to be trivial-for-calls, an object must be trivially copyable.
10 // (And it is only trivially relocatable, currently, if it is trivial for calls.)
11 // In this case, it is suppressed by an explicitly defined move constructor.
12 // Similar concerns apply to later tests that have #if defined(_WIN64) && !defined(__MINGW32__)
13 static_assert(!__is_trivially_relocatable(a<int>), "");
14 #else
15 static_assert(__is_trivially_relocatable(a<int>), "");
16 #endif
17 
18 struct [[clang::trivial_abi]] S0 {
19   int a;
20 };
21 static_assert(__is_trivially_relocatable(S0), "");
22 
23 struct __attribute__((trivial_abi)) S1 {
24   int a;
25 };
26 static_assert(__is_trivially_relocatable(S1), "");
27 
28 struct __attribute__((trivial_abi)) S3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3'}} expected-note {{is polymorphic}}
29   virtual void m();
30 };
31 static_assert(!__is_trivially_relocatable(S3), "");
32 
33 struct S3_2 {
34   virtual void m();
35 } __attribute__((trivial_abi)); // expected-warning {{'trivial_abi' cannot be applied to 'S3_2'}} expected-note {{is polymorphic}}
36 static_assert(!__is_trivially_relocatable(S3_2), "");
37 
38 struct __attribute__((trivial_abi)) S3_3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3_3'}} expected-note {{has a field of a non-trivial class type}}
39   S3_3(S3_3 &&);
40   S3_2 s32;
41 };
42 #ifdef __ORBIS__
43 // The ClangABI4OrPS4 calling convention kind passes classes in registers if the
44 // copy constructor is trivial for calls *or deleted*, while other platforms do
45 // not accept deleted constructors.
46 static_assert(__is_trivially_relocatable(S3_3), "");
47 #else
48 static_assert(!__is_trivially_relocatable(S3_3), "");
49 #endif
50 
51 // Diagnose invalid trivial_abi even when the type is templated because it has a non-trivial field.
52 template <class T>
53 struct __attribute__((trivial_abi)) S3_4 { // expected-warning {{'trivial_abi' cannot be applied to 'S3_4'}} expected-note {{has a field of a non-trivial class type}}
54   S3_4(S3_4 &&);
55   S3_2 s32;
56 };
57 static_assert(!__is_trivially_relocatable(S3_4<int>), "");
58 
59 struct S4 {
60   int a;
61 };
62 static_assert(__is_trivially_relocatable(S4), "");
63 
64 struct __attribute__((trivial_abi)) S5 : public virtual S4 { // expected-warning {{'trivial_abi' cannot be applied to 'S5'}} expected-note {{has a virtual base}}
65 };
66 static_assert(!__is_trivially_relocatable(S5), "");
67 
68 struct __attribute__((trivial_abi)) S9 : public S4 {
69 };
70 static_assert(__is_trivially_relocatable(S9), "");
71 
72 struct __attribute__((trivial_abi(1))) S8 { // expected-error {{'trivial_abi' attribute takes no arguments}}
73   int a;
74 };
75 
76 // Do not warn about deleted ctors  when 'trivial_abi' is used to annotate a template class.
77 template <class T>
78 struct __attribute__((trivial_abi)) S10 {
79   T p;
80 };
81 
82 S10<int *> p1;
83 static_assert(__is_trivially_relocatable(S10<int>), "");
84 static_assert(!__is_trivially_relocatable(S10<S3>), "");
85 
86 template <class T>
87 struct S14 {
88   T a;
89 };
90 
91 template <class T>
92 struct __attribute__((trivial_abi)) S15 : S14<T> {
93 };
94 
95 S15<int> s15;
96 static_assert(__is_trivially_relocatable(S15<int>), "");
97 static_assert(!__is_trivially_relocatable(S15<S3>), "");
98 
99 template <class T>
100 struct __attribute__((trivial_abi)) S16 {
101   S14<T> a;
102 };
103 static_assert(__is_trivially_relocatable(S16<int>), "");
104 static_assert(!__is_trivially_relocatable(S16<S3>), "");
105 
106 S16<int> s16;
107 
108 template <class T>
109 struct __attribute__((trivial_abi)) S17 {
110 };
111 
112 S17<int> s17;
113 static_assert(__is_trivially_relocatable(S17<int>), "");
114 static_assert(__is_trivially_relocatable(S17<S3>), "");
115 
116 namespace deletedCopyMoveConstructor {
117 struct __attribute__((trivial_abi)) CopyMoveDeleted { // expected-warning {{'trivial_abi' cannot be applied to 'CopyMoveDeleted'}} expected-note {{copy constructors and move constructors are all deleted}}
118   CopyMoveDeleted(const CopyMoveDeleted &) = delete;
119   CopyMoveDeleted(CopyMoveDeleted &&) = delete;
120 };
121 #ifdef __ORBIS__
122 static_assert(__is_trivially_relocatable(CopyMoveDeleted), "");
123 #else
124 static_assert(!__is_trivially_relocatable(CopyMoveDeleted), "");
125 #endif
126 
127 struct __attribute__((trivial_abi)) S18 { // expected-warning {{'trivial_abi' cannot be applied to 'S18'}} expected-note {{copy constructors and move constructors are all deleted}}
128   CopyMoveDeleted a;
129 };
130 #ifdef __ORBIS__
131 static_assert(__is_trivially_relocatable(S18), "");
132 #else
133 static_assert(!__is_trivially_relocatable(S18), "");
134 #endif
135 
136 struct __attribute__((trivial_abi)) CopyDeleted {
137   CopyDeleted(const CopyDeleted &) = delete;
138   CopyDeleted(CopyDeleted &&) = default;
139 };
140 #if defined(_WIN64) && !defined(__MINGW32__)
141 static_assert(!__is_trivially_relocatable(CopyDeleted), "");
142 #else
143 static_assert(__is_trivially_relocatable(CopyDeleted), "");
144 #endif
145 
146 struct __attribute__((trivial_abi)) MoveDeleted {
147   MoveDeleted(const MoveDeleted &) = default;
148   MoveDeleted(MoveDeleted &&) = delete;
149 };
150 static_assert(__is_trivially_relocatable(MoveDeleted), "");
151 
152 struct __attribute__((trivial_abi)) S19 { // expected-warning {{'trivial_abi' cannot be applied to 'S19'}} expected-note {{copy constructors and move constructors are all deleted}}
153   CopyDeleted a;
154   MoveDeleted b;
155 };
156 #ifdef __ORBIS__
157 static_assert(__is_trivially_relocatable(S19), "");
158 #else
159 static_assert(!__is_trivially_relocatable(S19), "");
160 #endif
161 
162 // This is fine since the move constructor isn't deleted.
163 struct __attribute__((trivial_abi)) S20 {
164   int &&a; // a member of rvalue reference type deletes the copy constructor.
165 };
166 #if defined(_WIN64) && !defined(__MINGW32__)
167 static_assert(!__is_trivially_relocatable(S20), "");
168 #else
169 static_assert(__is_trivially_relocatable(S20), "");
170 #endif
171 } // namespace deletedCopyMoveConstructor
172