[clang] ca9884d - [clang] Add missing type source info of `decltype` specifier in destructor call to AST (#197680)
via cfe-commits
cfe-commits at lists.llvm.org
Tue May 26 07:03:38 PDT 2026
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"}));
}
More information about the cfe-commits
mailing list