================ @@ -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(); } - // Determine the size of this argument pack. - unsigned NewPackSize, PendingPackExpansionSize = 0; - if (IsVarDeclPack) { - // Figure out whether we're instantiating to an argument pack or not. - llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation = - CurrentInstantiationScope->findInstantiationOf( - cast<NamedDecl *>(ParmPack.first)); - if (isa<DeclArgumentPack *>(*Instantiation)) { - // We could expand this function parameter pack. - NewPackSize = cast<DeclArgumentPack *>(*Instantiation)->size(); - } else { - // We can't expand this function parameter pack, so we can't expand - // the pack expansion. - ShouldExpand = false; - continue; - } - } else if (BindingPack) { - NewPackSize = BindingPack->getNumExpansions(); - } else { + if (Pos) { // If we don't have a template argument at this depth/index, then we // cannot expand the pack expansion. Make a note of this, but we still // want to check any parameter packs we *do* have arguments for. - if (Depth >= TemplateArgs.getNumLevels() || - !TemplateArgs.hasTemplateArgument(Depth, Index)) { + if (Pos->first >= TemplateArgs.getNumLevels() || + !TemplateArgs.hasTemplateArgument(Pos->first, Pos->second)) { ShouldExpand = false; continue; } - // Determine the size of the argument pack. ArrayRef<TemplateArgument> Pack = - TemplateArgs(Depth, Index).getPackAsArray(); + TemplateArgs(Pos->first, Pos->second).getPackAsArray(); NewPackSize = Pack.size(); PendingPackExpansionSize = - llvm::count_if(Pack, [](const TemplateArgument &TA) { - if (!TA.isPackExpansion()) - return false; - - if (TA.getKind() == TemplateArgument::Type) - return !TA.getAsType() - ->castAs<PackExpansionType>() - ->getNumExpansions(); - - if (TA.getKind() == TemplateArgument::Expression) - return !cast<PackExpansionExpr>(TA.getAsExpr()) - ->getNumExpansions(); - - return !TA.getNumTemplateExpansions(); - }); - } - - // C++0x [temp.arg.explicit]p9: - // Template argument deduction can extend the sequence of template - // arguments corresponding to a template parameter pack, even when the - // sequence contains explicitly specified template arguments. - if (!IsVarDeclPack && CurrentInstantiationScope) { - if (NamedDecl *PartialPack = - CurrentInstantiationScope->getPartiallySubstitutedPack()) { - unsigned PartialDepth, PartialIndex; - std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack); - if (PartialDepth == Depth && PartialIndex == Index) { + llvm::count_if(Pack, IsUnexpandedPackExpansion); + // C++0x [temp.arg.explicit]p9: + // Template argument deduction can extend the sequence of template + // arguments corresponding to a template parameter pack, even when the + // sequence contains explicitly specified template arguments. + if (CurrentInstantiationScope) + if (const NamedDecl *PartialPack = + CurrentInstantiationScope->getPartiallySubstitutedPack(); + PartialPack && getDepthAndIndex(PartialPack) == *Pos) { RetainExpansion = true; // We don't actually know the new pack size yet. - NumPartialExpansions = NewPackSize; - PartiallySubstitutedPackLoc = ParmPack.second; + PartialExpansion = {NewPackSize, Loc}; continue; } - } } - if (!NumExpansions) { + unsigned LeastNewPackSize = NewPackSize - PendingPackExpansionSize; + if (PendingPackExpansionSize) + CurMaximumOfLeastExpansions = + CurMaximumOfLeastExpansions + ? std::max(LeastNewPackSize, *CurMaximumOfLeastExpansions) + : LeastNewPackSize; + + // FIXME: Workaround for Canonical TTP. ---------------- cor3ntin wrote:
Can you add more details? 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