Silence a duplicate diagnostic about K&R C function definitions

We would issue the same diagnostic twice in the case that the K&R C
function definition is preceded by a static declaration of the function
with a prototype.

Fixes #58181
This commit is contained in:
Aaron Ballman 2022-10-06 10:07:16 -04:00
parent 364003e2da
commit f7170500cf
3 changed files with 39 additions and 10 deletions

View File

@ -231,6 +231,10 @@ Improvements to Clang's diagnostics
be selected.
- Add a fix-it hint for the ``-Wdefaulted-function-deleted`` warning to
explicitly delete the function.
- Fixed an accidental duplicate diagnostic involving the declaration of a
function definition without a prototype which is preceded by a static
declaration of the function with a prototype. Fixes
`Issue 58181 <https://github.com/llvm/llvm-project/issues/58181>`_.
Non-comprehensive list of changes in this release
-------------------------------------------------

View File

@ -14657,6 +14657,21 @@ void Sema::ActOnFinishInlineFunctionDef(FunctionDecl *D) {
Consumer.HandleInlineFunctionDefinition(D);
}
static bool FindPossiblePrototype(const FunctionDecl *FD,
const FunctionDecl *&PossiblePrototype) {
for (const FunctionDecl *Prev = FD->getPreviousDecl(); Prev;
Prev = Prev->getPreviousDecl()) {
// Ignore any declarations that occur in function or method
// scope, because they aren't visible from the header.
if (Prev->getLexicalDeclContext()->isFunctionOrMethod())
continue;
PossiblePrototype = Prev;
return Prev->getType()->isFunctionProtoType();
}
return false;
}
static bool
ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
const FunctionDecl *&PossiblePrototype) {
@ -14703,16 +14718,9 @@ ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
if (!FD->isExternallyVisible())
return false;
for (const FunctionDecl *Prev = FD->getPreviousDecl();
Prev; Prev = Prev->getPreviousDecl()) {
// Ignore any declarations that occur in function or method
// scope, because they aren't visible from the header.
if (Prev->getLexicalDeclContext()->isFunctionOrMethod())
continue;
PossiblePrototype = Prev;
return Prev->getType()->isFunctionNoProtoType();
}
// If we were able to find a potential prototype, don't warn.
if (FindPossiblePrototype(FD, PossiblePrototype))
return false;
return true;
}
@ -15280,6 +15288,12 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
}
}
// We might not have found a prototype because we didn't wish to warn on
// the lack of a missing prototype. Try again without the checks for
// whether we want to warn on the missing prototype.
if (!PossiblePrototype)
(void)FindPossiblePrototype(FD, PossiblePrototype);
// If the function being defined does not have a prototype, then we may
// need to diagnose it as changing behavior in C2x because we now know
// whether the function accepts arguments or not. This only handles the

View File

@ -105,3 +105,14 @@ void calls(void) {
func(1, 2); // OK
func(1, 2, 3); // both-warning {{too many arguments in call to 'func'}}
}
// Issue 58181 -- we would issue the warning about the function without a
// prototype twice when the function was declared static in the following
// example.
static int GH58181(int x, int y);
static int GH58181(x, y) // both-warning {{a function definition without a prototype is deprecated in all versions of C and is not supported in C2x}}
int x;
int y;
{
return x + y;
}