https://github.com/Samhitha1212 created https://github.com/llvm/llvm-project/pull/167007
### Summary Fixes incorrect source range for default/delete function definations outside struct/class. ### Description Previously, function and constructor definitions written outside the class body using '= delete' or '= default' had incorrect SourceRange end locations in the AST. This patch updates Parser.cpp to record the end location of the keyword token and apply it after Sema finalization. Includes new tests under clang/test/Parser/deleted_defaulted_func_range.cpp >From bc7eaa94dbfc0b413c2bdd7c47f4073757e134f0 Mon Sep 17 00:00:00 2001 From: ShravaniRamanolla <[email protected]> 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<FunctionDecl>(D)) { + FD->setRangeEnd(FuncRangeEnd); + } else if (auto *FT = dyn_cast<FunctionTemplateDecl>(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<FunctionDecl>(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 <[email protected]> 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 <typename T> +class U { + U(); + ~U(); +}; + +//CHECK: CXXConstructorDecl {{.*}} <{{.*}}:24:1, line:25:19> {{.*}} +template <typename T> +U<T>::U() = default; +//CHECK: CXXDestructorDecl {{.*}} <{{.*}}:27:1, line:28:20> {{.*}} +template <typename T> +U<T>::~U() = default; \ No newline at end of file >From cec4c3c1e4179ffc23c7992955474318b665f2f4 Mon Sep 17 00:00:00 2001 From: PoojithaGopu <[email protected]> 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'"); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
