[patch] Delay __fastcall attribute checking utnil after merging declarations

Nico Weber thakis at chromium.org
Sat Jul 26 15:05:55 PDT 2014


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140726/e5300186/attachment.html>
-------------- next part --------------
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 213724)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -7821,6 +7821,24 @@
   }
 
   // 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);
+  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.
+    if (NewType->getHasRegParm()) {
+      Diag(NewFD->getLocation(), diag::err_attributes_are_not_compatible)
+          << "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall);
+    }
+  }
+
   if (getLangOpts().CPlusPlus) {
     // C++-specific checks.
     if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp	(revision 213724)
+++ lib/Sema/SemaType.cpp	(working copy)
@@ -4564,25 +4564,6 @@
     }
   }
 
-  // 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;
-    }
-  }
-
   // Modify the CC from the wrapped function type, wrap it all back, and then
   // wrap the whole thing in an AttributedType as written.  The modified type
   // might have a different CC if we ignored the attribute.
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