Skip to content

Commit

Permalink
feat(cxx_indexer): Index dependent template specialization types.
Browse files Browse the repository at this point in the history
This should help us on the path to better handling e.g.
type_traits and associates, which in turn should help us
find dependent references.

At the moment the indexer does not emit a node for
template T::S; this is left for future work.
  • Loading branch information
zrlk committed Sep 21, 2023
1 parent 811f373 commit 99f31da
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 12 deletions.
49 changes: 37 additions & 12 deletions kythe/cxx/indexer/cxx/IndexerASTHooks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4568,22 +4568,47 @@ NodeSet IndexerASTVisitor::BuildNodeSetForDependentName(
return BuildNodeIdForDependentIdentifier(T.getQualifier(), T.getIdentifier());
}

std::vector<GraphObserver::NodeId>
IndexerASTVisitor::BuildNodeIdsForTemplateArgs(
clang::ArrayRef<clang::TemplateArgument> args) {
std::vector<GraphObserver::NodeId> ids;
ids.reserve(args.size());
for (const auto& arg : args) {
if (std::optional<GraphObserver::NodeId> arg_id =
BuildNodeIdForTemplateArgument(arg)) {
ids.push_back(*arg_id);
} else {
// If we can't produce an ID for any template argument (e.g., because
// some argument kind was unimplemented and the indexer is being run with
// --ignore_unimplemented), return nothing.
return {};
}
}
return ids;
}

NodeSet IndexerASTVisitor::BuildNodeSetForDependentTemplateSpecialization(
const clang::DependentTemplateSpecializationType& T) {
auto dep_name =
BuildNodeIdForDependentIdentifier(T.getQualifier(), T.getIdentifier());
std::vector<GraphObserver::NodeId> arg_ids =
BuildNodeIdsForTemplateArgs(T.template_arguments());
return arg_ids.size() == T.template_arguments().size()
? Observer.recordTappNode(dep_name, arg_ids)
: NodeSet::Empty();
}

NodeSet IndexerASTVisitor::BuildNodeSetForTemplateSpecialization(
const clang::TemplateSpecializationType& T) {
// This refers to a particular class template, type alias template,
// or template template parameter. Non-dependent template
// specializations appear as different types.
if (auto TemplateName = BuildNodeIdForTemplateName(T.getTemplateName())) {
std::vector<GraphObserver::NodeId> TemplateArgs;
TemplateArgs.reserve(T.template_arguments().size());
for (const auto& arg : T.template_arguments()) {
if (auto ArgId = BuildNodeIdForTemplateArgument(arg)) {
TemplateArgs.push_back(*ArgId);
} else {
return NodeSet::Empty();
}
}
return Observer.recordTappNode(*TemplateName, TemplateArgs);
if (auto template_name = BuildNodeIdForTemplateName(T.getTemplateName())) {
std::vector<GraphObserver::NodeId> arg_ids =
BuildNodeIdsForTemplateArgs(T.template_arguments());
return arg_ids.size() == T.template_arguments().size()
? Observer.recordTappNode(*template_name, arg_ids)
: NodeSet::Empty();
}
return NodeSet::Empty();
}
Expand Down Expand Up @@ -4860,8 +4885,8 @@ NodeSet IndexerASTVisitor::BuildNodeSetForTypeInternal(const clang::Type& T) {
DELEGATE_TYPE(DependentBitInt);
DELEGATE_TYPE(Adjusted);
DELEGATE_TYPE_TO_BASE(Decayed, Adjusted);
DELEGATE_TYPE(DependentTemplateSpecialization);
UNSUPPORTED_CLANG_TYPE(BTFTagAttributed);
UNSUPPORTED_CLANG_TYPE(DependentTemplateSpecialization);
UNSUPPORTED_CLANG_TYPE(Complex);
UNSUPPORTED_CLANG_TYPE(VariableArray);
UNSUPPORTED_CLANG_TYPE(DependentSizedExtVector);
Expand Down
6 changes: 6 additions & 0 deletions kythe/cxx/indexer/cxx/IndexerASTHooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,12 @@ class IndexerASTVisitor : public RecursiveTypeVisitor<IndexerASTVisitor> {
NodeSet BuildNodeSetForSubstTemplateTypeParm(
const clang::SubstTemplateTypeParmType& T);
NodeSet BuildNodeSetForDependentName(const clang::DependentNameType& T);
// Builds node IDs for the provided list of template arguments. Returns an
// empty vector if any node ID could not be generated.
std::vector<GraphObserver::NodeId> BuildNodeIdsForTemplateArgs(
clang::ArrayRef<clang::TemplateArgument> args);
NodeSet BuildNodeSetForDependentTemplateSpecialization(
const clang::DependentTemplateSpecializationType& T);
NodeSet BuildNodeSetForTemplateSpecialization(
const clang::TemplateSpecializationType& T);
NodeSet BuildNodeSetForPackExpansion(const clang::PackExpansionType& T);
Expand Down
7 changes: 7 additions & 0 deletions kythe/cxx/indexer/cxx/testdata/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2224,6 +2224,13 @@ cc_indexer_test(
tags = ["template"],
)

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

cc_indexer_test(
name = "template_depexpr_field_ref",
srcs = ["template/template_depexpr_field_ref.cc"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// We index dependent template specialization types.
//- @U defines/binding TvarU
template <typename T, typename U>
//- @A defines/binding AliasA
using A = T::template S<U>;
//- AliasA aliases TAppTSU
//- TAppTSU.node/kind tapp
//- TAppTSU param.0 _DependentTS // Dependent struct not yet indexed.
//- TAppTSU param.1 TvarU

0 comments on commit 99f31da

Please sign in to comment.