Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -2902,9 +2902,11 @@ SkipBodyInfo *SkipBody = nullptr); Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, - SkipBodyInfo *SkipBody = nullptr); + SkipBodyInfo *SkipBody = nullptr, + bool FnDeleted = false); Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D, - SkipBodyInfo *SkipBody = nullptr); + SkipBodyInfo *SkipBody = nullptr, + bool FnDeleted = false); void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D); ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr); ExprResult ActOnRequiresClause(ExprResult ConstraintExpr); Index: clang/lib/Parse/Parser.cpp =================================================================== --- clang/lib/Parse/Parser.cpp +++ clang/lib/Parse/Parser.cpp @@ -1302,11 +1302,13 @@ // Tell the actions module that we have entered a function definition with the // specified Declarator for the function. Sema::SkipBodyInfo SkipBody; + bool Delete = + Tok.is(tok::equal) && NextToken().is(tok::kw_delete) ? true : false; Decl *Res = Actions.ActOnStartOfFunctionDef(getCurScope(), D, TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams : MultiTemplateParamsArg(), - &SkipBody); + &SkipBody, Delete); if (SkipBody.ShouldSkip) { SkipFunctionBody(); @@ -1332,7 +1334,6 @@ if (TryConsumeToken(tok::equal)) { assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='"); - bool Delete = false; SourceLocation KWLoc; if (TryConsumeToken(tok::kw_delete, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -14185,7 +14185,7 @@ Decl * Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, - SkipBodyInfo *SkipBody) { + SkipBodyInfo *SkipBody, bool FnDeleted) { assert(getCurFunctionDecl() == nullptr && "Function parsing confused"); assert(D.isFunctionDeclarator() && "Not a function declarator!"); Scope *ParentScope = FnBodyScope->getParent(); @@ -14204,7 +14204,7 @@ D.setFunctionDefinitionKind(FunctionDefinitionKind::Definition); Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists); - Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody); + Decl *Dcl = ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody, FnDeleted); if (!Bases.empty()) ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Dcl, Bases); @@ -14380,7 +14380,7 @@ } Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, - SkipBodyInfo *SkipBody) { + SkipBodyInfo *SkipBody, bool FnDeleted) { if (!D) { // Parsing the function declaration failed in some way. Push on a fake scope // anyway so we can try to parse the function body. @@ -14470,10 +14470,11 @@ } // The return type of a function definition must be complete - // (C99 6.9.1p3, C++ [dcl.fct]p6). + // unless the function is deleted + // (C99 6.9.1p3, C++ [dcl.fct.def.general]p2). QualType ResultType = FD->getReturnType(); if (!ResultType->isDependentType() && !ResultType->isVoidType() && - !FD->isInvalidDecl() && + !FD->isInvalidDecl() && !FnDeleted && RequireCompleteType(FD->getLocation(), ResultType, diag::err_func_def_incomplete_result)) FD->setInvalidDecl(); @@ -14482,8 +14483,9 @@ PushDeclContext(FnBodyScope, FD); // Check the validity of our function parameters - CheckParmsForFunctionDef(FD->parameters(), - /*CheckParameterNames=*/true); + if (!FnDeleted) + CheckParmsForFunctionDef(FD->parameters(), + /*CheckParameterNames=*/true); // Add non-parameter declarations already in the function to the current // scope. Index: clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.general/p2.cpp =================================================================== --- /dev/null +++ clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.general/p2.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct Incomplete; // expected-note 4{{forward declaration of 'Incomplete'}} +Incomplete f(Incomplete) = delete; // well-formed +Incomplete g(Incomplete) {} // expected-error{{incomplete result type 'Incomplete' in function definition}}\ +// expected-error{{variable has incomplete type 'Incomplete'}} + +struct C { + Incomplete f(Incomplete) = delete; // well-formed + Incomplete g(Incomplete) {} // expected-error{{incomplete result type 'Incomplete' in function definition}}\ + // expected-error{{variable has incomplete type 'Incomplete'}} +};