Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -4672,7 +4672,8 @@ "no previous prototype for function %0">, InGroup>, 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">; + "this declaration is not a prototype; add %select{'void'|parameter declarations}0 " + "to make it %select{a prototype for a zero-parameter function|one}0">; def warn_strict_prototypes : Warning< "this %select{function declaration is not|block declaration is not|" "old-style function definition is not preceded by}0 a prototype">, Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -12777,8 +12777,9 @@ Consumer.HandleInlineFunctionDefinition(D); } -static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, - const FunctionDecl*& PossibleZeroParamPrototype) { +static bool +ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, + const FunctionDecl *&PossiblePrototype) { // Don't warn about invalid declarations. if (FD->isInvalidDecl()) return false; @@ -12815,7 +12816,6 @@ if (FD->isDeleted()) return false; - bool MissingPrototype = true; for (const FunctionDecl *Prev = FD->getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) { // Ignore any declarations that occur in function or method @@ -12823,13 +12823,11 @@ if (Prev->getLexicalDeclContext()->isFunctionOrMethod()) continue; - MissingPrototype = !Prev->getType()->isFunctionProtoType(); - if (FD->getNumParams() == 0) - PossibleZeroParamPrototype = Prev; - break; + PossiblePrototype = Prev; + return Prev->getType()->isFunctionNoProtoType(); } - return MissingPrototype; + return true; } void @@ -13349,21 +13347,22 @@ // prototype declaration. This warning is issued even if the // definition itself provides a prototype. The aim is to detect // global functions that fail to be declared in header files. - const FunctionDecl *PossibleZeroParamPrototype = nullptr; - if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) { + const FunctionDecl *PossiblePrototype = nullptr; + if (ShouldWarnAboutMissingPrototype(FD, PossiblePrototype)) { Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; - if (PossibleZeroParamPrototype) { + if (PossiblePrototype) { // We found a declaration that is not a prototype, // but that could be a zero-parameter prototype - if (TypeSourceInfo *TI = - PossibleZeroParamPrototype->getTypeSourceInfo()) { + if (TypeSourceInfo *TI = PossiblePrototype->getTypeSourceInfo()) { TypeLoc TL = TI->getTypeLoc(); if (FunctionNoProtoTypeLoc FTL = TL.getAs()) - Diag(PossibleZeroParamPrototype->getLocation(), + Diag(PossiblePrototype->getLocation(), diag::note_declaration_not_a_prototype) - << PossibleZeroParamPrototype - << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); + << (FD->getNumParams() != 0) + << (FD->getNumParams() == 0 + ? FixItHint::CreateInsertion(FTL.getRParenLoc(), "void") + : FixItHint{}); } } Index: cfe/trunk/test/Sema/warn-missing-prototypes.c =================================================================== --- cfe/trunk/test/Sema/warn-missing-prototypes.c +++ cfe/trunk/test/Sema/warn-missing-prototypes.c @@ -1,7 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -Wdocumentation -Wmissing-prototypes -verify %s // RUN: %clang_cc1 -fsyntax-only -Wdocumentation -Wmissing-prototypes -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s -int f(); +int f(); // expected-note{{this declaration is not a prototype; add parameter declarations to make it one}} +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:{{.*}}-[[@LINE-1]]:{{.*}}}:"{{.*}}" int f(int x) { return x; } // expected-warning{{no previous prototype for function 'f'}} @@ -15,7 +16,8 @@ void test(void); -int h3(); +int h3(); // expected-note{{this declaration is not a prototype; add parameter declarations to make it one}} +// CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:{{.*}}-[[@LINE-1]]:{{.*}}}:"{{.*}}" int h4(int); int h4(); @@ -38,6 +40,5 @@ int main(void) { return 0; } void not_a_prototype_test(); // expected-note{{this declaration is not a prototype; add 'void' to make it a prototype for a zero-parameter function}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:27-[[@LINE-1]]:27}:"void" void not_a_prototype_test() { } // expected-warning{{no previous prototype for function 'not_a_prototype_test'}} - -// CHECK: fix-it:"{{.*}}":{40:27-40:27}:"void"