From: Reid Kleckner Date: Mon, 3 Nov 2014 21:56:03 +0000 (+0000) Subject: Move the no-prototype calling conv check after decl merging X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8a8ccbf4fb898b7d12d9a0ac66e4c49044098118;p=clang Move the no-prototype calling conv check after decl merging Now we don't warn on this code: void __stdcall f(void); void __stdcall f(); My previous commit regressed this functionality because I didn't update the relevant test case which used a definition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@221188 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b9f8f637e2..109c01c889 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7383,10 +7383,21 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint()) CheckMSVCRTEntryPoint(NewFD); + if (!NewFD->isInvalidDecl()) + D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, + isExplicitSpecialization)); + else if (!Previous.empty()) + // Make graceful recovery from an invalid redeclaration. + D.setRedeclaration(true); + assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || + Previous.getResultKind() != LookupResult::FoundOverloaded) && + "previous declaration set still overloaded"); + // Diagnose no-prototype function declarations with calling conventions that - // don't support variadic calls. - const FunctionType *FT = R->castAs(); - if (FT->isFunctionNoProtoType() && !D.isFunctionDefinition()) { + // don't support variadic calls. Only do this in C and do it after merging + // possibly prototyped redeclarations. + const FunctionType *FT = NewFD->getType()->castAs(); + if (isa(FT) && !D.isFunctionDefinition()) { CallingConv CC = FT->getExtInfo().getCC(); if (!supportsVariadicCall(CC)) { // Windows system headers sometimes accidentally use stdcall without @@ -7397,16 +7408,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << FunctionType::getNameForCallConv(CC); } } - - if (!NewFD->isInvalidDecl()) - D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, - isExplicitSpecialization)); - else if (!Previous.empty()) - // Make graceful recovery from an invalid redeclaration. - D.setRedeclaration(true); - assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || - Previous.getResultKind() != LookupResult::FoundOverloaded) && - "previous declaration set still overloaded"); } else { // C++11 [replacement.functions]p3: // The program's definitions shall not be specified as inline. diff --git a/test/Sema/decl-microsoft-call-conv.c b/test/Sema/decl-microsoft-call-conv.c index cefaf4f40b..5a83b38b19 100644 --- a/test/Sema/decl-microsoft-call-conv.c +++ b/test/Sema/decl-microsoft-call-conv.c @@ -4,14 +4,19 @@ // This is fine, as CrcGenerateTable*() has a prototype. void __fastcall CrcGenerateTableFastcall(void); +void __fastcall CrcGenerateTableFastcall(); void __fastcall CrcGenerateTableFastcall() {} void __stdcall CrcGenerateTableStdcall(void); +void __stdcall CrcGenerateTableStdcall(); void __stdcall CrcGenerateTableStdcall() {} void __thiscall CrcGenerateTableThiscall(void); +void __thiscall CrcGenerateTableThiscall(); void __thiscall CrcGenerateTableThiscall() {} void __pascal CrcGenerateTablePascal(void); +void __pascal CrcGenerateTablePascal(); void __pascal CrcGenerateTablePascal() {} void __vectorcall CrcGenerateTableVectorcall(void); +void __vectorcall CrcGenerateTableVectorcall(); void __vectorcall CrcGenerateTableVectorcall() {} void __fastcall CrcGenerateTableNoProtoFastcall(); // expected-error{{function with no prototype cannot use the fastcall calling convention}}