https://github.com/zwuis updated 
https://github.com/llvm/llvm-project/pull/197680

>From 76ee55be130870c9f8f0c0add41a3f239cfae916 Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <[email protected]>
Date: Thu, 14 May 2026 21:26:01 +0800
Subject: [PATCH 1/2] Add missing location information of `decltype` specifier
 in destructor call to AST

---
 clang/lib/Sema/SemaExprCXX.cpp                 |  6 +++++-
 clang/test/AST/ast-dump-expr-json.cpp          |  4 ++--
 clang/test/AST/ast-dump-expr.cpp               |  2 +-
 .../unittests/Tooling/Syntax/BuildTreeTest.cpp | 18 ++++++++----------
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 357ceb7f4ea6d..e33b0b9578973 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -479,7 +479,11 @@ ParsedType Sema::getDestructorTypeForDecltype(const 
DeclSpec &DS,
     return nullptr;
   }
 
-  return ParsedType::make(T);
+  TypeLocBuilder TLB;
+  DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
+  DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc());
+  DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd());
+  return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
 }
 
 bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
diff --git a/clang/test/AST/ast-dump-expr-json.cpp 
b/clang/test/AST/ast-dump-expr-json.cpp
index 1415cecd58d36..4eabd5a84248e 100644
--- a/clang/test/AST/ast-dump-expr-json.cpp
+++ b/clang/test/AST/ast-dump-expr-json.cpp
@@ -3208,8 +3208,8 @@ void TestNonADLCall3() {
 // CHECK-NEXT:          "tokLen": 1
 // CHECK-NEXT:         },
 // CHECK-NEXT:         "end": {
-// CHECK-NEXT:          "offset": 1693,
-// CHECK-NEXT:          "col": 5,
+// CHECK-NEXT:          "offset": 1704,
+// CHECK-NEXT:          "col": 16,
 // CHECK-NEXT:          "tokLen": 1
 // CHECK-NEXT:         }
 // CHECK-NEXT:        },
diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp
index 7a686b28d80d1..e19c6d4b12451 100644
--- a/clang/test/AST/ast-dump-expr.cpp
+++ b/clang/test/AST/ast-dump-expr.cpp
@@ -216,7 +216,7 @@ void PostfixExpressions(S a, S *p, U<int> *r) {
   // the construct above.
   a.~decltype(a)();
   // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:18> 'void'
-  // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:5> '<bound member function 
type>' .~S 0x{{[^ ]*}}
+  // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:16> '<bound member 
function type>' .~S 0x{{[^ ]*}}
   // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'S' lvalue ParmVar 0x{{[^ 
]*}} 'a' 'S'
 
   p->::S::~S();
diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp 
b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
index d58e190923a1f..aea1a149ed85b 100644
--- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
+++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp
@@ -671,10 +671,6 @@ TEST_P(BuildSyntaxTreeTest, 
UnqualifiedId_DecltypeDestructor) {
       R"cpp(
 struct X { };
 void test(X x) {
-  // FIXME: Make `decltype(x)` a child of `MemberExpression`. It is currently
-  // not because `Expr::getSourceRange()` returns the range of `x.~` for the
-  // `MemberExpr` instead of the expected `x.~decltype(x)`, this is a bug in
-  // clang.
   [[x.~decltype(x)()]];
 }
 )cpp",
@@ -687,12 +683,14 @@ CallExpression Expression
 | |-'.' AccessToken
 | `-IdExpression Member
 |   `-UnqualifiedId UnqualifiedId
-|     `-'~'
-|-'decltype'
-|-'('
-|-'x'
-|-')'
-|-'('
+|     |-'~'
+|     |-'decltype'
+|     |-'('
+|     |-IdExpression
+|     | `-UnqualifiedId UnqualifiedId
+|     |   `-'x'
+|     `-')'
+|-'(' OpenParen
 `-')' CloseParen
 )txt"}));
 }

>From b68e0a3868998784517b61def41b2c8c16397023 Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <[email protected]>
Date: Sat, 16 May 2026 19:32:24 +0800
Subject: [PATCH 2/2] Remove redundant null checks, add a release note, and fix
 outdated documentation

---
 clang-tools-extra/clangd/Selection.cpp        | 14 +++--------
 .../clangd/SemanticHighlighting.cpp           | 25 +++++++++----------
 clang/docs/ReleaseNotes.rst                   |  1 +
 clang/include/clang/AST/DeclarationName.h     |  4 +--
 4 files changed, 19 insertions(+), 25 deletions(-)

diff --git a/clang-tools-extra/clangd/Selection.cpp 
b/clang-tools-extra/clangd/Selection.cpp
index 21c9e71d3db65..b79ffc7d5a6e9 100644
--- a/clang-tools-extra/clangd/Selection.cpp
+++ b/clang-tools-extra/clangd/Selection.cpp
@@ -895,19 +895,13 @@ class SelectionVisitor : public 
RecursiveASTVisitor<SelectionVisitor> {
     // rather than the TypeLoc nested inside it.
     // We still traverse the TypeLoc, because it may contain other targeted
     // things like the T in ~Foo<T>().
-    // FIXME: Investigate if getNamedTypeInfo() can still return null for
-    // invalid cases, and drop these checks when it never returns null.
-    if (const auto *CDD = N.get<CXXDestructorDecl>()) {
-      if (auto *TypeInfo = CDD->getNameInfo().getNamedTypeInfo())
-        return TypeInfo->getTypeLoc().getBeginLoc();
-    }
+    if (const auto *CDD = N.get<CXXDestructorDecl>())
+      return CDD->getNameInfo().getNamedTypeInfo()->getTypeLoc().getBeginLoc();
     if (const auto *ME = N.get<MemberExpr>()) {
       auto NameInfo = ME->getMemberNameInfo();
       if (NameInfo.getName().getNameKind() ==
-          DeclarationName::CXXDestructorName) {
-        if (auto *TypeInfo = NameInfo.getNamedTypeInfo())
-          return TypeInfo->getTypeLoc().getBeginLoc();
-      }
+          DeclarationName::CXXDestructorName)
+        return NameInfo.getNamedTypeInfo()->getTypeLoc().getBeginLoc();
     }
 
     return SourceRange();
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp 
b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index 751ee254d3623..d1ed3ea9bc88a 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -789,13 +789,12 @@ class CollectExtraHighlightings
   }
 
   bool VisitCXXDestructorDecl(CXXDestructorDecl *D) {
-    if (auto *TI = D->getNameInfo().getNamedTypeInfo()) {
-      SourceLocation Loc = TI->getTypeLoc().getBeginLoc();
-      H.addExtraModifier(Loc, HighlightingModifier::ConstructorOrDestructor);
-      H.addExtraModifier(Loc, HighlightingModifier::Declaration);
-      if (D->isThisDeclarationADefinition())
-        H.addExtraModifier(Loc, HighlightingModifier::Definition);
-    }
+    SourceLocation Loc =
+        D->getNameInfo().getNamedTypeInfo()->getTypeLoc().getBeginLoc();
+    H.addExtraModifier(Loc, HighlightingModifier::ConstructorOrDestructor);
+    H.addExtraModifier(Loc, HighlightingModifier::Declaration);
+    if (D->isThisDeclarationADefinition())
+      H.addExtraModifier(Loc, HighlightingModifier::Definition);
     return true;
   }
 
@@ -804,12 +803,12 @@ class CollectExtraHighlightings
     // `(foo.*pointer_to_member_fun)(arg);`
     if (auto *D = CE->getMethodDecl()) {
       if (isa<CXXDestructorDecl>(D)) {
-        if (auto *ME = dyn_cast<MemberExpr>(CE->getCallee())) {
-          if (auto *TI = ME->getMemberNameInfo().getNamedTypeInfo()) {
-            H.addExtraModifier(TI->getTypeLoc().getBeginLoc(),
-                               HighlightingModifier::ConstructorOrDestructor);
-          }
-        }
+        if (auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
+          H.addExtraModifier(ME->getMemberNameInfo()
+                                 .getNamedTypeInfo()
+                                 ->getTypeLoc()
+                                 .getBeginLoc(),
+                             HighlightingModifier::ConstructorOrDestructor);
       } else if (D->isOverloadedOperator()) {
         if (auto *ME = dyn_cast<MemberExpr>(CE->getCallee()))
           H.addToken(
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a9884beee2710..3f23cd852cffa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -619,6 +619,7 @@ Bug Fixes to AST Handling
 - Fixed a crash when parsing Doxygen ``@param`` commands attached to invalid 
declarations or non-function entities. (#GH182737)
 - Fixed the SourceLocation and SourceRange of reversed rewritten 
CXXOperatorCallExpr. (#GH192467)
 - Fixed a assertion when ``__block`` is used on global variables in C mode. 
(#GH183974)
+- Added missing AST nodes representing the ``decltype`` specifiers in 
destructor call to AST.
 
 Miscellaneous Bug Fixes
 ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/DeclarationName.h 
b/clang/include/clang/AST/DeclarationName.h
index a7185f5bce04b..56d66e1b5e110 100644
--- a/clang/include/clang/AST/DeclarationName.h
+++ b/clang/include/clang/AST/DeclarationName.h
@@ -830,8 +830,8 @@ struct DeclarationNameInfo {
   const DeclarationNameLoc &getInfo() const { return LocInfo; }
   void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; }
 
-  /// getNamedTypeInfo - Returns the source type info associated to
-  /// the name. Assumes it is a constructor, destructor or conversion.
+  /// @return The type source info associated to the name if it is a
+  /// constructor, destructor or conversion function, `nullptr` otherwise.
   TypeSourceInfo *getNamedTypeInfo() const {
     if (Name.getNameKind() != DeclarationName::CXXConstructorName &&
         Name.getNameKind() != DeclarationName::CXXDestructorName &&

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to