rZhBoYao updated this revision to Diff 421338.
rZhBoYao retitled this revision from "[Clang] Diagnose incomplete return/param
types only when function is not deleted" to "[Clang] CWG 1394: Incomplete types
as parameters of deleted functions".
rZhBoYao edited the summary of this revision.
rZhBoYao removed a reviewer: rtrieu.
rZhBoYao set the repository for this revision to rG LLVM Github Monorepo.
rZhBoYao added a comment.
Updating the status of CWG 1394 is the only change.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D122981/new/
https://reviews.llvm.org/D122981
Files:
clang/include/clang/Sema/Sema.h
clang/lib/Parse/Parser.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.general/p2.cpp
clang/www/cxx_dr_status.html
Index: clang/www/cxx_dr_status.html
===================================================================
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -8178,7 +8178,7 @@
<td><a href="https://wg21.link/cwg1394">1394</a></td>
<td>CD3</td>
<td>Incomplete types as parameters of deleted functions</td>
- <td class="none" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 15</td>
</tr>
<tr id="1395">
<td><a href="https://wg21.link/cwg1395">1395</a></td>
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,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct Incomplete; // expected-note 2{{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'}}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -17379,6 +17379,21 @@
}
}
+void Sema::SetFunctionBodyKind(Decl *D, SourceLocation Loc,
+ FnBodyKind BodyKind) {
+ switch (BodyKind) {
+ case FnBodyKind::Delete:
+ SetDeclDeleted(D, Loc);
+ break;
+ case FnBodyKind::Default:
+ SetDeclDefaulted(D, Loc);
+ break;
+ case FnBodyKind::Other:
+ llvm_unreachable(
+ "Parsed function body should be '= delete;' or '= default;'");
+ }
+}
+
bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
const auto *NewFT = New->getType()->castAs<FunctionProtoType>();
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, FnBodyKind BodyKind) {
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, BodyKind);
if (!Bases.empty())
ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Dcl, Bases);
@@ -14380,7 +14380,8 @@
}
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
- SkipBodyInfo *SkipBody) {
+ SkipBodyInfo *SkipBody,
+ FnBodyKind BodyKind) {
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.
@@ -14469,11 +14470,11 @@
}
}
- // The return type of a function definition must be complete
- // (C99 6.9.1p3, C++ [dcl.fct]p6).
+ // The return type of a function definition must be complete (C99 6.9.1p3),
+ // unless the function is deleted (C++ specifc, C++ [dcl.fct.def.general]p2)
QualType ResultType = FD->getReturnType();
if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
- !FD->isInvalidDecl() &&
+ !FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete &&
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 (BodyKind != FnBodyKind::Delete)
+ CheckParmsForFunctionDef(FD->parameters(),
+ /*CheckParameterNames=*/true);
// Add non-parameter declarations already in the function to the current
// scope.
Index: clang/lib/Parse/Parser.cpp
===================================================================
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -1299,6 +1299,41 @@
ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
+ // Parse function body eagerly if it is either '= delete;' or '= default;' as
+ // ActOnStartOfFunctionDef needs to know whether the function is deleted.
+ Sema::FnBodyKind BodyKind = Sema::FnBodyKind::Other;
+ SourceLocation KWLoc;
+ if (TryConsumeToken(tok::equal)) {
+ assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
+
+ if (TryConsumeToken(tok::kw_delete, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_defaulted_deleted_function
+ : diag::ext_defaulted_deleted_function)
+ << 1 /* deleted */;
+ BodyKind = Sema::FnBodyKind::Delete;
+ } else if (TryConsumeToken(tok::kw_default, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_defaulted_deleted_function
+ : diag::ext_defaulted_deleted_function)
+ << 0 /* defaulted */;
+ BodyKind = Sema::FnBodyKind::Default;
+ } else {
+ llvm_unreachable("function definition after = not 'delete' or 'default'");
+ }
+
+ if (Tok.is(tok::comma)) {
+ Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
+ << (BodyKind == Sema::FnBodyKind::Delete);
+ SkipUntil(tok::semi);
+ } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ BodyKind == Sema::FnBodyKind::Delete
+ ? "delete"
+ : "default")) {
+ SkipUntil(tok::semi);
+ }
+ }
+
// Tell the actions module that we have entered a function definition with the
// specified Declarator for the function.
Sema::SkipBodyInfo SkipBody;
@@ -1306,10 +1341,13 @@
TemplateInfo.TemplateParams
? *TemplateInfo.TemplateParams
: MultiTemplateParamsArg(),
- &SkipBody);
+ &SkipBody, BodyKind);
if (SkipBody.ShouldSkip) {
- SkipFunctionBody();
+ // Do NOT enter SkipFunctionBody if we already consumed the tokens.
+ if (BodyKind == Sema::FnBodyKind::Other)
+ SkipFunctionBody();
+
return Res;
}
@@ -1320,6 +1358,13 @@
// safe because we're always the sole owner.
D.getMutableDeclSpec().abort();
+ if (BodyKind != Sema::FnBodyKind::Other) {
+ Actions.SetFunctionBodyKind(Res, KWLoc, BodyKind);
+ Stmt *GeneratedBody = Res ? Res->getBody() : nullptr;
+ Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false);
+ return Res;
+ }
+
// With abbreviated function templates - we need to explicitly add depth to
// account for the implicit template parameter list induced by the template.
if (auto *Template = dyn_cast_or_null<FunctionTemplateDecl>(Res))
@@ -1329,42 +1374,6 @@
// parameter list was specified.
CurTemplateDepthTracker.addDepth(1);
- 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
- ? diag::warn_cxx98_compat_defaulted_deleted_function
- : diag::ext_defaulted_deleted_function)
- << 1 /* deleted */;
- Actions.SetDeclDeleted(Res, KWLoc);
- Delete = true;
- } else if (TryConsumeToken(tok::kw_default, KWLoc)) {
- Diag(KWLoc, getLangOpts().CPlusPlus11
- ? diag::warn_cxx98_compat_defaulted_deleted_function
- : diag::ext_defaulted_deleted_function)
- << 0 /* defaulted */;
- Actions.SetDeclDefaulted(Res, KWLoc);
- } else {
- llvm_unreachable("function definition after = not 'delete' or 'default'");
- }
-
- if (Tok.is(tok::comma)) {
- Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
- << Delete;
- SkipUntil(tok::semi);
- } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
- Delete ? "delete" : "default")) {
- SkipUntil(tok::semi);
- }
-
- Stmt *GeneratedBody = Res ? Res->getBody() : nullptr;
- Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false);
- return Res;
- }
-
if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) &&
trySkippingFunctionBody()) {
BodyScope.Exit();
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -2895,6 +2895,20 @@
void ActOnDocumentableDecl(Decl *D);
void ActOnDocumentableDecls(ArrayRef<Decl *> Group);
+ enum class FnBodyKind {
+ /// C++ [dcl.fct.def.general]p1
+ /// function-body:
+ /// = delete ;
+ /// = default ;
+ Delete,
+ Default,
+
+ /// Could be one of:
+ /// ctor-initializer[opt] compound-statement
+ /// function-try-block
+ Other
+ };
+
void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
SourceLocation LocAfterDecls);
void CheckForFunctionRedefinition(
@@ -2902,9 +2916,12 @@
SkipBodyInfo *SkipBody = nullptr);
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParamLists,
- SkipBodyInfo *SkipBody = nullptr);
+ SkipBodyInfo *SkipBody = nullptr,
+ FnBodyKind BodyKind = FnBodyKind::Other);
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
- SkipBodyInfo *SkipBody = nullptr);
+ SkipBodyInfo *SkipBody = nullptr,
+ FnBodyKind BodyKind = FnBodyKind::Other);
+ void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind);
void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits