Author: arphaman Date: Wed Dec 7 04:52:18 2016 New Revision: 288896 URL: http://llvm.org/viewvc/llvm-project?rev=288896&view=rev Log: Implement the -Wstrict-prototypes warning
This commit fixes PR20796. It implements the C only -Wstrict-prototypes warning. Clang now emits a warning for function declarations which have no parameters specified and for K&R function definitions with more than 0 parameters that are not preceded by a previous prototype declaration. The patch was originally submitted by Paul Titei! rdar://15060615 Differential Revision: https://reviews.llvm.org/D16533 Added: cfe/trunk/test/Sema/warn-strict-prototypes.c cfe/trunk/test/Sema/warn-strict-prototypes.m Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaType.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=288896&r1=288895&r2=288896&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Dec 7 04:52:18 2016 @@ -4411,6 +4411,10 @@ def warn_missing_prototype : Warning< InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore; def note_declaration_not_a_prototype : Note< "this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function">; +def warn_strict_prototypes : Warning< + "this %select{function declaration is not|" + "old-style function definition is not preceded by}0 a prototype">, + InGroup<DiagGroup<"strict-prototypes">>, DefaultIgnore; def warn_missing_variable_declarations : Warning< "no previous extern declaration for non-static variable %0">, InGroup<DiagGroup<"missing-variable-declarations">>, DefaultIgnore; Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=288896&r1=288895&r2=288896&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Dec 7 04:52:18 2016 @@ -11878,6 +11878,21 @@ Decl *Sema::ActOnFinishFunctionBody(Decl << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); } } + + // GNU warning -Wstrict-prototypes + // Warn if K&R function is defined without a previous declaration. + // This warning is issued only if the definition itself does not provide + // a prototype. Only K&R definitions do not provide a prototype. + // An empty list in a function declarator that is part of a definition + // of that function specifies that the function has no parameters + // (C99 6.7.5.3p14) + if (!FD->hasWrittenPrototype() && FD->getNumParams() > 0 && + !LangOpts.CPlusPlus) { + TypeSourceInfo *TI = FD->getTypeSourceInfo(); + TypeLoc TL = TI->getTypeLoc(); + FunctionTypeLoc FTL = TL.castAs<FunctionTypeLoc>(); + Diag(FTL.getLParenLoc(), diag::warn_strict_prototypes) << 1; + } } if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=288896&r1=288895&r2=288896&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Wed Dec 7 04:52:18 2016 @@ -4320,6 +4320,19 @@ static TypeSourceInfo *GetFullTypeForDec if (FTI.isAmbiguous) warnAboutAmbiguousFunction(S, D, DeclType, T); + // GNU warning -Wstrict-prototypes + // Warn if a function declaration is without a prototype. + // This warning is issued for all kinds of unprototyped function + // declarations (i.e. function type typedef, function pointer etc.) + // C99 6.7.5.3p14: + // The empty list in a function declarator that is not part of a + // definition of that function specifies that no information + // about the number or types of the parameters is supplied. + if (D.getFunctionDefinitionKind() == FDK_Declaration && + FTI.NumParams == 0 && !LangOpts.CPlusPlus) + S.Diag(DeclType.Loc, diag::warn_strict_prototypes) + << 0 << FixItHint::CreateInsertion(FTI.getRParenLoc(), "void"); + FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus) { Added: cfe/trunk/test/Sema/warn-strict-prototypes.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-strict-prototypes.c?rev=288896&view=auto ============================================================================== --- cfe/trunk/test/Sema/warn-strict-prototypes.c (added) +++ cfe/trunk/test/Sema/warn-strict-prototypes.c Wed Dec 7 04:52:18 2016 @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s + +// function declaration with unspecified params +void foo1(); // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:11}:"void" +// function declaration with 0 params +void foo2(void); + +// function definition with 0 params(for both cases), +// valid according to 6.7.5.3/14 +void foo1() {} +void foo2(void) {} + +// function type typedef unspecified params +typedef void foo3(); // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:19}:"void" + +// global fp unspecified params +void (*foo4)(); // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:14}:"void" + +// struct member fp unspecified params +struct { void (*foo5)(); } s; // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:23-[[@LINE-1]]:23}:"void" + +// param fp unspecified params +void bar2(void (*foo6)()) { // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:24-[[@LINE-1]]:24}:"void" + // local fp unspecified params + void (*foo7)() = 0; // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"void" + // array fp unspecified params + void (*foo8[2])() = {0}; // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:19}:"void" +} + +// function type cast using using an anonymous function declaration +void bar3(void) { + // casting function w/out prototype to unspecified params function type + (void)(void(*)()) foo1; // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:18-[[@LINE-1]]:18}:"void" + // .. specified params + (void)(void(*)(void)) foo1; +} + +// K&R function definition not preceded by full prototype +int foo9(a, b) // expected-warning {{old-style function definition is not preceded by a prototype}} + int a, b; +{ + return a + b; +} + +// Function declaration with no types +void foo10(); // expected-warning {{this function declaration is not a prototype}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:12-[[@LINE-1]]:12}:"void" +// K&R function definition with incomplete param list declared +void foo10(p, p2) void *p; {} // expected-warning {{old-style function definition is not preceded by a prototype}} + +// K&R function definition with previous prototype declared is not diagnosed. +void foo11(int p, int p2); +void foo11(p, p2) int p; int p2; {} Added: cfe/trunk/test/Sema/warn-strict-prototypes.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-strict-prototypes.m?rev=288896&view=auto ============================================================================== --- cfe/trunk/test/Sema/warn-strict-prototypes.m (added) +++ cfe/trunk/test/Sema/warn-strict-prototypes.m Wed Dec 7 04:52:18 2016 @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -Wstrict-prototypes -verify -fblocks %s + +@interface Foo + +@property (nonatomic, copy) void (^noProtoBlock)(); // expected-warning {{this function declaration is not a prototype}} +@property (nonatomic, copy) void (^block)(void); // no warning + +- doStuff:(void (^)()) completionHandler; // expected-warning {{this function declaration is not a prototype}} +- doOtherStuff:(void (^)(void)) completionHandler; // no warning + +@end + +void foo() { + void (^block)() = // expected-warning {{this function declaration is not a prototype}} + ^void(int arg) { // no warning + }; + void (^block2)(void) = // no warning + ^void() { // expected-warning {{this function declaration is not a prototype}} + }; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits