================ @@ -139,28 +165,63 @@ TemplateName::NameKind TemplateName::getKind() const { return AssumedTemplate; if (uncommon->getAsSubstTemplateTemplateParm()) return SubstTemplateTemplateParm; + if (uncommon->getAsDeducedTemplateName()) + return DeducedTemplate; + + assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr); return SubstTemplateTemplateParmPack; } -TemplateDecl *TemplateName::getAsTemplateDecl() const { - if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) { - if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing)) - return cast<TemplateDecl>(USD->getTargetDecl()); - - assert(isa<TemplateDecl>(TemplateOrUsing)); - return cast<TemplateDecl>(TemplateOrUsing); - } +TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const { + TemplateName Name = *this; + while (std::optional<TemplateName> UnderlyingOrNone = + Name.desugar(IgnoreDeduced)) + Name = *UnderlyingOrNone; - if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) - return QTN->getUnderlyingTemplate().getAsTemplateDecl(); + if (!IgnoreDeduced) + assert(Name.getAsDeducedTemplateName() == nullptr && + "Unexpected canonical DeducedTemplateName; Did you mean to use " + "getTemplateDeclAndDefaultArgs instead?"); - if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm()) - return sub->getReplacement().getAsTemplateDecl(); + return cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>()); +} - if (UsingShadowDecl *USD = getAsUsingShadowDecl()) - return cast<TemplateDecl>(USD->getTargetDecl()); +std::pair<TemplateDecl *, DefaultArguments> +TemplateName::getTemplateDeclAndDefaultArgs() const { + for (TemplateName Name = *this; /**/; /**/) { + if (Name.getKind() == TemplateName::DeducedTemplate) { + DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName(); + TemplateDecl *TD = + DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true); + DefaultArguments DefArgs = DTS->getDefaultArguments(); + if (TD && DefArgs) + assert(DefArgs.StartPos + DefArgs.Args.size() <= + TD->getTemplateParameters()->size()); + return {TD, DTS->getDefaultArguments()}; + } + if (std::optional<TemplateName> UnderlyingOrNone = + Name.desugar(/*IgnoreDeduced=*/false)) { + Name = *UnderlyingOrNone; + continue; + } + return {cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>()), {}}; + } +} - return nullptr; +std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const { ---------------- mizvekov wrote:
They were not fully fledged implemented like the other kinds of AST nodes. Their canonicalization plays by different rules, and this patch expands on that. https://github.com/llvm/llvm-project/pull/94981 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits