diff --git a/kythe/cxx/indexer/cxx/GraphObserver.h b/kythe/cxx/indexer/cxx/GraphObserver.h index 435b7116d0..cf712ae386 100644 --- a/kythe/cxx/indexer/cxx/GraphObserver.h +++ b/kythe/cxx/indexer/cxx/GraphObserver.h @@ -190,6 +190,13 @@ class GraphObserver { } const std::string& getRawIdentity() const { return Identity; } const ClaimToken* getToken() const { return Token; } + /// \brief Create a derived NodeId from this one. + /// + /// This is meant for debugging. You'll likely want to disable + /// `ForceEncodeString` in GraphObserver.cc. + NodeId derive(const std::string& s) const { + return NodeId(Token, Identity + s); + } private: friend class GraphObserver; diff --git a/kythe/cxx/indexer/cxx/IndexerASTHooks.cc b/kythe/cxx/indexer/cxx/IndexerASTHooks.cc index aecfbfd434..f77ad2689f 100644 --- a/kythe/cxx/indexer/cxx/IndexerASTHooks.cc +++ b/kythe/cxx/indexer/cxx/IndexerASTHooks.cc @@ -3756,6 +3756,15 @@ bool IndexerASTVisitor::VisitUsingShadowDecl( const clang::UsingShadowDecl* Decl) { if (auto RCC = ExplicitRangeInCurrentContext(RangeForNameOfDeclaration(Decl))) { + if (auto* ctd = llvm::dyn_cast_or_null( + Decl->getTargetDecl()); + ctd != nullptr && ctd->getTemplatedDecl() != nullptr && + absl::GetFlag(FLAGS_experimental_alias_template_instantiations)) { + Observer.recordDeclUseLocation( + RCC.value(), BuildNodeIdForDecl(ctd->getTemplatedDecl()), + GraphObserver::Claimability::Claimable, IsImplicit(RCC.value())); + return true; + } Observer.recordDeclUseLocation( RCC.value(), BuildNodeIdForDecl(Decl->getTargetDecl()), GraphObserver::Claimability::Claimable, IsImplicit(RCC.value())); @@ -4072,6 +4081,19 @@ IndexerASTVisitor::BuildNodeIdForTemplateName(const clang::TemplateName& Name) { LOG(FATAL) << "BuildNodeIdForTemplateName can't identify TemplateDecl"; } } + case TemplateName::UsingTemplate: { + // UsingShadowDecl::getIntroducer() will return the specific + // using-declaration. We don't index UsingShadowDecls as definition sites, + // so it's not helpful to point at that declaration. + const clang::UsingShadowDecl* decl = Name.getAsUsingShadowDecl(); + if (auto* ctd = llvm::dyn_cast_or_null( + decl->getTargetDecl()); + ctd != nullptr && ctd->getTemplatedDecl() != nullptr && + absl::GetFlag(FLAGS_experimental_alias_template_instantiations)) { + return BuildNodeIdForDecl(ctd->getTemplatedDecl()); + } + return BuildNodeIdForDecl(decl); + } case TemplateName::OverloadedTemplate: CHECK(options_.IgnoreUnimplemented) << "TN.OverloadedTemplate"; return std::nullopt; @@ -4090,9 +4112,6 @@ IndexerASTVisitor::BuildNodeIdForTemplateName(const clang::TemplateName& Name) { case TemplateName::SubstTemplateTemplateParmPack: CHECK(options_.IgnoreUnimplemented) << "TN.SubstTemplateTemplateParmPack"; return std::nullopt; - case TemplateName::UsingTemplate: - CHECK(options_.IgnoreUnimplemented) << "TN.UsingTemplate"; - return std::nullopt; } CHECK(options_.IgnoreUnimplemented) << "Unexpected TemplateName kind: " << Name.getKind(); diff --git a/kythe/cxx/indexer/cxx/testdata/BUILD b/kythe/cxx/indexer/cxx/testdata/BUILD index 550ab22065..b98ac9feba 100644 --- a/kythe/cxx/indexer/cxx/testdata/BUILD +++ b/kythe/cxx/indexer/cxx/testdata/BUILD @@ -2741,7 +2741,6 @@ cc_indexer_test( srcs = ["template/template_using_name.cc"], experimental_alias_template_instantiations = True, ignore_dups = True, - ignore_unimplemented = True, tags = ["template"], ) diff --git a/kythe/cxx/indexer/cxx/testdata/template/template_using_name.cc b/kythe/cxx/indexer/cxx/testdata/template/template_using_name.cc index f289f46bb3..2f323fb8f5 100644 --- a/kythe/cxx/indexer/cxx/testdata/template/template_using_name.cc +++ b/kythe/cxx/indexer/cxx/testdata/template/template_using_name.cc @@ -4,11 +4,10 @@ namespace ns { //- @S defines/binding TemplateS template struct S {}; } -//- !{@S ref TemplateS} // TODO(zrlk): Targets missing node. +// NB: using declaration cannot refer to a template specialization +//- @S ref TemplateS using ns::S; -// This trips an unimplemented check (TN.UsingTemplate) in -// BuildNodeIdForTemplateName //- @"S" ref TemplateSInt //- TemplateSInt param.0 TemplateS -//- !{@S ref TemplateS} // TODO(zrlk): No anchor for S +//- @S ref TemplateS S s;