[[clang::musttail]]ReturnsInt1();// expected-error {{'musttail' attribute only applies to return statements}}
[[clang::musttail(1, 2)]]returnReturnsInt1();// expected-error {{'musttail' attribute takes no arguments}}
[[clang::musttail]]return5;// expected-error {{'musttail' attribute requires that the return value is the result of a function call}}
[[clang::musttail]]returnReturnsInt1();
}
voidNoFunctionCall(){
[[clang::musttail]]return;// expected-error {{'musttail' attribute requires that the return value is the result of a function call}}
}
[[clang::musttail]]staticintint_val=ReturnsInt1();// expected-error {{'musttail' attribute cannot be applied to a declaration}}
voidNoParams();// expected-note {{target function has different number of parameters (expected 1 but has 0)}}
voidTestParamArityMismatch(intx){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnNoParams();// expected-error {{cannot perform a tail call to function 'NoParams' because its signature is incompatible with the calling function}}
}
voidLongParam(longx);// expected-note {{target function has type mismatch at 1st parameter (expected 'long' but has 'int')}}
voidTestParamTypeMismatch(intx){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnLongParam(x);// expected-error {{cannot perform a tail call to function 'LongParam' because its signature is incompatible with the calling function}}
}
longReturnsLong();// expected-note {{target function has different return type ('int' expected but has 'long')}}
intTestReturnTypeMismatch(){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnReturnsLong();// expected-error {{cannot perform a tail call to function 'ReturnsLong' because its signature is incompatible with the calling function}}
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnReturnsVoid();// expected-error{{non-static member function cannot perform a tail call to non-member function 'ReturnsVoid'}}
}
};
classHasNonTrivialDestructor{
public:
~HasNonTrivialDestructor(){}
intReturnsInt();
};
voidReturnsVoid2();
voidTestNonTrivialDestructorInScope(){
HasNonTrivialDestructorfoo;// expected-note {{jump exits scope of variable with non-trivial destructor}}
[[clang::musttail]]returnReturnsVoid();// expected-error {{cannot perform a tail call from this return statement}}
}
intNonTrivialParam(HasNonTrivialDestructorx);
intTestNonTrivialParam(HasNonTrivialDestructorx){
[[clang::musttail]]returnNonTrivialParam(x);// expected-error {{tail call requires that the return value, all parameters, and any temporaries created by the expression are trivially destructible}}
// FIXME: the diagnostic cannot currently distinguish between needing to run a
// destructor for the return value and needing to run a destructor for some
// other temporary created in the return statement.
[[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}}
[[clang::musttail]]returnHasNonTrivialDestructor();// expected-error {{'musttail' attribute requires that the return value is the result of a function call}}
// Outer non-trivial destructor does not affect nested class.
[[clang::musttail]]returnReturnsVoid2();
}
};
}
template<classT>
TTemplateFunc(Tx){// expected-note{{target function has different return type ('long' expected but has 'int')}}
returnx?5:10;
}
intOkTemplateFunc(intx){
[[clang::musttail]]returnTemplateFunc<int>(x);
}
template<classT>
TBadTemplateFunc(Tx){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnTemplateFunc<int>(x);// expected-error {{cannot perform a tail call to function 'TemplateFunc' because its signature is incompatible with the calling function}}
HasNonTrivialDestructorvla[x];// expected-note {{jump exits scope of variable with non-trivial destructor}}
[[clang::musttail]]returnIntParam(x);// expected-error {{cannot perform a tail call from this return statement}}
}
voidTestNonTrivialDestructorSubArg(intx){
[[clang::musttail]]returnIntParam(NonTrivialParam(HasNonTrivialDestructor()));// expected-error {{tail call requires that the return value, all parameters, and any temporaries created by the expression are trivially destructible}}
}
voidVariadicFunction(intx,...);
voidTestVariadicFunction(intx,...){
[[clang::musttail]]returnVariadicFunction(x);// expected-error {{'musttail' attribute may not be used with variadic functions}}
}
intTakesIntParam(intx);// expected-note {{target function has type mismatch at 1st parameter (expected 'int' but has 'short')}}
intTakesShortParam(shortx);// expected-note {{target function has type mismatch at 1st parameter (expected 'short' but has 'int')}}
intTestIntParamMismatch(intx){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnTakesShortParam(x);// expected-error {{cannot perform a tail call to function 'TakesShortParam' because its signature is incompatible with the calling function}}
}
intTestIntParamMismatch2(shortx){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnTakesIntParam(x);// expected-error {{cannot perform a tail call to function 'TakesIntParam' because its signature is incompatible with the calling function}}
}
structTestClassMismatch1{
voidToFunction();// expected-note{{target function is a member of different class (expected 'TestClassMismatch2' but has 'TestClassMismatch1')}}
};
TestClassMismatch1*tcm1;
structTestClassMismatch2{
voidFromFunction(){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returntcm1->ToFunction();// expected-error {{cannot perform a tail call to function 'ToFunction' because its signature is incompatible with the calling function}}
}
};
__regcallintRegCallReturnsInt();// expected-note {{target function has calling convention regcall (expected cdecl)}}
intTestMismatchCallingConvention(){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnRegCallReturnsInt();// expected-error {{cannot perform a tail call to function 'RegCallReturnsInt' because it uses an incompatible calling convention}}
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnlambda();// expected-error {{non-member function cannot perform a tail call to non-static member function 'operator()'}}
}
intTestNonTrivialTemporary(int){
[[clang::musttail]]returnTakesIntParam(HasNonTrivialDestructor().ReturnsInt());// expected-error {{tail call requires that the return value, all parameters, and any temporaries created by the expression are trivially destructible}}
}
voidReturnsVoid();
structTestDestructor{
~TestDestructor(){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnReturnsVoid();// expected-error {{destructor '~TestDestructor' must not return void expression}} // expected-error {{cannot perform a tail call from a destructor}}
}
};
structClassWithDestructor{// expected-note {{target destructor is declared here}}
voidTestExplicitDestructorCall(){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnthis->~ClassWithDestructor();// expected-error {{cannot perform a tail call to a destructor}}
// This is an elidable constructor, but when it is written explicitly
// we decline to elide it.
[[clang::musttail]]returnHasNonTrivialCopyConstructor(ReturnsClassByValue());// expected-error{{'musttail' attribute requires that the return value is the result of a function call}}
}
structClassWithConstructor{
ClassWithConstructor()=default;// expected-note {{target constructor is declared here}}
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returna.ClassWithConstructor::ClassWithConstructor();// expected-error{{cannot perform a tail call to a constructor}} expected-warning{{explicit constructor calls are a Microsoft extension}}
}
voidTestStatementExpression(){
({
HasNonTrivialDestructorfoo;// expected-note {{jump exits scope of variable with non-trivial destructor}}
[[clang::musttail]]returnReturnsVoid2();// expected-error {{cannot perform a tail call from this return statement}}
});
}
structMyException{};
voidTestTryBlock(){
try{// expected-note {{jump exits try block}}
[[clang::musttail]]returnReturnsVoid2();// expected-error {{cannot perform a tail call from this return statement}}
}catch(MyException&e){
}
}
usingIntFunctionType=int();
IntFunctionType*ReturnsIntFunction();
longTestRValueFunctionPointer(){
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnReturnsIntFunction()();// 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')}}
}
voidTestPseudoDestructor(){
intn;
usingT=int;
[[clang::musttail]]// expected-note {{tail call required by 'musttail' attribute here}}
returnn.~T();// expected-error{{cannot perform a tail call to a destructor}}
}
structStructPMF{
typedefvoid(StructPMF::*PMF)();
staticvoidTestReturnsPMF();
};
StructPMF*St;
StructPMF::PMFReturnsPMF();
voidStructPMF::TestReturnsPMF(){
[[clang::musttail]]// expected-note{{tail call required by 'musttail' attribute here}}
return(St->*ReturnsPMF())();// expected-error{{static member function cannot perform a tail call to pointer-to-member function}}
}
// These tests are merely verifying that we don't crash with incomplete or
// erroneous ASTs. These cases crashed the compiler in early iterations.
structTestBadPMF{
int(TestBadPMF::*pmf)();
voidBadPMF(){
[[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'}}
}
};
namespacens{}
voidTestCallNonValue(){
[[clang::musttail]]returnns;// expected-error {{unexpected namespace name 'ns': expected expression}}