[patch] Delay __fastcall attribute checking utnil after merging declarations

Nico Weber thakis at chromium.org
Thu Jul 31 09:45:11 PDT 2014


Thanks!

On Tue, Jul 29, 2014 at 10:40 AM, Reid Kleckner <rnk at google.com> wrote:

> +  // Diagnose the use of X86 fastcall on unprototyped functions.
>
> We should also diagnose unprototyped stdcall functions, but I'm not sure
> if that would be too disruptive.  Currently we accept this and always call
> _f at 0:
> void __stdcall f();
> int main() {
>   f(1);
>   f(1, 2);
>   f(1, 2, 3);
> }
>
> MSVC rejects with "t.c(5) : error C2708: 'f' : actual parameters length in
> bytes differs from previous call or reference".
>

I added a TODO for adding this and reshuffled the if to make this easy to
add. I'll give it a try once this patch is in.


>
> +  QualType NewQType = Context.getCanonicalType(NewFD->getType());
> +  const FunctionType *NewType = cast<FunctionType>(NewQType);
> +  FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
> +  if (NewTypeInfo.getCC() == CC_X86FastCall) {
> +    if (isa<FunctionNoProtoType>(NewType)) {
> +      Diag(NewFD->getLocation(), diag::err_cconv_knr)
> +          << FunctionType::getNameForCallConv(CC_X86FastCall);
> +    }
> +
> +    // Also diagnose fastcall with regparm.
>
> Before you moved this, there was other code to handle CC_X86FastCall and
> AT_Regparm nearby.  I think we should either move all regparm+fastcall
> diagnosis to after redeclaration merging or leave it where it is.
>

I moved the regparm code back to where it was.


>
> +    if (NewType->getHasRegParm()) {
> +      Diag(NewFD->getLocation(), diag::err_attributes_are_not_compatible)
> +          << "regparm" <<
> FunctionType::getNameForCallConv(CC_X86FastCall);
> +    }
> +  }
>
>
>
> On Sat, Jul 26, 2014 at 3:05 PM, Nico Weber <thakis at chromium.org> wrote:
>
>> Hi,
>>
>> the attached patch delays semantic analysis of __fastcall until after
>> MergeFunctionDecl() has been called, PR20386.
>>
>> The motivation is code like this in a .c file:
>>
>> void __fastcall CrcGenerateTable(void);
>> void __fastcall CrcGenerateTable() {}
>>
>> Without this patch, __fastcall is analyzed before the definition of
>> CrcGenerateTable() is merged with the declaration, so Sema thinks the
>> function doesn't have a prototype. Since the error is only emitted on
>> FunctionNoProto functions, and functions in C++ or functions with more than
>> 0 arguments have a proto, this is only an issue for functions with 0
>> parameters in C files. See the bug for some more notes.
>>
>> (A side effect of moving the diagnostic is that the diagnostic now points
>> at the function instead of the attribute, and that the attribute is no
>> longer marked invalid. Neither seems like a problem.)
>>
>> Nico
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140731/bb768474/attachment.html>
-------------- next part --------------
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 214046)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -7821,6 +7821,18 @@
   }
 
   // Semantic checking for this function declaration (in isolation).
+
+  // Diagnose the use of X86 fastcall on unprototyped functions.
+  QualType NewQType = Context.getCanonicalType(NewFD->getType());
+  const FunctionType *NewType = cast<FunctionType>(NewQType);
+  if (isa<FunctionNoProtoType>(NewType)) {
+    FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
+    if (NewTypeInfo.getCC() == CC_X86FastCall)
+      Diag(NewFD->getLocation(), diag::err_cconv_knr)
+          << FunctionType::getNameForCallConv(CC_X86FastCall);
+    // TODO: Also diagnose unprototyped stdcall functions?
+  }
+
   if (getLangOpts().CPlusPlus) {
     // C++-specific checks.
     if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 214046)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -4564,23 +4564,12 @@
     }
   }
 
-  // Diagnose the use of X86 fastcall on unprototyped functions.
-  if (CC == CC_X86FastCall) {
-    if (isa<FunctionNoProtoType>(fn)) {
-      S.Diag(attr.getLoc(), diag::err_cconv_knr)
-        << FunctionType::getNameForCallConv(CC);
-      attr.setInvalid();
-      return true;
-    }
-
-    // Also diagnose fastcall with regparm.
-    if (fn->getHasRegParm()) {
-      S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
-        << "regparm"
-        << FunctionType::getNameForCallConv(CC);
-      attr.setInvalid();
-      return true;
-    }
+  // Also diagnose fastcall with regparm.
+  if (CC == CC_X86FastCall && fn->getHasRegParm()) {
+    S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
+        << "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall);
+    attr.setInvalid();
+    return true;
   }
 
   // Modify the CC from the wrapped function type, wrap it all back, and then
Index: test/Sema/decl-microsoft-call-conv.c
===================================================================
--- test/Sema/decl-microsoft-call-conv.c	(revision 0)
+++ test/Sema/decl-microsoft-call-conv.c	(working copy)
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple i686-pc-win32 -verify %s
+
+// It's important that this is a .c file.
+
+// This is fine, as CrcGenerateTable() has a prototype.
+void __fastcall CrcGenerateTable(void);
+void __fastcall CrcGenerateTable() {}
+
+void __fastcall CrcGenerateTableNoProto() {} // expected-error{{function with no prototype cannot use fastcall calling convention}}


More information about the cfe-commits mailing list