Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -4652,7 +4652,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: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -12747,8 +12747,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; @@ -12785,7 +12786,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 @@ -12793,13 +12793,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 @@ -13319,21 +13317,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: test/Sema/warn-missing-prototypes.c =================================================================== --- test/Sema/warn-missing-prototypes.c +++ test/Sema/warn-missing-prototypes.c @@ -1,7 +1,7 @@ // 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}} int f(int x) { return x; } // expected-warning{{no previous prototype for function 'f'}} @@ -15,7 +15,7 @@ void test(void); -int h3(); +int h3(); // expected-note{{this declaration is not a prototype; add parameter declarations to make it one}} int h4(int); int h4();