From: Benjamin Kramer Date: Thu, 12 Mar 2015 14:28:47 +0000 (+0000) Subject: Sema: Don't emit a missing prototype warning for deleted functions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bcf994970a004598574cc45565be0b7f55cb8524;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@232040 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 7ccd2092a2..3b56102dcf 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -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; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index dc428569be..9c6f638119 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -10188,6 +10188,10 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, if (FD->hasAttr()) 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()) - 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()) + Diag(PossibleZeroParamPrototype->getLocation(), + diag::note_declaration_not_a_prototype) + << PossibleZeroParamPrototype + << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); + } + } + } + if (auto *MD = dyn_cast(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. diff --git a/test/SemaCXX/warn-missing-prototypes.cpp b/test/SemaCXX/warn-missing-prototypes.cpp index f7e8db38a4..cb41933602 100644 --- a/test/SemaCXX/warn-missing-prototypes.cpp +++ b/test/SemaCXX/warn-missing-prototypes.cpp @@ -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;