@@ -1646,6 +1646,21 @@ namespace {
16461646 SubstTemplateTypeParmPackTypeLoc TL,
16471647 bool SuppressObjCLifetime);
16481648
1649+ QualType
1650+ TransformSubstTemplateTypeParmType (TypeLocBuilder &TLB,
1651+ SubstTemplateTypeParmTypeLoc TL) {
1652+ if (SemaRef.CodeSynthesisContexts .back ().Kind !=
1653+ Sema::CodeSynthesisContext::ConstraintSubstitution)
1654+ return inherited::TransformSubstTemplateTypeParmType (TLB, TL);
1655+
1656+ auto PackIndex = TL.getTypePtr ()->getPackIndex ();
1657+ std::optional<Sema::ArgumentPackSubstitutionIndexRAII> SubstIndex;
1658+ if (SemaRef.ArgumentPackSubstitutionIndex == -1 && PackIndex)
1659+ SubstIndex.emplace (SemaRef, *PackIndex);
1660+
1661+ return inherited::TransformSubstTemplateTypeParmType (TLB, TL);
1662+ }
1663+
16491664 CXXRecordDecl::LambdaDependencyKind
16501665 ComputeLambdaDependency (LambdaScopeInfo *LSI) {
16511666 if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl (getSema ());
@@ -3056,6 +3071,46 @@ namespace {
30563071
30573072} // namespace
30583073
3074+ namespace {
3075+
3076+ struct ExpandPackedTypeConstraints
3077+ : TreeTransform<ExpandPackedTypeConstraints> {
3078+
3079+ using inherited = TreeTransform<ExpandPackedTypeConstraints>;
3080+
3081+ ExpandPackedTypeConstraints (Sema &SemaRef) : inherited(SemaRef) {}
3082+
3083+ using inherited::TransformTemplateTypeParmType;
3084+
3085+ QualType TransformTemplateTypeParmType (TypeLocBuilder &TLB,
3086+ TemplateTypeParmTypeLoc TL, bool ) {
3087+ const TemplateTypeParmType *T = TL.getTypePtr ();
3088+ if (!T->isParameterPack ()) {
3089+ TemplateTypeParmTypeLoc NewTL =
3090+ TLB.push <TemplateTypeParmTypeLoc>(TL.getType ());
3091+ NewTL.setNameLoc (TL.getNameLoc ());
3092+ return TL.getType ();
3093+ }
3094+
3095+ assert (SemaRef.ArgumentPackSubstitutionIndex != -1 );
3096+
3097+ QualType Result = SemaRef.Context .getSubstTemplateTypeParmType (
3098+ TL.getType (), T->getDecl (), T->getIndex (),
3099+ SemaRef.ArgumentPackSubstitutionIndex );
3100+ SubstTemplateTypeParmTypeLoc NewTL =
3101+ TLB.push <SubstTemplateTypeParmTypeLoc>(Result);
3102+ NewTL.setNameLoc (TL.getNameLoc ());
3103+ return Result;
3104+ }
3105+
3106+ bool SubstTemplateArguments (ArrayRef<TemplateArgumentLoc> Args,
3107+ TemplateArgumentListInfo &Out) {
3108+ return inherited::TransformTemplateArguments (Args.begin (), Args.end (), Out);
3109+ }
3110+ };
3111+
3112+ } // namespace
3113+
30593114bool Sema::SubstTypeConstraint (
30603115 TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
30613116 const MultiLevelTemplateArgumentList &TemplateArgs,
@@ -3064,9 +3119,62 @@ bool Sema::SubstTypeConstraint(
30643119 TC->getTemplateArgsAsWritten ();
30653120
30663121 if (!EvaluateConstraints) {
3067- Inst->setTypeConstraint (TC->getConceptReference (),
3068- TC->getImmediatelyDeclaredConstraint ());
3069- return false ;
3122+ bool ShouldExpandExplicitTemplateArgs =
3123+ TemplArgInfo && ArgumentPackSubstitutionIndex != -1 &&
3124+ llvm::any_of (TemplArgInfo->arguments (), [](auto &Arg) {
3125+ return Arg.getArgument ().containsUnexpandedParameterPack ();
3126+ });
3127+
3128+ // We want to transform the packs into Subst* nodes for type constraints
3129+ // inside a pack expansion. For example,
3130+ //
3131+ // template <class... Ts> void foo() {
3132+ // bar([](C<Ts> auto value) {}...);
3133+ // }
3134+ //
3135+ // As we expand Ts in the process of instantiating foo(), and retain
3136+ // the original template depths of Ts until the constraint evaluation, we
3137+ // would otherwise have no chance to expand Ts by the time of evaluating
3138+ // C<auto, Ts>.
3139+ //
3140+ // So we form a Subst* node for Ts along with a proper substitution index
3141+ // here, and substitute the node with a complete MLTAL later in evaluation.
3142+ if (ShouldExpandExplicitTemplateArgs) {
3143+ TemplateArgumentListInfo InstArgs;
3144+ InstArgs.setLAngleLoc (TemplArgInfo->LAngleLoc );
3145+ InstArgs.setRAngleLoc (TemplArgInfo->RAngleLoc );
3146+ if (ExpandPackedTypeConstraints (*this ).SubstTemplateArguments (
3147+ TemplArgInfo->arguments (), InstArgs))
3148+ return true ;
3149+
3150+ // The type of the original parameter.
3151+ auto *ConstraintExpr = TC->getImmediatelyDeclaredConstraint ();
3152+ QualType ConstrainedType;
3153+
3154+ if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr)) {
3155+ assert (FE->getLHS ());
3156+ ConstraintExpr = FE->getLHS ();
3157+ }
3158+ auto *CSE = cast<ConceptSpecializationExpr>(ConstraintExpr);
3159+ assert (!CSE->getTemplateArguments ().empty () &&
3160+ " Empty template arguments?" );
3161+ ConstrainedType = CSE->getTemplateArguments ()[0 ].getAsType ();
3162+ assert (!ConstrainedType.isNull () &&
3163+ " Failed to extract the original ConstrainedType?" );
3164+
3165+ return AttachTypeConstraint (
3166+ TC->getNestedNameSpecifierLoc (), TC->getConceptNameInfo (),
3167+ TC->getNamedConcept (),
3168+ /* FoundDecl=*/ TC->getConceptReference ()->getFoundDecl (), &InstArgs,
3169+ Inst, ConstrainedType,
3170+ Inst->isParameterPack ()
3171+ ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint ())
3172+ ->getEllipsisLoc ()
3173+ : SourceLocation ());
3174+ }
3175+ Inst->setTypeConstraint (TC->getConceptReference (),
3176+ TC->getImmediatelyDeclaredConstraint ());
3177+ return false ;
30703178 }
30713179
30723180 TemplateArgumentListInfo InstArgs;
@@ -3082,6 +3190,7 @@ bool Sema::SubstTypeConstraint(
30823190 TC->getNestedNameSpecifierLoc (), TC->getConceptNameInfo (),
30833191 TC->getNamedConcept (),
30843192 /* FoundDecl=*/ TC->getConceptReference ()->getFoundDecl (), &InstArgs, Inst,
3193+ Context.getTypeDeclType (Inst),
30853194 Inst->isParameterPack ()
30863195 ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint ())
30873196 ->getEllipsisLoc ()
0 commit comments