]> granicus.if.org Git - clang/commitdiff
Don't diagnose no-prototype callee-cleanup function definitions
authorReid Kleckner <reid@kleckner.net>
Mon, 3 Nov 2014 21:24:50 +0000 (21:24 +0000)
committerReid Kleckner <reid@kleckner.net>
Mon, 3 Nov 2014 21:24:50 +0000 (21:24 +0000)
We already have a warning on the call sites of code like this:
  void f() { }
  void g() { f(1, 2, 3); }
t.c:2:21: warning: too many arguments in call to 'f'

We can limit ourselves to diagnosing unprototyped forward declarations
of f to cut down on noise.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@221184 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/Sema/callingconv.c
test/Sema/decl-microsoft-call-conv.c

index fe5981121feb3301f6f1606e7f9d9a4a19f78a6c..b9f8f637e21d96112cc61ff8bbf2d2935fbee6be 100644 (file)
@@ -7383,6 +7383,21 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
     if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
       CheckMSVCRTEntryPoint(NewFD);
 
+    // Diagnose no-prototype function declarations with calling conventions that
+    // don't support variadic calls.
+    const FunctionType *FT = R->castAs<FunctionType>();
+    if (FT->isFunctionNoProtoType() && !D.isFunctionDefinition()) {
+      CallingConv CC = FT->getExtInfo().getCC();
+      if (!supportsVariadicCall(CC)) {
+        // Windows system headers sometimes accidentally use stdcall without
+        // (void) parameters, so we relax this to a warning.
+        int DiagID =
+            CC == CC_X86StdCall ? diag::warn_cconv_knr : diag::err_cconv_knr;
+        Diag(NewFD->getLocation(), DiagID)
+            << FunctionType::getNameForCallConv(CC);
+      }
+    }
+
     if (!NewFD->isInvalidDecl())
       D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
                                                   isExplicitSpecialization));
@@ -7948,21 +7963,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
 
   // Semantic checking for this function declaration (in isolation).
 
-  // Diagnose calling conventions that don't support variadic calls.
-  QualType NewQType = Context.getCanonicalType(NewFD->getType());
-  const FunctionType *NewType = cast<FunctionType>(NewQType);
-  if (isa<FunctionNoProtoType>(NewType)) {
-    FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
-    if (!supportsVariadicCall(NewTypeInfo.getCC())) {
-      // Windows system headers sometimes accidentally use stdcall without
-      // (void) parameters, so use a default-error warning in this case :-/
-      int DiagID = NewTypeInfo.getCC() == CC_X86StdCall
-          ? diag::warn_cconv_knr : diag::err_cconv_knr;
-      Diag(NewFD->getLocation(), DiagID)
-          << FunctionType::getNameForCallConv(NewTypeInfo.getCC());
-    }
-  }
-
   if (getLangOpts().CPlusPlus) {
     // C++-specific checks.
     if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
index 5ac5a4ad044f1296442eb2251e652fadfb7b9adb..6a8be5ae050f7cae37500e34725d4b7d11a2dea2 100644 (file)
@@ -10,7 +10,7 @@ void __attribute__((stdcall)) bar(float *a) {
 void __attribute__((fastcall(1))) baz(float *a) { // expected-error {{'fastcall' attribute takes no arguments}}
 }
 
-void __attribute__((fastcall)) test0() { // expected-error {{function with no prototype cannot use the fastcall calling convention}}
+void __attribute__((fastcall)) test0() {
 }
 
 void __attribute__((fastcall)) test1(void) {
index c8fb6e10f9be65d6af1443dcd03ddcc36ddbdf17..cefaf4f40b0e9a9566a5004b870230d6c4d8ccc9 100644 (file)
@@ -14,11 +14,17 @@ void __pascal CrcGenerateTablePascal() {}
 void __vectorcall CrcGenerateTableVectorcall(void);
 void __vectorcall CrcGenerateTableVectorcall() {}
 
-void __fastcall CrcGenerateTableNoProtoFastcall() {} // expected-error{{function with no prototype cannot use the fastcall calling convention}}
-void __stdcall CrcGenerateTableNoProtoStdcall() {} // expected-warning{{function with no prototype cannot use the stdcall calling convention}}
-void __thiscall CrcGenerateTableNoProtoThiscall() {} // expected-error{{function with no prototype cannot use the thiscall calling convention}}
-void __pascal CrcGenerateTableNoProtoPascal() {} // expected-error{{function with no prototype cannot use the pascal calling convention}}
-void __vectorcall CrcGenerateTableNoProtoVectorcall() {} // expected-error{{function with no prototype cannot use the vectorcall calling convention}}
+void __fastcall CrcGenerateTableNoProtoFastcall(); // expected-error{{function with no prototype cannot use the fastcall calling convention}}
+void __stdcall CrcGenerateTableNoProtoStdcall(); // expected-warning{{function with no prototype cannot use the stdcall calling convention}}
+void __thiscall CrcGenerateTableNoProtoThiscall(); // expected-error{{function with no prototype cannot use the thiscall calling convention}}
+void __pascal CrcGenerateTableNoProtoPascal(); // expected-error{{function with no prototype cannot use the pascal calling convention}}
+void __vectorcall CrcGenerateTableNoProtoVectorcall(); // expected-error{{function with no prototype cannot use the vectorcall calling convention}}
+
+void __fastcall CrcGenerateTableNoProtoDefFastcall() {}
+void __stdcall CrcGenerateTableNoProtoDefStdcall() {}
+void __thiscall CrcGenerateTableNoProtoDefThiscall() {}
+void __pascal CrcGenerateTableNoProtoDefPascal() {}
+void __vectorcall CrcGenerateTableNoProtoDefVectorcall() {}
 
 // Regular calling convention is fine.
 void CrcGenerateTableNoProto() {}