From bc7eaa94dbfc0b413c2bdd7c47f4073757e134f0 Mon Sep 17 00:00:00 2001 From: ShravaniRamanolla Date: Fri, 7 Nov 2025 00:53:23 +0530 Subject: [PATCH 1/3] [clang][Parser] Fix FunctionDecl source range for out-of-class '= delete'/'= default' definitions --- clang/lib/Parse/Parser.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index a6fc676f23a51..446a74177ea36 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/STLForwardCompat.h" #include "llvm/Support/Path.h" #include "llvm/Support/TimeProfiler.h" +#include "clang/Lex/Lexer.h" using namespace clang; @@ -1331,6 +1332,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, StringLiteral *DeletedMessage = nullptr; Sema::FnBodyKind BodyKind = Sema::FnBodyKind::Other; SourceLocation KWLoc; + SourceLocation FuncRangeEnd; if (TryConsumeToken(tok::equal)) { assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='"); @@ -1341,12 +1343,15 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, << 1 /* deleted */; BodyKind = Sema::FnBodyKind::Delete; DeletedMessage = ParseCXXDeletedFunctionMessage(); + FuncRangeEnd = clang::Lexer::getLocForEndOfToken(KWLoc, 0, PP.getSourceManager(), getLangOpts()); + } 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; + FuncRangeEnd = clang::Lexer::getLocForEndOfToken(KWLoc, 0, PP.getSourceManager(), getLangOpts()); } else { llvm_unreachable("function definition after = not 'delete' or 'default'"); } @@ -1374,6 +1379,18 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, : MultiTemplateParamsArg(), &SkipBody, BodyKind); + auto updateFuncRangeEnd = [&](Decl *D) { + if (!FuncRangeEnd.isValid() || !D) + return; + if (auto *FD = dyn_cast(D)) { + FD->setRangeEnd(FuncRangeEnd); + } else if (auto *FT = dyn_cast(D)) { + if (auto *InnerFD = FT->getTemplatedDecl()) + InnerFD->setRangeEnd(FuncRangeEnd); + } + }; + + if (SkipBody.ShouldSkip) { // Do NOT enter SkipFunctionBody if we already consumed the tokens. if (BodyKind == Sema::FnBodyKind::Other) @@ -1390,6 +1407,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // and PopExpressionEvaluationContext(). if (!isLambdaCallOperator(dyn_cast_if_present(Res))) Actions.PopExpressionEvaluationContext(); + + updateFuncRangeEnd(Res); return Res; } @@ -1404,6 +1423,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, Actions.SetFunctionBodyKind(Res, KWLoc, BodyKind, DeletedMessage); Stmt *GeneratedBody = Res ? Res->getBody() : nullptr; Actions.ActOnFinishFunctionBody(Res, GeneratedBody, false); + updateFuncRangeEnd(Res); return Res; } @@ -1424,12 +1444,15 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (SkipFunctionBodies && (!Res || Actions.canSkipFunctionBody(Res)) && trySkippingFunctionBody()) { BodyScope.Exit(); + updateFuncRangeEnd(Res); Actions.ActOnSkippedFunctionBody(Res); return Actions.ActOnFinishFunctionBody(Res, nullptr, false); } - if (Tok.is(tok::kw_try)) + if (Tok.is(tok::kw_try)){ + updateFuncRangeEnd(Res); return ParseFunctionTryBlock(Res, BodyScope); + } // If we have a colon, then we're probably parsing a C++ // ctor-initializer. @@ -1439,12 +1462,14 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Recover from error. if (!Tok.is(tok::l_brace)) { BodyScope.Exit(); + updateFuncRangeEnd(Res); Actions.ActOnFinishFunctionBody(Res, nullptr); return Res; } } else Actions.ActOnDefaultCtorInitializers(Res); + updateFuncRangeEnd(Res); return ParseFunctionStatementBody(Res, BodyScope); } From 5898d0804a68e0d32d4f6c36af1157f501882f85 Mon Sep 17 00:00:00 2001 From: Samhitha1212 Date: Fri, 7 Nov 2025 23:39:03 +0530 Subject: [PATCH 2/3] feat:Added testcase --- .../Parser/deleted_defaulted_func_range.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 clang/test/Parser/deleted_defaulted_func_range.cpp diff --git a/clang/test/Parser/deleted_defaulted_func_range.cpp b/clang/test/Parser/deleted_defaulted_func_range.cpp new file mode 100644 index 0000000000000..bb85a9cf7c243 --- /dev/null +++ b/clang/test/Parser/deleted_defaulted_func_range.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s + +// CHECK: FunctionDecl {{.*}} <{{.*}}:4:1, col:17> {{.*}} +void f() = delete; + + +struct S { + inline S(); + ~S(); +}; + +//CHECK: CXXConstructorDecl {{.*}} <{{.*}}:13:1, col:23> {{.*}} +inline S::S() = default; +//CHECK: CXXDestructorDecl {{.*}} <{{.*}}:15:1, col:17> {{.*}} +S::~S() = default; + +template +class U { + U(); + ~U(); +}; + +//CHECK: CXXConstructorDecl {{.*}} <{{.*}}:24:1, line:25:19> {{.*}} +template +U::U() = default; +//CHECK: CXXDestructorDecl {{.*}} <{{.*}}:27:1, line:28:20> {{.*}} +template +U::~U() = default; \ No newline at end of file From cec4c3c1e4179ffc23c7992955474318b665f2f4 Mon Sep 17 00:00:00 2001 From: PoojithaGopu Date: Fri, 7 Nov 2025 23:50:46 +0530 Subject: [PATCH 3/3] fix: endlocation --- clang/lib/Parse/Parser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 446a74177ea36..7d68821b71b8d 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1343,7 +1343,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, << 1 /* deleted */; BodyKind = Sema::FnBodyKind::Delete; DeletedMessage = ParseCXXDeletedFunctionMessage(); - FuncRangeEnd = clang::Lexer::getLocForEndOfToken(KWLoc, 0, PP.getSourceManager(), getLangOpts()); + FuncRangeEnd = clang::Lexer::getLocForEndOfToken(KWLoc, 0, PP.getSourceManager(), getLangOpts()).getLocWithOffset(-1); } else if (TryConsumeToken(tok::kw_default, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 @@ -1351,7 +1351,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, : diag::ext_defaulted_deleted_function) << 0 /* defaulted */; BodyKind = Sema::FnBodyKind::Default; - FuncRangeEnd = clang::Lexer::getLocForEndOfToken(KWLoc, 0, PP.getSourceManager(), getLangOpts()); + FuncRangeEnd = clang::Lexer::getLocForEndOfToken(KWLoc, 0, PP.getSourceManager(), getLangOpts()).getLocWithOffset(-1); } else { llvm_unreachable("function definition after = not 'delete' or 'default'"); }