From f98c88757d5873fcb5ca3d54656b5380b71c4e95 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 31 Jul 2014 17:19:18 +0000 Subject: [PATCH] Delay check for prototype on __fastcall functions until after MergeFunctionDecl. In C, it is only known after merging decls if a function with 0 arguments has a prototype. Fixes PR20386, see that for more notes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@214408 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 12 ++++++++++++ lib/Sema/SemaType.cpp | 23 ++++++----------------- test/Sema/decl-microsoft-call-conv.c | 9 +++++++++ 3 files changed, 27 insertions(+), 17 deletions(-) create mode 100644 test/Sema/decl-microsoft-call-conv.c diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9ce09288de..4abbbebf80 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7821,6 +7821,18 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } // 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(NewQType); + if (isa(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(NewFD)) { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 4ad066a7a7..47df3a69aa 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -4564,23 +4564,12 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } } - // Diagnose the use of X86 fastcall on unprototyped functions. - if (CC == CC_X86FastCall) { - if (isa(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 diff --git a/test/Sema/decl-microsoft-call-conv.c b/test/Sema/decl-microsoft-call-conv.c new file mode 100644 index 0000000000..88a6d920a0 --- /dev/null +++ b/test/Sema/decl-microsoft-call-conv.c @@ -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}} -- 2.40.0