================ @@ -749,132 +759,124 @@ ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, PackExpansionExpr(Context.DependentTy, Pattern, EllipsisLoc, NumExpansions); } +static bool IsUnexpandedPackExpansion(const TemplateArgument &TA) { + if (!TA.isPackExpansion()) + return false; + + if (TA.getKind() == TemplateArgument::Type) + return !TA.getAsType()->getAs<PackExpansionType>()->getNumExpansions(); + + if (TA.getKind() == TemplateArgument::Expression) + return !cast<PackExpansionExpr>(TA.getAsExpr())->getNumExpansions(); + + return !TA.getNumTemplateExpansions(); +} + bool Sema::CheckParameterPacksForExpansion( SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef<UnexpandedParameterPack> Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, bool &RetainExpansion, std::optional<unsigned> &NumExpansions) { ShouldExpand = true; RetainExpansion = false; - std::pair<IdentifierInfo *, SourceLocation> FirstPack; - bool HaveFirstPack = false; - std::optional<unsigned> NumPartialExpansions; - SourceLocation PartiallySubstitutedPackLoc; - typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; + std::pair<const IdentifierInfo *, SourceLocation> FirstPack; + std::optional<std::pair<unsigned, SourceLocation>> PartialExpansion; + std::optional<unsigned> CurNumExpansions, CurMaximumOfLeastExpansions; - for (UnexpandedParameterPack ParmPack : Unexpanded) { + for (auto [P, Loc] : Unexpanded) { // Compute the depth and index for this parameter pack. - unsigned Depth = 0, Index = 0; - IdentifierInfo *Name; - bool IsVarDeclPack = false; - FunctionParmPackExpr *BindingPack = nullptr; - - if (const TemplateTypeParmType *TTP = - ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) { - Depth = TTP->getDepth(); - Index = TTP->getIndex(); - Name = TTP->getIdentifier(); - } else { - NamedDecl *ND = cast<NamedDecl *>(ParmPack.first); - if (isa<VarDecl>(ND)) - IsVarDeclPack = true; - else if (isa<BindingDecl>(ND)) { + std::optional<std::pair<unsigned, unsigned>> Pos; + unsigned NewPackSize, PendingPackExpansionSize = 0; + const auto *ND = dyn_cast_if_present<const NamedDecl *>(P); + if (ND) { + if (isa<VarDecl>(ND)) { + auto *DAP = dyn_cast<LocalInstantiationScope::DeclArgumentPack *>( + *CurrentInstantiationScope->findInstantiationOf(ND)); + if (!DAP) { + // We can't expand this function parameter pack, so we can't expand + // the pack expansion. + ShouldExpand = false; + continue; + } + NewPackSize = DAP->size(); + } else if (isa<BindingDecl>(ND)) { // Find the instantiated BindingDecl and check it for a resolved pack. - llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation = - CurrentInstantiationScope->findInstantiationOf(ND); + llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> + *Instantiation = CurrentInstantiationScope->findInstantiationOf(ND); Decl *B = cast<Decl *>(*Instantiation); Expr *BindingExpr = cast<BindingDecl>(B)->getBinding(); - BindingPack = cast_if_present<FunctionParmPackExpr>(BindingExpr); + auto *BindingPack = cast_if_present<FunctionParmPackExpr>(BindingExpr); if (!BindingPack) { ShouldExpand = false; continue; } + NewPackSize = BindingPack->getNumExpansions(); } else - std::tie(Depth, Index) = getDepthAndIndex(ND); - - Name = ND->getIdentifier(); + Pos = getDepthAndIndex(ND); + } else if (const auto *TTP = dyn_cast<const TemplateTypeParmType *>(P)) { + Pos = {TTP->getDepth(), TTP->getIndex()}; + ND = TTP->getDecl(); + // FIXME: We either should have some fallback for canonical TTP, or + // never have canonical TTP here. + } else if (const auto *STP = + dyn_cast<const SubstTemplateTypeParmPackType *>(P)) { + NewPackSize = STP->getNumArgs(); + PendingPackExpansionSize = llvm::count_if( + STP->getArgumentPack().getPackAsArray(), IsUnexpandedPackExpansion); + ND = STP->getReplacedParameter(); + } else { + const auto *SEP = cast<const SubstNonTypeTemplateParmPackExpr *>(P); + NewPackSize = SEP->getArgumentPack().pack_size(); + PendingPackExpansionSize = llvm::count_if( + SEP->getArgumentPack().getPackAsArray(), IsUnexpandedPackExpansion); + ND = SEP->getParameterPack(); ---------------- zyn0217 wrote:
The function `CheckParameterPacksForExpansion` serves two purposes (though combining them is really confusing): 1. Given a (multi-level) template argument list, it determines the length to which an unexpanded pack would expand, if possible. 2. If we encounter a node that has already been expanded (with its previous expansion size tracked in NumExpansions), it checks whether the length of packs expanded in this round matches that from the previous round. If they differ, complain. Now that I mentioned 'last round', it's likely that in this round we'll encounter some `Subst*` nodes created previously because they haven't been expanded yet (but substituted!). This is exactly what this patch aims for: to recover the identifiers contained in those `Subst*` nodes - which correspond to the parameters that were *substituted but not expanded* in the previous round - so that we can improve our diagnostics by identifying which parameters conflict with the current expansion. So this should have answered the question (indirectly), that these `Subst*` nodes aren't used for substituting unexpanded parameters; in fact, they're solely used for name recovery. Their depths are less important this way because we don't need their corresponding template arguments. https://github.com/llvm/llvm-project/pull/121044 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits