https://github.com/SoulTch updated https://github.com/llvm/llvm-project/pull/218168
>From ef349a25d53f6f196ad11d016e26d6c882d9375d Mon Sep 17 00:00:00 2001 From: Jeongjin Lee <[email protected]> Date: Sat, 22 Aug 2026 17:32:21 -0400 Subject: [PATCH 1/3] [Clang] Mark the declaration invalid when a function definition has no body Fixes #194298 Assisted-by: Claude Opus 5 (Claude Code) --- clang/lib/Parse/ParseCXXInlineMethods.cpp | 1 + clang/lib/Parse/ParseTemplate.cpp | 4 +++- clang/lib/Parse/Parser.cpp | 2 ++ clang/test/SemaCXX/coroutines.cpp | 8 ++++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 3f101feb26a6d..51591011ca548 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -633,6 +633,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { // Error recovery. if (!Tok.is(tok::l_brace)) { FnScope.Exit(); + LM.D->getAsFunction()->setInvalidDecl(); Actions.ActOnFinishFunctionBody(LM.D, nullptr); return; } diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 735a9bd1f9f1c..e69d953215e89 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -1517,8 +1517,10 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { "current template being instantiated!"); ParseFunctionStatementBody(LPT.D, FnScope); Actions.UnmarkAsLateParsedTemplate(FunD); - } else + } else { + FunD->setInvalidDecl(); Actions.ActOnFinishFunctionBody(LPT.D, nullptr); + } } } diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index bad81ea92cd2d..5c39ba2ad71a1 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1407,6 +1407,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Recover from error. if (!Tok.is(tok::l_brace)) { BodyScope.Exit(); + if (Res) + Res->getAsFunction()->setInvalidDecl(); Actions.ActOnFinishFunctionBody(Res, nullptr); return Res; } diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp index 4cef2f2b7ea0f..19b2ce1678e1f 100644 --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -1566,3 +1566,11 @@ void g() { } } + +namespace GH194298 { +// https://github.com/llvm/llvm-project/issues/194298 +coro<promise_void> f1() : bar { co_await suspend_always{} }; // expected-error {{only constructors take base initializers}} +coro<promise> f2() : bar { co_yield 0 }; // expected-error {{only constructors take base initializers}} +coro<promise_void> f3() : bar { co_return }; // expected-error {{expected expression}} \ + // expected-error {{only constructors take base initializers}} +} >From 9bf413f28cd56584c112a80ce21098b7ff2847f8 Mon Sep 17 00:00:00 2001 From: SoulTch <[email protected]> Date: Sun, 23 Aug 2026 21:08:57 -0400 Subject: [PATCH 2/3] Add coroutine tests for base initializers Added test cases for coroutine base initializers. --- clang/test/SemaCXX/coroutines.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/test/SemaCXX/coroutines.cpp b/clang/test/SemaCXX/coroutines.cpp index 19b2ce1678e1f..207378256859d 100644 --- a/clang/test/SemaCXX/coroutines.cpp +++ b/clang/test/SemaCXX/coroutines.cpp @@ -1568,7 +1568,6 @@ void g() { } namespace GH194298 { -// https://github.com/llvm/llvm-project/issues/194298 coro<promise_void> f1() : bar { co_await suspend_always{} }; // expected-error {{only constructors take base initializers}} coro<promise> f2() : bar { co_yield 0 }; // expected-error {{only constructors take base initializers}} coro<promise_void> f3() : bar { co_return }; // expected-error {{expected expression}} \ >From 2d1bac3114b4d9664753530d932ca03cf52f50f1 Mon Sep 17 00:00:00 2001 From: Jeongjin Lee <[email protected]> Date: Wed, 26 Aug 2026 16:52:07 -0400 Subject: [PATCH 3/3] [Clang] Factor out function body parsing into Parser::ParseFunctionBody Assisted-by: Claude Opus 5 (Claude Code) --- clang/include/clang/Parse/Parser.h | 11 ++++++++ clang/lib/Parse/ParseCXXInlineMethods.cpp | 19 +------------- clang/lib/Parse/ParseTemplate.cpp | 31 +++++++---------------- clang/lib/Parse/Parser.cpp | 20 +++++++++------ 4 files changed, 33 insertions(+), 48 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 163aa483a84e3..207847f6d8057 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -7731,6 +7731,17 @@ class Parser : public CodeCompletionHandler { /// Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope); + /// ParseFunctionBody - Parse the body of a function definition. The + /// '= default' and '= delete' forms are handled by the caller. + /// + /// \verbatim + /// function-body: + /// ctor-initializer[opt] compound-statement + /// function-try-block + /// \endverbatim + /// + Decl *ParseFunctionBody(Decl *D, ParseScope &BodyScope); + /// When in code-completion, skip parsing of the function/method body /// unless the body contains the code-completion point. /// diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 51591011ca548..0340540b239cd 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -623,23 +623,6 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { Actions.ActOnFinishInlineFunctionDef(FD); }); - if (Tok.is(tok::kw_try)) { - ParseFunctionTryBlock(LM.D, FnScope); - return; - } - if (Tok.is(tok::colon)) { - ParseConstructorInitializer(LM.D); - - // Error recovery. - if (!Tok.is(tok::l_brace)) { - FnScope.Exit(); - LM.D->getAsFunction()->setInvalidDecl(); - Actions.ActOnFinishFunctionBody(LM.D, nullptr); - return; - } - } else - Actions.ActOnDefaultCtorInitializers(LM.D); - assert((Actions.getDiagnostics().hasErrorOccurred() || !isa<FunctionTemplateDecl>(LM.D) || cast<FunctionTemplateDecl>(LM.D)->getTemplateParameters()->getDepth() @@ -647,7 +630,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { "TemplateParameterDepth should be greater than the depth of " "current template being instantiated!"); - ParseFunctionStatementBody(LM.D, FnScope); + ParseFunctionBody(LM.D, FnScope); } void Parser::ParseLexedMemberInitializers(ParsingClass &Class) { diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index e69d953215e89..abb7e20c4602e 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -1500,28 +1500,15 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { Actions.ActOnStartOfFunctionDef(getCurScope(), FunD); - if (Tok.is(tok::kw_try)) { - ParseFunctionTryBlock(LPT.D, FnScope); - } else { - if (Tok.is(tok::colon)) - ParseConstructorInitializer(LPT.D); - else - Actions.ActOnDefaultCtorInitializers(LPT.D); - - if (Tok.is(tok::l_brace)) { - assert((!isa<FunctionTemplateDecl>(LPT.D) || - cast<FunctionTemplateDecl>(LPT.D) - ->getTemplateParameters() - ->getDepth() == TemplateParameterDepth - 1) && - "TemplateParameterDepth should be greater than the depth of " - "current template being instantiated!"); - ParseFunctionStatementBody(LPT.D, FnScope); - Actions.UnmarkAsLateParsedTemplate(FunD); - } else { - FunD->setInvalidDecl(); - Actions.ActOnFinishFunctionBody(LPT.D, nullptr); - } - } + assert((!isa<FunctionTemplateDecl>(LPT.D) || + cast<FunctionTemplateDecl>(LPT.D) + ->getTemplateParameters() + ->getDepth() == TemplateParameterDepth - 1) && + "TemplateParameterDepth should be greater than the depth of " + "current template being instantiated!"); + + ParseFunctionBody(LPT.D, FnScope); + Actions.UnmarkAsLateParsedTemplate(FunD); } void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) { diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 5c39ba2ad71a1..3685de2d5aa28 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1396,26 +1396,30 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return Actions.ActOnFinishFunctionBody(Res, nullptr, false); } + return ParseFunctionBody(Res, BodyScope); +} + +Decl *Parser::ParseFunctionBody(Decl *D, ParseScope &BodyScope) { if (Tok.is(tok::kw_try)) - return ParseFunctionTryBlock(Res, BodyScope); + return ParseFunctionTryBlock(D, BodyScope); // If we have a colon, then we're probably parsing a C++ // ctor-initializer. if (Tok.is(tok::colon)) { - ParseConstructorInitializer(Res); + ParseConstructorInitializer(D); // Recover from error. if (!Tok.is(tok::l_brace)) { BodyScope.Exit(); - if (Res) - Res->getAsFunction()->setInvalidDecl(); - Actions.ActOnFinishFunctionBody(Res, nullptr); - return Res; + if (D) + D->getAsFunction()->setInvalidDecl(); + Actions.ActOnFinishFunctionBody(D, nullptr); + return D; } } else - Actions.ActOnDefaultCtorInitializers(Res); + Actions.ActOnDefaultCtorInitializers(D); - return ParseFunctionStatementBody(Res, BodyScope); + return ParseFunctionStatementBody(D, BodyScope); } void Parser::SkipFunctionBody() { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
