From: John McCall Date: Wed, 4 Nov 2009 03:36:09 +0000 (+0000) Subject: Diagnose the use of 'fastcall' on functions without prototypes or with X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9112b93829da90b1612453bea4c491a1678272a4;p=clang Diagnose the use of 'fastcall' on functions without prototypes or with varargs prototypes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86001 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9aae77090a..99fddb5810 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -619,6 +619,10 @@ def warn_attribute_wrong_decl_type : Warning< def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; +def err_cconv_knr : Error< + "function with no prototype cannot use '%0' calling convention">; +def err_cconv_varargs : Error< + "variadic function cannot use '%0' calling convention">; def warn_attribute_ignored_for_field_of_type : Warning< "%0 attribute ignored for field of type %1">; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index a3f8eb5a0e..18f57da769 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1032,6 +1032,22 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) StdCallAttr()); } +/// Diagnose the use of a non-standard calling convention on the given +/// function. +static void DiagnoseCConv(FunctionDecl *D, const char *CConv, + SourceLocation Loc, Sema &S) { + if (!D->hasPrototype()) { + S.Diag(Loc, diag::err_cconv_knr) << CConv; + return; + } + + const FunctionProtoType *T = D->getType()->getAs(); + if (T->isVariadic()) { + S.Diag(Loc, diag::err_cconv_varargs) << CConv; + return; + } +} + static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Attribute has no arguments. if (Attr.getNumArgs() != 0) { @@ -1045,6 +1061,8 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } + DiagnoseCConv(cast(d), "fastcall", Attr.getLoc(), S); + // stdcall and fastcall attributes are mutually incompatible. if (d->getAttr()) { S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c index cb69c59c40..102115b3bf 100644 --- a/test/Sema/callingconv.c +++ b/test/Sema/callingconv.c @@ -8,3 +8,12 @@ void __attribute__((stdcall)) bar(float *a) { void __attribute__((fastcall(1))) baz(float *a) { // expected-error {{attribute requires 0 argument(s)}} } + +void __attribute__((fastcall)) test0() { // expected-error {{function with no prototype cannot use 'fastcall' calling convention}} +} + +void __attribute__((fastcall)) test1(void) { +} + +void __attribute__((fastcall)) test2(int a, ...) { // expected-error {{variadic function cannot use 'fastcall' calling convention}} +} diff --git a/test/Sema/stdcall-fastcall.c b/test/Sema/stdcall-fastcall.c index 353bbfc252..e0db63822f 100644 --- a/test/Sema/stdcall-fastcall.c +++ b/test/Sema/stdcall-fastcall.c @@ -5,6 +5,6 @@ int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' attribute only int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' attribute only applies to function types}} // Different CC qualifiers are not compatible -void __attribute__((stdcall, fastcall)) foo3(); // expected-error{{stdcall and fastcall attributes are not compatible}} +void __attribute__((stdcall, fastcall)) foo3(void); // expected-error{{stdcall and fastcall attributes are not compatible}} void __attribute__((stdcall)) foo4(); -void __attribute__((fastcall)) foo4(); // expected-error{{fastcall and stdcall attributes are not compatible}} +void __attribute__((fastcall)) foo4(void); // expected-error{{fastcall and stdcall attributes are not compatible}}