================ @@ -543,30 +672,330 @@ static ExprResult calculateConstraintSatisfaction( return ExprError(); } - assert(EvalResult.Val.isInt() && - "evaluating bool expression didn't produce int"); - Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); - if (!Satisfaction.IsSatisfied) - Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get()); + assert(EvalResult.Val.isInt() && + "evaluating bool expression didn't produce int"); + Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); + if (!Satisfaction.IsSatisfied) + Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get()); + + return SubstitutedAtomicExpr; +} + +ExprResult CalculateConstraintSatisfaction::Calculate( + const AtomicConstraint &Constraint, + const MultiLevelTemplateArgumentList &MLTAL) { + + unsigned Size = Satisfaction.Details.size(); + llvm::FoldingSetNodeID ID; + UnsignedOrNone OuterPackSubstIndex = + Constraint.getPackSubstitutionIndex() + ? Constraint.getPackSubstitutionIndex() + : PackSubstitutionIndex; + // Constraint.getConstraintExpr()->Profile(ID, S.Context, /*Canonical=*/true, + // /*ProfileLambdaExpr=*/true); + auto *Previous = Constraint.getConstraintExpr(); + ID.AddPointer(Constraint.getConstraintExpr()); + ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation()); + ID.AddBoolean(Constraint.hasParameterMapping()); + HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex) + .VisitConstraint(Constraint); + + if (auto Iter = S.ConceptIdSatisfactionCache.find(ID); + Iter != S.ConceptIdSatisfactionCache.end()) { + + auto &Cached = Iter->second.Satisfaction; + Satisfaction.ContainsErrors = Cached.ContainsErrors; + Satisfaction.IsSatisfied = Cached.IsSatisfied; + Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, + Cached.Details.begin(), Cached.Details.end()); + return Iter->second.SubstExpr; + } + + ExprResult E = CalculateSlow(Constraint, MLTAL); + + assert(Constraint.getConstraintExpr() == Previous); + + CachedConceptIdConstraint Cache; + Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors; + Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied; + std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(), + std::back_inserter(Cache.Satisfaction.Details)); + Cache.SubstExpr = E; + Cache.E = Constraint.getConstraintExpr(); + S.ConceptIdSatisfactionCache.insert({ID, std::move(Cache)}); + + return E; +} + +UnsignedOrNone +CalculateConstraintSatisfaction::EvaluateFoldExpandedConstraintSize( + const FoldExpandedConstraint &FE, + const MultiLevelTemplateArgumentList &MLTAL) { + + // We should ignore errors in the presence of packs of different size. + Sema::SFINAETrap Trap(S); + + Expr *Pattern = const_cast<Expr *>(FE.getPattern()); + + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + S.collectUnexpandedParameterPacks(Pattern, Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); + bool Expand = true; + bool RetainExpansion = false; + UnsignedOrNone NumExpansions(std::nullopt); + if (S.CheckParameterPacksForExpansion( + Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL, + /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion, + NumExpansions) || + !Expand || RetainExpansion) + return std::nullopt; + + if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions) { + S.Diag(Pattern->getExprLoc(), + clang::diag::err_fold_expression_limit_exceeded) + << *NumExpansions << S.getLangOpts().BracketDepth + << Pattern->getSourceRange(); + S.Diag(Pattern->getExprLoc(), diag::note_bracket_depth); + return std::nullopt; + } + return NumExpansions; +} + +ExprResult CalculateConstraintSatisfaction::Calculate( + const FoldExpandedConstraint &Constraint, + const MultiLevelTemplateArgumentList &MLTAL) { + bool Conjunction = Constraint.getFoldOperator() == + FoldExpandedConstraint::FoldOperatorKind::And; + unsigned EffectiveDetailEndIndex = Satisfaction.Details.size(); + + llvm::SmallVector<TemplateArgument> SubstitutedOuterMost; + // FIXME: Is PackSubstitutionIndex correct? + llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex); + std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs = + SubstitutionInTemplateArguments( + static_cast<const NormalizedConstraintWithParamMapping &>(Constraint), + MLTAL, SubstitutedOuterMost); + if (!SubstitutedArgs) { + Satisfaction.IsSatisfied = false; + return ExprError(); + } + + ExprResult Out; + UnsignedOrNone NumExpansions = + EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs); + if (!NumExpansions) + return ExprEmpty(); ---------------- zyn0217 wrote:
This includes a parameter mapping substitution which is expensive, so let's add a TODO of adding cache on it. https://github.com/llvm/llvm-project/pull/141776 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits