Index: include/clang/Index/IndexSymbol.h =================================================================== --- include/clang/Index/IndexSymbol.h +++ include/clang/Index/IndexSymbol.h @@ -118,8 +118,12 @@ RelationContainedBy = 1 << 17, RelationIBTypeOf = 1 << 18, RelationSpecializationOf = 1 << 19, + + // Symbol only references the name of the object as written. For example, a + // constructor references the class declaration using that role. + NameReference = 1 << 20, }; -static const unsigned SymbolRoleBitNum = 20; +static const unsigned SymbolRoleBitNum = 21; typedef unsigned SymbolRoleSet; /// Represents a relation to another symbol for a symbol occurrence. Index: lib/Index/IndexDecl.cpp =================================================================== --- lib/Index/IndexDecl.cpp +++ lib/Index/IndexDecl.cpp @@ -247,7 +247,8 @@ if (const CXXConstructorDecl *Ctor = dyn_cast(D)) { IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(), - Ctor->getParent(), Ctor->getDeclContext()); + Ctor->getParent(), Ctor->getDeclContext(), + (unsigned)SymbolRole::NameReference); // Constructor initializers. for (const auto *Init : Ctor->inits()) { @@ -263,7 +264,8 @@ if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { IndexCtx.handleReference(Dtor->getParent(), TypeNameInfo->getTypeLoc().getBeginLoc(), - Dtor->getParent(), Dtor->getDeclContext()); + Dtor->getParent(), Dtor->getDeclContext(), + (unsigned)SymbolRole::NameReference); } } else if (const auto *Guide = dyn_cast(D)) { IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(), Index: lib/Index/IndexSymbol.cpp =================================================================== --- lib/Index/IndexSymbol.cpp +++ lib/Index/IndexSymbol.cpp @@ -396,6 +396,7 @@ APPLY_FOR_ROLE(RelationContainedBy); APPLY_FOR_ROLE(RelationIBTypeOf); APPLY_FOR_ROLE(RelationSpecializationOf); + APPLY_FOR_ROLE(NameReference); #undef APPLY_FOR_ROLE @@ -438,6 +439,7 @@ case SymbolRole::RelationContainedBy: OS << "RelCont"; break; case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break; case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break; + case SymbolRole::NameReference: OS << "NameReference"; break; } }); } Index: lib/Index/IndexingContext.cpp =================================================================== --- lib/Index/IndexingContext.cpp +++ lib/Index/IndexingContext.cpp @@ -332,6 +332,7 @@ case SymbolRole::RelationCalledBy: case SymbolRole::RelationContainedBy: case SymbolRole::RelationSpecializationOf: + case SymbolRole::NameReference: return true; } llvm_unreachable("Unsupported SymbolRole value!"); Index: test/Index/Core/index-source.cpp =================================================================== --- test/Index/Core/index-source.cpp +++ test/Index/Core/index-source.cpp @@ -5,17 +5,17 @@ class Cls { public: // CHECK: [[@LINE+3]]:3 | constructor/C++ | Cls | c:@S@Cls@F@Cls#I# | __ZN3ClsC1Ei | Decl,RelChild | rel: 1 // CHECK-NEXT: RelChild | Cls | c:@S@Cls - // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 + // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont,NameReference | rel: 1 Cls(int x); // CHECK: [[@LINE+2]]:3 | constructor/cxx-copy-ctor/C++ | Cls | c:@S@Cls@F@Cls#&1$@S@Cls# | __ZN3ClsC1ERKS_ | Decl,RelChild | rel: 1 - // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 + // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont,NameReference | rel: 1 Cls(const Cls &); // CHECK: [[@LINE+2]]:3 | constructor/cxx-move-ctor/C++ | Cls | c:@S@Cls@F@Cls#&&$@S@Cls# | __ZN3ClsC1EOS_ | Decl,RelChild | rel: 1 - // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 + // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont,NameReference | rel: 1 Cls(Cls &&); // CHECK: [[@LINE+2]]:3 | destructor/C++ | ~Cls | c:@S@Cls@F@~Cls# | __ZN3ClsD1Ev | Decl,RelChild | rel: 1 - // CHECK: [[@LINE+1]]:4 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 + // CHECK: [[@LINE+1]]:4 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont,NameReference | rel: 1 ~Cls(); }; @@ -35,12 +35,12 @@ Cls::Cls(int x) {} // CHECK: [[@LINE-1]]:6 | constructor/C++ | Cls | c:@S@Cls@F@Cls#I# | __ZN3ClsC1Ei | Def,RelChild | rel: 1 // CHECK: [[@LINE-2]]:1 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 -// CHECK: [[@LINE-3]]:6 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-3]]:6 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont,NameReference | rel: 1 Cls::~/*a comment*/Cls() {} // CHECK: [[@LINE-1]]:6 | destructor/C++ | ~Cls | c:@S@Cls@F@~Cls# | __ZN3ClsD1Ev | Def,RelChild | rel: 1 // CHECK: [[@LINE-2]]:1 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 -// CHECK: [[@LINE-3]]:20 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-3]]:20 | class/C++ | Cls | c:@S@Cls | | Ref,RelCont,NameReference | rel: 1 template class TemplCls { @@ -394,7 +394,7 @@ // CHECK: [[@LINE-1]]:3 | constructor/cxx-copy-ctor/C++ | DeletedMethods | c:@S@DeletedMethods@F@DeletedMethods#&1$@S@DeletedMethods# | __ZN14DeletedMethodsC1ERKS_ | Def,RelChild | rel: 1 // CHECK: RelChild | DeletedMethods | c:@S@DeletedMethods // CHECK: [[@LINE-3]]:24 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | | Ref,RelCont | rel: 1 -// CHECK: [[@LINE-4]]:3 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | | Ref,RelCont | rel: 1 +// CHECK: [[@LINE-4]]:3 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | | Ref,RelCont,NameReference | rel: 1 }; namespace ns2 { @@ -494,7 +494,7 @@ // CHECK: [[@LINE-1]]:69 | variable/C++ | structuredBinding2 | c:@N@cpp17structuredBinding@structuredBinding2 | | Ref,Read,RelCont | rel: 1 // CHECK-NEXT: RelCont | localStructuredBindingAndRef | c:@N@cpp17structuredBinding@F@localStructuredBindingAndRef# // CHECK-NOT: localBinding -// LOCAL: [[@LINE-4]]:9 | variable(local)/C++ | localBinding1 | c:index-source.cpp@25408@N@cpp17structuredBinding@F@localStructuredBindingAndRef#@localBinding1 +// LOCAL: [[@LINE-4]]:9 | variable(local)/C++ | localBinding1 | c:index-source.cpp@{{.*}}@N@cpp17structuredBinding@F@localStructuredBindingAndRef#@localBinding1 } } Index: unittests/Index/IndexTests.cpp =================================================================== --- unittests/Index/IndexTests.cpp +++ unittests/Index/IndexTests.cpp @@ -58,11 +58,13 @@ Position WrittenPos; Position DeclPos; SymbolInfo SymInfo; + SymbolRoleSet Roles; // FIXME: add more information. }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) { - return OS << S.QName << '[' << S.WrittenPos << ']' << '@' << S.DeclPos; + return OS << S.QName << '[' << S.WrittenPos << ']' << '@' << S.DeclPos << '(' + << static_cast(S.SymInfo.Kind) << ')'; } class Indexer : public IndexDataConsumer { @@ -84,6 +86,7 @@ S.WrittenPos = Position::fromSourceLocation(Loc, AST->getSourceManager()); S.DeclPos = Position::fromSourceLocation(D->getLocation(), AST->getSourceManager()); + S.Roles = Roles; Symbols.push_back(std::move(S)); return true; } @@ -143,6 +146,7 @@ MATCHER_P(WrittenAt, Pos, "") { return arg.WrittenPos == Pos; } MATCHER_P(DeclAt, Pos, "") { return arg.DeclPos == Pos; } MATCHER_P(Kind, SymKind, "") { return arg.SymInfo.Kind == SymKind; } +MATCHER_P(HasRole, Role, "") { return arg.Roles & static_cast(Role); } TEST(IndexTest, Simple) { auto Index = std::make_shared(); @@ -257,6 +261,32 @@ Contains(AllOf(QName("std::foo"), Kind(SymbolKind::Using)))); } +TEST(IndexTest, Constructors) { + std::string Code = R"cpp( + struct Foo { + Foo(int); + ~Foo(); + }; + )cpp"; + auto Index = std::make_shared(); + IndexingOptions Opts; + tooling::runToolOnCode(new IndexAction(Index, Opts), Code); + EXPECT_THAT( + Index->Symbols, + UnorderedElementsAre( + AllOf(QName("Foo"), Kind(SymbolKind::Struct), + WrittenAt(Position(2, 12))), + AllOf(QName("Foo::Foo"), Kind(SymbolKind::Constructor), + WrittenAt(Position(3, 7))), + AllOf(QName("Foo"), Kind(SymbolKind::Struct), + HasRole(SymbolRole::NameReference), WrittenAt(Position(3, 7))), + AllOf(QName("Foo::~Foo"), Kind(SymbolKind::Destructor), + WrittenAt(Position(4, 7))), + AllOf(QName("Foo"), Kind(SymbolKind::Struct), + HasRole(SymbolRole::NameReference), + WrittenAt(Position(4, 8))))); +} + } // namespace } // namespace index } // namespace clang