1 // RUN: %clang_cc1 -verify -fsyntax-only -fms-extensions -fcxx-exceptions -fopenmp -triple x86_64-linux %s
2 
3 int ReturnsInt1();
Func1()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();
9 }
10 
NoFunctionCall()11 void NoFunctionCall() {
12   [[clang::musttail]] return; // expected-error {{'musttail' attribute requires that the return value is the result of a function call}}
13 }
14 
15 [[clang::musttail]] static int int_val = ReturnsInt1(); // expected-error {{'musttail' attribute cannot be applied to a declaration}}
16 
17 void NoParams(); // expected-note {{target function has different number of parameters (expected 1 but has 0)}}
TestParamArityMismatch(int x)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}}
21 }
22 
23 void LongParam(long x); // expected-note {{target function has type mismatch at 1st parameter (expected 'long' but has 'int')}}
TestParamTypeMismatch(int x)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}}
27 }
28 
29 long ReturnsLong(); // expected-note {{target function has different return type ('int' expected but has 'long')}}
TestReturnTypeMismatch()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}}
33 }
34 
35 struct Struct1 {
36   void MemberFunction(); // expected-note {{'MemberFunction' declared here}}
37 };
TestNonMemberToMember()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'}}
42 }
43 
44 void ReturnsVoid(); // expected-note {{'ReturnsVoid' declared here}}
45 struct Struct2 {
TestMemberToNonMemberStruct246   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'}}
49   }
50 };
51 
52 class HasNonTrivialDestructor {
53 public:
~HasNonTrivialDestructor()54   ~HasNonTrivialDestructor() {}
55   int ReturnsInt();
56 };
57 
58 void ReturnsVoid2();
TestNonTrivialDestructorInScope()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}}
62 }
63 
64 int NonTrivialParam(HasNonTrivialDestructor x);
TestNonTrivialParam(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}}
67 }
68 
69 HasNonTrivialDestructor ReturnsNonTrivialValue();
TestReturnsNonTrivialValue()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}}
75 }
76 
TestReturnsNonTrivialNonFunctionCall()77 HasNonTrivialDestructor TestReturnsNonTrivialNonFunctionCall() {
78   [[clang::musttail]] return HasNonTrivialDestructor(); // expected-error {{'musttail' attribute requires that the return value is the result of a function call}}
79 }
80 
81 struct UsesPointerToMember {
82   void (UsesPointerToMember::*p_mem)(); // expected-note {{'p_mem' declared here}}
83 };
TestUsesPointerToMember(UsesPointerToMember * foo)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'}}
88 }
89 
90 void ReturnsVoid2();
TestNestedClass()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();
97     }
98   };
99 }
100 
101 template <class T>
TemplateFunc(T x)102 T TemplateFunc(T x) { // expected-note{{target function has different return type ('long' expected but has 'int')}}
103   return x ? 5 : 10;
104 }
OkTemplateFunc(int x)105 int OkTemplateFunc(int x) {
106   [[clang::musttail]] return TemplateFunc<int>(x);
107 }
108 template <class T>
BadTemplateFunc(T x)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}}
112 }
TestBadTemplateFunc(long x)113 long TestBadTemplateFunc(long x) {
114   return BadTemplateFunc<long>(x); // expected-note {{in instantiation of}}
115 }
116 
117 void IntParam(int x);
TestVLA(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}}
121 }
122 
TestNonTrivialDestructorSubArg(int x)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}}
125 }
126 
127 void VariadicFunction(int x, ...);
TestVariadicFunction(int x,...)128 void TestVariadicFunction(int x, ...) {
129   [[clang::musttail]] return VariadicFunction(x); // expected-error {{'musttail' attribute may not be used with variadic functions}}
130 }
131 
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')}}
TestIntParamMismatch(int x)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}}
137 }
TestIntParamMismatch2(short x)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}}
141 }
142 
143 struct TestClassMismatch1 {
144   void ToFunction(); // expected-note{{target function is a member of different class (expected 'TestClassMismatch2' but has 'TestClassMismatch1')}}
145 };
146 TestClassMismatch1 *tcm1;
147 struct TestClassMismatch2 {
FromFunctionTestClassMismatch2148   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}}
151   }
152 };
153 
154 __regcall int RegCallReturnsInt(); // expected-note {{target function has calling convention regcall (expected cdecl)}}
TestMismatchCallingConvention()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}}
158 }
159 
TestNonCapturingLambda()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()'}}
164 
165   // This works.
166   auto lambda_fptr = static_cast<int (*)()>(lambda);
167   [[clang::musttail]] return lambda_fptr();
168   [[clang::musttail]] return (+lambda)();
169 }
170 
TestCapturingLambda()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()'}}
176 }
177 
TestNonTrivialTemporary(int)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}}
180 }
181 
182 void ReturnsVoid();
183 struct TestDestructor {
~TestDestructorTestDestructor184   ~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}}
187   }
188 };
189 
190 struct ClassWithDestructor { // expected-note {{target destructor is declared here}}
TestExplicitDestructorCallClassWithDestructor191   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}}
194   }
195 };
196 
197 struct HasNonTrivialCopyConstructor {
198   HasNonTrivialCopyConstructor(const HasNonTrivialCopyConstructor &);
199 };
200 HasNonTrivialCopyConstructor ReturnsClassByValue();
TestNonElidableCopyConstructor()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}}
205 }
206 
207 struct ClassWithConstructor {
208   ClassWithConstructor() = default; // expected-note {{target constructor is declared here}}
209 };
TestExplicitConstructorCall(ClassWithConstructor a)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}}
213 }
214 
TestStatementExpression()215 void TestStatementExpression() {
216   ({
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}}
219   });
220 }
221 
222 struct MyException {};
TestTryBlock()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) {
227   }
228 }
229 
230 using IntFunctionType = int();
231 IntFunctionType *ReturnsIntFunction();
TestRValueFunctionPointer()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')}}
235 }
236 
TestPseudoDestructor()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}}
242 }
243 
244 struct StructPMF {
245   typedef void (StructPMF::*PMF)();
246   static void TestReturnsPMF();
247 };
248 
249 StructPMF *St;
250 StructPMF::PMF ReturnsPMF();
TestReturnsPMF()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}}
254 }
255 
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.
258 
259 struct TestBadPMF {
260   int (TestBadPMF::*pmf)();
BadPMFTestBadPMF261   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'}}
263   }
264 };
265 
266 namespace ns {}
TestCallNonValue()267 void TestCallNonValue() {
268   [[clang::musttail]] return ns; // expected-error {{unexpected namespace name 'ns': expected expression}}
269 }
270