================ @@ -5054,95 +5089,128 @@ bool TreeTransform<Derived>::TransformTemplateArguments( } if (In.getArgument().isPackExpansion()) { - // We have a pack expansion, for which we will be substituting into - // the pattern. - SourceLocation Ellipsis; - UnsignedOrNone OrigNumExpansions = std::nullopt; - TemplateArgumentLoc Pattern - = getSema().getTemplateArgumentPackExpansionPattern( - In, Ellipsis, OrigNumExpansions); - - SmallVector<UnexpandedParameterPack, 2> Unexpanded; - getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); - assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); - - // Determine whether the set of unexpanded parameter packs can and should - // be expanded. - bool Expand = true; - bool RetainExpansion = false; - UnsignedOrNone NumExpansions = OrigNumExpansions; - if (getDerived().TryExpandParameterPacks(Ellipsis, - Pattern.getSourceRange(), - Unexpanded, - Expand, - RetainExpansion, - NumExpansions)) + if (ExpandTemplateArgument(In, Outputs, Uneval, true)) return true; + continue; + } - if (!Expand) { - // The transform has determined that we should perform a simple - // transformation on the pack expansion, producing another pack - // expansion. - TemplateArgumentLoc OutPattern; - Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), std::nullopt); - if (getDerived().TransformTemplateArgument(Pattern, OutPattern, Uneval)) - return true; + // The simple case: + if (getDerived().TransformTemplateArgument(In, Out, Uneval)) + return true; - Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis, - NumExpansions); - if (Out.getArgument().isNull()) - return true; + Outputs.addArgument(Out); + } - Outputs.addArgument(Out); - continue; - } + return false; +} - // The transform has determined that we should perform an elementwise - // expansion of the pattern. Do so. - for (unsigned I = 0; I != *NumExpansions; ++I) { - Sema::ArgPackSubstIndexRAII SubstIndex(getSema(), I); +template <typename Derived> +bool TreeTransform<Derived>::ExpandTemplateArgument( + TemplateArgumentLoc In, TemplateArgumentListInfo &Outputs, bool Uneval, + bool TryExpandingSubstPacks) { + assert(In.getArgument().isPackExpansion()); + // We have a pack expansion, for which we will be substituting into the + // pattern. + SourceLocation Ellipsis; + UnsignedOrNone OrigNumExpansions = std::nullopt; + TemplateArgumentLoc Pattern = + getSema().getTemplateArgumentPackExpansionPattern(In, Ellipsis, + OrigNumExpansions); - if (getDerived().TransformTemplateArgument(Pattern, Out, Uneval)) - return true; + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); + if (!TryExpandingSubstPacks) { + // Only do something if there is an opportunity for late expansion. + bool SawPackTypes = llvm::any_of(Unexpanded, [](UnexpandedParameterPack P) { + return P.first.dyn_cast<const SubstBuiltinTemplatePackType *>(); + }); + if (!SawPackTypes) { + Outputs.addArgument(In); + return false; + } + } + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); - if (Out.getArgument().containsUnexpandedParameterPack()) { - Out = getDerived().RebuildPackExpansion(Out, Ellipsis, - OrigNumExpansions); - if (Out.getArgument().isNull()) - return true; - } + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + UnsignedOrNone NumExpansions = OrigNumExpansions; + if (getDerived().TryExpandParameterPacks(Ellipsis, Pattern.getSourceRange(), + Unexpanded, Expand, RetainExpansion, + NumExpansions)) + return true; - Outputs.addArgument(Out); - } + TemplateArgumentLoc Out; + if (!Expand) { + // No opportunity for late expansion, return as is. + if (!TryExpandingSubstPacks) { + Outputs.addArgument(In); + return false; + } + // The transform has determined that we should perform a simple + // transformation on the pack expansion, producing another pack + // expansion. + TemplateArgumentLoc OutPattern; + std::optional<Sema::ArgPackSubstIndexRAII> SubstIndex( + std::in_place, getSema(), std::nullopt); + if (getDerived().TransformTemplateArgument(Pattern, OutPattern, Uneval)) + return true; - // If we're supposed to retain a pack expansion, do so by temporarily - // forgetting the partially-substituted parameter pack. - if (RetainExpansion) { - ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + Out = + getDerived().RebuildPackExpansion(OutPattern, Ellipsis, NumExpansions); + if (Out.getArgument().isNull()) + return true; + SubstIndex.reset(); + + // Some packs only know their lengths after substitution. We might be able + // to expand those here. + if (TryExpandingSubstPacks && + OutPattern.getArgument().containsUnexpandedParameterPack()) { ---------------- zyn0217 wrote:
So this branch is used when rebuilding a substituted `dedup` node. E.g. for `Ts = <int, int, int, float>`, we're, at this point, having `dedup<int, int, int, float>...` plus a canonical `SubstBuiltinTemplatePackType` which is used to mark it as an unexpanded pack. This feels a bit peculiar to me because we're trying to inline node-specific logic (?) into what's supposed to be a generic expansion handler. https://github.com/llvm/llvm-project/pull/106730 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits