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.
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(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()) {
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<CXXDeductionGuideDecl>(D)) {
IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
APPLY_FOR_ROLE(RelationContainedBy);
APPLY_FOR_ROLE(RelationIBTypeOf);
APPLY_FOR_ROLE(RelationSpecializationOf);
+ APPLY_FOR_ROLE(NameReference);
#undef APPLY_FOR_ROLE
case SymbolRole::RelationContainedBy: OS << "RelCont"; break;
case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break;
case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break;
+ case SymbolRole::NameReference: OS << "NameReference"; break;
}
});
}
case SymbolRole::RelationCalledBy:
case SymbolRole::RelationContainedBy:
case SymbolRole::RelationSpecializationOf:
+ case SymbolRole::NameReference:
return true;
}
llvm_unreachable("Unsupported SymbolRole value!");
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 | <no-cgname> | Ref,RelCont | rel: 1
+ // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | 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 | <no-cgname> | Ref,RelCont | rel: 1
+ // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | 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 | <no-cgname> | Ref,RelCont | rel: 1
+ // CHECK: [[@LINE+1]]:3 | class/C++ | Cls | c:@S@Cls | <no-cgname> | 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 | <no-cgname> | Ref,RelCont | rel: 1
+ // CHECK: [[@LINE+1]]:4 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont,NameReference | rel: 1
~Cls();
};
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 | <no-cgname> | Ref,RelCont | rel: 1
-// CHECK: [[@LINE-3]]:6 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK: [[@LINE-3]]:6 | class/C++ | Cls | c:@S@Cls | <no-cgname> | 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 | <no-cgname> | Ref,RelCont | rel: 1
-// CHECK: [[@LINE-3]]:20 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK: [[@LINE-3]]:20 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont,NameReference | rel: 1
template <typename TemplArg>
class TemplCls {
// 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 | <no-cgname> | Ref,RelCont | rel: 1
-// CHECK: [[@LINE-4]]:3 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK: [[@LINE-4]]:3 | struct/C++ | DeletedMethods | c:@S@DeletedMethods | <no-cgname> | Ref,RelCont,NameReference | rel: 1
};
namespace ns2 {
// CHECK: [[@LINE-1]]:69 | variable/C++ | structuredBinding2 | c:@N@cpp17structuredBinding@structuredBinding2 | <no-cgname> | 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
}
}
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<unsigned>(S.SymInfo.Kind) << ')';
}
class Indexer : public IndexDataConsumer {
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;
}
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<unsigned>(Role); }
TEST(IndexTest, Simple) {
auto Index = std::make_shared<Indexer>();
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<Indexer>();
+ 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