diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -2058,6 +2058,7 @@ void foo() { Foo f; f.[[^~]]Foo(); + [[delete]] &f; } )cpp", R"cpp(// Lambda capture initializer diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -362,6 +362,22 @@ Parent, ParentDC, Roles, Relations, E); } + bool VisitCXXDeleteExpr(CXXDeleteExpr *E) { + CXXDestructorDecl *Destructor = nullptr; + if (const Type *T = E->getDestroyedType().getTypePtrOrNull()) { + if (const auto *CRD = T->getAsCXXRecordDecl()) + Destructor = CRD->getDestructor(); + } + if (Destructor) { + SymbolRoleSet Roles{}; + SmallVector Relations; + addCallRole(Roles, Relations); + return IndexCtx.handleReference(Destructor, E->getBeginLoc(), Parent, + ParentDC, Roles, Relations, E); + } + return true; + } + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, DataRecursionQueue *Q = nullptr) { if (E->getOperatorLoc().isInvalid()) diff --git a/clang/test/Index/index-refs.cpp b/clang/test/Index/index-refs.cpp --- a/clang/test/Index/index-refs.cpp +++ b/clang/test/Index/index-refs.cpp @@ -24,6 +24,7 @@ S& operator=(int x); S& operator!=(int x); S& operator()(int x); + ~S(); }; void foo2(S &s) { @@ -32,6 +33,7 @@ s = 3; (void)(s != 3); s(3); + delete &s; } namespace NS { @@ -98,41 +100,42 @@ // CHECK-NEXT: [indexEntityReference]: kind: c++-instance-method | name: operator= // CHECK-NEXT: [indexEntityReference]: kind: c++-instance-method | name: operator!= // CHECK-NEXT: [indexEntityReference]: kind: c++-instance-method | name: operator() - -// CHECK: [indexEntityReference]: kind: namespace | name: NS | {{.*}} | loc: 42:17 -// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: NS | {{.*}} | loc: 43:17 -// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: Inn | {{.*}} | loc: 43:21 -// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: NS | {{.*}} | loc: 44:7 -// CHECK-NEXT: [indexEntityReference]: kind: typedef | name: Foo | {{.*}} | loc: 44:11 - -// CHECK: [indexDeclaration]: kind: c++-class-template | name: TS | {{.*}} | loc: 47:8 -// CHECK-NEXT: [indexDeclaration]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 50:8 -// CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@SP>1#T@TS>#t0.0#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] -// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:47:8 | loc: 50:8 | :: <> | container: [TU] | refkind: direct | role: ref +// CHECK-NEXT: [indexEntityReference]: kind: destructor | name: ~S + +// CHECK: [indexEntityReference]: kind: namespace | name: NS | {{.*}} | loc: 44:17 +// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: NS | {{.*}} | loc: 45:17 +// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: Inn | {{.*}} | loc: 45:21 +// CHECK-NEXT: [indexEntityReference]: kind: namespace | name: NS | {{.*}} | loc: 46:7 +// CHECK-NEXT: [indexEntityReference]: kind: typedef | name: Foo | {{.*}} | loc: 46:11 + +// CHECK: [indexDeclaration]: kind: c++-class-template | name: TS | {{.*}} | loc: 49:8 +// CHECK-NEXT: [indexDeclaration]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 52:8 +// CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@SP>1#T@TS>#t0.0#I@T@MyInt | {{.*}} | loc: 53:15 | semantic-container: [TS:52:8] | lexical-container: [TS:52:8] +// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:49:8 | loc: 52:8 | :: <> | container: [TU] | refkind: direct | role: ref /* when indexing implicit instantiations - [indexDeclaration]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 50:8 - [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@593@S@TS>#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] + [indexDeclaration]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 52:8 + [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@593@S@TS>#I@T@MyInt | {{.*}} | loc: 53:15 | semantic-container: [TS:52:8] | lexical-container: [TS:52:8] */ // CHECK-NEXT: [indexDeclaration]: kind: function | name: foo3 /* when indexing implicit instantiations - [indexEntityReference]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 55:3 + [indexEntityReference]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 57:3 */ -// CHECK-NEXT: [indexEntityReference]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 55:3 +// CHECK-NEXT: [indexEntityReference]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 57:3 -// CHECK: [indexEntityReference]: kind: variable | name: array_size | {{.*}} | loc: 59:22 -// CHECK: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19 | {{.*}} | role: ref read -// CHECK-NOT: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 62:19 +// CHECK: [indexEntityReference]: kind: variable | name: array_size | {{.*}} | loc: 61:22 +// CHECK: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 64:19 | {{.*}} | role: ref read +// CHECK-NOT: [indexEntityReference]: kind: variable | name: default_param | {{.*}} | loc: 64:19 -// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20 -// CHECK-NEXT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 69:28 -// CHECK-NOT: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 69:20 -// CHECK-NOT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 69:28 +// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 71:20 +// CHECK-NEXT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 71:28 +// CHECK-NOT: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 71:20 +// CHECK-NOT: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 71:28 -// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 70:5 | {{.*}} | role: ref write -// CHECK: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 70:11 | {{.*}} | role: ref read -// CHECK: [indexEntityReference]: kind: function | name: foo3 | {{.*}} | loc: 71:10 | {{.*}} | role: ref addr -// CHECK: [indexEntityReference]: kind: function | name: foo4 | {{.*}} | loc: 72:3 | {{.*}} | role: ref call +// CHECK: [indexEntityReference]: kind: field | name: y | {{.*}} | loc: 72:5 | {{.*}} | role: ref write +// CHECK: [indexEntityReference]: kind: field | name: x | {{.*}} | loc: 72:11 | {{.*}} | role: ref read +// CHECK: [indexEntityReference]: kind: function | name: foo3 | {{.*}} | loc: 73:10 | {{.*}} | role: ref addr +// CHECK: [indexEntityReference]: kind: function | name: foo4 | {{.*}} | loc: 74:3 | {{.*}} | role: ref call // CHECK: [indexDeclaration]: kind: variable | name: ginitlist | -// CHECK: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 75:20 -// CHECK-NOT: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 75:20 +// CHECK: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 77:20 +// CHECK-NOT: [indexEntityReference]: kind: enumerator | name: EnumVal | {{.*}} | loc: 77:20