@@ -461,13 +461,17 @@ static ExprResult calculateConstraintSatisfaction(
461461 return ExprError ();
462462
463463 llvm::FoldingSetNodeID ID;
464+ // llvm::errs() << "Preparing for checking " << Template << "\n";
464465 if (Template &&
465466 DiagRecursiveConstraintEval (S, ID, Template, AtomicExpr, MLTAL)) {
467+ // Template->dump();
466468 Satisfaction.IsSatisfied = false ;
467469 Satisfaction.ContainsErrors = true ;
470+ // __builtin_trap();
468471 return ExprEmpty ();
469472 }
470473
474+ // llvm::errs() << "Pushing " << Template << "\n";
471475 SatisfactionStackRAII StackRAII (S, Template, ID);
472476
473477 // We do not want error diagnostics escaping here.
@@ -1122,6 +1126,139 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
11221126 PointOfInstantiation, Satisfaction);
11231127}
11241128
1129+ namespace {
1130+
1131+ // We employ a TreeTransform because RAV couldn't recurse into a bunch of
1132+ // Exprs e.g. SizeOfPackExpr, CXXFoldExpr, etc.
1133+ // FIXME: Could we do the Decl instantiation as we substitute into
1134+ // the constraint expressions?
1135+ class InstantiateReferencedParameter
1136+ : public TreeTransform<InstantiateReferencedParameter> {
1137+ const MultiLevelTemplateArgumentList &TemplateArgs;
1138+
1139+ DeclContext *FunctionDC;
1140+
1141+ using inherited = TreeTransform<InstantiateReferencedParameter>;
1142+
1143+ bool instantiateParameterToScope (ParmVarDecl *OldParm,
1144+ LocalInstantiationScope &Scope) {
1145+ // Current context might have been changed by lambda expressions. So resume
1146+ // it before we substitute parameters.
1147+ Sema::ContextRAII Context (SemaRef, FunctionDC);
1148+ std::optional<unsigned > NumExpansions;
1149+ ParmVarDecl *NewParm = nullptr ;
1150+ unsigned IndexAdjustment = 0 ;
1151+ if (OldParm->isParameterPack ()) {
1152+ SmallVector<UnexpandedParameterPack, 2 > Unexpanded;
1153+ TypeLoc TL = OldParm->getTypeSourceInfo ()->getTypeLoc ();
1154+ PackExpansionTypeLoc ExpansionTL = TL.castAs <PackExpansionTypeLoc>();
1155+ TypeLoc Pattern = ExpansionTL.getPatternLoc ();
1156+ SemaRef.collectUnexpandedParameterPacks (Pattern, Unexpanded);
1157+
1158+ assert (!Unexpanded.empty () &&
1159+ " A pack Decl doesn't contain anything unexpanded?" );
1160+
1161+ bool ShouldExpand = false ;
1162+ bool RetainExpansion = false ;
1163+ std::optional<unsigned > OrigNumExpansions =
1164+ ExpansionTL.getTypePtr ()->getNumExpansions ();
1165+ NumExpansions = OrigNumExpansions;
1166+ if (SemaRef.CheckParameterPacksForExpansion (
1167+ ExpansionTL.getEllipsisLoc (), Pattern.getSourceRange (),
1168+ Unexpanded, TemplateArgs, ShouldExpand, RetainExpansion,
1169+ NumExpansions))
1170+ return true ;
1171+
1172+ assert (ShouldExpand && !RetainExpansion &&
1173+ " Shouldn't retain an expansion here!" );
1174+ Scope.MakeInstantiatedLocalArgPack (OldParm);
1175+
1176+ for (unsigned I = 0 ; I != *NumExpansions; ++I) {
1177+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex (SemaRef, I);
1178+ ParmVarDecl *NewParm = SemaRef.SubstParmVarDecl (
1179+ OldParm, TemplateArgs, /* indexAdjustment=*/ IndexAdjustment++,
1180+ NumExpansions, /* ExpectParameterPack=*/ false ,
1181+ /* EvaluateConstraints=*/ false );
1182+ if (!NewParm)
1183+ return true ;
1184+ }
1185+
1186+ return false ;
1187+ }
1188+ NewParm = SemaRef.SubstParmVarDecl (OldParm, TemplateArgs,
1189+ /* indexAdjustment=*/ IndexAdjustment,
1190+ std::nullopt ,
1191+ /* ExpectParameterPack=*/ false );
1192+ if (!NewParm)
1193+ return true ;
1194+ Scope.InstantiatedLocal (OldParm, NewParm);
1195+ return false ;
1196+ }
1197+
1198+ public:
1199+ InstantiateReferencedParameter (
1200+ Sema &SemaRef, const MultiLevelTemplateArgumentList &TemplateArgs,
1201+ DeclContext *FunctionDC)
1202+ : inherited(SemaRef), TemplateArgs(TemplateArgs), FunctionDC(FunctionDC) {
1203+ }
1204+
1205+ Decl *TransformDecl (SourceLocation Loc, Decl *D) {
1206+ if (auto *PVD = dyn_cast<ParmVarDecl>(D))
1207+ instantiateParameterToScope (PVD, *SemaRef.CurrentInstantiationScope );
1208+ return D;
1209+ }
1210+
1211+ void TraverseConstraintExprs (ArrayRef<const Expr *> Exprs) {
1212+ for (auto *E : Exprs)
1213+ TransformExpr (const_cast <Expr *>(E));
1214+ }
1215+ };
1216+
1217+ } // namespace
1218+
1219+ bool Sema::CheckFunctionConstraintsWithoutInstantiation (
1220+ SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template,
1221+ ArrayRef<TemplateArgument> TemplateArgs,
1222+ ConstraintSatisfaction &Satisfaction) {
1223+ FunctionDecl *FD = Template->getTemplatedDecl ();
1224+ SmallVector<const Expr *, 3 > TemplateAC;
1225+ Template->getAssociatedConstraints (TemplateAC);
1226+ if (TemplateAC.empty ()) {
1227+ Satisfaction.IsSatisfied = true ;
1228+ return false ;
1229+ }
1230+
1231+ // Enter the scope of this instantiation. We don't use
1232+ // PushDeclContext because we don't have a scope.
1233+ LocalInstantiationScope Scope (*this );
1234+
1235+ // Collect the list of template arguments relative to the 'primary'
1236+ // template. We need the entire list, since the constraint is completely
1237+ // uninstantiated at this point.
1238+ DeclContext *NextDC = FD->getFriendObjectKind () ? FD->getLexicalDeclContext ()
1239+ : FD->getDeclContext ();
1240+ MultiLevelTemplateArgumentList MLTAL =
1241+ getTemplateInstantiationArgs (FD, NextDC,
1242+ /* Final=*/ false ,
1243+ /* Innermost=*/ TemplateArgs,
1244+ /* RelativeToPrimary=*/ true ,
1245+ /* Pattern=*/ nullptr ,
1246+ /* ForConstraintInstantiation=*/ true );
1247+
1248+ InstantiateReferencedParameter (*this , MLTAL, FD)
1249+ .TraverseConstraintExprs (TemplateAC);
1250+
1251+ Qualifiers ThisQuals;
1252+ CXXRecordDecl *Record = nullptr ;
1253+ if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
1254+ ThisQuals = Method->getMethodQualifiers ();
1255+ Record = Method->getParent ();
1256+ }
1257+ CXXThisScopeRAII ThisScope (*this , Record, ThisQuals, Record != nullptr );
1258+ return CheckConstraintSatisfaction (Template, TemplateAC, MLTAL,
1259+ PointOfInstantiation, Satisfaction);
1260+ }
1261+
11251262static void diagnoseUnsatisfiedRequirement (Sema &S,
11261263 concepts::ExprRequirement *Req,
11271264 bool First) {
0 commit comments