Skip to content

Commit

Permalink
feat(cxx_indexer): Add support for member pointers and uses of them a… (
Browse files Browse the repository at this point in the history
#3258)

* feat(cxx_indexer): Add support for member pointers and uses of them as template parameters

* fix(cxx_indexer): add space between pointee and class for member pointer marked source
  • Loading branch information
shahms committed Nov 15, 2018
1 parent 3fb994e commit a83e856
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 50 deletions.
27 changes: 26 additions & 1 deletion kythe/cxx/indexer/cxx/IndexerASTHooks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1838,6 +1838,20 @@ bool IndexerASTVisitor::TraverseDependentAddressSpaceTypeLoc(
return Base::TraverseDependentAddressSpaceTypeLoc(TL);
}

bool IndexerASTVisitor::TraverseMemberPointerTypeLoc(
clang::MemberPointerTypeLoc TL) {
// TODO(shahms): Fix this upstream. RecursiveASTVisitor calls:
// TraverseType(Class);
// TraverseTypeLoc(Pointee);
// Rather than TraverseTypeLoc on both.
if (auto* TSI = TL.getClassTInfo()) {
return TraverseTypeLoc(TSI->getTypeLoc()) &&
TraverseTypeLoc(TL.getPointeeLoc());
} else {
return Base::TraverseMemberPointerTypeLoc(TL);
}
}

bool IndexerASTVisitor::VisitDesignatedInitExpr(
const clang::DesignatedInitExpr* DIE) {
for (const auto& D : DIE->designators()) {
Expand Down Expand Up @@ -4054,6 +4068,17 @@ NodeSet IndexerASTVisitor::BuildNodeSetForPointer(clang::PointerTypeLoc TL) {
return NodeSet::Empty();
}

NodeSet IndexerASTVisitor::BuildNodeSetForMemberPointer(
clang::MemberPointerTypeLoc TL) {
if (auto PointeeID = BuildNodeIdForType(TL.getPointeeLoc())) {
if (auto ClassID = BuildNodeIdForType(clang::QualType(TL.getClass(), 0))) {
auto tapp = Observer.getNodeIdForBuiltinType("mptr");
return Observer.recordTappNode(tapp, {*PointeeID, *ClassID});
}
}
return NodeSet::Empty();
}

NodeSet IndexerASTVisitor::BuildNodeSetForLValueReference(
clang::LValueReferenceTypeLoc TL) {
if (auto PointeeID = BuildNodeIdForType(TL.getPointeeLoc())) {
Expand Down Expand Up @@ -4401,6 +4426,7 @@ NodeSet IndexerASTVisitor::BuildNodeSetForType(const clang::TypeLoc& TL) {
DELEGATE_TYPE(ObjCTypeParam);
DELEGATE_TYPE(ObjCObject);
DELEGATE_TYPE(Pointer);
DELEGATE_TYPE(MemberPointer);
DELEGATE_TYPE(LValueReference);
DELEGATE_TYPE(RValueReference);
DELEGATE_TYPE(Auto);
Expand Down Expand Up @@ -4429,7 +4455,6 @@ NodeSet IndexerASTVisitor::BuildNodeSetForType(const clang::TypeLoc& TL) {
DELEGATE_TYPE(DependentAddressSpace);
UNSUPPORTED_CLANG_TYPE(DependentTemplateSpecialization);
UNSUPPORTED_CLANG_TYPE(Complex);
UNSUPPORTED_CLANG_TYPE(MemberPointer);
UNSUPPORTED_CLANG_TYPE(VariableArray);
UNSUPPORTED_CLANG_TYPE(DependentSizedExtVector);
UNSUPPORTED_CLANG_TYPE(Vector);
Expand Down
3 changes: 3 additions & 0 deletions kythe/cxx/indexer/cxx/IndexerASTHooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ class IndexerASTVisitor : public clang::RecursiveASTVisitor<IndexerASTVisitor> {
bool TraverseDependentAddressSpaceTypeLoc(
clang::DependentAddressSpaceTypeLoc TL);

bool TraverseMemberPointerTypeLoc(clang::MemberPointerTypeLoc TL);

// Emit edges for an anchor pointing to the indicated type.
bool EmitTypeLocNodes(clang::TypeLoc TL);

Expand Down Expand Up @@ -263,6 +265,7 @@ class IndexerASTVisitor : public clang::RecursiveASTVisitor<IndexerASTVisitor> {
NodeSet BuildNodeSetForInjectedClassName(clang::InjectedClassNameTypeLoc TL);
NodeSet BuildNodeSetForTemplateTypeParm(clang::TemplateTypeParmTypeLoc TL);
NodeSet BuildNodeSetForPointer(clang::PointerTypeLoc TL);
NodeSet BuildNodeSetForMemberPointer(clang::MemberPointerTypeLoc TL);
NodeSet BuildNodeSetForLValueReference(clang::LValueReferenceTypeLoc TL);
NodeSet BuildNodeSetForRValueReference(clang::RValueReferenceTypeLoc TL);

Expand Down
116 changes: 69 additions & 47 deletions kythe/cxx/indexer/cxx/KytheGraphObserver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1383,53 +1383,75 @@ void KytheGraphObserver::RegisterBuiltins() {
RegisterTokenBuiltin("TypeUnion", "TypeUnion");
RegisterTokenBuiltin("__float128", "__float128");

MarkedSource lhs_tycon_builtin;
auto* lhs_tycon = lhs_tycon_builtin.add_child();
auto* lookup = lhs_tycon_builtin.add_child();
lookup->set_kind(MarkedSource::LOOKUP_BY_PARAM);
lookup->set_lookup_index(1);
lhs_tycon->set_kind(MarkedSource::IDENTIFIER);
lhs_tycon->set_pre_text("const ");
RegisterBuiltin("const", lhs_tycon_builtin);
lhs_tycon->set_pre_text("volatile ");
RegisterBuiltin("volatile", lhs_tycon_builtin);
lhs_tycon->set_pre_text("restrict ");
RegisterBuiltin("restrict", lhs_tycon_builtin);

MarkedSource rhs_tycon_builtin;
lookup = rhs_tycon_builtin.add_child();
auto* rhs_tycon = rhs_tycon_builtin.add_child();
lookup->set_kind(MarkedSource::LOOKUP_BY_PARAM);
lookup->set_lookup_index(1);
rhs_tycon->set_kind(MarkedSource::IDENTIFIER);
rhs_tycon->set_pre_text("*");
RegisterBuiltin("ptr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("&");
RegisterBuiltin("lvr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("&&");
RegisterBuiltin("rvr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("[incomplete]");
RegisterBuiltin("iarr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("[const]");
RegisterBuiltin("carr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("[dependent]");
RegisterBuiltin("darr", rhs_tycon_builtin);

MarkedSource function_tycon_builtin;
auto* return_type = function_tycon_builtin.add_child();
return_type->set_kind(MarkedSource::LOOKUP_BY_PARAM);
return_type->set_lookup_index(1);
auto* args = function_tycon_builtin.add_child();
args->set_kind(MarkedSource::PARAMETER_LOOKUP_BY_PARAM);
args->set_pre_text("(");
args->set_post_child_text(", ");
args->set_post_text(")");
args->set_lookup_index(2);
RegisterBuiltin("fn", function_tycon_builtin);
auto* vararg_keyword = function_tycon_builtin.add_child();
vararg_keyword->set_kind(MarkedSource::IDENTIFIER);
vararg_keyword->set_pre_text("vararg");
RegisterBuiltin("fnvararg", function_tycon_builtin);
{
MarkedSource lhs_tycon_builtin;
auto* lhs_tycon = lhs_tycon_builtin.add_child();
auto* lookup = lhs_tycon_builtin.add_child();
lookup->set_kind(MarkedSource::LOOKUP_BY_PARAM);
lookup->set_lookup_index(1);
lhs_tycon->set_kind(MarkedSource::IDENTIFIER);
lhs_tycon->set_pre_text("const ");
RegisterBuiltin("const", lhs_tycon_builtin);
lhs_tycon->set_pre_text("volatile ");
RegisterBuiltin("volatile", lhs_tycon_builtin);
lhs_tycon->set_pre_text("restrict ");
RegisterBuiltin("restrict", lhs_tycon_builtin);
}

{
MarkedSource rhs_tycon_builtin;
auto* lookup = rhs_tycon_builtin.add_child();
auto* rhs_tycon = rhs_tycon_builtin.add_child();
lookup->set_kind(MarkedSource::LOOKUP_BY_PARAM);
lookup->set_lookup_index(1);
rhs_tycon->set_kind(MarkedSource::IDENTIFIER);
rhs_tycon->set_pre_text("*");
RegisterBuiltin("ptr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("&");
RegisterBuiltin("lvr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("&&");
RegisterBuiltin("rvr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("[incomplete]");
RegisterBuiltin("iarr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("[const]");
RegisterBuiltin("carr", rhs_tycon_builtin);
rhs_tycon->set_pre_text("[dependent]");
RegisterBuiltin("darr", rhs_tycon_builtin);
}

{
MarkedSource mem_ptr_tycon_builtin;
auto* pointee_type = mem_ptr_tycon_builtin.add_child();
pointee_type->set_kind(MarkedSource::LOOKUP_BY_PARAM);
pointee_type->set_lookup_index(1);
auto* class_type = mem_ptr_tycon_builtin.add_child();
class_type->set_kind(MarkedSource::LOOKUP_BY_PARAM);
class_type->set_lookup_index(2);
class_type->set_pre_text(" ");
class_type->set_post_text("::");
auto* ident = mem_ptr_tycon_builtin.add_child();
ident->set_kind(MarkedSource::IDENTIFIER);
ident->set_pre_text("*");
RegisterBuiltin("mptr", mem_ptr_tycon_builtin);
}

{
MarkedSource function_tycon_builtin;
auto* return_type = function_tycon_builtin.add_child();
return_type->set_kind(MarkedSource::LOOKUP_BY_PARAM);
return_type->set_lookup_index(1);
auto* args = function_tycon_builtin.add_child();
args->set_kind(MarkedSource::PARAMETER_LOOKUP_BY_PARAM);
args->set_pre_text("(");
args->set_post_child_text(", ");
args->set_post_text(")");
args->set_lookup_index(2);
RegisterBuiltin("fn", function_tycon_builtin);
auto* vararg_keyword = function_tycon_builtin.add_child();
vararg_keyword->set_kind(MarkedSource::IDENTIFIER);
vararg_keyword->set_pre_text("vararg");
RegisterBuiltin("fnvararg", function_tycon_builtin);
}
}

void KytheGraphObserver::EmitBuiltin(Builtin* builtin) const {
Expand Down
5 changes: 3 additions & 2 deletions kythe/cxx/indexer/cxx/semantic_hash.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ uint64_t SemanticHash::Hash(const clang::TemplateArgument& arg) const {
case TemplateArgument::Type:
return Hash(arg.getAsType()) ^ 0x2020202002020202LL;
case TemplateArgument::Declaration:
CHECK(ignore_unimplemented_) << "SemanticHash(Declaration)";
return 0;
return Hash(arg.getParamTypeForDecl()) ^
std::hash<std::string>()(
arg.getAsDecl()->getQualifiedNameAsString());
case TemplateArgument::NullPtr:
return 0;
case TemplateArgument::Integral: {
Expand Down
14 changes: 14 additions & 0 deletions kythe/cxx/indexer/cxx/testdata/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,13 @@ cc_indexer_test(
tags = ["rec"],
)

cc_indexer_test(
name = "rec_class_member_ptr",
srcs = ["rec/rec_class_member_ptr.cc"],
check_for_singletons = True,
tags = ["rec"],
)

test_suite(
name = "indexer_rec",
tags = ["rec"],
Expand All @@ -1770,6 +1777,13 @@ cc_indexer_test(
tags = ["template"],
)

cc_indexer_test(
name = "template_decl_arg",
srcs = ["template/template_decl_arg.cc"],
ignore_dups = True,
tags = ["template"],
)

cc_indexer_test(
name = "template_alias_naming",
srcs = ["template/template_alias_naming.cc"],
Expand Down
20 changes: 20 additions & 0 deletions kythe/cxx/indexer/cxx/testdata/rec/rec_class_member_ptr.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//- @C defines/binding CDecl
struct C {
//- @member defines/binding MemberDecl
int member;
};

void fn() {
//- @C ref CDecl
//- @mptr defines/binding PtrDecl
//- PtrDecl typed MemPtrType
//- MemPtrType.node/kind tapp
//- MemPtrType param.0 vname("mptr#builtin", "", "", "", "c++")
//- MemPtrType param.1 vname("int#builtin", "", "", "", "c++")
//- MemPtrType param.2 CDecl
int C::* mptr;
//- @C ref CDecl
//- @member ref MemberDecl
//- @mptr ref PtrDecl
mptr = &C::member;
}
38 changes: 38 additions & 0 deletions kythe/cxx/indexer/cxx/testdata/template/template_decl_arg.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Verify that we support using pointers, references and pointer-to-members in
// non-type template parameters.

template <typename Type, Type Value>
struct Pair {
using type = Type;
static constexpr type value() { return Value; }
};

//- @Value defines/binding ValueType
struct Value {
//- @member defines/binding ValueMember
int member;
};

//- @fn defines/binding FnDecl
void fn();

//- @Alias defines/binding AliasDecl
//- @Value ref ValueType
//- @member ref ValueMember
using Alias = Pair<decltype(&Value::member),
//- @Value ref ValueType
//- @member ref ValueMember
&Value::member>;


//- @FnPtrAlias defines/binding FnPtrAliasType
//- @fn ref FnDecl
using FnPtrAlias = Pair<decltype(&fn),
//- @fn ref FnDecl
&fn>;

//- @FnRefAlias defines/binding FnRefAliasType
//- @fn ref FnDecl
using FnRefAlias = Pair<decltype(*fn),
//- @fn ref FnDecl
fn>;

0 comments on commit a83e856

Please sign in to comment.