forked from OSchip/llvm-project
Sema: Don't emit a missing prototype warning for deleted functions.
This is a bit more involved than I anticipated, so here's a breakdown of the changes: 1. Call ActOnFinishFunctionBody _after_ we parsed =default and =delete specifiers. Saying that we finished the body before parsing =default is just wrong. Changing this allows us to use isDefaulted and isDeleted on a decl in ActOnFinishFunctionBody. 2. Check for -Wmissing-prototypes after we parsed the function body. 3. Disable -Wmissing-prototypes when the Decl isDeleted. llvm-svn: 232040
This commit is contained in:
parent
e4812148e1
commit
8610cae98a
|
@ -1048,7 +1048,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
|
|||
|
||||
if (TryConsumeToken(tok::equal)) {
|
||||
assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
|
||||
Actions.ActOnFinishFunctionBody(Res, nullptr, false);
|
||||
|
||||
bool Delete = false;
|
||||
SourceLocation KWLoc;
|
||||
|
@ -1076,6 +1075,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
|
|||
SkipUntil(tok::semi);
|
||||
}
|
||||
|
||||
Stmt *GeneratedBody = Res ? Res->getBody() : nullptr;
|
||||
Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false);
|
||||
return Res;
|
||||
}
|
||||
|
||||
|
|
|
@ -10188,6 +10188,10 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
|
|||
if (FD->hasAttr<OpenCLKernelAttr>())
|
||||
return false;
|
||||
|
||||
// Don't warn on explicitly deleted functions.
|
||||
if (FD->isDeleted())
|
||||
return false;
|
||||
|
||||
bool MissingPrototype = true;
|
||||
for (const FunctionDecl *Prev = FD->getPreviousDecl();
|
||||
Prev; Prev = Prev->getPreviousDecl()) {
|
||||
|
@ -10330,30 +10334,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
|
|||
diag::err_func_def_incomplete_result))
|
||||
FD->setInvalidDecl();
|
||||
|
||||
// GNU warning -Wmissing-prototypes:
|
||||
// Warn if a global function is defined without a previous
|
||||
// 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)) {
|
||||
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
|
||||
|
||||
if (PossibleZeroParamPrototype) {
|
||||
// We found a declaration that is not a prototype,
|
||||
// but that could be a zero-parameter prototype
|
||||
if (TypeSourceInfo *TI =
|
||||
PossibleZeroParamPrototype->getTypeSourceInfo()) {
|
||||
TypeLoc TL = TI->getTypeLoc();
|
||||
if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
|
||||
Diag(PossibleZeroParamPrototype->getLocation(),
|
||||
diag::note_declaration_not_a_prototype)
|
||||
<< PossibleZeroParamPrototype
|
||||
<< FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FnBodyScope)
|
||||
PushDeclContext(FnBodyScope, FD);
|
||||
|
||||
|
@ -10555,7 +10535,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
|
||||
if (!FD->isInvalidDecl()) {
|
||||
// Don't diagnose unused parameters of defaulted or deleted functions.
|
||||
if (Body)
|
||||
if (!FD->isDeleted() && !FD->isDefaulted())
|
||||
DiagnoseUnusedParameters(FD->param_begin(), FD->param_end());
|
||||
DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(),
|
||||
FD->getReturnType(), FD);
|
||||
|
@ -10574,6 +10554,30 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
computeNRVO(Body, getCurFunction());
|
||||
}
|
||||
|
||||
// GNU warning -Wmissing-prototypes:
|
||||
// Warn if a global function is defined without a previous
|
||||
// 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)) {
|
||||
Diag(FD->getLocation(), diag::warn_missing_prototype) << FD;
|
||||
|
||||
if (PossibleZeroParamPrototype) {
|
||||
// We found a declaration that is not a prototype,
|
||||
// but that could be a zero-parameter prototype
|
||||
if (TypeSourceInfo *TI =
|
||||
PossibleZeroParamPrototype->getTypeSourceInfo()) {
|
||||
TypeLoc TL = TI->getTypeLoc();
|
||||
if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>())
|
||||
Diag(PossibleZeroParamPrototype->getLocation(),
|
||||
diag::note_declaration_not_a_prototype)
|
||||
<< PossibleZeroParamPrototype
|
||||
<< FixItHint::CreateInsertion(FTL.getRParenLoc(), "void");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
||||
const CXXMethodDecl *KeyFunction;
|
||||
if (MD->isOutOfLine() && (MD = MD->getCanonicalDecl()) &&
|
||||
|
@ -10659,7 +10663,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
"handled in the block above.");
|
||||
|
||||
// Verify and clean out per-function state.
|
||||
if (Body) {
|
||||
if (Body && (!FD || !FD->isDefaulted())) {
|
||||
// C++ constructors that have function-try-blocks can't have return
|
||||
// statements in the handlers of that block. (C++ [except.handle]p14)
|
||||
// Verify this.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-prototypes %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-prototypes -std=c++11 %s
|
||||
|
||||
void f() { } // expected-warning {{no previous prototype for function 'f'}}
|
||||
|
||||
|
@ -30,3 +30,5 @@ class I {
|
|||
friend void I_friend() {}
|
||||
};
|
||||
|
||||
// Don't warn on explicitly deleted functions.
|
||||
void j() = delete;
|
||||
|
|
Loading…
Reference in New Issue