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
