@@ -1646,6 +1646,21 @@ namespace {
1646
1646
SubstTemplateTypeParmPackTypeLoc TL,
1647
1647
bool SuppressObjCLifetime);
1648
1648
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
+
1649
1664
CXXRecordDecl::LambdaDependencyKind
1650
1665
ComputeLambdaDependency (LambdaScopeInfo *LSI) {
1651
1666
if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl (getSema ());
@@ -3056,6 +3071,46 @@ namespace {
3056
3071
3057
3072
} // namespace
3058
3073
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
+
3059
3114
bool Sema::SubstTypeConstraint (
3060
3115
TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
3061
3116
const MultiLevelTemplateArgumentList &TemplateArgs,
@@ -3064,9 +3119,62 @@ bool Sema::SubstTypeConstraint(
3064
3119
TC->getTemplateArgsAsWritten ();
3065
3120
3066
3121
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 ;
3070
3178
}
3071
3179
3072
3180
TemplateArgumentListInfo InstArgs;
@@ -3082,6 +3190,7 @@ bool Sema::SubstTypeConstraint(
3082
3190
TC->getNestedNameSpecifierLoc (), TC->getConceptNameInfo (),
3083
3191
TC->getNamedConcept (),
3084
3192
/* FoundDecl=*/ TC->getConceptReference ()->getFoundDecl (), &InstArgs, Inst,
3193
+ Context.getTypeDeclType (Inst),
3085
3194
Inst->isParameterPack ()
3086
3195
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint ())
3087
3196
->getEllipsisLoc ()
0 commit comments