[clang] [Clang][AST] Add source range for deleted and defaulted functions (PR #205408)
Shreyansh Lodha via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 9 05:02:36 PDT 2026
https://github.com/lodha1503 updated https://github.com/llvm/llvm-project/pull/205408
>From 788a78fb0b95a2975d263eb593cb1efc58b82afc Mon Sep 17 00:00:00 2001
From: lodha1503 <lodhashreyansh1603 at gmail.com>
Date: Wed, 24 Jun 2026 00:40:22 +0530
Subject: [PATCH 1/4] [Clang][AST] Add source range for deleted and defaulted
functions
---
clang/lib/Parse/Parser.cpp | 2 ++
.../AST/ast-dump-deleted-defaulted-range.cpp | 33 +++++++++++++++++++
2 files changed, 35 insertions(+)
create mode 100644 clang/test/AST/ast-dump-deleted-defaulted-range.cpp
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 5e1fd4df1a3f0..6bf1315ede69b 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1308,12 +1308,14 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
<< 1 /* deleted */;
BodyKind = Sema::FnBodyKind::Delete;
DeletedMessage = ParseCXXDeletedFunctionMessage();
+ D.SetRangeEnd(PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
} 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;
+ D.SetRangeEnd(PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
}
diff --git a/clang/test/AST/ast-dump-deleted-defaulted-range.cpp b/clang/test/AST/ast-dump-deleted-defaulted-range.cpp
new file mode 100644
index 0000000000000..5eb0a5cecd778
--- /dev/null
+++ b/clang/test/AST/ast-dump-deleted-defaulted-range.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s
+
+void delfunc() = delete;
+// CHECK: FunctionDecl{{.*}} <{{.*}}[[@LINE-1]]:1, col:23> col:6 delfunc 'void ()' delete
+
+struct S {
+ inline S();
+};
+
+inline S::S() = default;
+// CHECK: CXXConstructorDecl{{.*}} <line:[[@LINE-1]]:1, col:23>{{.*}}S 'void ()' inline default
+
+struct v {
+ void f() = delete;
+};
+// CHECK: CXXMethodDecl{{.*}} <line:[[@LINE-2]]:3, col:19> col:8 f 'void ()' delete
+
+class Truck {
+ inline Truck();
+};
+
+inline Truck::Truck() = default;
+// CHECK: CXXConstructorDecl{{.*}} <line:[[@LINE-1]]:1, col:31>{{.*}}Truck 'void ()' inline default
+
+template <class T> void bubbleSort(T a[], int n) = delete;
+// CHECK: FunctionTemplateDecl{{.*}} <line:[[@LINE-1]]:1, col:57> col:25 bubbleSort
+
+template <typename T> class Array {
+public:
+ Array(T arr[], int s);
+ void print() = delete;
+};
+// CHECK: CXXMethodDecl{{.*}} <line:[[@LINE-2]]:5, col:25> col:10 print 'void ()' delete
>From 3ad87ceb3c750ac049f0dadb7b051a8952d53cdf Mon Sep 17 00:00:00 2001
From: lodha1503 <lodhashreyansh1603 at gmail.com>
Date: Fri, 26 Jun 2026 20:33:47 +0530
Subject: [PATCH 2/4] Resolved Comments and fixed delete with message
---
clang/lib/Parse/ParseCXXInlineMethods.cpp | 5 ++---
clang/lib/Parse/Parser.cpp | 2 +-
.../AST/ast-dump-deleted-defaulted-range.cpp | 17 +++++++++--------
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 6189c854e5fbf..8c66d53aea0f4 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -101,7 +101,6 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
bool Delete = false;
SourceLocation KWLoc;
- SourceLocation KWEndLoc = Tok.getEndLoc().getLocWithOffset(-1);
if (TryConsumeToken(tok::kw_delete, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_defaulted_deleted_function
@@ -111,7 +110,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
Actions.SetDeclDeleted(FnD, KWLoc, Message);
Delete = true;
if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
- DeclAsFunction->setRangeEnd(KWEndLoc);
+ DeclAsFunction->setRangeEnd( Message? PrevTokLocation : PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
}
} else if (TryConsumeToken(tok::kw_default, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
@@ -120,7 +119,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
<< 0 /* defaulted */;
Actions.SetDeclDefaulted(FnD, KWLoc);
if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
- DeclAsFunction->setRangeEnd(KWEndLoc);
+ DeclAsFunction->setRangeEnd(PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
}
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 6bf1315ede69b..08b4181243a4b 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1308,7 +1308,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
<< 1 /* deleted */;
BodyKind = Sema::FnBodyKind::Delete;
DeletedMessage = ParseCXXDeletedFunctionMessage();
- D.SetRangeEnd(PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
+ D.SetRangeEnd(DeletedMessage? PrevTokLocation: PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
} else if (TryConsumeToken(tok::kw_default, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_defaulted_deleted_function
diff --git a/clang/test/AST/ast-dump-deleted-defaulted-range.cpp b/clang/test/AST/ast-dump-deleted-defaulted-range.cpp
index 5eb0a5cecd778..c2a18f1ce4d2e 100644
--- a/clang/test/AST/ast-dump-deleted-defaulted-range.cpp
+++ b/clang/test/AST/ast-dump-deleted-defaulted-range.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s
+// RUN: %clang_cc1 -ast-dump %s | FileCheck %s
void delfunc() = delete;
// CHECK: FunctionDecl{{.*}} <{{.*}}[[@LINE-1]]:1, col:23> col:6 delfunc 'void ()' delete
@@ -15,13 +15,6 @@ struct v {
};
// CHECK: CXXMethodDecl{{.*}} <line:[[@LINE-2]]:3, col:19> col:8 f 'void ()' delete
-class Truck {
- inline Truck();
-};
-
-inline Truck::Truck() = default;
-// CHECK: CXXConstructorDecl{{.*}} <line:[[@LINE-1]]:1, col:31>{{.*}}Truck 'void ()' inline default
-
template <class T> void bubbleSort(T a[], int n) = delete;
// CHECK: FunctionTemplateDecl{{.*}} <line:[[@LINE-1]]:1, col:57> col:25 bubbleSort
@@ -31,3 +24,11 @@ template <typename T> class Array {
void print() = delete;
};
// CHECK: CXXMethodDecl{{.*}} <line:[[@LINE-2]]:5, col:25> col:10 print 'void ()' delete
+
+void delfunc2() = delete("reason");
+// CHECK: FunctionDecl{{.*}} <{{.*}}[[@LINE-1]]:1, col:34> col:6 delfunc2 'void ()' delete
+
+struct w {
+ void g() = delete("reason");
+};
+// CHECK: CXXMethodDecl{{.*}} <line:[[@LINE-2]]:3, col:29> col:8 g 'void ()' delete
>From 228533290137e4f617be07ddc7010a73a474127a Mon Sep 17 00:00:00 2001
From: lodha1503 <lodhashreyansh1603 at gmail.com>
Date: Sat, 27 Jun 2026 00:56:08 +0530
Subject: [PATCH 3/4] [Clang][AST] Update tests for extended source range of
defaulted functions
---
clang/test/CoverageMapping/default-method.cpp | 2 +-
.../Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/test/CoverageMapping/default-method.cpp b/clang/test/CoverageMapping/default-method.cpp
index beaac0db2fc78..4293d5c5dcf8e 100644
--- a/clang/test/CoverageMapping/default-method.cpp
+++ b/clang/test/CoverageMapping/default-method.cpp
@@ -11,7 +11,7 @@ namespace PR39822 {
};
// CHECK: _ZN7PR398223fooaSERS0_:
- // CHECK-NEXT: File 0, [[@LINE+1]]:28 -> [[@LINE+1]]:29 = #0
+ // CHECK-NEXT: File 0, [[@LINE+1]]:38 -> [[@LINE+1]]:39 = #0
foo &foo::operator=(foo &) = default;
} // namespace PR39822
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
index 1eeb3df81a316..18de085973195 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
@@ -34,9 +34,9 @@ TEST(RecursiveASTVisitor, CXXMethodDeclNoDefaultBodyVisited) {
for (bool VisitImplCode : {false, true}) {
CXXMethodDeclVisitor Visitor(VisitImplCode);
if (VisitImplCode)
- Visitor.ExpectMatch("declref", 8, 28);
+ Visitor.ExpectMatch("declref", 8, 38);
else
- Visitor.DisallowMatch("declref", 8, 28);
+ Visitor.DisallowMatch("declref", 8, 38);
Visitor.ExpectMatch("parm", 8, 27);
llvm::StringRef Code = R"cpp(
>From efb823a78f19327f7173f56caf85746d6306118f Mon Sep 17 00:00:00 2001
From: lodha1503 <lodhashreyansh1603 at gmail.com>
Date: Thu, 9 Jul 2026 15:36:19 +0530
Subject: [PATCH 4/4] clang-format: fix formatting in Parser and
ParseCXXInlineMethods
---
clang/lib/Parse/ParseCXXInlineMethods.cpp | 7 +++++--
clang/lib/Parse/Parser.cpp | 4 +++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index c3013b6848883..77260755ac64e 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -110,7 +110,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
Actions.SetDeclDeleted(FnD, KWLoc, Message);
Delete = true;
if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
- DeclAsFunction->setRangeEnd( Message? PrevTokLocation : PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
+ DeclAsFunction->setRangeEnd(
+ Message ? PrevTokLocation
+ : PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
}
} else if (TryConsumeToken(tok::kw_default, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
@@ -119,7 +121,8 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
<< 0 /* defaulted */;
Actions.SetDeclDefaulted(FnD, KWLoc);
if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) {
- DeclAsFunction->setRangeEnd(PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
+ DeclAsFunction->setRangeEnd(
+ PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
}
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 08b4181243a4b..62b1a8a24c17f 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1308,7 +1308,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
<< 1 /* deleted */;
BodyKind = Sema::FnBodyKind::Delete;
DeletedMessage = ParseCXXDeletedFunctionMessage();
- D.SetRangeEnd(DeletedMessage? PrevTokLocation: PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
+ D.SetRangeEnd(DeletedMessage
+ ? PrevTokLocation
+ : PP.getLocForEndOfToken(KWLoc).getLocWithOffset(-1));
} else if (TryConsumeToken(tok::kw_default, KWLoc)) {
Diag(KWLoc, getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_defaulted_deleted_function
More information about the cfe-commits
mailing list