1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===// 2a7dea167SDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric // 9a7dea167SDimitry Andric // This file implements semantic analysis for C++ constraints and concepts. 10a7dea167SDimitry Andric // 11a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 12a7dea167SDimitry Andric 13480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h" 1406c3fb27SDimitry Andric #include "TreeTransform.h" 15bdd1243dSDimitry Andric #include "clang/AST/ASTLambda.h" 16feb5b0c7SDimitry Andric #include "clang/AST/DeclCXX.h" 1755e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h" 18480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 19480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h" 2006c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h" 2106c3fb27SDimitry Andric #include "clang/Sema/Initialization.h" 2206c3fb27SDimitry Andric #include "clang/Sema/Overload.h" 23feb5b0c7SDimitry Andric #include "clang/Sema/ScopeInfo.h" 2406c3fb27SDimitry Andric #include "clang/Sema/Sema.h" 2506c3fb27SDimitry Andric #include "clang/Sema/SemaDiagnostic.h" 2606c3fb27SDimitry Andric #include "clang/Sema/SemaInternal.h" 2706c3fb27SDimitry Andric #include "clang/Sema/Template.h" 2806c3fb27SDimitry Andric #include "clang/Sema/TemplateDeduction.h" 29480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h" 30480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h" 31fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h" 32bdd1243dSDimitry Andric #include <optional> 33fe6060f1SDimitry Andric 34a7dea167SDimitry Andric using namespace clang; 35a7dea167SDimitry Andric using namespace sema; 36a7dea167SDimitry Andric 375ffd83dbSDimitry Andric namespace { 385ffd83dbSDimitry Andric class LogicalBinOp { 39bdd1243dSDimitry Andric SourceLocation Loc; 405ffd83dbSDimitry Andric OverloadedOperatorKind Op = OO_None; 415ffd83dbSDimitry Andric const Expr *LHS = nullptr; 425ffd83dbSDimitry Andric const Expr *RHS = nullptr; 435ffd83dbSDimitry Andric 445ffd83dbSDimitry Andric public: 455ffd83dbSDimitry Andric LogicalBinOp(const Expr *E) { 465ffd83dbSDimitry Andric if (auto *BO = dyn_cast<BinaryOperator>(E)) { 475ffd83dbSDimitry Andric Op = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 485ffd83dbSDimitry Andric LHS = BO->getLHS(); 495ffd83dbSDimitry Andric RHS = BO->getRHS(); 50bdd1243dSDimitry Andric Loc = BO->getExprLoc(); 515ffd83dbSDimitry Andric } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) { 52fe6060f1SDimitry Andric // If OO is not || or && it might not have exactly 2 arguments. 53fe6060f1SDimitry Andric if (OO->getNumArgs() == 2) { 545ffd83dbSDimitry Andric Op = OO->getOperator(); 555ffd83dbSDimitry Andric LHS = OO->getArg(0); 565ffd83dbSDimitry Andric RHS = OO->getArg(1); 57bdd1243dSDimitry Andric Loc = OO->getOperatorLoc(); 585ffd83dbSDimitry Andric } 595ffd83dbSDimitry Andric } 60fe6060f1SDimitry Andric } 615ffd83dbSDimitry Andric 625ffd83dbSDimitry Andric bool isAnd() const { return Op == OO_AmpAmp; } 635ffd83dbSDimitry Andric bool isOr() const { return Op == OO_PipePipe; } 645ffd83dbSDimitry Andric explicit operator bool() const { return isAnd() || isOr(); } 655ffd83dbSDimitry Andric 665ffd83dbSDimitry Andric const Expr *getLHS() const { return LHS; } 675ffd83dbSDimitry Andric const Expr *getRHS() const { return RHS; } 680fca6ea1SDimitry Andric OverloadedOperatorKind getOp() const { return Op; } 69bdd1243dSDimitry Andric 70bdd1243dSDimitry Andric ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const { 71bdd1243dSDimitry Andric return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS())); 72bdd1243dSDimitry Andric } 73bdd1243dSDimitry Andric 74bdd1243dSDimitry Andric ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS, 75bdd1243dSDimitry Andric ExprResult RHS) const { 76bdd1243dSDimitry Andric assert((isAnd() || isOr()) && "Not the right kind of op?"); 77bdd1243dSDimitry Andric assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?"); 78bdd1243dSDimitry Andric 79bdd1243dSDimitry Andric if (!LHS.isUsable() || !RHS.isUsable()) 80bdd1243dSDimitry Andric return ExprEmpty(); 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric // We should just be able to 'normalize' these to the builtin Binary 83bdd1243dSDimitry Andric // Operator, since that is how they are evaluated in constriant checks. 84bdd1243dSDimitry Andric return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(), 85bdd1243dSDimitry Andric BinaryOperator::getOverloadedOpcode(Op), 86bdd1243dSDimitry Andric SemaRef.Context.BoolTy, VK_PRValue, 87bdd1243dSDimitry Andric OK_Ordinary, Loc, FPOptionsOverride{}); 88bdd1243dSDimitry Andric } 895ffd83dbSDimitry Andric }; 905ffd83dbSDimitry Andric } 915ffd83dbSDimitry Andric 925ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression, 935ffd83dbSDimitry Andric Token NextToken, bool *PossibleNonPrimary, 94480093f4SDimitry Andric bool IsTrailingRequiresClause) { 95a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 96a7dea167SDimitry Andric // ..E shall be a constant expression of type bool. 97a7dea167SDimitry Andric 98a7dea167SDimitry Andric ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts(); 99a7dea167SDimitry Andric 1005ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpression) { 1015ffd83dbSDimitry Andric return CheckConstraintExpression(BO.getLHS(), NextToken, 102480093f4SDimitry Andric PossibleNonPrimary) && 1035ffd83dbSDimitry Andric CheckConstraintExpression(BO.getRHS(), NextToken, 104480093f4SDimitry Andric PossibleNonPrimary); 105a7dea167SDimitry Andric } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression)) 106480093f4SDimitry Andric return CheckConstraintExpression(C->getSubExpr(), NextToken, 107480093f4SDimitry Andric PossibleNonPrimary); 108a7dea167SDimitry Andric 109a7dea167SDimitry Andric QualType Type = ConstraintExpression->getType(); 110480093f4SDimitry Andric 111480093f4SDimitry Andric auto CheckForNonPrimary = [&] { 11206c3fb27SDimitry Andric if (!PossibleNonPrimary) 11306c3fb27SDimitry Andric return; 11406c3fb27SDimitry Andric 115480093f4SDimitry Andric *PossibleNonPrimary = 116480093f4SDimitry Andric // We have the following case: 117480093f4SDimitry Andric // template<typename> requires func(0) struct S { }; 118480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 119480093f4SDimitry Andric // the function call, and we're only going to parse 'func' as the 120480093f4SDimitry Andric // primary-expression, and complain that it is of non-bool type. 12106c3fb27SDimitry Andric // 12206c3fb27SDimitry Andric // However, if we're in a lambda, this might also be: 12306c3fb27SDimitry Andric // []<typename> requires var () {}; 12406c3fb27SDimitry Andric // Which also looks like a function call due to the lambda parentheses, 12506c3fb27SDimitry Andric // but unlike the first case, isn't an error, so this check is skipped. 126480093f4SDimitry Andric (NextToken.is(tok::l_paren) && 127480093f4SDimitry Andric (IsTrailingRequiresClause || 128480093f4SDimitry Andric (Type->isDependentType() && 12906c3fb27SDimitry Andric isa<UnresolvedLookupExpr>(ConstraintExpression) && 13006c3fb27SDimitry Andric !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) || 131480093f4SDimitry Andric Type->isFunctionType() || 132480093f4SDimitry Andric Type->isSpecificBuiltinType(BuiltinType::Overload))) || 133480093f4SDimitry Andric // We have the following case: 134480093f4SDimitry Andric // template<typename T> requires size_<T> == 0 struct S { }; 135480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 136480093f4SDimitry Andric // the binary operator, and we're only going to parse 'func' as the 137480093f4SDimitry Andric // first operand, and complain that it is of non-bool type. 138480093f4SDimitry Andric getBinOpPrecedence(NextToken.getKind(), 139480093f4SDimitry Andric /*GreaterThanIsOperator=*/true, 140480093f4SDimitry Andric getLangOpts().CPlusPlus11) > prec::LogicalAnd; 141480093f4SDimitry Andric }; 142480093f4SDimitry Andric 143480093f4SDimitry Andric // An atomic constraint! 144480093f4SDimitry Andric if (ConstraintExpression->isTypeDependent()) { 145480093f4SDimitry Andric CheckForNonPrimary(); 146480093f4SDimitry Andric return true; 147480093f4SDimitry Andric } 148480093f4SDimitry Andric 149a7dea167SDimitry Andric if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) { 150a7dea167SDimitry Andric Diag(ConstraintExpression->getExprLoc(), 151a7dea167SDimitry Andric diag::err_non_bool_atomic_constraint) << Type 152a7dea167SDimitry Andric << ConstraintExpression->getSourceRange(); 153480093f4SDimitry Andric CheckForNonPrimary(); 154a7dea167SDimitry Andric return false; 155a7dea167SDimitry Andric } 156480093f4SDimitry Andric 157480093f4SDimitry Andric if (PossibleNonPrimary) 158480093f4SDimitry Andric *PossibleNonPrimary = false; 159a7dea167SDimitry Andric return true; 160a7dea167SDimitry Andric } 161a7dea167SDimitry Andric 162bdd1243dSDimitry Andric namespace { 163bdd1243dSDimitry Andric struct SatisfactionStackRAII { 164bdd1243dSDimitry Andric Sema &SemaRef; 1651ac55f4cSDimitry Andric bool Inserted = false; 1661ac55f4cSDimitry Andric SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND, 16706c3fb27SDimitry Andric const llvm::FoldingSetNodeID &FSNID) 168bdd1243dSDimitry Andric : SemaRef(SemaRef) { 1691ac55f4cSDimitry Andric if (ND) { 1701ac55f4cSDimitry Andric SemaRef.PushSatisfactionStackEntry(ND, FSNID); 1711ac55f4cSDimitry Andric Inserted = true; 172bdd1243dSDimitry Andric } 1731ac55f4cSDimitry Andric } 1741ac55f4cSDimitry Andric ~SatisfactionStackRAII() { 1751ac55f4cSDimitry Andric if (Inserted) 1761ac55f4cSDimitry Andric SemaRef.PopSatisfactionStackEntry(); 1771ac55f4cSDimitry Andric } 178bdd1243dSDimitry Andric }; 179bdd1243dSDimitry Andric } // namespace 180bdd1243dSDimitry Andric 1810fca6ea1SDimitry Andric template <typename ConstraintEvaluator> 182bdd1243dSDimitry Andric static ExprResult 183480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, 184480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction, 1850fca6ea1SDimitry Andric const ConstraintEvaluator &Evaluator); 186a7dea167SDimitry Andric 1870fca6ea1SDimitry Andric template <typename ConstraintEvaluator> 1880fca6ea1SDimitry Andric static ExprResult 1890fca6ea1SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *LHS, 1900fca6ea1SDimitry Andric OverloadedOperatorKind Op, const Expr *RHS, 1910fca6ea1SDimitry Andric ConstraintSatisfaction &Satisfaction, 1920fca6ea1SDimitry Andric const ConstraintEvaluator &Evaluator) { 1935f757f3fSDimitry Andric size_t EffectiveDetailEndIndex = Satisfaction.Details.size(); 1940fca6ea1SDimitry Andric 1950fca6ea1SDimitry Andric ExprResult LHSRes = 1960fca6ea1SDimitry Andric calculateConstraintSatisfaction(S, LHS, Satisfaction, Evaluator); 197bdd1243dSDimitry Andric 198bdd1243dSDimitry Andric if (LHSRes.isInvalid()) 199bdd1243dSDimitry Andric return ExprError(); 200480093f4SDimitry Andric 201480093f4SDimitry Andric bool IsLHSSatisfied = Satisfaction.IsSatisfied; 202480093f4SDimitry Andric 2030fca6ea1SDimitry Andric if (Op == clang::OO_PipePipe && IsLHSSatisfied) 204480093f4SDimitry Andric // [temp.constr.op] p3 205480093f4SDimitry Andric // A disjunction is a constraint taking two operands. To determine if 206480093f4SDimitry Andric // a disjunction is satisfied, the satisfaction of the first operand 207480093f4SDimitry Andric // is checked. If that is satisfied, the disjunction is satisfied. 208480093f4SDimitry Andric // Otherwise, the disjunction is satisfied if and only if the second 209480093f4SDimitry Andric // operand is satisfied. 210bdd1243dSDimitry Andric // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 211bdd1243dSDimitry Andric return LHSRes; 212480093f4SDimitry Andric 2130fca6ea1SDimitry Andric if (Op == clang::OO_AmpAmp && !IsLHSSatisfied) 214480093f4SDimitry Andric // [temp.constr.op] p2 215480093f4SDimitry Andric // A conjunction is a constraint taking two operands. To determine if 216480093f4SDimitry Andric // a conjunction is satisfied, the satisfaction of the first operand 217480093f4SDimitry Andric // is checked. If that is not satisfied, the conjunction is not 218480093f4SDimitry Andric // satisfied. Otherwise, the conjunction is satisfied if and only if 219480093f4SDimitry Andric // the second operand is satisfied. 220bdd1243dSDimitry Andric // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 221bdd1243dSDimitry Andric return LHSRes; 222480093f4SDimitry Andric 2230fca6ea1SDimitry Andric ExprResult RHSRes = 2240fca6ea1SDimitry Andric calculateConstraintSatisfaction(S, RHS, Satisfaction, Evaluator); 225bdd1243dSDimitry Andric if (RHSRes.isInvalid()) 226bdd1243dSDimitry Andric return ExprError(); 227bdd1243dSDimitry Andric 2285f757f3fSDimitry Andric bool IsRHSSatisfied = Satisfaction.IsSatisfied; 2295f757f3fSDimitry Andric // Current implementation adds diagnostic information about the falsity 2305f757f3fSDimitry Andric // of each false atomic constraint expression when it evaluates them. 2315f757f3fSDimitry Andric // When the evaluation results to `false || true`, the information 2325f757f3fSDimitry Andric // generated during the evaluation of left-hand side is meaningless 2335f757f3fSDimitry Andric // because the whole expression evaluates to true. 2345f757f3fSDimitry Andric // The following code removes the irrelevant diagnostic information. 2355f757f3fSDimitry Andric // FIXME: We should probably delay the addition of diagnostic information 2365f757f3fSDimitry Andric // until we know the entire expression is false. 2370fca6ea1SDimitry Andric if (Op == clang::OO_PipePipe && IsRHSSatisfied) { 2380fca6ea1SDimitry Andric auto EffectiveDetailEnd = Satisfaction.Details.begin(); 2390fca6ea1SDimitry Andric std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex); 2400fca6ea1SDimitry Andric Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end()); 2410fca6ea1SDimitry Andric } 2420fca6ea1SDimitry Andric 2430fca6ea1SDimitry Andric if (!LHSRes.isUsable() || !RHSRes.isUsable()) 2440fca6ea1SDimitry Andric return ExprEmpty(); 2450fca6ea1SDimitry Andric 2460fca6ea1SDimitry Andric return BinaryOperator::Create(S.Context, LHSRes.get(), RHSRes.get(), 2470fca6ea1SDimitry Andric BinaryOperator::getOverloadedOpcode(Op), 2480fca6ea1SDimitry Andric S.Context.BoolTy, VK_PRValue, OK_Ordinary, 2490fca6ea1SDimitry Andric LHS->getBeginLoc(), FPOptionsOverride{}); 2500fca6ea1SDimitry Andric } 2510fca6ea1SDimitry Andric 2520fca6ea1SDimitry Andric template <typename ConstraintEvaluator> 2530fca6ea1SDimitry Andric static ExprResult 2540fca6ea1SDimitry Andric calculateConstraintSatisfaction(Sema &S, const CXXFoldExpr *FE, 2550fca6ea1SDimitry Andric ConstraintSatisfaction &Satisfaction, 2560fca6ea1SDimitry Andric const ConstraintEvaluator &Evaluator) { 2570fca6ea1SDimitry Andric bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd; 2580fca6ea1SDimitry Andric size_t EffectiveDetailEndIndex = Satisfaction.Details.size(); 2590fca6ea1SDimitry Andric 2600fca6ea1SDimitry Andric ExprResult Out; 2610fca6ea1SDimitry Andric if (FE->isLeftFold() && FE->getInit()) { 2620fca6ea1SDimitry Andric Out = calculateConstraintSatisfaction(S, FE->getInit(), Satisfaction, 2630fca6ea1SDimitry Andric Evaluator); 2640fca6ea1SDimitry Andric if (Out.isInvalid()) 2650fca6ea1SDimitry Andric return ExprError(); 2660fca6ea1SDimitry Andric 2670fca6ea1SDimitry Andric // If the first clause of a conjunction is not satisfied, 2680fca6ea1SDimitry Andric // or if the first clause of a disjection is satisfied, 2690fca6ea1SDimitry Andric // we have established satisfaction of the whole constraint 2700fca6ea1SDimitry Andric // and we should not continue further. 2710fca6ea1SDimitry Andric if (Conjunction != Satisfaction.IsSatisfied) 2720fca6ea1SDimitry Andric return Out; 2730fca6ea1SDimitry Andric } 2740fca6ea1SDimitry Andric std::optional<unsigned> NumExpansions = 2750fca6ea1SDimitry Andric Evaluator.EvaluateFoldExpandedConstraintSize(FE); 2760fca6ea1SDimitry Andric if (!NumExpansions) 2770fca6ea1SDimitry Andric return ExprError(); 2780fca6ea1SDimitry Andric for (unsigned I = 0; I < *NumExpansions; I++) { 2790fca6ea1SDimitry Andric Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I); 2800fca6ea1SDimitry Andric ExprResult Res = calculateConstraintSatisfaction(S, FE->getPattern(), 2810fca6ea1SDimitry Andric Satisfaction, Evaluator); 2820fca6ea1SDimitry Andric if (Res.isInvalid()) 2830fca6ea1SDimitry Andric return ExprError(); 2840fca6ea1SDimitry Andric bool IsRHSSatisfied = Satisfaction.IsSatisfied; 2850fca6ea1SDimitry Andric if (!Conjunction && IsRHSSatisfied) { 2865f757f3fSDimitry Andric auto EffectiveDetailEnd = Satisfaction.Details.begin(); 2875f757f3fSDimitry Andric std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex); 2885f757f3fSDimitry Andric Satisfaction.Details.erase(EffectiveDetailEnd, 2895f757f3fSDimitry Andric Satisfaction.Details.end()); 2905f757f3fSDimitry Andric } 2910fca6ea1SDimitry Andric if (Out.isUnset()) 2920fca6ea1SDimitry Andric Out = Res; 2930fca6ea1SDimitry Andric else if (!Res.isUnset()) { 2940fca6ea1SDimitry Andric Out = BinaryOperator::Create( 2950fca6ea1SDimitry Andric S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy, 2960fca6ea1SDimitry Andric VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{}); 297bdd1243dSDimitry Andric } 2980fca6ea1SDimitry Andric if (Conjunction != IsRHSSatisfied) 2990fca6ea1SDimitry Andric return Out; 3000fca6ea1SDimitry Andric } 3010fca6ea1SDimitry Andric 3020fca6ea1SDimitry Andric if (FE->isRightFold() && FE->getInit()) { 3030fca6ea1SDimitry Andric ExprResult Res = calculateConstraintSatisfaction(S, FE->getInit(), 3040fca6ea1SDimitry Andric Satisfaction, Evaluator); 3050fca6ea1SDimitry Andric if (Out.isInvalid()) 3060fca6ea1SDimitry Andric return ExprError(); 3070fca6ea1SDimitry Andric 3080fca6ea1SDimitry Andric if (Out.isUnset()) 3090fca6ea1SDimitry Andric Out = Res; 3100fca6ea1SDimitry Andric else if (!Res.isUnset()) { 3110fca6ea1SDimitry Andric Out = BinaryOperator::Create( 3120fca6ea1SDimitry Andric S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy, 3130fca6ea1SDimitry Andric VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{}); 3140fca6ea1SDimitry Andric } 3150fca6ea1SDimitry Andric } 3160fca6ea1SDimitry Andric 3170fca6ea1SDimitry Andric if (Out.isUnset()) { 3180fca6ea1SDimitry Andric Satisfaction.IsSatisfied = Conjunction; 3190fca6ea1SDimitry Andric Out = S.BuildEmptyCXXFoldExpr(FE->getBeginLoc(), FE->getOperator()); 3200fca6ea1SDimitry Andric } 3210fca6ea1SDimitry Andric return Out; 3220fca6ea1SDimitry Andric } 3230fca6ea1SDimitry Andric 3240fca6ea1SDimitry Andric template <typename ConstraintEvaluator> 3250fca6ea1SDimitry Andric static ExprResult 3260fca6ea1SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, 3270fca6ea1SDimitry Andric ConstraintSatisfaction &Satisfaction, 3280fca6ea1SDimitry Andric const ConstraintEvaluator &Evaluator) { 3290fca6ea1SDimitry Andric ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); 3300fca6ea1SDimitry Andric 3310fca6ea1SDimitry Andric if (LogicalBinOp BO = ConstraintExpr) 3320fca6ea1SDimitry Andric return calculateConstraintSatisfaction( 3330fca6ea1SDimitry Andric S, BO.getLHS(), BO.getOp(), BO.getRHS(), Satisfaction, Evaluator); 334bdd1243dSDimitry Andric 335bdd1243dSDimitry Andric if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) { 336bdd1243dSDimitry Andric // These aren't evaluated, so we don't care about cleanups, so we can just 337bdd1243dSDimitry Andric // evaluate these as if the cleanups didn't exist. 3380fca6ea1SDimitry Andric return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction, 3390fca6ea1SDimitry Andric Evaluator); 3400fca6ea1SDimitry Andric } 3410fca6ea1SDimitry Andric 3420fca6ea1SDimitry Andric if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr); 3430fca6ea1SDimitry Andric FE && S.getLangOpts().CPlusPlus26 && 3440fca6ea1SDimitry Andric (FE->getOperator() == BinaryOperatorKind::BO_LAnd || 3450fca6ea1SDimitry Andric FE->getOperator() == BinaryOperatorKind::BO_LOr)) { 3460fca6ea1SDimitry Andric return calculateConstraintSatisfaction(S, FE, Satisfaction, Evaluator); 3475ffd83dbSDimitry Andric } 348480093f4SDimitry Andric 349480093f4SDimitry Andric // An atomic constraint expression 3500fca6ea1SDimitry Andric ExprResult SubstitutedAtomicExpr = 3510fca6ea1SDimitry Andric Evaluator.EvaluateAtomicConstraint(ConstraintExpr); 352480093f4SDimitry Andric 353480093f4SDimitry Andric if (SubstitutedAtomicExpr.isInvalid()) 354bdd1243dSDimitry Andric return ExprError(); 355480093f4SDimitry Andric 356480093f4SDimitry Andric if (!SubstitutedAtomicExpr.isUsable()) 357480093f4SDimitry Andric // Evaluator has decided satisfaction without yielding an expression. 358bdd1243dSDimitry Andric return ExprEmpty(); 359bdd1243dSDimitry Andric 360bdd1243dSDimitry Andric // We don't have the ability to evaluate this, since it contains a 361bdd1243dSDimitry Andric // RecoveryExpr, so we want to fail overload resolution. Otherwise, 362bdd1243dSDimitry Andric // we'd potentially pick up a different overload, and cause confusing 363bdd1243dSDimitry Andric // diagnostics. SO, add a failure detail that will cause us to make this 364bdd1243dSDimitry Andric // overload set not viable. 365bdd1243dSDimitry Andric if (SubstitutedAtomicExpr.get()->containsErrors()) { 366bdd1243dSDimitry Andric Satisfaction.IsSatisfied = false; 367bdd1243dSDimitry Andric Satisfaction.ContainsErrors = true; 368bdd1243dSDimitry Andric 369bdd1243dSDimitry Andric PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error); 370bdd1243dSDimitry Andric SmallString<128> DiagString; 371bdd1243dSDimitry Andric DiagString = ": "; 372bdd1243dSDimitry Andric Msg.EmitToString(S.getDiagnostics(), DiagString); 373bdd1243dSDimitry Andric unsigned MessageSize = DiagString.size(); 374bdd1243dSDimitry Andric char *Mem = new (S.Context) char[MessageSize]; 375bdd1243dSDimitry Andric memcpy(Mem, DiagString.c_str(), MessageSize); 376bdd1243dSDimitry Andric Satisfaction.Details.emplace_back( 377bdd1243dSDimitry Andric new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 378bdd1243dSDimitry Andric SubstitutedAtomicExpr.get()->getBeginLoc(), 379bdd1243dSDimitry Andric StringRef(Mem, MessageSize)}); 380bdd1243dSDimitry Andric return SubstitutedAtomicExpr; 381bdd1243dSDimitry Andric } 382a7dea167SDimitry Andric 383a7dea167SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 384480093f4SDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 385a7dea167SDimitry Andric SmallVector<PartialDiagnosticAt, 2> EvaluationDiags; 386a7dea167SDimitry Andric Expr::EvalResult EvalResult; 387a7dea167SDimitry Andric EvalResult.Diag = &EvaluationDiags; 388fe6060f1SDimitry Andric if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult, 389fe6060f1SDimitry Andric S.Context) || 390fe6060f1SDimitry Andric !EvaluationDiags.empty()) { 391a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 392a7dea167SDimitry Andric // ...E shall be a constant expression of type bool. 393480093f4SDimitry Andric S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(), 394a7dea167SDimitry Andric diag::err_non_constant_constraint_expression) 395480093f4SDimitry Andric << SubstitutedAtomicExpr.get()->getSourceRange(); 396a7dea167SDimitry Andric for (const PartialDiagnosticAt &PDiag : EvaluationDiags) 397480093f4SDimitry Andric S.Diag(PDiag.first, PDiag.second); 398bdd1243dSDimitry Andric return ExprError(); 399a7dea167SDimitry Andric } 400a7dea167SDimitry Andric 401fe6060f1SDimitry Andric assert(EvalResult.Val.isInt() && 402fe6060f1SDimitry Andric "evaluating bool expression didn't produce int"); 403480093f4SDimitry Andric Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); 404480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) 4050fca6ea1SDimitry Andric Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get()); 406a7dea167SDimitry Andric 407bdd1243dSDimitry Andric return SubstitutedAtomicExpr; 408bdd1243dSDimitry Andric } 409bdd1243dSDimitry Andric 410bdd1243dSDimitry Andric static bool 4111ac55f4cSDimitry Andric DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, 4121ac55f4cSDimitry Andric const NamedDecl *Templ, const Expr *E, 413bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL) { 414bdd1243dSDimitry Andric E->Profile(ID, S.Context, /*Canonical=*/true); 415bdd1243dSDimitry Andric for (const auto &List : MLTAL) 416bdd1243dSDimitry Andric for (const auto &TemplateArg : List.Args) 417bdd1243dSDimitry Andric TemplateArg.Profile(ID, S.Context); 418bdd1243dSDimitry Andric 419bdd1243dSDimitry Andric // Note that we have to do this with our own collection, because there are 420bdd1243dSDimitry Andric // times where a constraint-expression check can cause us to need to evaluate 421bdd1243dSDimitry Andric // other constriants that are unrelated, such as when evaluating a recovery 422bdd1243dSDimitry Andric // expression, or when trying to determine the constexpr-ness of special 423bdd1243dSDimitry Andric // members. Otherwise we could just use the 424bdd1243dSDimitry Andric // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function. 4251ac55f4cSDimitry Andric if (S.SatisfactionStackContains(Templ, ID)) { 426bdd1243dSDimitry Andric S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self) 427bdd1243dSDimitry Andric << const_cast<Expr *>(E) << E->getSourceRange(); 428bdd1243dSDimitry Andric return true; 429bdd1243dSDimitry Andric } 430bdd1243dSDimitry Andric 431a7dea167SDimitry Andric return false; 432a7dea167SDimitry Andric } 433480093f4SDimitry Andric 434bdd1243dSDimitry Andric static ExprResult calculateConstraintSatisfaction( 435bdd1243dSDimitry Andric Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc, 436bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr, 437bdd1243dSDimitry Andric ConstraintSatisfaction &Satisfaction) { 4380fca6ea1SDimitry Andric 4390fca6ea1SDimitry Andric struct ConstraintEvaluator { 4400fca6ea1SDimitry Andric Sema &S; 4410fca6ea1SDimitry Andric const NamedDecl *Template; 4420fca6ea1SDimitry Andric SourceLocation TemplateNameLoc; 4430fca6ea1SDimitry Andric const MultiLevelTemplateArgumentList &MLTAL; 4440fca6ea1SDimitry Andric ConstraintSatisfaction &Satisfaction; 4450fca6ea1SDimitry Andric 4460fca6ea1SDimitry Andric ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const { 447480093f4SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 448bdd1243dSDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated, 449bdd1243dSDimitry Andric Sema::ReuseLambdaContextDecl); 450480093f4SDimitry Andric 451480093f4SDimitry Andric // Atomic constraint - substitute arguments and check satisfaction. 452480093f4SDimitry Andric ExprResult SubstitutedExpression; 453480093f4SDimitry Andric { 454480093f4SDimitry Andric TemplateDeductionInfo Info(TemplateNameLoc); 4550fca6ea1SDimitry Andric Sema::InstantiatingTemplate Inst( 4560fca6ea1SDimitry Andric S, AtomicExpr->getBeginLoc(), 45713138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintSubstitution{}, 45813138422SDimitry Andric const_cast<NamedDecl *>(Template), Info, 45913138422SDimitry Andric AtomicExpr->getSourceRange()); 460480093f4SDimitry Andric if (Inst.isInvalid()) 461480093f4SDimitry Andric return ExprError(); 462bdd1243dSDimitry Andric 463bdd1243dSDimitry Andric llvm::FoldingSetNodeID ID; 4641ac55f4cSDimitry Andric if (Template && 4651ac55f4cSDimitry Andric DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) { 466bdd1243dSDimitry Andric Satisfaction.IsSatisfied = false; 467bdd1243dSDimitry Andric Satisfaction.ContainsErrors = true; 468bdd1243dSDimitry Andric return ExprEmpty(); 469bdd1243dSDimitry Andric } 470bdd1243dSDimitry Andric 4711ac55f4cSDimitry Andric SatisfactionStackRAII StackRAII(S, Template, ID); 472bdd1243dSDimitry Andric 473480093f4SDimitry Andric // We do not want error diagnostics escaping here. 474480093f4SDimitry Andric Sema::SFINAETrap Trap(S); 475fe6060f1SDimitry Andric SubstitutedExpression = 476bdd1243dSDimitry Andric S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL); 477bdd1243dSDimitry Andric 478480093f4SDimitry Andric if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) { 479480093f4SDimitry Andric // C++2a [temp.constr.atomic]p1 480480093f4SDimitry Andric // ...If substitution results in an invalid type or expression, the 481480093f4SDimitry Andric // constraint is not satisfied. 482480093f4SDimitry Andric if (!Trap.hasErrorOccurred()) 483349cc55cSDimitry Andric // A non-SFINAE error has occurred as a result of this 484480093f4SDimitry Andric // substitution. 485480093f4SDimitry Andric return ExprError(); 486480093f4SDimitry Andric 487480093f4SDimitry Andric PartialDiagnosticAt SubstDiag{SourceLocation(), 488480093f4SDimitry Andric PartialDiagnostic::NullDiagnostic()}; 489480093f4SDimitry Andric Info.takeSFINAEDiagnostic(SubstDiag); 490480093f4SDimitry Andric // FIXME: Concepts: This is an unfortunate consequence of there 491480093f4SDimitry Andric // being no serialization code for PartialDiagnostics and the fact 492480093f4SDimitry Andric // that serializing them would likely take a lot more storage than 493480093f4SDimitry Andric // just storing them as strings. We would still like, in the 494480093f4SDimitry Andric // future, to serialize the proper PartialDiagnostic as serializing 495480093f4SDimitry Andric // it as a string defeats the purpose of the diagnostic mechanism. 496480093f4SDimitry Andric SmallString<128> DiagString; 497480093f4SDimitry Andric DiagString = ": "; 498480093f4SDimitry Andric SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString); 499480093f4SDimitry Andric unsigned MessageSize = DiagString.size(); 500480093f4SDimitry Andric char *Mem = new (S.Context) char[MessageSize]; 501480093f4SDimitry Andric memcpy(Mem, DiagString.c_str(), MessageSize); 502480093f4SDimitry Andric Satisfaction.Details.emplace_back( 503480093f4SDimitry Andric new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 504480093f4SDimitry Andric SubstDiag.first, StringRef(Mem, MessageSize)}); 505480093f4SDimitry Andric Satisfaction.IsSatisfied = false; 506480093f4SDimitry Andric return ExprEmpty(); 507480093f4SDimitry Andric } 508480093f4SDimitry Andric } 509480093f4SDimitry Andric 510480093f4SDimitry Andric if (!S.CheckConstraintExpression(SubstitutedExpression.get())) 511480093f4SDimitry Andric return ExprError(); 512480093f4SDimitry Andric 513bdd1243dSDimitry Andric // [temp.constr.atomic]p3: To determine if an atomic constraint is 514bdd1243dSDimitry Andric // satisfied, the parameter mapping and template arguments are first 515bdd1243dSDimitry Andric // substituted into its expression. If substitution results in an 516bdd1243dSDimitry Andric // invalid type or expression, the constraint is not satisfied. 517bdd1243dSDimitry Andric // Otherwise, the lvalue-to-rvalue conversion is performed if necessary, 518bdd1243dSDimitry Andric // and E shall be a constant expression of type bool. 519bdd1243dSDimitry Andric // 520bdd1243dSDimitry Andric // Perform the L to R Value conversion if necessary. We do so for all 521bdd1243dSDimitry Andric // non-PRValue categories, else we fail to extend the lifetime of 522bdd1243dSDimitry Andric // temporaries, and that fails the constant expression check. 523bdd1243dSDimitry Andric if (!SubstitutedExpression.get()->isPRValue()) 524bdd1243dSDimitry Andric SubstitutedExpression = ImplicitCastExpr::Create( 525bdd1243dSDimitry Andric S.Context, SubstitutedExpression.get()->getType(), 526bdd1243dSDimitry Andric CK_LValueToRValue, SubstitutedExpression.get(), 527bdd1243dSDimitry Andric /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride()); 528bdd1243dSDimitry Andric 529480093f4SDimitry Andric return SubstitutedExpression; 5300fca6ea1SDimitry Andric } 5310fca6ea1SDimitry Andric 5320fca6ea1SDimitry Andric std::optional<unsigned> 5330fca6ea1SDimitry Andric EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const { 53462987288SDimitry Andric 53562987288SDimitry Andric // We should ignore errors in the presence of packs of different size. 53662987288SDimitry Andric Sema::SFINAETrap Trap(S); 53762987288SDimitry Andric 5380fca6ea1SDimitry Andric Expr *Pattern = FE->getPattern(); 5390fca6ea1SDimitry Andric 5400fca6ea1SDimitry Andric SmallVector<UnexpandedParameterPack, 2> Unexpanded; 5410fca6ea1SDimitry Andric S.collectUnexpandedParameterPacks(Pattern, Unexpanded); 5420fca6ea1SDimitry Andric assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); 5430fca6ea1SDimitry Andric bool Expand = true; 5440fca6ea1SDimitry Andric bool RetainExpansion = false; 5450fca6ea1SDimitry Andric std::optional<unsigned> OrigNumExpansions = FE->getNumExpansions(), 5460fca6ea1SDimitry Andric NumExpansions = OrigNumExpansions; 5470fca6ea1SDimitry Andric if (S.CheckParameterPacksForExpansion( 5480fca6ea1SDimitry Andric FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, 5490fca6ea1SDimitry Andric MLTAL, Expand, RetainExpansion, NumExpansions) || 5500fca6ea1SDimitry Andric !Expand || RetainExpansion) 5510fca6ea1SDimitry Andric return std::nullopt; 5520fca6ea1SDimitry Andric 5530fca6ea1SDimitry Andric if (NumExpansions && S.getLangOpts().BracketDepth < NumExpansions) { 5540fca6ea1SDimitry Andric S.Diag(FE->getEllipsisLoc(), 5550fca6ea1SDimitry Andric clang::diag::err_fold_expression_limit_exceeded) 5560fca6ea1SDimitry Andric << *NumExpansions << S.getLangOpts().BracketDepth 5570fca6ea1SDimitry Andric << FE->getSourceRange(); 5580fca6ea1SDimitry Andric S.Diag(FE->getEllipsisLoc(), diag::note_bracket_depth); 5590fca6ea1SDimitry Andric return std::nullopt; 5600fca6ea1SDimitry Andric } 5610fca6ea1SDimitry Andric return NumExpansions; 5620fca6ea1SDimitry Andric } 5630fca6ea1SDimitry Andric }; 5640fca6ea1SDimitry Andric 5650fca6ea1SDimitry Andric return calculateConstraintSatisfaction( 5660fca6ea1SDimitry Andric S, ConstraintExpr, Satisfaction, 5670fca6ea1SDimitry Andric ConstraintEvaluator{S, Template, TemplateNameLoc, MLTAL, Satisfaction}); 568480093f4SDimitry Andric } 569480093f4SDimitry Andric 570bdd1243dSDimitry Andric static bool CheckConstraintSatisfaction( 571bdd1243dSDimitry Andric Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 572bdd1243dSDimitry Andric llvm::SmallVectorImpl<Expr *> &Converted, 573bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &TemplateArgsLists, 574bdd1243dSDimitry Andric SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { 575480093f4SDimitry Andric if (ConstraintExprs.empty()) { 576480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 577480093f4SDimitry Andric return false; 578480093f4SDimitry Andric } 579480093f4SDimitry Andric 580bdd1243dSDimitry Andric if (TemplateArgsLists.isAnyArgInstantiationDependent()) { 581480093f4SDimitry Andric // No need to check satisfaction for dependent constraint expressions. 582480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 583480093f4SDimitry Andric return false; 584480093f4SDimitry Andric } 585480093f4SDimitry Andric 586bdd1243dSDimitry Andric ArrayRef<TemplateArgument> TemplateArgs = 587bdd1243dSDimitry Andric TemplateArgsLists.getNumSubstitutedLevels() > 0 588bdd1243dSDimitry Andric ? TemplateArgsLists.getOutermost() 589bdd1243dSDimitry Andric : ArrayRef<TemplateArgument> {}; 590480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), 59113138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, 59213138422SDimitry Andric const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); 593480093f4SDimitry Andric if (Inst.isInvalid()) 594480093f4SDimitry Andric return true; 595480093f4SDimitry Andric 596480093f4SDimitry Andric for (const Expr *ConstraintExpr : ConstraintExprs) { 597bdd1243dSDimitry Andric ExprResult Res = calculateConstraintSatisfaction( 598bdd1243dSDimitry Andric S, Template, TemplateIDRange.getBegin(), TemplateArgsLists, 599bdd1243dSDimitry Andric ConstraintExpr, Satisfaction); 600bdd1243dSDimitry Andric if (Res.isInvalid()) 601480093f4SDimitry Andric return true; 602bdd1243dSDimitry Andric 603bdd1243dSDimitry Andric Converted.push_back(Res.get()); 604bdd1243dSDimitry Andric if (!Satisfaction.IsSatisfied) { 605bdd1243dSDimitry Andric // Backfill the 'converted' list with nulls so we can keep the Converted 606bdd1243dSDimitry Andric // and unconverted lists in sync. 607bdd1243dSDimitry Andric Converted.append(ConstraintExprs.size() - Converted.size(), nullptr); 608480093f4SDimitry Andric // [temp.constr.op] p2 609480093f4SDimitry Andric // [...] To determine if a conjunction is satisfied, the satisfaction 610480093f4SDimitry Andric // of the first operand is checked. If that is not satisfied, the 611480093f4SDimitry Andric // conjunction is not satisfied. [...] 612480093f4SDimitry Andric return false; 613480093f4SDimitry Andric } 614bdd1243dSDimitry Andric } 615480093f4SDimitry Andric return false; 616480093f4SDimitry Andric } 617480093f4SDimitry Andric 61855e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction( 61913138422SDimitry Andric const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 620bdd1243dSDimitry Andric llvm::SmallVectorImpl<Expr *> &ConvertedConstraints, 621bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &TemplateArgsLists, 622bdd1243dSDimitry Andric SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) { 62355e4f9d5SDimitry Andric if (ConstraintExprs.empty()) { 62455e4f9d5SDimitry Andric OutSatisfaction.IsSatisfied = true; 62555e4f9d5SDimitry Andric return false; 626480093f4SDimitry Andric } 62781ad6265SDimitry Andric if (!Template) { 628bdd1243dSDimitry Andric return ::CheckConstraintSatisfaction( 629bdd1243dSDimitry Andric *this, nullptr, ConstraintExprs, ConvertedConstraints, 630bdd1243dSDimitry Andric TemplateArgsLists, TemplateIDRange, OutSatisfaction); 63181ad6265SDimitry Andric } 6320fca6ea1SDimitry Andric // Invalid templates could make their way here. Substituting them could result 6330fca6ea1SDimitry Andric // in dependent expressions. 6340fca6ea1SDimitry Andric if (Template->isInvalidDecl()) { 6350fca6ea1SDimitry Andric OutSatisfaction.IsSatisfied = false; 6360fca6ea1SDimitry Andric return true; 6370fca6ea1SDimitry Andric } 638bdd1243dSDimitry Andric 639bdd1243dSDimitry Andric // A list of the template argument list flattened in a predictible manner for 640bdd1243dSDimitry Andric // the purposes of caching. The ConstraintSatisfaction type is in AST so it 641bdd1243dSDimitry Andric // has no access to the MultiLevelTemplateArgumentList, so this has to happen 642bdd1243dSDimitry Andric // here. 643bdd1243dSDimitry Andric llvm::SmallVector<TemplateArgument, 4> FlattenedArgs; 644bdd1243dSDimitry Andric for (auto List : TemplateArgsLists) 645bdd1243dSDimitry Andric FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(), 646bdd1243dSDimitry Andric List.Args.end()); 647bdd1243dSDimitry Andric 64855e4f9d5SDimitry Andric llvm::FoldingSetNodeID ID; 649bdd1243dSDimitry Andric ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs); 65081ad6265SDimitry Andric void *InsertPos; 65181ad6265SDimitry Andric if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 65281ad6265SDimitry Andric OutSatisfaction = *Cached; 65355e4f9d5SDimitry Andric return false; 65455e4f9d5SDimitry Andric } 655bdd1243dSDimitry Andric 65681ad6265SDimitry Andric auto Satisfaction = 657bdd1243dSDimitry Andric std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs); 65813138422SDimitry Andric if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, 659bdd1243dSDimitry Andric ConvertedConstraints, TemplateArgsLists, 660bdd1243dSDimitry Andric TemplateIDRange, *Satisfaction)) { 661bdd1243dSDimitry Andric OutSatisfaction = *Satisfaction; 66255e4f9d5SDimitry Andric return true; 663480093f4SDimitry Andric } 664bdd1243dSDimitry Andric 665bdd1243dSDimitry Andric if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 666bdd1243dSDimitry Andric // The evaluation of this constraint resulted in us trying to re-evaluate it 667bdd1243dSDimitry Andric // recursively. This isn't really possible, except we try to form a 668bdd1243dSDimitry Andric // RecoveryExpr as a part of the evaluation. If this is the case, just 669bdd1243dSDimitry Andric // return the 'cached' version (which will have the same result), and save 670bdd1243dSDimitry Andric // ourselves the extra-insert. If it ever becomes possible to legitimately 671bdd1243dSDimitry Andric // recursively check a constraint, we should skip checking the 'inner' one 672bdd1243dSDimitry Andric // above, and replace the cached version with this one, as it would be more 673bdd1243dSDimitry Andric // specific. 674bdd1243dSDimitry Andric OutSatisfaction = *Cached; 675bdd1243dSDimitry Andric return false; 676bdd1243dSDimitry Andric } 677bdd1243dSDimitry Andric 678bdd1243dSDimitry Andric // Else we can simply add this satisfaction to the list. 67955e4f9d5SDimitry Andric OutSatisfaction = *Satisfaction; 68081ad6265SDimitry Andric // We cannot use InsertPos here because CheckConstraintSatisfaction might have 68181ad6265SDimitry Andric // invalidated it. 68281ad6265SDimitry Andric // Note that entries of SatisfactionCache are deleted in Sema's destructor. 68381ad6265SDimitry Andric SatisfactionCache.InsertNode(Satisfaction.release()); 68455e4f9d5SDimitry Andric return false; 685480093f4SDimitry Andric } 686480093f4SDimitry Andric 687480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr, 688480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction) { 6890fca6ea1SDimitry Andric 6900fca6ea1SDimitry Andric struct ConstraintEvaluator { 6910fca6ea1SDimitry Andric Sema &S; 6920fca6ea1SDimitry Andric ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const { 6930fca6ea1SDimitry Andric return S.PerformContextuallyConvertToBool(const_cast<Expr *>(AtomicExpr)); 6940fca6ea1SDimitry Andric } 6950fca6ea1SDimitry Andric 6960fca6ea1SDimitry Andric std::optional<unsigned> 6970fca6ea1SDimitry Andric EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const { 6980fca6ea1SDimitry Andric return 0; 6990fca6ea1SDimitry Andric } 7000fca6ea1SDimitry Andric }; 7010fca6ea1SDimitry Andric 7020fca6ea1SDimitry Andric return calculateConstraintSatisfaction(*this, ConstraintExpr, Satisfaction, 7030fca6ea1SDimitry Andric ConstraintEvaluator{*this}) 704bdd1243dSDimitry Andric .isInvalid(); 705bdd1243dSDimitry Andric } 706bdd1243dSDimitry Andric 70706c3fb27SDimitry Andric bool Sema::addInstantiatedCapturesToScope( 70806c3fb27SDimitry Andric FunctionDecl *Function, const FunctionDecl *PatternDecl, 70906c3fb27SDimitry Andric LocalInstantiationScope &Scope, 71006c3fb27SDimitry Andric const MultiLevelTemplateArgumentList &TemplateArgs) { 71106c3fb27SDimitry Andric const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent(); 71206c3fb27SDimitry Andric const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent(); 71306c3fb27SDimitry Andric 71406c3fb27SDimitry Andric unsigned Instantiated = 0; 71506c3fb27SDimitry Andric 71606c3fb27SDimitry Andric auto AddSingleCapture = [&](const ValueDecl *CapturedPattern, 71706c3fb27SDimitry Andric unsigned Index) { 71806c3fb27SDimitry Andric ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar(); 71906c3fb27SDimitry Andric if (CapturedVar->isInitCapture()) 72006c3fb27SDimitry Andric Scope.InstantiatedLocal(CapturedPattern, CapturedVar); 72106c3fb27SDimitry Andric }; 72206c3fb27SDimitry Andric 72306c3fb27SDimitry Andric for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) { 72406c3fb27SDimitry Andric if (!CapturePattern.capturesVariable()) { 72506c3fb27SDimitry Andric Instantiated++; 72606c3fb27SDimitry Andric continue; 72706c3fb27SDimitry Andric } 72806c3fb27SDimitry Andric const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar(); 72906c3fb27SDimitry Andric if (!CapturedPattern->isParameterPack()) { 73006c3fb27SDimitry Andric AddSingleCapture(CapturedPattern, Instantiated++); 73106c3fb27SDimitry Andric } else { 73206c3fb27SDimitry Andric Scope.MakeInstantiatedLocalArgPack(CapturedPattern); 73306c3fb27SDimitry Andric std::optional<unsigned> NumArgumentsInExpansion = 73406c3fb27SDimitry Andric getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs); 73506c3fb27SDimitry Andric if (!NumArgumentsInExpansion) 73606c3fb27SDimitry Andric continue; 73706c3fb27SDimitry Andric for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) 73806c3fb27SDimitry Andric AddSingleCapture(CapturedPattern, Instantiated++); 73906c3fb27SDimitry Andric } 74006c3fb27SDimitry Andric } 74106c3fb27SDimitry Andric return false; 74206c3fb27SDimitry Andric } 74306c3fb27SDimitry Andric 744bdd1243dSDimitry Andric bool Sema::SetupConstraintScope( 745bdd1243dSDimitry Andric FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 7460fca6ea1SDimitry Andric const MultiLevelTemplateArgumentList &MLTAL, 7470fca6ea1SDimitry Andric LocalInstantiationScope &Scope) { 748bdd1243dSDimitry Andric if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { 749bdd1243dSDimitry Andric FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); 750bdd1243dSDimitry Andric InstantiatingTemplate Inst( 751bdd1243dSDimitry Andric *this, FD->getPointOfInstantiation(), 752bdd1243dSDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate, 753bdd1243dSDimitry Andric TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 754bdd1243dSDimitry Andric SourceRange()); 755bdd1243dSDimitry Andric if (Inst.isInvalid()) 756bdd1243dSDimitry Andric return true; 757bdd1243dSDimitry Andric 758bdd1243dSDimitry Andric // addInstantiatedParametersToScope creates a map of 'uninstantiated' to 759bdd1243dSDimitry Andric // 'instantiated' parameters and adds it to the context. For the case where 760bdd1243dSDimitry Andric // this function is a template being instantiated NOW, we also need to add 761bdd1243dSDimitry Andric // the list of current template arguments to the list so that they also can 762bdd1243dSDimitry Andric // be picked out of the map. 763bdd1243dSDimitry Andric if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) { 764bdd1243dSDimitry Andric MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(), 765bdd1243dSDimitry Andric /*Final=*/false); 766bdd1243dSDimitry Andric if (addInstantiatedParametersToScope( 767bdd1243dSDimitry Andric FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs)) 768bdd1243dSDimitry Andric return true; 769bdd1243dSDimitry Andric } 770bdd1243dSDimitry Andric 771bdd1243dSDimitry Andric // If this is a member function, make sure we get the parameters that 772bdd1243dSDimitry Andric // reference the original primary template. 773b3edf446SDimitry Andric // We walk up the instantiated template chain so that nested lambdas get 774b3edf446SDimitry Andric // handled properly. 7750fca6ea1SDimitry Andric // We should only collect instantiated parameters from the primary template. 7760fca6ea1SDimitry Andric // Otherwise, we may have mismatched template parameter depth! 7770fca6ea1SDimitry Andric if (FunctionTemplateDecl *FromMemTempl = 7780fca6ea1SDimitry Andric PrimaryTemplate->getInstantiatedFromMemberTemplate()) { 7790fca6ea1SDimitry Andric while (FromMemTempl->getInstantiatedFromMemberTemplate()) 7800fca6ea1SDimitry Andric FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate(); 781bdd1243dSDimitry Andric if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(), 782bdd1243dSDimitry Andric Scope, MLTAL)) 783bdd1243dSDimitry Andric return true; 784bdd1243dSDimitry Andric } 785bdd1243dSDimitry Andric 786bdd1243dSDimitry Andric return false; 787bdd1243dSDimitry Andric } 788bdd1243dSDimitry Andric 789bdd1243dSDimitry Andric if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || 790bdd1243dSDimitry Andric FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) { 791bdd1243dSDimitry Andric FunctionDecl *InstantiatedFrom = 792bdd1243dSDimitry Andric FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization 793bdd1243dSDimitry Andric ? FD->getInstantiatedFromMemberFunction() 794bdd1243dSDimitry Andric : FD->getInstantiatedFromDecl(); 795bdd1243dSDimitry Andric 796bdd1243dSDimitry Andric InstantiatingTemplate Inst( 797bdd1243dSDimitry Andric *this, FD->getPointOfInstantiation(), 798bdd1243dSDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom, 799bdd1243dSDimitry Andric TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 800bdd1243dSDimitry Andric SourceRange()); 801bdd1243dSDimitry Andric if (Inst.isInvalid()) 802bdd1243dSDimitry Andric return true; 803bdd1243dSDimitry Andric 804bdd1243dSDimitry Andric // Case where this was not a template, but instantiated as a 805bdd1243dSDimitry Andric // child-function. 806bdd1243dSDimitry Andric if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL)) 807bdd1243dSDimitry Andric return true; 808bdd1243dSDimitry Andric } 809bdd1243dSDimitry Andric 810bdd1243dSDimitry Andric return false; 811bdd1243dSDimitry Andric } 812bdd1243dSDimitry Andric 813bdd1243dSDimitry Andric // This function collects all of the template arguments for the purposes of 814bdd1243dSDimitry Andric // constraint-instantiation and checking. 815bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> 816bdd1243dSDimitry Andric Sema::SetupConstraintCheckingTemplateArgumentsAndScope( 817bdd1243dSDimitry Andric FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 818bdd1243dSDimitry Andric LocalInstantiationScope &Scope) { 819bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL; 820bdd1243dSDimitry Andric 821bdd1243dSDimitry Andric // Collect the list of template arguments relative to the 'primary' template. 822bdd1243dSDimitry Andric // We need the entire list, since the constraint is completely uninstantiated 823bdd1243dSDimitry Andric // at this point. 8240fca6ea1SDimitry Andric MLTAL = 8250fca6ea1SDimitry Andric getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), 8260fca6ea1SDimitry Andric /*Final=*/false, /*Innermost=*/std::nullopt, 827bdd1243dSDimitry Andric /*RelativeToPrimary=*/true, 828bdd1243dSDimitry Andric /*Pattern=*/nullptr, 829bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true); 830bdd1243dSDimitry Andric if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) 831bdd1243dSDimitry Andric return std::nullopt; 832bdd1243dSDimitry Andric 833bdd1243dSDimitry Andric return MLTAL; 834480093f4SDimitry Andric } 835480093f4SDimitry Andric 83613138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, 83713138422SDimitry Andric ConstraintSatisfaction &Satisfaction, 838bdd1243dSDimitry Andric SourceLocation UsageLoc, 839bdd1243dSDimitry Andric bool ForOverloadResolution) { 840bdd1243dSDimitry Andric // Don't check constraints if the function is dependent. Also don't check if 841bdd1243dSDimitry Andric // this is a function template specialization, as the call to 842bdd1243dSDimitry Andric // CheckinstantiatedFunctionTemplateConstraints after this will check it 843bdd1243dSDimitry Andric // better. 844bdd1243dSDimitry Andric if (FD->isDependentContext() || 845bdd1243dSDimitry Andric FD->getTemplatedKind() == 846bdd1243dSDimitry Andric FunctionDecl::TK_FunctionTemplateSpecialization) { 84713138422SDimitry Andric Satisfaction.IsSatisfied = true; 84813138422SDimitry Andric return false; 84913138422SDimitry Andric } 850bdd1243dSDimitry Andric 85106c3fb27SDimitry Andric // A lambda conversion operator has the same constraints as the call operator 85206c3fb27SDimitry Andric // and constraints checking relies on whether we are in a lambda call operator 85306c3fb27SDimitry Andric // (and may refer to its parameters), so check the call operator instead. 8540fca6ea1SDimitry Andric // Note that the declarations outside of the lambda should also be 8550fca6ea1SDimitry Andric // considered. Turning on the 'ForOverloadResolution' flag results in the 8560fca6ea1SDimitry Andric // LocalInstantiationScope not looking into its parents, but we can still 8570fca6ea1SDimitry Andric // access Decls from the parents while building a lambda RAII scope later. 85806c3fb27SDimitry Andric if (const auto *MD = dyn_cast<CXXConversionDecl>(FD); 85906c3fb27SDimitry Andric MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD))) 86006c3fb27SDimitry Andric return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(), 86106c3fb27SDimitry Andric Satisfaction, UsageLoc, 8620fca6ea1SDimitry Andric /*ShouldAddDeclsFromParentScope=*/true); 86306c3fb27SDimitry Andric 864bdd1243dSDimitry Andric DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD); 865bdd1243dSDimitry Andric 866bdd1243dSDimitry Andric while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) { 867bdd1243dSDimitry Andric if (isLambdaCallOperator(CtxToSave)) 868bdd1243dSDimitry Andric CtxToSave = CtxToSave->getParent()->getParent(); 869bdd1243dSDimitry Andric else 870bdd1243dSDimitry Andric CtxToSave = CtxToSave->getNonTransparentContext(); 871bdd1243dSDimitry Andric } 872bdd1243dSDimitry Andric 873bdd1243dSDimitry Andric ContextRAII SavedContext{*this, CtxToSave}; 8745f757f3fSDimitry Andric LocalInstantiationScope Scope(*this, !ForOverloadResolution); 875bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> MLTAL = 876bdd1243dSDimitry Andric SetupConstraintCheckingTemplateArgumentsAndScope( 877bdd1243dSDimitry Andric const_cast<FunctionDecl *>(FD), {}, Scope); 878bdd1243dSDimitry Andric 879bdd1243dSDimitry Andric if (!MLTAL) 880bdd1243dSDimitry Andric return true; 881bdd1243dSDimitry Andric 88213138422SDimitry Andric Qualifiers ThisQuals; 88313138422SDimitry Andric CXXRecordDecl *Record = nullptr; 88413138422SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { 88513138422SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 88613138422SDimitry Andric Record = const_cast<CXXRecordDecl *>(Method->getParent()); 88713138422SDimitry Andric } 88813138422SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 889feb5b0c7SDimitry Andric 890feb5b0c7SDimitry Andric LambdaScopeForCallOperatorInstantiationRAII LambdaScope( 8915f757f3fSDimitry Andric *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope, 8925f757f3fSDimitry Andric ForOverloadResolution); 893feb5b0c7SDimitry Andric 89406c3fb27SDimitry Andric return CheckConstraintSatisfaction( 89506c3fb27SDimitry Andric FD, {FD->getTrailingRequiresClause()}, *MLTAL, 89613138422SDimitry Andric SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), 89706c3fb27SDimitry Andric Satisfaction); 898bdd1243dSDimitry Andric } 899bdd1243dSDimitry Andric 900bdd1243dSDimitry Andric 901bdd1243dSDimitry Andric // Figure out the to-translation-unit depth for this function declaration for 902bdd1243dSDimitry Andric // the purpose of seeing if they differ by constraints. This isn't the same as 903bdd1243dSDimitry Andric // getTemplateDepth, because it includes already instantiated parents. 904bdd1243dSDimitry Andric static unsigned 905bdd1243dSDimitry Andric CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, 906bdd1243dSDimitry Andric bool SkipForSpecialization = false) { 907bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 9080fca6ea1SDimitry Andric ND, ND->getLexicalDeclContext(), /*Final=*/false, 9090fca6ea1SDimitry Andric /*Innermost=*/std::nullopt, 9105f757f3fSDimitry Andric /*RelativeToPrimary=*/true, 911bdd1243dSDimitry Andric /*Pattern=*/nullptr, 912bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true, SkipForSpecialization); 91306c3fb27SDimitry Andric return MLTAL.getNumLevels(); 914bdd1243dSDimitry Andric } 915bdd1243dSDimitry Andric 916bdd1243dSDimitry Andric namespace { 917bdd1243dSDimitry Andric class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> { 918bdd1243dSDimitry Andric unsigned TemplateDepth = 0; 919bdd1243dSDimitry Andric public: 920bdd1243dSDimitry Andric using inherited = TreeTransform<AdjustConstraintDepth>; 921bdd1243dSDimitry Andric AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth) 922bdd1243dSDimitry Andric : inherited(SemaRef), TemplateDepth(TemplateDepth) {} 923bdd1243dSDimitry Andric 924bdd1243dSDimitry Andric using inherited::TransformTemplateTypeParmType; 925bdd1243dSDimitry Andric QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, 926bdd1243dSDimitry Andric TemplateTypeParmTypeLoc TL, bool) { 927bdd1243dSDimitry Andric const TemplateTypeParmType *T = TL.getTypePtr(); 928bdd1243dSDimitry Andric 929bdd1243dSDimitry Andric TemplateTypeParmDecl *NewTTPDecl = nullptr; 930bdd1243dSDimitry Andric if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) 931bdd1243dSDimitry Andric NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( 932bdd1243dSDimitry Andric TransformDecl(TL.getNameLoc(), OldTTPDecl)); 933bdd1243dSDimitry Andric 934bdd1243dSDimitry Andric QualType Result = getSema().Context.getTemplateTypeParmType( 935bdd1243dSDimitry Andric T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(), 936bdd1243dSDimitry Andric NewTTPDecl); 937bdd1243dSDimitry Andric TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); 938bdd1243dSDimitry Andric NewTL.setNameLoc(TL.getNameLoc()); 939bdd1243dSDimitry Andric return Result; 940bdd1243dSDimitry Andric } 941bdd1243dSDimitry Andric }; 942bdd1243dSDimitry Andric } // namespace 943bdd1243dSDimitry Andric 9441db9f3b2SDimitry Andric static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( 9451db9f3b2SDimitry Andric Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, 94606c3fb27SDimitry Andric const Expr *ConstrExpr) { 94706c3fb27SDimitry Andric MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 9485f757f3fSDimitry Andric DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, 9490fca6ea1SDimitry Andric /*Innermost=*/std::nullopt, 95006c3fb27SDimitry Andric /*RelativeToPrimary=*/true, 95106c3fb27SDimitry Andric /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, 95206c3fb27SDimitry Andric /*SkipForSpecialization*/ false); 9535f757f3fSDimitry Andric 95406c3fb27SDimitry Andric if (MLTAL.getNumSubstitutedLevels() == 0) 95506c3fb27SDimitry Andric return ConstrExpr; 95606c3fb27SDimitry Andric 95706c3fb27SDimitry Andric Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false); 95806c3fb27SDimitry Andric 95906c3fb27SDimitry Andric Sema::InstantiatingTemplate Inst( 9605f757f3fSDimitry Andric S, DeclInfo.getLocation(), 96106c3fb27SDimitry Andric Sema::InstantiatingTemplate::ConstraintNormalization{}, 9625f757f3fSDimitry Andric const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{}); 96306c3fb27SDimitry Andric if (Inst.isInvalid()) 96406c3fb27SDimitry Andric return nullptr; 96506c3fb27SDimitry Andric 9660fca6ea1SDimitry Andric // Set up a dummy 'instantiation' scope in the case of reference to function 9670fca6ea1SDimitry Andric // parameters that the surrounding function hasn't been instantiated yet. Note 9680fca6ea1SDimitry Andric // this may happen while we're comparing two templates' constraint 9690fca6ea1SDimitry Andric // equivalence. 970*415efcecSDimitry Andric LocalInstantiationScope ScopeForParameters(S, /*CombineWithOuterScope=*/true); 9710fca6ea1SDimitry Andric if (auto *FD = DeclInfo.getDecl()->getAsFunction()) 9726e516c87SDimitry Andric for (auto *PVD : FD->parameters()) { 9736e516c87SDimitry Andric if (!PVD->isParameterPack()) { 9740fca6ea1SDimitry Andric ScopeForParameters.InstantiatedLocal(PVD, PVD); 9756e516c87SDimitry Andric continue; 9766e516c87SDimitry Andric } 9776e516c87SDimitry Andric // This is hacky: we're mapping the parameter pack to a size-of-1 argument 9786e516c87SDimitry Andric // to avoid building SubstTemplateTypeParmPackTypes for 9796e516c87SDimitry Andric // PackExpansionTypes. The SubstTemplateTypeParmPackType node would 9806e516c87SDimitry Andric // otherwise reference the AssociatedDecl of the template arguments, which 9816e516c87SDimitry Andric // is, in this case, the template declaration. 9826e516c87SDimitry Andric // 9836e516c87SDimitry Andric // However, as we are in the process of comparing potential 9846e516c87SDimitry Andric // re-declarations, the canonical declaration is the declaration itself at 9856e516c87SDimitry Andric // this point. So if we didn't expand these packs, we would end up with an 9866e516c87SDimitry Andric // incorrect profile difference because we will be profiling the 9876e516c87SDimitry Andric // canonical types! 9886e516c87SDimitry Andric // 9896e516c87SDimitry Andric // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so 9906e516c87SDimitry Andric // that we can eliminate the Scope in the cases where the declarations are 9916e516c87SDimitry Andric // not necessarily instantiated. It would also benefit the noexcept 9926e516c87SDimitry Andric // specifier comparison. 9936e516c87SDimitry Andric ScopeForParameters.MakeInstantiatedLocalArgPack(PVD); 9946e516c87SDimitry Andric ScopeForParameters.InstantiatedLocalPackArg(PVD, PVD); 9956e516c87SDimitry Andric } 9960fca6ea1SDimitry Andric 99706c3fb27SDimitry Andric std::optional<Sema::CXXThisScopeRAII> ThisScope; 9980fca6ea1SDimitry Andric 9990fca6ea1SDimitry Andric // See TreeTransform::RebuildTemplateSpecializationType. A context scope is 10000fca6ea1SDimitry Andric // essential for having an injected class as the canonical type for a template 10010fca6ea1SDimitry Andric // specialization type at the rebuilding stage. This guarantees that, for 10020fca6ea1SDimitry Andric // out-of-line definitions, injected class name types and their equivalent 10030fca6ea1SDimitry Andric // template specializations can be profiled to the same value, which makes it 10040fca6ea1SDimitry Andric // possible that e.g. constraints involving C<Class<T>> and C<Class> are 10050fca6ea1SDimitry Andric // perceived identical. 10060fca6ea1SDimitry Andric std::optional<Sema::ContextRAII> ContextScope; 10070fca6ea1SDimitry Andric if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext())) { 100806c3fb27SDimitry Andric ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers()); 10090fca6ea1SDimitry Andric ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)), 10100fca6ea1SDimitry Andric /*NewThisContext=*/false); 10110fca6ea1SDimitry Andric } 10121db9f3b2SDimitry Andric ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction( 10131db9f3b2SDimitry Andric const_cast<clang::Expr *>(ConstrExpr), MLTAL); 101406c3fb27SDimitry Andric if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable()) 101506c3fb27SDimitry Andric return nullptr; 101606c3fb27SDimitry Andric return SubstConstr.get(); 101706c3fb27SDimitry Andric } 101806c3fb27SDimitry Andric 1019bdd1243dSDimitry Andric bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, 1020bdd1243dSDimitry Andric const Expr *OldConstr, 10215f757f3fSDimitry Andric const TemplateCompareNewDeclInfo &New, 1022bdd1243dSDimitry Andric const Expr *NewConstr) { 102306c3fb27SDimitry Andric if (OldConstr == NewConstr) 102406c3fb27SDimitry Andric return true; 102506c3fb27SDimitry Andric // C++ [temp.constr.decl]p4 10265f757f3fSDimitry Andric if (Old && !New.isInvalid() && !New.ContainsDecl(Old) && 10275f757f3fSDimitry Andric Old->getLexicalDeclContext() != New.getLexicalDeclContext()) { 102806c3fb27SDimitry Andric if (const Expr *SubstConstr = 10291db9f3b2SDimitry Andric SubstituteConstraintExpressionWithoutSatisfaction(*this, Old, 10301db9f3b2SDimitry Andric OldConstr)) 103106c3fb27SDimitry Andric OldConstr = SubstConstr; 103206c3fb27SDimitry Andric else 103306c3fb27SDimitry Andric return false; 103406c3fb27SDimitry Andric if (const Expr *SubstConstr = 10351db9f3b2SDimitry Andric SubstituteConstraintExpressionWithoutSatisfaction(*this, New, 10361db9f3b2SDimitry Andric NewConstr)) 103706c3fb27SDimitry Andric NewConstr = SubstConstr; 103806c3fb27SDimitry Andric else 103906c3fb27SDimitry Andric return false; 1040bdd1243dSDimitry Andric } 1041bdd1243dSDimitry Andric 1042bdd1243dSDimitry Andric llvm::FoldingSetNodeID ID1, ID2; 1043bdd1243dSDimitry Andric OldConstr->Profile(ID1, Context, /*Canonical=*/true); 1044bdd1243dSDimitry Andric NewConstr->Profile(ID2, Context, /*Canonical=*/true); 1045bdd1243dSDimitry Andric return ID1 == ID2; 1046bdd1243dSDimitry Andric } 1047bdd1243dSDimitry Andric 1048bdd1243dSDimitry Andric bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { 1049bdd1243dSDimitry Andric assert(FD->getFriendObjectKind() && "Must be a friend!"); 1050bdd1243dSDimitry Andric 1051bdd1243dSDimitry Andric // The logic for non-templates is handled in ASTContext::isSameEntity, so we 1052bdd1243dSDimitry Andric // don't have to bother checking 'DependsOnEnclosingTemplate' for a 1053bdd1243dSDimitry Andric // non-function-template. 1054bdd1243dSDimitry Andric assert(FD->getDescribedFunctionTemplate() && 1055bdd1243dSDimitry Andric "Non-function templates don't need to be checked"); 1056bdd1243dSDimitry Andric 1057bdd1243dSDimitry Andric SmallVector<const Expr *, 3> ACs; 1058bdd1243dSDimitry Andric FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); 1059bdd1243dSDimitry Andric 1060bdd1243dSDimitry Andric unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD); 1061bdd1243dSDimitry Andric for (const Expr *Constraint : ACs) 1062bdd1243dSDimitry Andric if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth, 1063bdd1243dSDimitry Andric Constraint)) 1064bdd1243dSDimitry Andric return true; 1065bdd1243dSDimitry Andric 1066bdd1243dSDimitry Andric return false; 106713138422SDimitry Andric } 106813138422SDimitry Andric 1069480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints( 1070bdd1243dSDimitry Andric TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists, 1071480093f4SDimitry Andric SourceRange TemplateIDRange) { 1072480093f4SDimitry Andric ConstraintSatisfaction Satisfaction; 1073480093f4SDimitry Andric llvm::SmallVector<const Expr *, 3> AssociatedConstraints; 1074480093f4SDimitry Andric TD->getAssociatedConstraints(AssociatedConstraints); 1075bdd1243dSDimitry Andric if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists, 1076480093f4SDimitry Andric TemplateIDRange, Satisfaction)) 1077480093f4SDimitry Andric return true; 1078480093f4SDimitry Andric 1079480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) { 1080480093f4SDimitry Andric SmallString<128> TemplateArgString; 1081480093f4SDimitry Andric TemplateArgString = " "; 1082480093f4SDimitry Andric TemplateArgString += getTemplateArgumentBindingsText( 1083bdd1243dSDimitry Andric TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(), 1084bdd1243dSDimitry Andric TemplateArgsLists.getInnermost().size()); 1085480093f4SDimitry Andric 1086480093f4SDimitry Andric Diag(TemplateIDRange.getBegin(), 1087480093f4SDimitry Andric diag::err_template_arg_list_constraints_not_satisfied) 1088480093f4SDimitry Andric << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD 1089480093f4SDimitry Andric << TemplateArgString << TemplateIDRange; 1090480093f4SDimitry Andric DiagnoseUnsatisfiedConstraint(Satisfaction); 1091480093f4SDimitry Andric return true; 1092480093f4SDimitry Andric } 1093480093f4SDimitry Andric return false; 1094480093f4SDimitry Andric } 1095480093f4SDimitry Andric 109681ad6265SDimitry Andric bool Sema::CheckInstantiatedFunctionTemplateConstraints( 109781ad6265SDimitry Andric SourceLocation PointOfInstantiation, FunctionDecl *Decl, 109881ad6265SDimitry Andric ArrayRef<TemplateArgument> TemplateArgs, 109981ad6265SDimitry Andric ConstraintSatisfaction &Satisfaction) { 110081ad6265SDimitry Andric // In most cases we're not going to have constraints, so check for that first. 110181ad6265SDimitry Andric FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); 110281ad6265SDimitry Andric // Note - code synthesis context for the constraints check is created 110381ad6265SDimitry Andric // inside CheckConstraintsSatisfaction. 110481ad6265SDimitry Andric SmallVector<const Expr *, 3> TemplateAC; 110581ad6265SDimitry Andric Template->getAssociatedConstraints(TemplateAC); 110681ad6265SDimitry Andric if (TemplateAC.empty()) { 110781ad6265SDimitry Andric Satisfaction.IsSatisfied = true; 110881ad6265SDimitry Andric return false; 110981ad6265SDimitry Andric } 111081ad6265SDimitry Andric 111181ad6265SDimitry Andric // Enter the scope of this instantiation. We don't use 111281ad6265SDimitry Andric // PushDeclContext because we don't have a scope. 111381ad6265SDimitry Andric Sema::ContextRAII savedContext(*this, Decl); 111481ad6265SDimitry Andric LocalInstantiationScope Scope(*this); 111581ad6265SDimitry Andric 1116bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> MLTAL = 1117bdd1243dSDimitry Andric SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs, 1118bdd1243dSDimitry Andric Scope); 1119bdd1243dSDimitry Andric 1120bdd1243dSDimitry Andric if (!MLTAL) 112181ad6265SDimitry Andric return true; 1122bdd1243dSDimitry Andric 112381ad6265SDimitry Andric Qualifiers ThisQuals; 112481ad6265SDimitry Andric CXXRecordDecl *Record = nullptr; 112581ad6265SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { 112681ad6265SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 112781ad6265SDimitry Andric Record = Method->getParent(); 112881ad6265SDimitry Andric } 1129feb5b0c7SDimitry Andric 113081ad6265SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 1131feb5b0c7SDimitry Andric LambdaScopeForCallOperatorInstantiationRAII LambdaScope( 1132feb5b0c7SDimitry Andric *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope); 1133bdd1243dSDimitry Andric 1134bdd1243dSDimitry Andric llvm::SmallVector<Expr *, 1> Converted; 1135bdd1243dSDimitry Andric return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL, 113681ad6265SDimitry Andric PointOfInstantiation, Satisfaction); 113781ad6265SDimitry Andric } 113881ad6265SDimitry Andric 113955e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 114055e4f9d5SDimitry Andric concepts::ExprRequirement *Req, 114155e4f9d5SDimitry Andric bool First) { 114255e4f9d5SDimitry Andric assert(!Req->isSatisfied() 114355e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 114455e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 114555e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Dependent: 114655e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 114755e4f9d5SDimitry Andric break; 114855e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ExprSubstitutionFailure: { 114955e4f9d5SDimitry Andric auto *SubstDiag = Req->getExprSubstitutionDiagnostic(); 115055e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 115155e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 115255e4f9d5SDimitry Andric diag::note_expr_requirement_expr_substitution_error) 115355e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 115455e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 115555e4f9d5SDimitry Andric else 115655e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 115755e4f9d5SDimitry Andric diag::note_expr_requirement_expr_unknown_substitution_error) 115855e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 115955e4f9d5SDimitry Andric break; 116055e4f9d5SDimitry Andric } 116155e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_NoexceptNotMet: 116255e4f9d5SDimitry Andric S.Diag(Req->getNoexceptLoc(), 116355e4f9d5SDimitry Andric diag::note_expr_requirement_noexcept_not_met) 116455e4f9d5SDimitry Andric << (int)First << Req->getExpr(); 116555e4f9d5SDimitry Andric break; 116655e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: { 116755e4f9d5SDimitry Andric auto *SubstDiag = 116855e4f9d5SDimitry Andric Req->getReturnTypeRequirement().getSubstitutionDiagnostic(); 116955e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 117055e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 117155e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_substitution_error) 117255e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 117355e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 117455e4f9d5SDimitry Andric else 117555e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 117655e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_unknown_substitution_error) 117755e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 117855e4f9d5SDimitry Andric break; 117955e4f9d5SDimitry Andric } 118055e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { 118155e4f9d5SDimitry Andric ConceptSpecializationExpr *ConstraintExpr = 118255e4f9d5SDimitry Andric Req->getReturnTypeRequirementSubstitutedConstraintExpr(); 1183fe6060f1SDimitry Andric if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 118455e4f9d5SDimitry Andric // A simple case - expr type is the type being constrained and the concept 118555e4f9d5SDimitry Andric // was not provided arguments. 1186fe6060f1SDimitry Andric Expr *e = Req->getExpr(); 1187fe6060f1SDimitry Andric S.Diag(e->getBeginLoc(), 118855e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied_simple) 1189349cc55cSDimitry Andric << (int)First << S.Context.getReferenceQualifiedType(e) 119055e4f9d5SDimitry Andric << ConstraintExpr->getNamedConcept(); 1191fe6060f1SDimitry Andric } else { 119255e4f9d5SDimitry Andric S.Diag(ConstraintExpr->getBeginLoc(), 119355e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied) 119455e4f9d5SDimitry Andric << (int)First << ConstraintExpr; 1195fe6060f1SDimitry Andric } 119655e4f9d5SDimitry Andric S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); 119755e4f9d5SDimitry Andric break; 119855e4f9d5SDimitry Andric } 119955e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Satisfied: 120055e4f9d5SDimitry Andric llvm_unreachable("We checked this above"); 120155e4f9d5SDimitry Andric } 120255e4f9d5SDimitry Andric } 120355e4f9d5SDimitry Andric 120455e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 120555e4f9d5SDimitry Andric concepts::TypeRequirement *Req, 120655e4f9d5SDimitry Andric bool First) { 120755e4f9d5SDimitry Andric assert(!Req->isSatisfied() 120855e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 120955e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 121055e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_Dependent: 121155e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 121255e4f9d5SDimitry Andric return; 121355e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_SubstitutionFailure: { 121455e4f9d5SDimitry Andric auto *SubstDiag = Req->getSubstitutionDiagnostic(); 121555e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 121655e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 121755e4f9d5SDimitry Andric diag::note_type_requirement_substitution_error) << (int)First 121855e4f9d5SDimitry Andric << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage; 121955e4f9d5SDimitry Andric else 122055e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 122155e4f9d5SDimitry Andric diag::note_type_requirement_unknown_substitution_error) 122255e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 122355e4f9d5SDimitry Andric return; 122455e4f9d5SDimitry Andric } 122555e4f9d5SDimitry Andric default: 122655e4f9d5SDimitry Andric llvm_unreachable("Unknown satisfaction status"); 122755e4f9d5SDimitry Andric return; 122855e4f9d5SDimitry Andric } 122955e4f9d5SDimitry Andric } 1230bdd1243dSDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 1231bdd1243dSDimitry Andric Expr *SubstExpr, 1232bdd1243dSDimitry Andric bool First = true); 123355e4f9d5SDimitry Andric 123455e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 123555e4f9d5SDimitry Andric concepts::NestedRequirement *Req, 123655e4f9d5SDimitry Andric bool First) { 1237bdd1243dSDimitry Andric using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; 12380fca6ea1SDimitry Andric for (auto &Record : Req->getConstraintSatisfaction()) { 12390fca6ea1SDimitry Andric if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>()) 1240bdd1243dSDimitry Andric S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error) 12410fca6ea1SDimitry Andric << (int)First << Req->getInvalidConstraintEntity() 12420fca6ea1SDimitry Andric << SubstDiag->second; 124355e4f9d5SDimitry Andric else 12440fca6ea1SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, Record.dyn_cast<Expr *>(), 12450fca6ea1SDimitry Andric First); 1246bdd1243dSDimitry Andric First = false; 124755e4f9d5SDimitry Andric } 124855e4f9d5SDimitry Andric } 124955e4f9d5SDimitry Andric 1250480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 1251480093f4SDimitry Andric Expr *SubstExpr, 1252bdd1243dSDimitry Andric bool First) { 1253480093f4SDimitry Andric SubstExpr = SubstExpr->IgnoreParenImpCasts(); 1254480093f4SDimitry Andric if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) { 1255480093f4SDimitry Andric switch (BO->getOpcode()) { 1256480093f4SDimitry Andric // These two cases will in practice only be reached when using fold 1257480093f4SDimitry Andric // expressions with || and &&, since otherwise the || and && will have been 1258480093f4SDimitry Andric // broken down into atomic constraints during satisfaction checking. 1259480093f4SDimitry Andric case BO_LOr: 1260480093f4SDimitry Andric // Or evaluated to false - meaning both RHS and LHS evaluated to false. 1261480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 1262480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 1263480093f4SDimitry Andric /*First=*/false); 1264480093f4SDimitry Andric return; 1265fe6060f1SDimitry Andric case BO_LAnd: { 1266fe6060f1SDimitry Andric bool LHSSatisfied = 1267fe6060f1SDimitry Andric BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 1268480093f4SDimitry Andric if (LHSSatisfied) { 1269480093f4SDimitry Andric // LHS is true, so RHS must be false. 1270480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First); 1271480093f4SDimitry Andric return; 1272480093f4SDimitry Andric } 1273480093f4SDimitry Andric // LHS is false 1274480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 1275480093f4SDimitry Andric 1276480093f4SDimitry Andric // RHS might also be false 1277fe6060f1SDimitry Andric bool RHSSatisfied = 1278fe6060f1SDimitry Andric BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 1279480093f4SDimitry Andric if (!RHSSatisfied) 1280480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 1281480093f4SDimitry Andric /*First=*/false); 1282480093f4SDimitry Andric return; 1283fe6060f1SDimitry Andric } 1284480093f4SDimitry Andric case BO_GE: 1285480093f4SDimitry Andric case BO_LE: 1286480093f4SDimitry Andric case BO_GT: 1287480093f4SDimitry Andric case BO_LT: 1288480093f4SDimitry Andric case BO_EQ: 1289480093f4SDimitry Andric case BO_NE: 1290480093f4SDimitry Andric if (BO->getLHS()->getType()->isIntegerType() && 1291480093f4SDimitry Andric BO->getRHS()->getType()->isIntegerType()) { 1292480093f4SDimitry Andric Expr::EvalResult SimplifiedLHS; 1293480093f4SDimitry Andric Expr::EvalResult SimplifiedRHS; 1294fe6060f1SDimitry Andric BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context, 1295fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 1296fe6060f1SDimitry Andric /*InConstantContext=*/true); 1297fe6060f1SDimitry Andric BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context, 1298fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 1299fe6060f1SDimitry Andric /*InConstantContext=*/true); 1300480093f4SDimitry Andric if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) { 1301480093f4SDimitry Andric S.Diag(SubstExpr->getBeginLoc(), 1302480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false_elaborated) 1303480093f4SDimitry Andric << (int)First << SubstExpr 1304fe6060f1SDimitry Andric << toString(SimplifiedLHS.Val.getInt(), 10) 1305480093f4SDimitry Andric << BinaryOperator::getOpcodeStr(BO->getOpcode()) 1306fe6060f1SDimitry Andric << toString(SimplifiedRHS.Val.getInt(), 10); 1307480093f4SDimitry Andric return; 1308480093f4SDimitry Andric } 1309480093f4SDimitry Andric } 1310480093f4SDimitry Andric break; 1311480093f4SDimitry Andric 1312480093f4SDimitry Andric default: 1313480093f4SDimitry Andric break; 1314480093f4SDimitry Andric } 1315480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) { 1316480093f4SDimitry Andric if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 1317480093f4SDimitry Andric S.Diag( 1318480093f4SDimitry Andric CSE->getSourceRange().getBegin(), 1319480093f4SDimitry Andric diag:: 1320480093f4SDimitry Andric note_single_arg_concept_specialization_constraint_evaluated_to_false) 1321480093f4SDimitry Andric << (int)First 1322480093f4SDimitry Andric << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument() 1323480093f4SDimitry Andric << CSE->getNamedConcept(); 1324480093f4SDimitry Andric } else { 1325480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 1326480093f4SDimitry Andric diag::note_concept_specialization_constraint_evaluated_to_false) 1327480093f4SDimitry Andric << (int)First << CSE; 1328480093f4SDimitry Andric } 1329480093f4SDimitry Andric S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction()); 1330480093f4SDimitry Andric return; 133155e4f9d5SDimitry Andric } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) { 1332bdd1243dSDimitry Andric // FIXME: RequiresExpr should store dependent diagnostics. 133355e4f9d5SDimitry Andric for (concepts::Requirement *Req : RE->getRequirements()) 133455e4f9d5SDimitry Andric if (!Req->isDependent() && !Req->isSatisfied()) { 133555e4f9d5SDimitry Andric if (auto *E = dyn_cast<concepts::ExprRequirement>(Req)) 133655e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, E, First); 133755e4f9d5SDimitry Andric else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req)) 133855e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, T, First); 133955e4f9d5SDimitry Andric else 134055e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement( 134155e4f9d5SDimitry Andric S, cast<concepts::NestedRequirement>(Req), First); 134255e4f9d5SDimitry Andric break; 134355e4f9d5SDimitry Andric } 134455e4f9d5SDimitry Andric return; 13450fca6ea1SDimitry Andric } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr); 13460fca6ea1SDimitry Andric TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) { 13470fca6ea1SDimitry Andric assert(TTE->getNumArgs() == 2); 13480fca6ea1SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 13490fca6ea1SDimitry Andric diag::note_is_deducible_constraint_evaluated_to_false) 13500fca6ea1SDimitry Andric << TTE->getArg(0)->getType() << TTE->getArg(1)->getType(); 13510fca6ea1SDimitry Andric return; 1352480093f4SDimitry Andric } 1353480093f4SDimitry Andric 1354480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 1355480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false) 1356480093f4SDimitry Andric << (int)First << SubstExpr; 1357480093f4SDimitry Andric } 1358480093f4SDimitry Andric 1359480093f4SDimitry Andric template <typename SubstitutionDiagnostic> 1360480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr( 13610fca6ea1SDimitry Andric Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record, 1362480093f4SDimitry Andric bool First = true) { 1363480093f4SDimitry Andric if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) { 1364480093f4SDimitry Andric S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed) 1365480093f4SDimitry Andric << Diag->second; 1366480093f4SDimitry Andric return; 1367480093f4SDimitry Andric } 1368480093f4SDimitry Andric 1369480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, 1370480093f4SDimitry Andric Record.template get<Expr *>(), First); 1371480093f4SDimitry Andric } 1372480093f4SDimitry Andric 137355e4f9d5SDimitry Andric void 137455e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, 137555e4f9d5SDimitry Andric bool First) { 1376480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 1377480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 13780fca6ea1SDimitry Andric for (auto &Record : Satisfaction.Details) { 13790fca6ea1SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Record, First); 1380480093f4SDimitry Andric First = false; 1381480093f4SDimitry Andric } 1382480093f4SDimitry Andric } 1383480093f4SDimitry Andric 1384480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint( 138555e4f9d5SDimitry Andric const ASTConstraintSatisfaction &Satisfaction, 138655e4f9d5SDimitry Andric bool First) { 1387480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 1388480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 13890fca6ea1SDimitry Andric for (auto &Record : Satisfaction) { 13900fca6ea1SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Record, First); 1391480093f4SDimitry Andric First = false; 1392480093f4SDimitry Andric } 1393480093f4SDimitry Andric } 1394480093f4SDimitry Andric 1395480093f4SDimitry Andric const NormalizedConstraint * 1396480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints( 1397480093f4SDimitry Andric NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) { 139806c3fb27SDimitry Andric // In case the ConstrainedDecl comes from modules, it is necessary to use 139906c3fb27SDimitry Andric // the canonical decl to avoid different atomic constraints with the 'same' 140006c3fb27SDimitry Andric // declarations. 140106c3fb27SDimitry Andric ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl()); 140206c3fb27SDimitry Andric 1403480093f4SDimitry Andric auto CacheEntry = NormalizationCache.find(ConstrainedDecl); 1404480093f4SDimitry Andric if (CacheEntry == NormalizationCache.end()) { 1405480093f4SDimitry Andric auto Normalized = 1406480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl, 1407480093f4SDimitry Andric AssociatedConstraints); 1408480093f4SDimitry Andric CacheEntry = 1409480093f4SDimitry Andric NormalizationCache 1410480093f4SDimitry Andric .try_emplace(ConstrainedDecl, 1411480093f4SDimitry Andric Normalized 1412480093f4SDimitry Andric ? new (Context) NormalizedConstraint( 1413480093f4SDimitry Andric std::move(*Normalized)) 1414480093f4SDimitry Andric : nullptr) 1415480093f4SDimitry Andric .first; 1416480093f4SDimitry Andric } 1417480093f4SDimitry Andric return CacheEntry->second; 1418480093f4SDimitry Andric } 1419480093f4SDimitry Andric 14200fca6ea1SDimitry Andric const NormalizedConstraint *clang::getNormalizedAssociatedConstraints( 14210fca6ea1SDimitry Andric Sema &S, NamedDecl *ConstrainedDecl, 14220fca6ea1SDimitry Andric ArrayRef<const Expr *> AssociatedConstraints) { 14230fca6ea1SDimitry Andric return S.getNormalizedAssociatedConstraints(ConstrainedDecl, 14240fca6ea1SDimitry Andric AssociatedConstraints); 14250fca6ea1SDimitry Andric } 14260fca6ea1SDimitry Andric 1427bdd1243dSDimitry Andric static bool 1428bdd1243dSDimitry Andric substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1429bdd1243dSDimitry Andric ConceptDecl *Concept, 1430bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL, 1431480093f4SDimitry Andric const ASTTemplateArgumentListInfo *ArgsAsWritten) { 14320fca6ea1SDimitry Andric 14330fca6ea1SDimitry Andric if (N.isCompound()) { 1434bdd1243dSDimitry Andric if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL, 1435480093f4SDimitry Andric ArgsAsWritten)) 1436480093f4SDimitry Andric return true; 1437bdd1243dSDimitry Andric return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL, 1438480093f4SDimitry Andric ArgsAsWritten); 1439480093f4SDimitry Andric } 14400fca6ea1SDimitry Andric 14410fca6ea1SDimitry Andric if (N.isFoldExpanded()) { 14420fca6ea1SDimitry Andric Sema::ArgumentPackSubstitutionIndexRAII _(S, -1); 14430fca6ea1SDimitry Andric return substituteParameterMappings( 14440fca6ea1SDimitry Andric S, N.getFoldExpandedConstraint()->Constraint, Concept, MLTAL, 14450fca6ea1SDimitry Andric ArgsAsWritten); 14460fca6ea1SDimitry Andric } 14470fca6ea1SDimitry Andric 1448480093f4SDimitry Andric TemplateParameterList *TemplateParams = Concept->getTemplateParameters(); 1449480093f4SDimitry Andric 1450480093f4SDimitry Andric AtomicConstraint &Atomic = *N.getAtomicConstraint(); 1451480093f4SDimitry Andric TemplateArgumentListInfo SubstArgs; 1452480093f4SDimitry Andric if (!Atomic.ParameterMapping) { 1453480093f4SDimitry Andric llvm::SmallBitVector OccurringIndices(TemplateParams->size()); 1454480093f4SDimitry Andric S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false, 1455480093f4SDimitry Andric /*Depth=*/0, OccurringIndices); 1456bdd1243dSDimitry Andric TemplateArgumentLoc *TempArgs = 1457bdd1243dSDimitry Andric new (S.Context) TemplateArgumentLoc[OccurringIndices.count()]; 1458480093f4SDimitry Andric for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) 1459480093f4SDimitry Andric if (OccurringIndices[I]) 1460bdd1243dSDimitry Andric new (&(TempArgs)[J++]) 1461bdd1243dSDimitry Andric TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc( 1462bdd1243dSDimitry Andric TemplateParams->begin()[I], 1463480093f4SDimitry Andric // Here we assume we do not support things like 1464480093f4SDimitry Andric // template<typename A, typename B> 1465480093f4SDimitry Andric // concept C = ...; 1466480093f4SDimitry Andric // 1467480093f4SDimitry Andric // template<typename... Ts> requires C<Ts...> 1468480093f4SDimitry Andric // struct S { }; 1469480093f4SDimitry Andric // The above currently yields a diagnostic. 1470480093f4SDimitry Andric // We still might have default arguments for concept parameters. 1471bdd1243dSDimitry Andric ArgsAsWritten->NumTemplateArgs > I 1472bdd1243dSDimitry Andric ? ArgsAsWritten->arguments()[I].getLocation() 1473bdd1243dSDimitry Andric : SourceLocation())); 1474bdd1243dSDimitry Andric Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count()); 1475480093f4SDimitry Andric } 14760fca6ea1SDimitry Andric SourceLocation InstLocBegin = 14770fca6ea1SDimitry Andric ArgsAsWritten->arguments().empty() 14780fca6ea1SDimitry Andric ? ArgsAsWritten->getLAngleLoc() 14790fca6ea1SDimitry Andric : ArgsAsWritten->arguments().front().getSourceRange().getBegin(); 14800fca6ea1SDimitry Andric SourceLocation InstLocEnd = 14810fca6ea1SDimitry Andric ArgsAsWritten->arguments().empty() 14820fca6ea1SDimitry Andric ? ArgsAsWritten->getRAngleLoc() 14830fca6ea1SDimitry Andric : ArgsAsWritten->arguments().front().getSourceRange().getEnd(); 1484480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 14850fca6ea1SDimitry Andric S, InstLocBegin, 1486480093f4SDimitry Andric Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, 14870fca6ea1SDimitry Andric {InstLocBegin, InstLocEnd}); 14880fca6ea1SDimitry Andric if (Inst.isInvalid()) 14890fca6ea1SDimitry Andric return true; 1490480093f4SDimitry Andric if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) 1491480093f4SDimitry Andric return true; 1492bdd1243dSDimitry Andric 1493bdd1243dSDimitry Andric TemplateArgumentLoc *TempArgs = 1494bdd1243dSDimitry Andric new (S.Context) TemplateArgumentLoc[SubstArgs.size()]; 1495480093f4SDimitry Andric std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(), 1496bdd1243dSDimitry Andric TempArgs); 1497bdd1243dSDimitry Andric Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size()); 1498480093f4SDimitry Andric return false; 1499480093f4SDimitry Andric } 1500480093f4SDimitry Andric 1501bdd1243dSDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1502bdd1243dSDimitry Andric const ConceptSpecializationExpr *CSE) { 1503bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 15045f757f3fSDimitry Andric CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(), 15050fca6ea1SDimitry Andric /*Final=*/false, CSE->getTemplateArguments(), 1506bdd1243dSDimitry Andric /*RelativeToPrimary=*/true, 1507bdd1243dSDimitry Andric /*Pattern=*/nullptr, 1508bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true); 1509bdd1243dSDimitry Andric 1510bdd1243dSDimitry Andric return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL, 1511bdd1243dSDimitry Andric CSE->getTemplateArgsAsWritten()); 1512bdd1243dSDimitry Andric } 1513bdd1243dSDimitry Andric 15140fca6ea1SDimitry Andric NormalizedConstraint::NormalizedConstraint(ASTContext &C, 15150fca6ea1SDimitry Andric NormalizedConstraint LHS, 15160fca6ea1SDimitry Andric NormalizedConstraint RHS, 15170fca6ea1SDimitry Andric CompoundConstraintKind Kind) 15180fca6ea1SDimitry Andric : Constraint{CompoundConstraint{ 15190fca6ea1SDimitry Andric new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)}, 15200fca6ea1SDimitry Andric Kind}} {} 15210fca6ea1SDimitry Andric 15220fca6ea1SDimitry Andric NormalizedConstraint::NormalizedConstraint(ASTContext &C, 15230fca6ea1SDimitry Andric const NormalizedConstraint &Other) { 15240fca6ea1SDimitry Andric if (Other.isAtomic()) { 15250fca6ea1SDimitry Andric Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint()); 15260fca6ea1SDimitry Andric } else if (Other.isFoldExpanded()) { 15270fca6ea1SDimitry Andric Constraint = new (C) FoldExpandedConstraint( 15280fca6ea1SDimitry Andric Other.getFoldExpandedConstraint()->Kind, 15290fca6ea1SDimitry Andric NormalizedConstraint(C, Other.getFoldExpandedConstraint()->Constraint), 15300fca6ea1SDimitry Andric Other.getFoldExpandedConstraint()->Pattern); 15310fca6ea1SDimitry Andric } else { 15320fca6ea1SDimitry Andric Constraint = CompoundConstraint( 15330fca6ea1SDimitry Andric new (C) 15340fca6ea1SDimitry Andric NormalizedConstraintPair{NormalizedConstraint(C, Other.getLHS()), 15350fca6ea1SDimitry Andric NormalizedConstraint(C, Other.getRHS())}, 15360fca6ea1SDimitry Andric Other.getCompoundKind()); 15370fca6ea1SDimitry Andric } 15380fca6ea1SDimitry Andric } 15390fca6ea1SDimitry Andric 15400fca6ea1SDimitry Andric NormalizedConstraint &NormalizedConstraint::getLHS() const { 15410fca6ea1SDimitry Andric assert(isCompound() && "getLHS called on a non-compound constraint."); 15420fca6ea1SDimitry Andric return Constraint.get<CompoundConstraint>().getPointer()->LHS; 15430fca6ea1SDimitry Andric } 15440fca6ea1SDimitry Andric 15450fca6ea1SDimitry Andric NormalizedConstraint &NormalizedConstraint::getRHS() const { 15460fca6ea1SDimitry Andric assert(isCompound() && "getRHS called on a non-compound constraint."); 15470fca6ea1SDimitry Andric return Constraint.get<CompoundConstraint>().getPointer()->RHS; 15480fca6ea1SDimitry Andric } 15490fca6ea1SDimitry Andric 1550bdd1243dSDimitry Andric std::optional<NormalizedConstraint> 1551480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D, 1552480093f4SDimitry Andric ArrayRef<const Expr *> E) { 1553480093f4SDimitry Andric assert(E.size() != 0); 15546e75b2fbSDimitry Andric auto Conjunction = fromConstraintExpr(S, D, E[0]); 15556e75b2fbSDimitry Andric if (!Conjunction) 1556bdd1243dSDimitry Andric return std::nullopt; 15576e75b2fbSDimitry Andric for (unsigned I = 1; I < E.size(); ++I) { 1558480093f4SDimitry Andric auto Next = fromConstraintExpr(S, D, E[I]); 1559480093f4SDimitry Andric if (!Next) 1560bdd1243dSDimitry Andric return std::nullopt; 15616e75b2fbSDimitry Andric *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction), 1562480093f4SDimitry Andric std::move(*Next), CCK_Conjunction); 1563480093f4SDimitry Andric } 1564480093f4SDimitry Andric return Conjunction; 1565480093f4SDimitry Andric } 1566480093f4SDimitry Andric 1567bdd1243dSDimitry Andric std::optional<NormalizedConstraint> 1568480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) { 1569480093f4SDimitry Andric assert(E != nullptr); 1570480093f4SDimitry Andric 1571480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 1572480093f4SDimitry Andric // [...] 1573480093f4SDimitry Andric // - The normal form of an expression (E) is the normal form of E. 1574480093f4SDimitry Andric // [...] 1575480093f4SDimitry Andric E = E->IgnoreParenImpCasts(); 1576bdd1243dSDimitry Andric 1577bdd1243dSDimitry Andric // C++2a [temp.param]p4: 1578bdd1243dSDimitry Andric // [...] If T is not a pack, then E is E', otherwise E is (E' && ...). 1579bdd1243dSDimitry Andric // Fold expression is considered atomic constraints per current wording. 1580bdd1243dSDimitry Andric // See http://cplusplus.github.io/concepts-ts/ts-active.html#28 1581bdd1243dSDimitry Andric 15825ffd83dbSDimitry Andric if (LogicalBinOp BO = E) { 15835ffd83dbSDimitry Andric auto LHS = fromConstraintExpr(S, D, BO.getLHS()); 1584480093f4SDimitry Andric if (!LHS) 1585bdd1243dSDimitry Andric return std::nullopt; 15865ffd83dbSDimitry Andric auto RHS = fromConstraintExpr(S, D, BO.getRHS()); 1587480093f4SDimitry Andric if (!RHS) 1588bdd1243dSDimitry Andric return std::nullopt; 1589480093f4SDimitry Andric 15905ffd83dbSDimitry Andric return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS), 15915ffd83dbSDimitry Andric BO.isAnd() ? CCK_Conjunction : CCK_Disjunction); 1592480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) { 1593480093f4SDimitry Andric const NormalizedConstraint *SubNF; 1594480093f4SDimitry Andric { 1595480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 1596480093f4SDimitry Andric S, CSE->getExprLoc(), 1597480093f4SDimitry Andric Sema::InstantiatingTemplate::ConstraintNormalization{}, D, 1598480093f4SDimitry Andric CSE->getSourceRange()); 15990fca6ea1SDimitry Andric if (Inst.isInvalid()) 16000fca6ea1SDimitry Andric return std::nullopt; 1601480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 1602480093f4SDimitry Andric // [...] 1603480093f4SDimitry Andric // The normal form of an id-expression of the form C<A1, A2, ..., AN>, 1604480093f4SDimitry Andric // where C names a concept, is the normal form of the 1605480093f4SDimitry Andric // constraint-expression of C, after substituting A1, A2, ..., AN for C’s 1606480093f4SDimitry Andric // respective template parameters in the parameter mappings in each atomic 1607480093f4SDimitry Andric // constraint. If any such substitution results in an invalid type or 1608480093f4SDimitry Andric // expression, the program is ill-formed; no diagnostic is required. 1609480093f4SDimitry Andric // [...] 1610480093f4SDimitry Andric ConceptDecl *CD = CSE->getNamedConcept(); 1611480093f4SDimitry Andric SubNF = S.getNormalizedAssociatedConstraints(CD, 1612480093f4SDimitry Andric {CD->getConstraintExpr()}); 1613480093f4SDimitry Andric if (!SubNF) 1614bdd1243dSDimitry Andric return std::nullopt; 1615480093f4SDimitry Andric } 1616480093f4SDimitry Andric 1617bdd1243dSDimitry Andric std::optional<NormalizedConstraint> New; 1618480093f4SDimitry Andric New.emplace(S.Context, *SubNF); 1619480093f4SDimitry Andric 1620bdd1243dSDimitry Andric if (substituteParameterMappings(S, *New, CSE)) 1621bdd1243dSDimitry Andric return std::nullopt; 1622480093f4SDimitry Andric 1623480093f4SDimitry Andric return New; 16240fca6ea1SDimitry Andric } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E); 16250fca6ea1SDimitry Andric FE && S.getLangOpts().CPlusPlus26 && 16260fca6ea1SDimitry Andric (FE->getOperator() == BinaryOperatorKind::BO_LAnd || 16270fca6ea1SDimitry Andric FE->getOperator() == BinaryOperatorKind::BO_LOr)) { 16280fca6ea1SDimitry Andric 16290fca6ea1SDimitry Andric // Normalize fold expressions in C++26. 16300fca6ea1SDimitry Andric 16310fca6ea1SDimitry Andric FoldExpandedConstraint::FoldOperatorKind Kind = 16320fca6ea1SDimitry Andric FE->getOperator() == BinaryOperatorKind::BO_LAnd 16330fca6ea1SDimitry Andric ? FoldExpandedConstraint::FoldOperatorKind::And 16340fca6ea1SDimitry Andric : FoldExpandedConstraint::FoldOperatorKind::Or; 16350fca6ea1SDimitry Andric 16360fca6ea1SDimitry Andric if (FE->getInit()) { 16370fca6ea1SDimitry Andric auto LHS = fromConstraintExpr(S, D, FE->getLHS()); 16380fca6ea1SDimitry Andric auto RHS = fromConstraintExpr(S, D, FE->getRHS()); 16390fca6ea1SDimitry Andric if (!LHS || !RHS) 16400fca6ea1SDimitry Andric return std::nullopt; 16410fca6ea1SDimitry Andric 16420fca6ea1SDimitry Andric if (FE->isRightFold()) 16430fca6ea1SDimitry Andric RHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 16440fca6ea1SDimitry Andric Kind, std::move(*RHS), FE->getPattern()}}; 16450fca6ea1SDimitry Andric else 16460fca6ea1SDimitry Andric LHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 16470fca6ea1SDimitry Andric Kind, std::move(*LHS), FE->getPattern()}}; 16480fca6ea1SDimitry Andric 16490fca6ea1SDimitry Andric return NormalizedConstraint( 16500fca6ea1SDimitry Andric S.Context, std::move(*LHS), std::move(*RHS), 16510fca6ea1SDimitry Andric FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction 16520fca6ea1SDimitry Andric : CCK_Disjunction); 1653480093f4SDimitry Andric } 16540fca6ea1SDimitry Andric auto Sub = fromConstraintExpr(S, D, FE->getPattern()); 16550fca6ea1SDimitry Andric if (!Sub) 16560fca6ea1SDimitry Andric return std::nullopt; 16570fca6ea1SDimitry Andric return NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 16580fca6ea1SDimitry Andric Kind, std::move(*Sub), FE->getPattern()}}; 16590fca6ea1SDimitry Andric } 16600fca6ea1SDimitry Andric 1661480093f4SDimitry Andric return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)}; 1662480093f4SDimitry Andric } 1663480093f4SDimitry Andric 16640fca6ea1SDimitry Andric bool FoldExpandedConstraint::AreCompatibleForSubsumption( 16650fca6ea1SDimitry Andric const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) { 1666480093f4SDimitry Andric 16670fca6ea1SDimitry Andric // [C++26] [temp.constr.fold] 16680fca6ea1SDimitry Andric // Two fold expanded constraints are compatible for subsumption 16690fca6ea1SDimitry Andric // if their respective constraints both contain an equivalent unexpanded pack. 16700fca6ea1SDimitry Andric 16710fca6ea1SDimitry Andric llvm::SmallVector<UnexpandedParameterPack> APacks, BPacks; 16720fca6ea1SDimitry Andric Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.Pattern), APacks); 16730fca6ea1SDimitry Andric Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks); 16740fca6ea1SDimitry Andric 16750fca6ea1SDimitry Andric for (const UnexpandedParameterPack &APack : APacks) { 16760fca6ea1SDimitry Andric std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack); 16770fca6ea1SDimitry Andric auto it = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) { 16780fca6ea1SDimitry Andric return getDepthAndIndex(BPack) == DepthAndIndex; 16790fca6ea1SDimitry Andric }); 16800fca6ea1SDimitry Andric if (it != BPacks.end()) 16810fca6ea1SDimitry Andric return true; 16820fca6ea1SDimitry Andric } 16830fca6ea1SDimitry Andric return false; 16840fca6ea1SDimitry Andric } 16850fca6ea1SDimitry Andric 16860fca6ea1SDimitry Andric NormalForm clang::makeCNF(const NormalizedConstraint &Normalized) { 1687480093f4SDimitry Andric if (Normalized.isAtomic()) 1688480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 1689480093f4SDimitry Andric 16900fca6ea1SDimitry Andric else if (Normalized.isFoldExpanded()) 16910fca6ea1SDimitry Andric return {{Normalized.getFoldExpandedConstraint()}}; 16920fca6ea1SDimitry Andric 1693480093f4SDimitry Andric NormalForm LCNF = makeCNF(Normalized.getLHS()); 1694480093f4SDimitry Andric NormalForm RCNF = makeCNF(Normalized.getRHS()); 1695480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) { 1696480093f4SDimitry Andric LCNF.reserve(LCNF.size() + RCNF.size()); 1697480093f4SDimitry Andric while (!RCNF.empty()) 1698480093f4SDimitry Andric LCNF.push_back(RCNF.pop_back_val()); 1699480093f4SDimitry Andric return LCNF; 1700480093f4SDimitry Andric } 1701480093f4SDimitry Andric 1702480093f4SDimitry Andric // Disjunction 1703480093f4SDimitry Andric NormalForm Res; 1704480093f4SDimitry Andric Res.reserve(LCNF.size() * RCNF.size()); 1705480093f4SDimitry Andric for (auto &LDisjunction : LCNF) 1706480093f4SDimitry Andric for (auto &RDisjunction : RCNF) { 1707480093f4SDimitry Andric NormalForm::value_type Combined; 1708480093f4SDimitry Andric Combined.reserve(LDisjunction.size() + RDisjunction.size()); 1709480093f4SDimitry Andric std::copy(LDisjunction.begin(), LDisjunction.end(), 1710480093f4SDimitry Andric std::back_inserter(Combined)); 1711480093f4SDimitry Andric std::copy(RDisjunction.begin(), RDisjunction.end(), 1712480093f4SDimitry Andric std::back_inserter(Combined)); 1713480093f4SDimitry Andric Res.emplace_back(Combined); 1714480093f4SDimitry Andric } 1715480093f4SDimitry Andric return Res; 1716480093f4SDimitry Andric } 1717480093f4SDimitry Andric 17180fca6ea1SDimitry Andric NormalForm clang::makeDNF(const NormalizedConstraint &Normalized) { 1719480093f4SDimitry Andric if (Normalized.isAtomic()) 1720480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 1721480093f4SDimitry Andric 17220fca6ea1SDimitry Andric else if (Normalized.isFoldExpanded()) 17230fca6ea1SDimitry Andric return {{Normalized.getFoldExpandedConstraint()}}; 17240fca6ea1SDimitry Andric 1725480093f4SDimitry Andric NormalForm LDNF = makeDNF(Normalized.getLHS()); 1726480093f4SDimitry Andric NormalForm RDNF = makeDNF(Normalized.getRHS()); 1727480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) { 1728480093f4SDimitry Andric LDNF.reserve(LDNF.size() + RDNF.size()); 1729480093f4SDimitry Andric while (!RDNF.empty()) 1730480093f4SDimitry Andric LDNF.push_back(RDNF.pop_back_val()); 1731480093f4SDimitry Andric return LDNF; 1732480093f4SDimitry Andric } 1733480093f4SDimitry Andric 1734480093f4SDimitry Andric // Conjunction 1735480093f4SDimitry Andric NormalForm Res; 1736480093f4SDimitry Andric Res.reserve(LDNF.size() * RDNF.size()); 1737480093f4SDimitry Andric for (auto &LConjunction : LDNF) { 1738480093f4SDimitry Andric for (auto &RConjunction : RDNF) { 1739480093f4SDimitry Andric NormalForm::value_type Combined; 1740480093f4SDimitry Andric Combined.reserve(LConjunction.size() + RConjunction.size()); 1741480093f4SDimitry Andric std::copy(LConjunction.begin(), LConjunction.end(), 1742480093f4SDimitry Andric std::back_inserter(Combined)); 1743480093f4SDimitry Andric std::copy(RConjunction.begin(), RConjunction.end(), 1744480093f4SDimitry Andric std::back_inserter(Combined)); 1745480093f4SDimitry Andric Res.emplace_back(Combined); 1746480093f4SDimitry Andric } 1747480093f4SDimitry Andric } 1748480093f4SDimitry Andric return Res; 1749480093f4SDimitry Andric } 1750480093f4SDimitry Andric 1751bdd1243dSDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, 1752bdd1243dSDimitry Andric MutableArrayRef<const Expr *> AC1, 1753bdd1243dSDimitry Andric NamedDecl *D2, 1754bdd1243dSDimitry Andric MutableArrayRef<const Expr *> AC2, 1755480093f4SDimitry Andric bool &Result) { 1756bdd1243dSDimitry Andric if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) { 1757bdd1243dSDimitry Andric auto IsExpectedEntity = [](const FunctionDecl *FD) { 1758bdd1243dSDimitry Andric FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind(); 1759bdd1243dSDimitry Andric return Kind == FunctionDecl::TK_NonTemplate || 1760bdd1243dSDimitry Andric Kind == FunctionDecl::TK_FunctionTemplate; 1761bdd1243dSDimitry Andric }; 1762bdd1243dSDimitry Andric const auto *FD2 = dyn_cast<FunctionDecl>(D2); 1763bdd1243dSDimitry Andric (void)IsExpectedEntity; 1764bdd1243dSDimitry Andric (void)FD1; 1765bdd1243dSDimitry Andric (void)FD2; 1766bdd1243dSDimitry Andric assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) && 1767bdd1243dSDimitry Andric "use non-instantiated function declaration for constraints partial " 1768bdd1243dSDimitry Andric "ordering"); 1769bdd1243dSDimitry Andric } 1770bdd1243dSDimitry Andric 1771480093f4SDimitry Andric if (AC1.empty()) { 1772480093f4SDimitry Andric Result = AC2.empty(); 1773480093f4SDimitry Andric return false; 1774480093f4SDimitry Andric } 1775480093f4SDimitry Andric if (AC2.empty()) { 1776480093f4SDimitry Andric // TD1 has associated constraints and TD2 does not. 1777480093f4SDimitry Andric Result = true; 1778480093f4SDimitry Andric return false; 1779480093f4SDimitry Andric } 1780480093f4SDimitry Andric 1781480093f4SDimitry Andric std::pair<NamedDecl *, NamedDecl *> Key{D1, D2}; 1782480093f4SDimitry Andric auto CacheEntry = SubsumptionCache.find(Key); 1783480093f4SDimitry Andric if (CacheEntry != SubsumptionCache.end()) { 1784480093f4SDimitry Andric Result = CacheEntry->second; 1785480093f4SDimitry Andric return false; 1786480093f4SDimitry Andric } 1787480093f4SDimitry Andric 1788bdd1243dSDimitry Andric unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true); 1789bdd1243dSDimitry Andric unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true); 1790bdd1243dSDimitry Andric 1791bdd1243dSDimitry Andric for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) { 1792bdd1243dSDimitry Andric if (Depth2 > Depth1) { 1793bdd1243dSDimitry Andric AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1) 1794bdd1243dSDimitry Andric .TransformExpr(const_cast<Expr *>(AC1[I])) 1795bdd1243dSDimitry Andric .get(); 1796bdd1243dSDimitry Andric } else if (Depth1 > Depth2) { 1797bdd1243dSDimitry Andric AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2) 1798bdd1243dSDimitry Andric .TransformExpr(const_cast<Expr *>(AC2[I])) 1799bdd1243dSDimitry Andric .get(); 1800bdd1243dSDimitry Andric } 1801bdd1243dSDimitry Andric } 1802bdd1243dSDimitry Andric 18030fca6ea1SDimitry Andric if (clang::subsumes( 18040fca6ea1SDimitry Andric *this, D1, AC1, D2, AC2, Result, 1805480093f4SDimitry Andric [this](const AtomicConstraint &A, const AtomicConstraint &B) { 1806480093f4SDimitry Andric return A.subsumes(Context, B); 1807480093f4SDimitry Andric })) 1808480093f4SDimitry Andric return true; 1809480093f4SDimitry Andric SubsumptionCache.try_emplace(Key, Result); 1810480093f4SDimitry Andric return false; 1811480093f4SDimitry Andric } 1812480093f4SDimitry Andric 1813480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, 1814480093f4SDimitry Andric ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) { 1815480093f4SDimitry Andric if (isSFINAEContext()) 1816480093f4SDimitry Andric // No need to work here because our notes would be discarded. 1817480093f4SDimitry Andric return false; 1818480093f4SDimitry Andric 1819480093f4SDimitry Andric if (AC1.empty() || AC2.empty()) 1820480093f4SDimitry Andric return false; 1821480093f4SDimitry Andric 1822480093f4SDimitry Andric auto NormalExprEvaluator = 1823480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 1824480093f4SDimitry Andric return A.subsumes(Context, B); 1825480093f4SDimitry Andric }; 1826480093f4SDimitry Andric 1827480093f4SDimitry Andric const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr; 1828480093f4SDimitry Andric auto IdenticalExprEvaluator = 1829480093f4SDimitry Andric [&] (const AtomicConstraint &A, const AtomicConstraint &B) { 1830480093f4SDimitry Andric if (!A.hasMatchingParameterMapping(Context, B)) 1831480093f4SDimitry Andric return false; 1832480093f4SDimitry Andric const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr; 1833480093f4SDimitry Andric if (EA == EB) 1834480093f4SDimitry Andric return true; 1835480093f4SDimitry Andric 1836480093f4SDimitry Andric // Not the same source level expression - are the expressions 1837480093f4SDimitry Andric // identical? 1838480093f4SDimitry Andric llvm::FoldingSetNodeID IDA, IDB; 1839349cc55cSDimitry Andric EA->Profile(IDA, Context, /*Canonical=*/true); 1840349cc55cSDimitry Andric EB->Profile(IDB, Context, /*Canonical=*/true); 1841480093f4SDimitry Andric if (IDA != IDB) 1842480093f4SDimitry Andric return false; 1843480093f4SDimitry Andric 1844480093f4SDimitry Andric AmbiguousAtomic1 = EA; 1845480093f4SDimitry Andric AmbiguousAtomic2 = EB; 1846480093f4SDimitry Andric return true; 1847480093f4SDimitry Andric }; 1848480093f4SDimitry Andric 1849480093f4SDimitry Andric { 1850480093f4SDimitry Andric // The subsumption checks might cause diagnostics 1851480093f4SDimitry Andric SFINAETrap Trap(*this); 1852480093f4SDimitry Andric auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1); 1853480093f4SDimitry Andric if (!Normalized1) 1854480093f4SDimitry Andric return false; 1855480093f4SDimitry Andric const NormalForm DNF1 = makeDNF(*Normalized1); 1856480093f4SDimitry Andric const NormalForm CNF1 = makeCNF(*Normalized1); 1857480093f4SDimitry Andric 1858480093f4SDimitry Andric auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2); 1859480093f4SDimitry Andric if (!Normalized2) 1860480093f4SDimitry Andric return false; 1861480093f4SDimitry Andric const NormalForm DNF2 = makeDNF(*Normalized2); 1862480093f4SDimitry Andric const NormalForm CNF2 = makeCNF(*Normalized2); 1863480093f4SDimitry Andric 18640fca6ea1SDimitry Andric bool Is1AtLeastAs2Normally = 18650fca6ea1SDimitry Andric clang::subsumes(DNF1, CNF2, NormalExprEvaluator); 18660fca6ea1SDimitry Andric bool Is2AtLeastAs1Normally = 18670fca6ea1SDimitry Andric clang::subsumes(DNF2, CNF1, NormalExprEvaluator); 18680fca6ea1SDimitry Andric bool Is1AtLeastAs2 = clang::subsumes(DNF1, CNF2, IdenticalExprEvaluator); 18690fca6ea1SDimitry Andric bool Is2AtLeastAs1 = clang::subsumes(DNF2, CNF1, IdenticalExprEvaluator); 1870480093f4SDimitry Andric if (Is1AtLeastAs2 == Is1AtLeastAs2Normally && 1871480093f4SDimitry Andric Is2AtLeastAs1 == Is2AtLeastAs1Normally) 1872480093f4SDimitry Andric // Same result - no ambiguity was caused by identical atomic expressions. 1873480093f4SDimitry Andric return false; 1874480093f4SDimitry Andric } 1875480093f4SDimitry Andric 1876480093f4SDimitry Andric // A different result! Some ambiguous atomic constraint(s) caused a difference 1877480093f4SDimitry Andric assert(AmbiguousAtomic1 && AmbiguousAtomic2); 1878480093f4SDimitry Andric 1879480093f4SDimitry Andric Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints) 1880480093f4SDimitry Andric << AmbiguousAtomic1->getSourceRange(); 1881480093f4SDimitry Andric Diag(AmbiguousAtomic2->getBeginLoc(), 1882480093f4SDimitry Andric diag::note_ambiguous_atomic_constraints_similar_expression) 1883480093f4SDimitry Andric << AmbiguousAtomic2->getSourceRange(); 1884480093f4SDimitry Andric return true; 1885480093f4SDimitry Andric } 188655e4f9d5SDimitry Andric 188755e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 188855e4f9d5SDimitry Andric Expr *E, bool IsSimple, SourceLocation NoexceptLoc, 188955e4f9d5SDimitry Andric ReturnTypeRequirement Req, SatisfactionStatus Status, 189055e4f9d5SDimitry Andric ConceptSpecializationExpr *SubstitutedConstraintExpr) : 189155e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, 189255e4f9d5SDimitry Andric Status == SS_Dependent && 189355e4f9d5SDimitry Andric (E->containsUnexpandedParameterPack() || 189455e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack()), 189555e4f9d5SDimitry Andric Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc), 189655e4f9d5SDimitry Andric TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr), 189755e4f9d5SDimitry Andric Status(Status) { 189855e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 189955e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 190055e4f9d5SDimitry Andric "noexcept specification"); 190155e4f9d5SDimitry Andric assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == 190255e4f9d5SDimitry Andric (SubstitutedConstraintExpr != nullptr)); 190355e4f9d5SDimitry Andric } 190455e4f9d5SDimitry Andric 190555e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 190655e4f9d5SDimitry Andric SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, 190755e4f9d5SDimitry Andric SourceLocation NoexceptLoc, ReturnTypeRequirement Req) : 190855e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), 190955e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), 191055e4f9d5SDimitry Andric Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), 191155e4f9d5SDimitry Andric Status(SS_ExprSubstitutionFailure) { 191255e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 191355e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 191455e4f9d5SDimitry Andric "noexcept specification"); 191555e4f9d5SDimitry Andric } 191655e4f9d5SDimitry Andric 191755e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement:: 191855e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) : 191904eeddc0SDimitry Andric TypeConstraintInfo(TPL, false) { 192055e4f9d5SDimitry Andric assert(TPL->size() == 1); 192155e4f9d5SDimitry Andric const TypeConstraint *TC = 192255e4f9d5SDimitry Andric cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint(); 192355e4f9d5SDimitry Andric assert(TC && 192455e4f9d5SDimitry Andric "TPL must have a template type parameter with a type constraint"); 192555e4f9d5SDimitry Andric auto *Constraint = 1926349cc55cSDimitry Andric cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint()); 1927e8d8bef9SDimitry Andric bool Dependent = 1928e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten() && 1929e8d8bef9SDimitry Andric TemplateSpecializationType::anyInstantiationDependentTemplateArguments( 1930e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)); 193104eeddc0SDimitry Andric TypeConstraintInfo.setInt(Dependent ? true : false); 193255e4f9d5SDimitry Andric } 193355e4f9d5SDimitry Andric 193455e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) : 1935e8d8bef9SDimitry Andric Requirement(RK_Type, T->getType()->isInstantiationDependentType(), 193655e4f9d5SDimitry Andric T->getType()->containsUnexpandedParameterPack(), 193755e4f9d5SDimitry Andric // We reach this ctor with either dependent types (in which 193855e4f9d5SDimitry Andric // IsSatisfied doesn't matter) or with non-dependent type in 193955e4f9d5SDimitry Andric // which the existence of the type indicates satisfaction. 1940e8d8bef9SDimitry Andric /*IsSatisfied=*/true), 1941e8d8bef9SDimitry Andric Value(T), 1942e8d8bef9SDimitry Andric Status(T->getType()->isInstantiationDependentType() ? SS_Dependent 1943e8d8bef9SDimitry Andric : SS_Satisfied) {} 1944