[clang-cl] Ignore /Wv and /Wv:17 flags
[llvm-project.git] / clang / test / SemaCXX / attr-musttail.cpp
blob561184e7a24f9482b51e64862ea2a38bd4418a0b
1 // RUN: %clang_cc1 -verify -fsyntax-only -fms-extensions -fcxx-exceptions -fopenmp -triple x86_64-linux %s
3 int ReturnsInt1();
4 int Func1() {
5 [[clang::musttail]] ReturnsInt1(); // expected-error {{'musttail' attribute only applies to return statements}}
6 [[clang::musttail(1, 2)]] return ReturnsInt1(); // expected-error {{'musttail' attribute takes no arguments}}
7 [[clang::musttail]] return 5; // expected-error {{'musttail' attribute requires that the return value is the result of a function call}}
8 [[clang::musttail]] return ReturnsInt1();
11 void NoFunctionCall() {
12 [[clang::musttail]] return; // expected-error {{'musttail' attribute requires that the return value is the result of a function call}}
15 [[clang::musttail]] static int int_val = ReturnsInt1(); // expected-error {{'musttail' attribute cannot be applied to a declaration}}
17 void NoParams(); // expected-note {{target function has different number of parameters (expected 1 but has 0)}}
18 void TestParamArityMismatch(int x) {
19 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
20 return NoParams(); // expected-error {{cannot perform a tail call to function 'NoParams' because its signature is incompatible with the calling function}}
23 void LongParam(long x); // expected-note {{target function has type mismatch at 1st parameter (expected 'long' but has 'int')}}
24 void TestParamTypeMismatch(int x) {
25 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
26 return LongParam(x); // expected-error {{cannot perform a tail call to function 'LongParam' because its signature is incompatible with the calling function}}
29 long ReturnsLong(); // expected-note {{target function has different return type ('int' expected but has 'long')}}
30 int TestReturnTypeMismatch() {
31 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
32 return ReturnsLong(); // expected-error {{cannot perform a tail call to function 'ReturnsLong' because its signature is incompatible with the calling function}}
35 struct Struct1 {
36 void MemberFunction(); // expected-note {{'MemberFunction' declared here}}
38 void TestNonMemberToMember() {
39 Struct1 st;
40 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
41 return st.MemberFunction(); // expected-error {{non-member function cannot perform a tail call to non-static member function 'MemberFunction'}}
44 void ReturnsVoid(); // expected-note {{'ReturnsVoid' declared here}}
45 struct Struct2 {
46 void TestMemberToNonMember() {
47 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
48 return ReturnsVoid(); // expected-error{{non-static member function cannot perform a tail call to non-member function 'ReturnsVoid'}}
52 class HasNonTrivialDestructor {
53 public:
54 ~HasNonTrivialDestructor() {}
55 int ReturnsInt();
58 void ReturnsVoid2();
59 void TestNonTrivialDestructorInScope() {
60 HasNonTrivialDestructor foo; // expected-note {{jump exits scope of variable with non-trivial destructor}}
61 [[clang::musttail]] return ReturnsVoid(); // expected-error {{cannot perform a tail call from this return statement}}
64 int NonTrivialParam(HasNonTrivialDestructor x);
65 int TestNonTrivialParam(HasNonTrivialDestructor x) {
66 [[clang::musttail]] return NonTrivialParam(x); // expected-error {{tail call requires that the return value, all parameters, and any temporaries created by the expression are trivially destructible}}
69 HasNonTrivialDestructor ReturnsNonTrivialValue();
70 HasNonTrivialDestructor TestReturnsNonTrivialValue() {
71 // FIXME: the diagnostic cannot currently distinguish between needing to run a
72 // destructor for the return value and needing to run a destructor for some
73 // other temporary created in the return statement.
74 [[clang::musttail]] return (ReturnsNonTrivialValue()); // expected-error {{tail call requires that the return value, all parameters, and any temporaries created by the expression are trivially destructible}}
77 HasNonTrivialDestructor TestReturnsNonTrivialNonFunctionCall() {
78 [[clang::musttail]] return HasNonTrivialDestructor(); // expected-error {{'musttail' attribute requires that the return value is the result of a function call}}
81 struct UsesPointerToMember {
82 void (UsesPointerToMember::*p_mem)(); // expected-note {{'p_mem' declared here}}
84 void TestUsesPointerToMember(UsesPointerToMember *foo) {
85 // "this" pointer cannot double as first parameter.
86 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
87 return (foo->*(foo->p_mem))(); // expected-error {{non-member function cannot perform a tail call to pointer-to-member function 'p_mem'}}
90 void ReturnsVoid2();
91 void TestNestedClass() {
92 HasNonTrivialDestructor foo;
93 class Nested {
94 __attribute__((noinline)) static void NestedMethod() {
95 // Outer non-trivial destructor does not affect nested class.
96 [[clang::musttail]] return ReturnsVoid2();
101 template <class T>
102 T TemplateFunc(T x) { // expected-note{{target function has different return type ('long' expected but has 'int')}}
103 return x ? 5 : 10;
105 int OkTemplateFunc(int x) {
106 [[clang::musttail]] return TemplateFunc<int>(x);
108 template <class T>
109 T BadTemplateFunc(T x) {
110 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
111 return TemplateFunc<int>(x); // expected-error {{cannot perform a tail call to function 'TemplateFunc' because its signature is incompatible with the calling function}}
113 long TestBadTemplateFunc(long x) {
114 return BadTemplateFunc<long>(x); // expected-note {{in instantiation of}}
117 void IntParam(int x);
118 void TestVLA(int x) {
119 HasNonTrivialDestructor vla[x]; // expected-note {{jump exits scope of variable with non-trivial destructor}}
120 [[clang::musttail]] return IntParam(x); // expected-error {{cannot perform a tail call from this return statement}}
123 void TestNonTrivialDestructorSubArg(int x) {
124 [[clang::musttail]] return IntParam(NonTrivialParam(HasNonTrivialDestructor())); // expected-error {{tail call requires that the return value, all parameters, and any temporaries created by the expression are trivially destructible}}
127 void VariadicFunction(int x, ...);
128 void TestVariadicFunction(int x, ...) {
129 [[clang::musttail]] return VariadicFunction(x); // expected-error {{'musttail' attribute may not be used with variadic functions}}
132 int TakesIntParam(int x); // expected-note {{target function has type mismatch at 1st parameter (expected 'int' but has 'short')}}
133 int TakesShortParam(short x); // expected-note {{target function has type mismatch at 1st parameter (expected 'short' but has 'int')}}
134 int TestIntParamMismatch(int x) {
135 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
136 return TakesShortParam(x); // expected-error {{cannot perform a tail call to function 'TakesShortParam' because its signature is incompatible with the calling function}}
138 int TestIntParamMismatch2(short x) {
139 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
140 return TakesIntParam(x); // expected-error {{cannot perform a tail call to function 'TakesIntParam' because its signature is incompatible with the calling function}}
143 struct TestClassMismatch1 {
144 void ToFunction(); // expected-note{{target function is a member of different class (expected 'TestClassMismatch2' but has 'TestClassMismatch1')}}
146 TestClassMismatch1 *tcm1;
147 struct TestClassMismatch2 {
148 void FromFunction() {
149 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
150 return tcm1->ToFunction(); // expected-error {{cannot perform a tail call to function 'ToFunction' because its signature is incompatible with the calling function}}
154 __regcall int RegCallReturnsInt(); // expected-note {{target function has calling convention regcall (expected cdecl)}}
155 int TestMismatchCallingConvention() {
156 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
157 return RegCallReturnsInt(); // expected-error {{cannot perform a tail call to function 'RegCallReturnsInt' because it uses an incompatible calling convention}}
160 int TestNonCapturingLambda() {
161 auto lambda = []() { return 12; }; // expected-note {{'operator()' declared here}}
162 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
163 return lambda(); // expected-error {{non-member function cannot perform a tail call to non-static member function 'operator()'}}
165 // This works.
166 auto lambda_fptr = static_cast<int (*)()>(lambda);
167 [[clang::musttail]] return lambda_fptr();
168 [[clang::musttail]] return (+lambda)();
171 int TestCapturingLambda() {
172 int x;
173 auto lambda = [x]() { return 12; }; // expected-note {{'operator()' declared here}}
174 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
175 return lambda(); // expected-error {{non-member function cannot perform a tail call to non-static member function 'operator()'}}
178 int TestNonTrivialTemporary(int) {
179 [[clang::musttail]] return TakesIntParam(HasNonTrivialDestructor().ReturnsInt()); // expected-error {{tail call requires that the return value, all parameters, and any temporaries created by the expression are trivially destructible}}
182 void ReturnsVoid();
183 struct TestDestructor {
184 ~TestDestructor() {
185 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
186 return ReturnsVoid(); // expected-error {{destructor '~TestDestructor' must not return void expression}} // expected-error {{cannot perform a tail call from a destructor}}
190 struct ClassWithDestructor { // expected-note {{target destructor is declared here}}
191 void TestExplicitDestructorCall() {
192 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
193 return this->~ClassWithDestructor(); // expected-error {{cannot perform a tail call to a destructor}}
197 struct HasNonTrivialCopyConstructor {
198 HasNonTrivialCopyConstructor(const HasNonTrivialCopyConstructor &);
200 HasNonTrivialCopyConstructor ReturnsClassByValue();
201 HasNonTrivialCopyConstructor TestNonElidableCopyConstructor() {
202 // This is an elidable constructor, but when it is written explicitly
203 // we decline to elide it.
204 [[clang::musttail]] return HasNonTrivialCopyConstructor(ReturnsClassByValue()); // expected-error{{'musttail' attribute requires that the return value is the result of a function call}}
207 struct ClassWithConstructor {
208 ClassWithConstructor() = default; // expected-note {{target constructor is declared here}}
210 void TestExplicitConstructorCall(ClassWithConstructor a) {
211 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
212 return a.ClassWithConstructor::ClassWithConstructor(); // expected-error{{cannot perform a tail call to a constructor}} expected-warning{{explicit constructor calls are a Microsoft extension}}
215 void TestStatementExpression() {
217 HasNonTrivialDestructor foo; // expected-note {{jump exits scope of variable with non-trivial destructor}}
218 [[clang::musttail]] return ReturnsVoid2(); // expected-error {{cannot perform a tail call from this return statement}}
222 struct MyException {};
223 void TestTryBlock() {
224 try { // expected-note {{jump exits try block}}
225 [[clang::musttail]] return ReturnsVoid2(); // expected-error {{cannot perform a tail call from this return statement}}
226 } catch (MyException &e) {
230 using IntFunctionType = int();
231 IntFunctionType *ReturnsIntFunction();
232 long TestRValueFunctionPointer() {
233 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
234 return ReturnsIntFunction()(); // expected-error{{cannot perform a tail call to function because its signature is incompatible with the calling function}} // expected-note{{target function has different return type ('long' expected but has 'int')}}
237 void TestPseudoDestructor() {
238 int n;
239 using T = int;
240 [[clang::musttail]] // expected-note {{tail call required by 'musttail' attribute here}}
241 return n.~T(); // expected-error{{cannot perform a tail call to a destructor}}
244 struct StructPMF {
245 typedef void (StructPMF::*PMF)();
246 static void TestReturnsPMF();
249 StructPMF *St;
250 StructPMF::PMF ReturnsPMF();
251 void StructPMF::TestReturnsPMF() {
252 [[clang::musttail]] // expected-note{{tail call required by 'musttail' attribute here}}
253 return (St->*ReturnsPMF())(); // expected-error{{static member function cannot perform a tail call to pointer-to-member function}}
256 // These tests are merely verifying that we don't crash with incomplete or
257 // erroneous ASTs. These cases crashed the compiler in early iterations.
259 struct TestBadPMF {
260 int (TestBadPMF::*pmf)();
261 void BadPMF() {
262 [[clang::musttail]] return ((*this)->*pmf)(); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'TestBadPMF'}}
266 namespace ns {}
267 void TestCallNonValue() {
268 [[clang::musttail]] return ns; // expected-error {{unexpected namespace name 'ns': expected expression}}