diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 09ebbc085fe5..2a54bcc3afbd 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2560,6 +2560,17 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, if (!unwrapped.isFunctionType()) return false; + // Diagnose regparm with fastcall. + const FunctionType *fn = unwrapped.get(); + CallingConv CC = fn->getCallConv(); + if (CC == CC_X86FastCall) { + S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) + << FunctionType::getNameForCallConv(CC) + << "regparm"; + attr.setInvalid(); + return true; + } + FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withRegParm(value); type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); @@ -2578,7 +2589,8 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, CallingConv CCOld = fn->getCallConv(); if (S.Context.getCanonicalCallConv(CC) == S.Context.getCanonicalCallConv(CCOld)) { - attr.setInvalid(); + FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC); + type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); return true; } @@ -2607,6 +2619,15 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, attr.setInvalid(); return true; } + + // Also diagnose fastcall with regparm. + if (fn->getRegParmType()) { + S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) + << "regparm" + << FunctionType::getNameForCallConv(CC); + attr.setInvalid(); + return true; + } } FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC); diff --git a/clang/test/Sema/stdcall-fastcall.c b/clang/test/Sema/stdcall-fastcall.c index dffcb969a997..4531eb2a81c8 100644 --- a/clang/test/Sema/stdcall-fastcall.c +++ b/clang/test/Sema/stdcall-fastcall.c @@ -8,3 +8,13 @@ int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{fastcall and stdcall attributes are not compatible}} void __attribute__((stdcall)) foo4(); // expected-note{{previous declaration is here}} void __attribute__((fastcall)) foo4(void); // expected-error{{function declared 'fastcall' here was previously declared 'stdcall'}} + +// rdar://8876096 +void rdar8876096foo1(int i, int j) __attribute__((fastcall, cdecl)); // expected-error {{not compatible}} +void rdar8876096foo2(int i, int j) __attribute__((fastcall, stdcall)); // expected-error {{not compatible}} +void rdar8876096foo3(int i, int j) __attribute__((fastcall, regparm(2))); // expected-error {{not compatible}} +void rdar8876096foo4(int i, int j) __attribute__((stdcall, cdecl)); // expected-error {{not compatible}} +void rdar8876096foo5(int i, int j) __attribute__((stdcall, fastcall)); // expected-error {{not compatible}} +void rdar8876096foo6(int i, int j) __attribute__((cdecl, fastcall)); // expected-error {{not compatible}} +void rdar8876096foo7(int i, int j) __attribute__((cdecl, stdcall)); // expected-error {{not compatible}} +void rdar8876096foo8(int i, int j) __attribute__((regparm(2), fastcall)); // expected-error {{not compatible}}