Author: Yanzuo Liu Date: 2026-05-26T22:03:32+08:00 New Revision: ca9884dd065961cb112f4940b3f80339765a0104
URL: https://github.com/llvm/llvm-project/commit/ca9884dd065961cb112f4940b3f80339765a0104 DIFF: https://github.com/llvm/llvm-project/commit/ca9884dd065961cb112f4940b3f80339765a0104.diff LOG: [clang] Add missing type source info of `decltype` specifier in destructor call to AST (#197680) The type source info will be stored in `MemberExpr::MemberDNLoc`. This patch fixes the underlying issue of #195788. Added: Modified: clang-tools-extra/clangd/Selection.cpp clang-tools-extra/clangd/SemanticHighlighting.cpp clang/docs/ReleaseNotes.rst clang/include/clang/AST/DeclarationName.h clang/lib/Sema/SemaExprCXX.cpp clang/test/AST/ast-dump-expr-json.cpp clang/test/AST/ast-dump-expr.cpp clang/unittests/Tooling/Syntax/BuildTreeTest.cpp Removed: ################################################################################ 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 cef93e25f1e7d..fb70b83d6a7c4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -687,6 +687,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 && diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index db1cf1fb6eaa0..a60e1b84d3e4b 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"})); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
