15d98ba60SSaar Raz //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===// 25d98ba60SSaar Raz // 3c874dd53SChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c874dd53SChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information. 5c874dd53SChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65d98ba60SSaar Raz // 75d98ba60SSaar Raz //===----------------------------------------------------------------------===// 85d98ba60SSaar Raz // 95d98ba60SSaar Raz // This file implements semantic analysis for C++ constraints and concepts. 105d98ba60SSaar Raz // 115d98ba60SSaar Raz //===----------------------------------------------------------------------===// 125d98ba60SSaar Raz 13b65b1f32SSaar Raz #include "clang/Sema/SemaConcept.h" 146d688055SDavid Stone #include "TreeTransform.h" 15babdef27SErich Keane #include "clang/AST/ASTLambda.h" 16158f4f30SCorentin Jabot #include "clang/AST/DeclCXX.h" 17a0f50d73SSaar Raz #include "clang/AST/ExprConcepts.h" 18b65b1f32SSaar Raz #include "clang/Basic/OperatorPrecedence.h" 196d688055SDavid Stone #include "clang/Sema/EnterExpressionEvaluationContext.h" 206d688055SDavid Stone #include "clang/Sema/Initialization.h" 216d688055SDavid Stone #include "clang/Sema/Overload.h" 22158f4f30SCorentin Jabot #include "clang/Sema/ScopeInfo.h" 236d688055SDavid Stone #include "clang/Sema/Sema.h" 246d688055SDavid Stone #include "clang/Sema/SemaInternal.h" 256d688055SDavid Stone #include "clang/Sema/Template.h" 266d688055SDavid Stone #include "clang/Sema/TemplateDeduction.h" 27fdf80e86SSaar Raz #include "llvm/ADT/DenseMap.h" 28fdf80e86SSaar Raz #include "llvm/ADT/PointerUnion.h" 2961cdaf66SSimon Pilgrim #include "llvm/ADT/StringExtras.h" 30a1580d7bSKazu Hirata #include <optional> 3161cdaf66SSimon Pilgrim 325d98ba60SSaar Raz using namespace clang; 335d98ba60SSaar Raz using namespace sema; 345d98ba60SSaar Raz 356c29073eSRichard Smith namespace { 366c29073eSRichard Smith class LogicalBinOp { 37babdef27SErich Keane SourceLocation Loc; 386c29073eSRichard Smith OverloadedOperatorKind Op = OO_None; 396c29073eSRichard Smith const Expr *LHS = nullptr; 406c29073eSRichard Smith const Expr *RHS = nullptr; 416c29073eSRichard Smith 426c29073eSRichard Smith public: 436c29073eSRichard Smith LogicalBinOp(const Expr *E) { 446c29073eSRichard Smith if (auto *BO = dyn_cast<BinaryOperator>(E)) { 456c29073eSRichard Smith Op = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 466c29073eSRichard Smith LHS = BO->getLHS(); 476c29073eSRichard Smith RHS = BO->getRHS(); 48babdef27SErich Keane Loc = BO->getExprLoc(); 496c29073eSRichard Smith } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) { 5022aa3680SCorentin Jabot // If OO is not || or && it might not have exactly 2 arguments. 5122aa3680SCorentin Jabot if (OO->getNumArgs() == 2) { 526c29073eSRichard Smith Op = OO->getOperator(); 536c29073eSRichard Smith LHS = OO->getArg(0); 546c29073eSRichard Smith RHS = OO->getArg(1); 55babdef27SErich Keane Loc = OO->getOperatorLoc(); 566c29073eSRichard Smith } 576c29073eSRichard Smith } 5822aa3680SCorentin Jabot } 596c29073eSRichard Smith 606c29073eSRichard Smith bool isAnd() const { return Op == OO_AmpAmp; } 616c29073eSRichard Smith bool isOr() const { return Op == OO_PipePipe; } 626c29073eSRichard Smith explicit operator bool() const { return isAnd() || isOr(); } 636c29073eSRichard Smith 646c29073eSRichard Smith const Expr *getLHS() const { return LHS; } 656c29073eSRichard Smith const Expr *getRHS() const { return RHS; } 66b330d800Scor3ntin OverloadedOperatorKind getOp() const { return Op; } 67babdef27SErich Keane 68babdef27SErich Keane ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const { 69babdef27SErich Keane return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS())); 70babdef27SErich Keane } 71babdef27SErich Keane 72babdef27SErich Keane ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS, 73babdef27SErich Keane ExprResult RHS) const { 74babdef27SErich Keane assert((isAnd() || isOr()) && "Not the right kind of op?"); 75babdef27SErich Keane assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?"); 76babdef27SErich Keane 77babdef27SErich Keane if (!LHS.isUsable() || !RHS.isUsable()) 78babdef27SErich Keane return ExprEmpty(); 79babdef27SErich Keane 80babdef27SErich Keane // We should just be able to 'normalize' these to the builtin Binary 81babdef27SErich Keane // Operator, since that is how they are evaluated in constriant checks. 82babdef27SErich Keane return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(), 83babdef27SErich Keane BinaryOperator::getOverloadedOpcode(Op), 84babdef27SErich Keane SemaRef.Context.BoolTy, VK_PRValue, 85babdef27SErich Keane OK_Ordinary, Loc, FPOptionsOverride{}); 86babdef27SErich Keane } 876c29073eSRichard Smith }; 886c29073eSRichard Smith } 896c29073eSRichard Smith 906c29073eSRichard Smith bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression, 916c29073eSRichard Smith Token NextToken, bool *PossibleNonPrimary, 92b65b1f32SSaar Raz bool IsTrailingRequiresClause) { 935d98ba60SSaar Raz // C++2a [temp.constr.atomic]p1 945d98ba60SSaar Raz // ..E shall be a constant expression of type bool. 955d98ba60SSaar Raz 965d98ba60SSaar Raz ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts(); 975d98ba60SSaar Raz 986c29073eSRichard Smith if (LogicalBinOp BO = ConstraintExpression) { 996c29073eSRichard Smith return CheckConstraintExpression(BO.getLHS(), NextToken, 100b65b1f32SSaar Raz PossibleNonPrimary) && 1016c29073eSRichard Smith CheckConstraintExpression(BO.getRHS(), NextToken, 102b65b1f32SSaar Raz PossibleNonPrimary); 1035d98ba60SSaar Raz } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression)) 104b65b1f32SSaar Raz return CheckConstraintExpression(C->getSubExpr(), NextToken, 105b65b1f32SSaar Raz PossibleNonPrimary); 1065d98ba60SSaar Raz 1075d98ba60SSaar Raz QualType Type = ConstraintExpression->getType(); 108b65b1f32SSaar Raz 109b65b1f32SSaar Raz auto CheckForNonPrimary = [&] { 1106acdf589SEmilia Dreamer if (!PossibleNonPrimary) 1116acdf589SEmilia Dreamer return; 1126acdf589SEmilia Dreamer 113b65b1f32SSaar Raz *PossibleNonPrimary = 114b65b1f32SSaar Raz // We have the following case: 115b65b1f32SSaar Raz // template<typename> requires func(0) struct S { }; 116b65b1f32SSaar Raz // The user probably isn't aware of the parentheses required around 117b65b1f32SSaar Raz // the function call, and we're only going to parse 'func' as the 118b65b1f32SSaar Raz // primary-expression, and complain that it is of non-bool type. 1196acdf589SEmilia Dreamer // 1206acdf589SEmilia Dreamer // However, if we're in a lambda, this might also be: 1216acdf589SEmilia Dreamer // []<typename> requires var () {}; 1226acdf589SEmilia Dreamer // Which also looks like a function call due to the lambda parentheses, 1236acdf589SEmilia Dreamer // but unlike the first case, isn't an error, so this check is skipped. 124b65b1f32SSaar Raz (NextToken.is(tok::l_paren) && 125b65b1f32SSaar Raz (IsTrailingRequiresClause || 126b65b1f32SSaar Raz (Type->isDependentType() && 1276acdf589SEmilia Dreamer isa<UnresolvedLookupExpr>(ConstraintExpression) && 1286acdf589SEmilia Dreamer !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) || 129b65b1f32SSaar Raz Type->isFunctionType() || 130b65b1f32SSaar Raz Type->isSpecificBuiltinType(BuiltinType::Overload))) || 131b65b1f32SSaar Raz // We have the following case: 132b65b1f32SSaar Raz // template<typename T> requires size_<T> == 0 struct S { }; 133b65b1f32SSaar Raz // The user probably isn't aware of the parentheses required around 134b65b1f32SSaar Raz // the binary operator, and we're only going to parse 'func' as the 135b65b1f32SSaar Raz // first operand, and complain that it is of non-bool type. 136b65b1f32SSaar Raz getBinOpPrecedence(NextToken.getKind(), 137b65b1f32SSaar Raz /*GreaterThanIsOperator=*/true, 138b65b1f32SSaar Raz getLangOpts().CPlusPlus11) > prec::LogicalAnd; 139b65b1f32SSaar Raz }; 140b65b1f32SSaar Raz 141b65b1f32SSaar Raz // An atomic constraint! 142b65b1f32SSaar Raz if (ConstraintExpression->isTypeDependent()) { 143b65b1f32SSaar Raz CheckForNonPrimary(); 144b65b1f32SSaar Raz return true; 145b65b1f32SSaar Raz } 146b65b1f32SSaar Raz 1475d98ba60SSaar Raz if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) { 1485d98ba60SSaar Raz Diag(ConstraintExpression->getExprLoc(), 1495d98ba60SSaar Raz diag::err_non_bool_atomic_constraint) << Type 1505d98ba60SSaar Raz << ConstraintExpression->getSourceRange(); 151b65b1f32SSaar Raz CheckForNonPrimary(); 1525d98ba60SSaar Raz return false; 1535d98ba60SSaar Raz } 154b65b1f32SSaar Raz 155b65b1f32SSaar Raz if (PossibleNonPrimary) 156b65b1f32SSaar Raz *PossibleNonPrimary = false; 1575d98ba60SSaar Raz return true; 1585d98ba60SSaar Raz } 1595d98ba60SSaar Raz 1602cee2663SErich Keane namespace { 1612cee2663SErich Keane struct SatisfactionStackRAII { 1622cee2663SErich Keane Sema &SemaRef; 16342667563SErich Keane bool Inserted = false; 16442667563SErich Keane SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND, 16533cf2a39SManna, Soumi const llvm::FoldingSetNodeID &FSNID) 1662cee2663SErich Keane : SemaRef(SemaRef) { 16742667563SErich Keane if (ND) { 16842667563SErich Keane SemaRef.PushSatisfactionStackEntry(ND, FSNID); 16942667563SErich Keane Inserted = true; 1702cee2663SErich Keane } 17142667563SErich Keane } 17242667563SErich Keane ~SatisfactionStackRAII() { 17342667563SErich Keane if (Inserted) 17442667563SErich Keane SemaRef.PopSatisfactionStackEntry(); 17542667563SErich Keane } 1762cee2663SErich Keane }; 1772cee2663SErich Keane } // namespace 1782cee2663SErich Keane 179b330d800Scor3ntin template <typename ConstraintEvaluator> 180babdef27SErich Keane static ExprResult 181fdf80e86SSaar Raz calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, 182fdf80e86SSaar Raz ConstraintSatisfaction &Satisfaction, 183b330d800Scor3ntin const ConstraintEvaluator &Evaluator); 1845d98ba60SSaar Raz 185b330d800Scor3ntin template <typename ConstraintEvaluator> 186b330d800Scor3ntin static ExprResult 187b330d800Scor3ntin calculateConstraintSatisfaction(Sema &S, const Expr *LHS, 188b330d800Scor3ntin OverloadedOperatorKind Op, const Expr *RHS, 189b330d800Scor3ntin ConstraintSatisfaction &Satisfaction, 190b330d800Scor3ntin const ConstraintEvaluator &Evaluator) { 1914af62db0STakuya Shimizu size_t EffectiveDetailEndIndex = Satisfaction.Details.size(); 192b330d800Scor3ntin 193b330d800Scor3ntin ExprResult LHSRes = 194b330d800Scor3ntin calculateConstraintSatisfaction(S, LHS, Satisfaction, Evaluator); 195babdef27SErich Keane 196babdef27SErich Keane if (LHSRes.isInvalid()) 197babdef27SErich Keane return ExprError(); 198fdf80e86SSaar Raz 199fdf80e86SSaar Raz bool IsLHSSatisfied = Satisfaction.IsSatisfied; 200fdf80e86SSaar Raz 201b330d800Scor3ntin if (Op == clang::OO_PipePipe && IsLHSSatisfied) 202fdf80e86SSaar Raz // [temp.constr.op] p3 203fdf80e86SSaar Raz // A disjunction is a constraint taking two operands. To determine if 204fdf80e86SSaar Raz // a disjunction is satisfied, the satisfaction of the first operand 205fdf80e86SSaar Raz // is checked. If that is satisfied, the disjunction is satisfied. 206fdf80e86SSaar Raz // Otherwise, the disjunction is satisfied if and only if the second 207fdf80e86SSaar Raz // operand is satisfied. 208b3ce8728SUtkarsh Saxena // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 209b3ce8728SUtkarsh Saxena return LHSRes; 210fdf80e86SSaar Raz 211b330d800Scor3ntin if (Op == clang::OO_AmpAmp && !IsLHSSatisfied) 212fdf80e86SSaar Raz // [temp.constr.op] p2 213fdf80e86SSaar Raz // A conjunction is a constraint taking two operands. To determine if 214fdf80e86SSaar Raz // a conjunction is satisfied, the satisfaction of the first operand 215fdf80e86SSaar Raz // is checked. If that is not satisfied, the conjunction is not 216fdf80e86SSaar Raz // satisfied. Otherwise, the conjunction is satisfied if and only if 217fdf80e86SSaar Raz // the second operand is satisfied. 218b3ce8728SUtkarsh Saxena // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 219b3ce8728SUtkarsh Saxena return LHSRes; 220fdf80e86SSaar Raz 221b330d800Scor3ntin ExprResult RHSRes = 222b330d800Scor3ntin calculateConstraintSatisfaction(S, RHS, Satisfaction, Evaluator); 223babdef27SErich Keane if (RHSRes.isInvalid()) 224babdef27SErich Keane return ExprError(); 225babdef27SErich Keane 226b2cd9db5STakuya Shimizu bool IsRHSSatisfied = Satisfaction.IsSatisfied; 227b2cd9db5STakuya Shimizu // Current implementation adds diagnostic information about the falsity 228b2cd9db5STakuya Shimizu // of each false atomic constraint expression when it evaluates them. 229b2cd9db5STakuya Shimizu // When the evaluation results to `false || true`, the information 230b2cd9db5STakuya Shimizu // generated during the evaluation of left-hand side is meaningless 231b2cd9db5STakuya Shimizu // because the whole expression evaluates to true. 232b2cd9db5STakuya Shimizu // The following code removes the irrelevant diagnostic information. 233b2cd9db5STakuya Shimizu // FIXME: We should probably delay the addition of diagnostic information 234b2cd9db5STakuya Shimizu // until we know the entire expression is false. 235b330d800Scor3ntin if (Op == clang::OO_PipePipe && IsRHSSatisfied) { 236b330d800Scor3ntin auto EffectiveDetailEnd = Satisfaction.Details.begin(); 237b330d800Scor3ntin std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex); 238b330d800Scor3ntin Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end()); 239b330d800Scor3ntin } 240b330d800Scor3ntin 241b330d800Scor3ntin if (!LHSRes.isUsable() || !RHSRes.isUsable()) 242b330d800Scor3ntin return ExprEmpty(); 243b330d800Scor3ntin 244b330d800Scor3ntin return BinaryOperator::Create(S.Context, LHSRes.get(), RHSRes.get(), 245b330d800Scor3ntin BinaryOperator::getOverloadedOpcode(Op), 246b330d800Scor3ntin S.Context.BoolTy, VK_PRValue, OK_Ordinary, 247b330d800Scor3ntin LHS->getBeginLoc(), FPOptionsOverride{}); 248b330d800Scor3ntin } 249b330d800Scor3ntin 250b330d800Scor3ntin template <typename ConstraintEvaluator> 251b330d800Scor3ntin static ExprResult 252b330d800Scor3ntin calculateConstraintSatisfaction(Sema &S, const CXXFoldExpr *FE, 253b330d800Scor3ntin ConstraintSatisfaction &Satisfaction, 254b330d800Scor3ntin const ConstraintEvaluator &Evaluator) { 255b330d800Scor3ntin bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd; 256b330d800Scor3ntin size_t EffectiveDetailEndIndex = Satisfaction.Details.size(); 257b330d800Scor3ntin 258b330d800Scor3ntin ExprResult Out; 259b330d800Scor3ntin if (FE->isLeftFold() && FE->getInit()) { 260b330d800Scor3ntin Out = calculateConstraintSatisfaction(S, FE->getInit(), Satisfaction, 261b330d800Scor3ntin Evaluator); 262b330d800Scor3ntin if (Out.isInvalid()) 263b330d800Scor3ntin return ExprError(); 264b330d800Scor3ntin 265b330d800Scor3ntin // If the first clause of a conjunction is not satisfied, 266b330d800Scor3ntin // or if the first clause of a disjection is satisfied, 267b330d800Scor3ntin // we have established satisfaction of the whole constraint 268b330d800Scor3ntin // and we should not continue further. 269b330d800Scor3ntin if (Conjunction != Satisfaction.IsSatisfied) 270b330d800Scor3ntin return Out; 271b330d800Scor3ntin } 272b330d800Scor3ntin std::optional<unsigned> NumExpansions = 273b330d800Scor3ntin Evaluator.EvaluateFoldExpandedConstraintSize(FE); 274b330d800Scor3ntin if (!NumExpansions) 275b330d800Scor3ntin return ExprError(); 276b330d800Scor3ntin for (unsigned I = 0; I < *NumExpansions; I++) { 277b330d800Scor3ntin Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I); 278b330d800Scor3ntin ExprResult Res = calculateConstraintSatisfaction(S, FE->getPattern(), 279b330d800Scor3ntin Satisfaction, Evaluator); 280b330d800Scor3ntin if (Res.isInvalid()) 281b330d800Scor3ntin return ExprError(); 282b330d800Scor3ntin bool IsRHSSatisfied = Satisfaction.IsSatisfied; 283b330d800Scor3ntin if (!Conjunction && IsRHSSatisfied) { 2844af62db0STakuya Shimizu auto EffectiveDetailEnd = Satisfaction.Details.begin(); 2854af62db0STakuya Shimizu std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex); 286b2cd9db5STakuya Shimizu Satisfaction.Details.erase(EffectiveDetailEnd, 287b2cd9db5STakuya Shimizu Satisfaction.Details.end()); 2884af62db0STakuya Shimizu } 289b330d800Scor3ntin if (Out.isUnset()) 290b330d800Scor3ntin Out = Res; 291b330d800Scor3ntin else if (!Res.isUnset()) { 292b330d800Scor3ntin Out = BinaryOperator::Create( 293b330d800Scor3ntin S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy, 294b330d800Scor3ntin VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{}); 29524489273Scor3ntin } 296b330d800Scor3ntin if (Conjunction != IsRHSSatisfied) 297b330d800Scor3ntin return Out; 298b330d800Scor3ntin } 299b330d800Scor3ntin 300b330d800Scor3ntin if (FE->isRightFold() && FE->getInit()) { 301b330d800Scor3ntin ExprResult Res = calculateConstraintSatisfaction(S, FE->getInit(), 302b330d800Scor3ntin Satisfaction, Evaluator); 303b330d800Scor3ntin if (Out.isInvalid()) 304b330d800Scor3ntin return ExprError(); 305b330d800Scor3ntin 306b330d800Scor3ntin if (Out.isUnset()) 307b330d800Scor3ntin Out = Res; 308b330d800Scor3ntin else if (!Res.isUnset()) { 309b330d800Scor3ntin Out = BinaryOperator::Create( 310b330d800Scor3ntin S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy, 311b330d800Scor3ntin VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{}); 312b330d800Scor3ntin } 313b330d800Scor3ntin } 314b330d800Scor3ntin 315b330d800Scor3ntin if (Out.isUnset()) { 316b330d800Scor3ntin Satisfaction.IsSatisfied = Conjunction; 317b330d800Scor3ntin Out = S.BuildEmptyCXXFoldExpr(FE->getBeginLoc(), FE->getOperator()); 318b330d800Scor3ntin } 319b330d800Scor3ntin return Out; 320b330d800Scor3ntin } 321b330d800Scor3ntin 322b330d800Scor3ntin template <typename ConstraintEvaluator> 323b330d800Scor3ntin static ExprResult 324b330d800Scor3ntin calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, 325b330d800Scor3ntin ConstraintSatisfaction &Satisfaction, 326b330d800Scor3ntin const ConstraintEvaluator &Evaluator) { 327b330d800Scor3ntin ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); 328b330d800Scor3ntin 329b330d800Scor3ntin if (LogicalBinOp BO = ConstraintExpr) 330b330d800Scor3ntin return calculateConstraintSatisfaction( 331b330d800Scor3ntin S, BO.getLHS(), BO.getOp(), BO.getRHS(), Satisfaction, Evaluator); 332babdef27SErich Keane 333babdef27SErich Keane if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) { 334babdef27SErich Keane // These aren't evaluated, so we don't care about cleanups, so we can just 335babdef27SErich Keane // evaluate these as if the cleanups didn't exist. 336b330d800Scor3ntin return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction, 337b330d800Scor3ntin Evaluator); 338b330d800Scor3ntin } 339b330d800Scor3ntin 340b330d800Scor3ntin if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr); 341b330d800Scor3ntin FE && S.getLangOpts().CPlusPlus26 && 342b330d800Scor3ntin (FE->getOperator() == BinaryOperatorKind::BO_LAnd || 343b330d800Scor3ntin FE->getOperator() == BinaryOperatorKind::BO_LOr)) { 344b330d800Scor3ntin return calculateConstraintSatisfaction(S, FE, Satisfaction, Evaluator); 3456c29073eSRichard Smith } 346fdf80e86SSaar Raz 347fdf80e86SSaar Raz // An atomic constraint expression 348b330d800Scor3ntin ExprResult SubstitutedAtomicExpr = 349b330d800Scor3ntin Evaluator.EvaluateAtomicConstraint(ConstraintExpr); 350fdf80e86SSaar Raz 351fdf80e86SSaar Raz if (SubstitutedAtomicExpr.isInvalid()) 352babdef27SErich Keane return ExprError(); 353fdf80e86SSaar Raz 354fdf80e86SSaar Raz if (!SubstitutedAtomicExpr.isUsable()) 355fdf80e86SSaar Raz // Evaluator has decided satisfaction without yielding an expression. 356babdef27SErich Keane return ExprEmpty(); 3575d98ba60SSaar Raz 358684a7896SErich Keane // We don't have the ability to evaluate this, since it contains a 359684a7896SErich Keane // RecoveryExpr, so we want to fail overload resolution. Otherwise, 360684a7896SErich Keane // we'd potentially pick up a different overload, and cause confusing 361684a7896SErich Keane // diagnostics. SO, add a failure detail that will cause us to make this 362684a7896SErich Keane // overload set not viable. 363684a7896SErich Keane if (SubstitutedAtomicExpr.get()->containsErrors()) { 364684a7896SErich Keane Satisfaction.IsSatisfied = false; 365684a7896SErich Keane Satisfaction.ContainsErrors = true; 366684a7896SErich Keane 367684a7896SErich Keane PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error); 368684a7896SErich Keane SmallString<128> DiagString; 369684a7896SErich Keane DiagString = ": "; 370684a7896SErich Keane Msg.EmitToString(S.getDiagnostics(), DiagString); 371684a7896SErich Keane unsigned MessageSize = DiagString.size(); 372684a7896SErich Keane char *Mem = new (S.Context) char[MessageSize]; 373684a7896SErich Keane memcpy(Mem, DiagString.c_str(), MessageSize); 374684a7896SErich Keane Satisfaction.Details.emplace_back( 375684a7896SErich Keane new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 376684a7896SErich Keane SubstitutedAtomicExpr.get()->getBeginLoc(), 377684a7896SErich Keane StringRef(Mem, MessageSize)}); 378684a7896SErich Keane return SubstitutedAtomicExpr; 379684a7896SErich Keane } 380684a7896SErich Keane 3815d98ba60SSaar Raz EnterExpressionEvaluationContext ConstantEvaluated( 382fdf80e86SSaar Raz S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 38338839d08SVlad Tsyrklevich SmallVector<PartialDiagnosticAt, 2> EvaluationDiags; 38438839d08SVlad Tsyrklevich Expr::EvalResult EvalResult; 38538839d08SVlad Tsyrklevich EvalResult.Diag = &EvaluationDiags; 3862f8ac075SRichard Smith if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult, 3872f8ac075SRichard Smith S.Context) || 3882f8ac075SRichard Smith !EvaluationDiags.empty()) { 38938839d08SVlad Tsyrklevich // C++2a [temp.constr.atomic]p1 39038839d08SVlad Tsyrklevich // ...E shall be a constant expression of type bool. 391fdf80e86SSaar Raz S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(), 39238839d08SVlad Tsyrklevich diag::err_non_constant_constraint_expression) 393fdf80e86SSaar Raz << SubstitutedAtomicExpr.get()->getSourceRange(); 39438839d08SVlad Tsyrklevich for (const PartialDiagnosticAt &PDiag : EvaluationDiags) 395fdf80e86SSaar Raz S.Diag(PDiag.first, PDiag.second); 396babdef27SErich Keane return ExprError(); 397ffa214efSSaar Raz } 39838839d08SVlad Tsyrklevich 3992f8ac075SRichard Smith assert(EvalResult.Val.isInt() && 4002f8ac075SRichard Smith "evaluating bool expression didn't produce int"); 401fdf80e86SSaar Raz Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); 402fdf80e86SSaar Raz if (!Satisfaction.IsSatisfied) 403fb196495SYounan Zhang Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get()); 40438839d08SVlad Tsyrklevich 405babdef27SErich Keane return SubstitutedAtomicExpr; 406ffa214efSSaar Raz } 407fdf80e86SSaar Raz 4082cee2663SErich Keane static bool 40942667563SErich Keane DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, 41042667563SErich Keane const NamedDecl *Templ, const Expr *E, 4112cee2663SErich Keane const MultiLevelTemplateArgumentList &MLTAL) { 4122cee2663SErich Keane E->Profile(ID, S.Context, /*Canonical=*/true); 4132cee2663SErich Keane for (const auto &List : MLTAL) 4142cee2663SErich Keane for (const auto &TemplateArg : List.Args) 41500139ae1SMatheus Izvekov TemplateArg.Profile(ID, S.Context); 4162cee2663SErich Keane 4172cee2663SErich Keane // Note that we have to do this with our own collection, because there are 4182cee2663SErich Keane // times where a constraint-expression check can cause us to need to evaluate 4192cee2663SErich Keane // other constriants that are unrelated, such as when evaluating a recovery 4202cee2663SErich Keane // expression, or when trying to determine the constexpr-ness of special 4212cee2663SErich Keane // members. Otherwise we could just use the 4222cee2663SErich Keane // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function. 42342667563SErich Keane if (S.SatisfactionStackContains(Templ, ID)) { 4242cee2663SErich Keane S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self) 4252cee2663SErich Keane << const_cast<Expr *>(E) << E->getSourceRange(); 4262cee2663SErich Keane return true; 4272cee2663SErich Keane } 4282cee2663SErich Keane 4292cee2663SErich Keane return false; 4302cee2663SErich Keane } 4312cee2663SErich Keane 432babdef27SErich Keane static ExprResult calculateConstraintSatisfaction( 433b2590273SErich Keane Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc, 434b2590273SErich Keane const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr, 435b2590273SErich Keane ConstraintSatisfaction &Satisfaction) { 436b330d800Scor3ntin 437b330d800Scor3ntin struct ConstraintEvaluator { 438b330d800Scor3ntin Sema &S; 439b330d800Scor3ntin const NamedDecl *Template; 440b330d800Scor3ntin SourceLocation TemplateNameLoc; 441b330d800Scor3ntin const MultiLevelTemplateArgumentList &MLTAL; 442b330d800Scor3ntin ConstraintSatisfaction &Satisfaction; 443b330d800Scor3ntin 444b330d800Scor3ntin ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const { 445fdf80e86SSaar Raz EnterExpressionEvaluationContext ConstantEvaluated( 446975740bfSErich Keane S, Sema::ExpressionEvaluationContext::ConstantEvaluated, 447975740bfSErich Keane Sema::ReuseLambdaContextDecl); 448fdf80e86SSaar Raz 449fdf80e86SSaar Raz // Atomic constraint - substitute arguments and check satisfaction. 450fdf80e86SSaar Raz ExprResult SubstitutedExpression; 451fdf80e86SSaar Raz { 452fdf80e86SSaar Raz TemplateDeductionInfo Info(TemplateNameLoc); 453b330d800Scor3ntin Sema::InstantiatingTemplate Inst( 454b330d800Scor3ntin S, AtomicExpr->getBeginLoc(), 455713562f5SSaar Raz Sema::InstantiatingTemplate::ConstraintSubstitution{}, 456713562f5SSaar Raz const_cast<NamedDecl *>(Template), Info, 457713562f5SSaar Raz AtomicExpr->getSourceRange()); 458fdf80e86SSaar Raz if (Inst.isInvalid()) 459fdf80e86SSaar Raz return ExprError(); 4602cee2663SErich Keane 4612cee2663SErich Keane llvm::FoldingSetNodeID ID; 46242667563SErich Keane if (Template && 46342667563SErich Keane DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) { 4642cee2663SErich Keane Satisfaction.IsSatisfied = false; 4652cee2663SErich Keane Satisfaction.ContainsErrors = true; 4662cee2663SErich Keane return ExprEmpty(); 4672cee2663SErich Keane } 4682cee2663SErich Keane 46942667563SErich Keane SatisfactionStackRAII StackRAII(S, Template, ID); 4702cee2663SErich Keane 471fdf80e86SSaar Raz // We do not want error diagnostics escaping here. 472fdf80e86SSaar Raz Sema::SFINAETrap Trap(S); 473babdef27SErich Keane SubstitutedExpression = 474babdef27SErich Keane S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL); 475b5d9f00bSErich Keane 476fdf80e86SSaar Raz if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) { 477fdf80e86SSaar Raz // C++2a [temp.constr.atomic]p1 478fdf80e86SSaar Raz // ...If substitution results in an invalid type or expression, the 479fdf80e86SSaar Raz // constraint is not satisfied. 480fdf80e86SSaar Raz if (!Trap.hasErrorOccurred()) 481bde305baSNico Weber // A non-SFINAE error has occurred as a result of this 482fdf80e86SSaar Raz // substitution. 483fdf80e86SSaar Raz return ExprError(); 484fdf80e86SSaar Raz 485fdf80e86SSaar Raz PartialDiagnosticAt SubstDiag{SourceLocation(), 486fdf80e86SSaar Raz PartialDiagnostic::NullDiagnostic()}; 487fdf80e86SSaar Raz Info.takeSFINAEDiagnostic(SubstDiag); 488fdf80e86SSaar Raz // FIXME: Concepts: This is an unfortunate consequence of there 489fdf80e86SSaar Raz // being no serialization code for PartialDiagnostics and the fact 490fdf80e86SSaar Raz // that serializing them would likely take a lot more storage than 491fdf80e86SSaar Raz // just storing them as strings. We would still like, in the 492fdf80e86SSaar Raz // future, to serialize the proper PartialDiagnostic as serializing 493fdf80e86SSaar Raz // it as a string defeats the purpose of the diagnostic mechanism. 494fdf80e86SSaar Raz SmallString<128> DiagString; 495fdf80e86SSaar Raz DiagString = ": "; 496fdf80e86SSaar Raz SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString); 497fdf80e86SSaar Raz unsigned MessageSize = DiagString.size(); 498fdf80e86SSaar Raz char *Mem = new (S.Context) char[MessageSize]; 499fdf80e86SSaar Raz memcpy(Mem, DiagString.c_str(), MessageSize); 500fdf80e86SSaar Raz Satisfaction.Details.emplace_back( 501fdf80e86SSaar Raz new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 502fdf80e86SSaar Raz SubstDiag.first, StringRef(Mem, MessageSize)}); 503fdf80e86SSaar Raz Satisfaction.IsSatisfied = false; 504fdf80e86SSaar Raz return ExprEmpty(); 505fdf80e86SSaar Raz } 506fdf80e86SSaar Raz } 507fdf80e86SSaar Raz 508fdf80e86SSaar Raz if (!S.CheckConstraintExpression(SubstitutedExpression.get())) 509fdf80e86SSaar Raz return ExprError(); 510fdf80e86SSaar Raz 511b5d9f00bSErich Keane // [temp.constr.atomic]p3: To determine if an atomic constraint is 512b5d9f00bSErich Keane // satisfied, the parameter mapping and template arguments are first 513b5d9f00bSErich Keane // substituted into its expression. If substitution results in an 514b5d9f00bSErich Keane // invalid type or expression, the constraint is not satisfied. 515b5d9f00bSErich Keane // Otherwise, the lvalue-to-rvalue conversion is performed if necessary, 516b5d9f00bSErich Keane // and E shall be a constant expression of type bool. 517b5d9f00bSErich Keane // 518b5d9f00bSErich Keane // Perform the L to R Value conversion if necessary. We do so for all 519b5d9f00bSErich Keane // non-PRValue categories, else we fail to extend the lifetime of 520b5d9f00bSErich Keane // temporaries, and that fails the constant expression check. 521b5d9f00bSErich Keane if (!SubstitutedExpression.get()->isPRValue()) 522b5d9f00bSErich Keane SubstitutedExpression = ImplicitCastExpr::Create( 523b5d9f00bSErich Keane S.Context, SubstitutedExpression.get()->getType(), 524b5d9f00bSErich Keane CK_LValueToRValue, SubstitutedExpression.get(), 525b5d9f00bSErich Keane /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride()); 526b5d9f00bSErich Keane 527fdf80e86SSaar Raz return SubstitutedExpression; 528b330d800Scor3ntin } 529b330d800Scor3ntin 530b330d800Scor3ntin std::optional<unsigned> 531b330d800Scor3ntin EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const { 532da380b26Scor3ntin 533da380b26Scor3ntin // We should ignore errors in the presence of packs of different size. 534da380b26Scor3ntin Sema::SFINAETrap Trap(S); 535da380b26Scor3ntin 536b330d800Scor3ntin Expr *Pattern = FE->getPattern(); 537b330d800Scor3ntin 538b330d800Scor3ntin SmallVector<UnexpandedParameterPack, 2> Unexpanded; 539b330d800Scor3ntin S.collectUnexpandedParameterPacks(Pattern, Unexpanded); 540b330d800Scor3ntin assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); 541b330d800Scor3ntin bool Expand = true; 542b330d800Scor3ntin bool RetainExpansion = false; 543b330d800Scor3ntin std::optional<unsigned> OrigNumExpansions = FE->getNumExpansions(), 544b330d800Scor3ntin NumExpansions = OrigNumExpansions; 545b330d800Scor3ntin if (S.CheckParameterPacksForExpansion( 546b330d800Scor3ntin FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, 547b330d800Scor3ntin MLTAL, Expand, RetainExpansion, NumExpansions) || 548b330d800Scor3ntin !Expand || RetainExpansion) 549b330d800Scor3ntin return std::nullopt; 550b330d800Scor3ntin 551b330d800Scor3ntin if (NumExpansions && S.getLangOpts().BracketDepth < NumExpansions) { 552b330d800Scor3ntin S.Diag(FE->getEllipsisLoc(), 553b330d800Scor3ntin clang::diag::err_fold_expression_limit_exceeded) 554b330d800Scor3ntin << *NumExpansions << S.getLangOpts().BracketDepth 555b330d800Scor3ntin << FE->getSourceRange(); 556b330d800Scor3ntin S.Diag(FE->getEllipsisLoc(), diag::note_bracket_depth); 557b330d800Scor3ntin return std::nullopt; 558b330d800Scor3ntin } 559b330d800Scor3ntin return NumExpansions; 560b330d800Scor3ntin } 561b330d800Scor3ntin }; 562b330d800Scor3ntin 563b330d800Scor3ntin return calculateConstraintSatisfaction( 564b330d800Scor3ntin S, ConstraintExpr, Satisfaction, 565b330d800Scor3ntin ConstraintEvaluator{S, Template, TemplateNameLoc, MLTAL, Satisfaction}); 566fdf80e86SSaar Raz } 567fdf80e86SSaar Raz 568b2590273SErich Keane static bool CheckConstraintSatisfaction( 569b2590273SErich Keane Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 570babdef27SErich Keane llvm::SmallVectorImpl<Expr *> &Converted, 571b2590273SErich Keane const MultiLevelTemplateArgumentList &TemplateArgsLists, 572b2590273SErich Keane SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { 573fdf80e86SSaar Raz if (ConstraintExprs.empty()) { 574fdf80e86SSaar Raz Satisfaction.IsSatisfied = true; 575fdf80e86SSaar Raz return false; 576fdf80e86SSaar Raz } 577fdf80e86SSaar Raz 578b2590273SErich Keane if (TemplateArgsLists.isAnyArgInstantiationDependent()) { 579fdf80e86SSaar Raz // No need to check satisfaction for dependent constraint expressions. 580fdf80e86SSaar Raz Satisfaction.IsSatisfied = true; 581fdf80e86SSaar Raz return false; 582fdf80e86SSaar Raz } 583fdf80e86SSaar Raz 584b2590273SErich Keane ArrayRef<TemplateArgument> TemplateArgs = 585b2590273SErich Keane TemplateArgsLists.getNumSubstitutedLevels() > 0 58644ab3805SKrystian Stasiowski ? TemplateArgsLists.getOutermost() 587b2590273SErich Keane : ArrayRef<TemplateArgument>{}; 588258c3aeeSErich Keane Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), 589713562f5SSaar Raz Sema::InstantiatingTemplate::ConstraintsCheck{}, 590713562f5SSaar Raz const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); 591fdf80e86SSaar Raz if (Inst.isInvalid()) 592fdf80e86SSaar Raz return true; 593fdf80e86SSaar Raz 594258c3aeeSErich Keane for (const Expr *ConstraintExpr : ConstraintExprs) { 595babdef27SErich Keane ExprResult Res = calculateConstraintSatisfaction( 596babdef27SErich Keane S, Template, TemplateIDRange.getBegin(), TemplateArgsLists, 597babdef27SErich Keane ConstraintExpr, Satisfaction); 598babdef27SErich Keane if (Res.isInvalid()) 599258c3aeeSErich Keane return true; 600babdef27SErich Keane 601babdef27SErich Keane Converted.push_back(Res.get()); 602babdef27SErich Keane if (!Satisfaction.IsSatisfied) { 603babdef27SErich Keane // Backfill the 'converted' list with nulls so we can keep the Converted 604babdef27SErich Keane // and unconverted lists in sync. 605babdef27SErich Keane Converted.append(ConstraintExprs.size() - Converted.size(), nullptr); 606fdf80e86SSaar Raz // [temp.constr.op] p2 607fdf80e86SSaar Raz // [...] To determine if a conjunction is satisfied, the satisfaction 608fdf80e86SSaar Raz // of the first operand is checked. If that is not satisfied, the 609fdf80e86SSaar Raz // conjunction is not satisfied. [...] 610fdf80e86SSaar Raz return false; 611fdf80e86SSaar Raz } 612babdef27SErich Keane } 613fdf80e86SSaar Raz return false; 614fdf80e86SSaar Raz } 615fdf80e86SSaar Raz 616b933d37cSSaar Raz bool Sema::CheckConstraintSatisfaction( 617713562f5SSaar Raz const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 618babdef27SErich Keane llvm::SmallVectorImpl<Expr *> &ConvertedConstraints, 619b2590273SErich Keane const MultiLevelTemplateArgumentList &TemplateArgsLists, 620b2590273SErich Keane SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) { 621b933d37cSSaar Raz if (ConstraintExprs.empty()) { 622b933d37cSSaar Raz OutSatisfaction.IsSatisfied = true; 623b933d37cSSaar Raz return false; 624fdf80e86SSaar Raz } 625e13c28ecSIlya Biryukov if (!Template) { 626babdef27SErich Keane return ::CheckConstraintSatisfaction( 627babdef27SErich Keane *this, nullptr, ConstraintExprs, ConvertedConstraints, 628babdef27SErich Keane TemplateArgsLists, TemplateIDRange, OutSatisfaction); 629726d7b07SIlya Biryukov } 630440fffadSYounan Zhang // Invalid templates could make their way here. Substituting them could result 631440fffadSYounan Zhang // in dependent expressions. 632440fffadSYounan Zhang if (Template->isInvalidDecl()) { 633440fffadSYounan Zhang OutSatisfaction.IsSatisfied = false; 634440fffadSYounan Zhang return true; 635440fffadSYounan Zhang } 636b2590273SErich Keane 637b2590273SErich Keane // A list of the template argument list flattened in a predictible manner for 638b2590273SErich Keane // the purposes of caching. The ConstraintSatisfaction type is in AST so it 639b2590273SErich Keane // has no access to the MultiLevelTemplateArgumentList, so this has to happen 640b2590273SErich Keane // here. 641b2590273SErich Keane llvm::SmallVector<TemplateArgument, 4> FlattenedArgs; 642bcd9ba2bSMatheus Izvekov for (auto List : TemplateArgsLists) 64300139ae1SMatheus Izvekov FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(), 64400139ae1SMatheus Izvekov List.Args.end()); 645b2590273SErich Keane 646726d7b07SIlya Biryukov llvm::FoldingSetNodeID ID; 647b2590273SErich Keane ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs); 648726d7b07SIlya Biryukov void *InsertPos; 649726d7b07SIlya Biryukov if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 650726d7b07SIlya Biryukov OutSatisfaction = *Cached; 651b933d37cSSaar Raz return false; 652b933d37cSSaar Raz } 653b9a77b56SErich Keane 654726d7b07SIlya Biryukov auto Satisfaction = 655b2590273SErich Keane std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs); 656713562f5SSaar Raz if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, 657babdef27SErich Keane ConvertedConstraints, TemplateArgsLists, 658babdef27SErich Keane TemplateIDRange, *Satisfaction)) { 6592cee2663SErich Keane OutSatisfaction = *Satisfaction; 660b933d37cSSaar Raz return true; 661fdf80e86SSaar Raz } 662b9a77b56SErich Keane 663b9a77b56SErich Keane if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 664b9a77b56SErich Keane // The evaluation of this constraint resulted in us trying to re-evaluate it 665b9a77b56SErich Keane // recursively. This isn't really possible, except we try to form a 666b9a77b56SErich Keane // RecoveryExpr as a part of the evaluation. If this is the case, just 667b9a77b56SErich Keane // return the 'cached' version (which will have the same result), and save 668b9a77b56SErich Keane // ourselves the extra-insert. If it ever becomes possible to legitimately 669b9a77b56SErich Keane // recursively check a constraint, we should skip checking the 'inner' one 670b9a77b56SErich Keane // above, and replace the cached version with this one, as it would be more 671b9a77b56SErich Keane // specific. 672b9a77b56SErich Keane OutSatisfaction = *Cached; 673b9a77b56SErich Keane return false; 674b9a77b56SErich Keane } 675b9a77b56SErich Keane 676b9a77b56SErich Keane // Else we can simply add this satisfaction to the list. 677b933d37cSSaar Raz OutSatisfaction = *Satisfaction; 678726d7b07SIlya Biryukov // We cannot use InsertPos here because CheckConstraintSatisfaction might have 679726d7b07SIlya Biryukov // invalidated it. 680ad2263deSIlya Biryukov // Note that entries of SatisfactionCache are deleted in Sema's destructor. 681726d7b07SIlya Biryukov SatisfactionCache.InsertNode(Satisfaction.release()); 682b933d37cSSaar Raz return false; 683fdf80e86SSaar Raz } 684fdf80e86SSaar Raz 685fdf80e86SSaar Raz bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr, 686fdf80e86SSaar Raz ConstraintSatisfaction &Satisfaction) { 687b330d800Scor3ntin 688b330d800Scor3ntin struct ConstraintEvaluator { 689b330d800Scor3ntin Sema &S; 690b330d800Scor3ntin ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const { 691b330d800Scor3ntin return S.PerformContextuallyConvertToBool(const_cast<Expr *>(AtomicExpr)); 692b330d800Scor3ntin } 693b330d800Scor3ntin 694b330d800Scor3ntin std::optional<unsigned> 695b330d800Scor3ntin EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const { 696b330d800Scor3ntin return 0; 697b330d800Scor3ntin } 698b330d800Scor3ntin }; 699b330d800Scor3ntin 700b330d800Scor3ntin return calculateConstraintSatisfaction(*this, ConstraintExpr, Satisfaction, 701b330d800Scor3ntin ConstraintEvaluator{*this}) 702babdef27SErich Keane .isInvalid(); 703babdef27SErich Keane } 704babdef27SErich Keane 70593d7002dSCorentin Jabot bool Sema::addInstantiatedCapturesToScope( 70693d7002dSCorentin Jabot FunctionDecl *Function, const FunctionDecl *PatternDecl, 70793d7002dSCorentin Jabot LocalInstantiationScope &Scope, 70893d7002dSCorentin Jabot const MultiLevelTemplateArgumentList &TemplateArgs) { 70993d7002dSCorentin Jabot const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent(); 71093d7002dSCorentin Jabot const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent(); 71193d7002dSCorentin Jabot 71293d7002dSCorentin Jabot unsigned Instantiated = 0; 71393d7002dSCorentin Jabot 71493d7002dSCorentin Jabot auto AddSingleCapture = [&](const ValueDecl *CapturedPattern, 71593d7002dSCorentin Jabot unsigned Index) { 71693d7002dSCorentin Jabot ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar(); 71752126dc7SYupei Liu assert(CapturedVar->isInitCapture()); 71893d7002dSCorentin Jabot Scope.InstantiatedLocal(CapturedPattern, CapturedVar); 71993d7002dSCorentin Jabot }; 72093d7002dSCorentin Jabot 72193d7002dSCorentin Jabot for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) { 72293d7002dSCorentin Jabot if (!CapturePattern.capturesVariable()) { 72393d7002dSCorentin Jabot Instantiated++; 72493d7002dSCorentin Jabot continue; 72593d7002dSCorentin Jabot } 72652126dc7SYupei Liu ValueDecl *CapturedPattern = CapturePattern.getCapturedVar(); 72752126dc7SYupei Liu 72852126dc7SYupei Liu if (!CapturedPattern->isInitCapture()) { 7295064c4c4SYounan Zhang Instantiated++; 73052126dc7SYupei Liu continue; 73152126dc7SYupei Liu } 73252126dc7SYupei Liu 73393d7002dSCorentin Jabot if (!CapturedPattern->isParameterPack()) { 73493d7002dSCorentin Jabot AddSingleCapture(CapturedPattern, Instantiated++); 73593d7002dSCorentin Jabot } else { 73693d7002dSCorentin Jabot Scope.MakeInstantiatedLocalArgPack(CapturedPattern); 73752126dc7SYupei Liu SmallVector<UnexpandedParameterPack, 2> Unexpanded; 73852126dc7SYupei Liu SemaRef.collectUnexpandedParameterPacks( 73952126dc7SYupei Liu dyn_cast<VarDecl>(CapturedPattern)->getInit(), Unexpanded); 74052126dc7SYupei Liu auto NumArgumentsInExpansion = 74152126dc7SYupei Liu getNumArgumentsInExpansionFromUnexpanded(Unexpanded, TemplateArgs); 74293d7002dSCorentin Jabot if (!NumArgumentsInExpansion) 74393d7002dSCorentin Jabot continue; 74493d7002dSCorentin Jabot for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) 74593d7002dSCorentin Jabot AddSingleCapture(CapturedPattern, Instantiated++); 74693d7002dSCorentin Jabot } 74793d7002dSCorentin Jabot } 74893d7002dSCorentin Jabot return false; 74993d7002dSCorentin Jabot } 75093d7002dSCorentin Jabot 751babdef27SErich Keane bool Sema::SetupConstraintScope( 7526ad0788cSKazu Hirata FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 7535d98d882SYounan Zhang const MultiLevelTemplateArgumentList &MLTAL, 7545d98d882SYounan Zhang LocalInstantiationScope &Scope) { 755f07e5162SYounan Zhang assert(!isLambdaCallOperator(FD) && 756f07e5162SYounan Zhang "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda " 757f07e5162SYounan Zhang "instantiations"); 758babdef27SErich Keane if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { 759babdef27SErich Keane FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); 760babdef27SErich Keane InstantiatingTemplate Inst( 761babdef27SErich Keane *this, FD->getPointOfInstantiation(), 762babdef27SErich Keane Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate, 763babdef27SErich Keane TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 764babdef27SErich Keane SourceRange()); 765babdef27SErich Keane if (Inst.isInvalid()) 766babdef27SErich Keane return true; 767babdef27SErich Keane 768babdef27SErich Keane // addInstantiatedParametersToScope creates a map of 'uninstantiated' to 769babdef27SErich Keane // 'instantiated' parameters and adds it to the context. For the case where 770babdef27SErich Keane // this function is a template being instantiated NOW, we also need to add 771babdef27SErich Keane // the list of current template arguments to the list so that they also can 772babdef27SErich Keane // be picked out of the map. 773babdef27SErich Keane if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) { 774326feaafSMatheus Izvekov MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(), 775326feaafSMatheus Izvekov /*Final=*/false); 776babdef27SErich Keane if (addInstantiatedParametersToScope( 777babdef27SErich Keane FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs)) 778babdef27SErich Keane return true; 779babdef27SErich Keane } 780babdef27SErich Keane 781babdef27SErich Keane // If this is a member function, make sure we get the parameters that 782babdef27SErich Keane // reference the original primary template. 783843cc474SYounan Zhang if (FunctionTemplateDecl *FromMemTempl = 784843cc474SYounan Zhang PrimaryTemplate->getInstantiatedFromMemberTemplate()) { 785babdef27SErich Keane if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(), 786babdef27SErich Keane Scope, MLTAL)) 787babdef27SErich Keane return true; 788babdef27SErich Keane } 789babdef27SErich Keane 790babdef27SErich Keane return false; 791babdef27SErich Keane } 792babdef27SErich Keane 793babdef27SErich Keane if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || 794babdef27SErich Keane FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) { 795babdef27SErich Keane FunctionDecl *InstantiatedFrom = 796babdef27SErich Keane FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization 797babdef27SErich Keane ? FD->getInstantiatedFromMemberFunction() 798babdef27SErich Keane : FD->getInstantiatedFromDecl(); 799babdef27SErich Keane 800babdef27SErich Keane InstantiatingTemplate Inst( 801babdef27SErich Keane *this, FD->getPointOfInstantiation(), 802babdef27SErich Keane Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom, 803babdef27SErich Keane TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 804babdef27SErich Keane SourceRange()); 805babdef27SErich Keane if (Inst.isInvalid()) 806babdef27SErich Keane return true; 807babdef27SErich Keane 808babdef27SErich Keane // Case where this was not a template, but instantiated as a 809babdef27SErich Keane // child-function. 810babdef27SErich Keane if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL)) 811babdef27SErich Keane return true; 812babdef27SErich Keane } 813babdef27SErich Keane 814babdef27SErich Keane return false; 815babdef27SErich Keane } 816babdef27SErich Keane 817babdef27SErich Keane // This function collects all of the template arguments for the purposes of 818babdef27SErich Keane // constraint-instantiation and checking. 8196ad0788cSKazu Hirata std::optional<MultiLevelTemplateArgumentList> 820babdef27SErich Keane Sema::SetupConstraintCheckingTemplateArgumentsAndScope( 8216ad0788cSKazu Hirata FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 822babdef27SErich Keane LocalInstantiationScope &Scope) { 823babdef27SErich Keane MultiLevelTemplateArgumentList MLTAL; 824babdef27SErich Keane 825babdef27SErich Keane // Collect the list of template arguments relative to the 'primary' template. 826babdef27SErich Keane // We need the entire list, since the constraint is completely uninstantiated 827babdef27SErich Keane // at this point. 8284739a97fSKrystian Stasiowski MLTAL = 8294739a97fSKrystian Stasiowski getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), 8304739a97fSKrystian Stasiowski /*Final=*/false, /*Innermost=*/std::nullopt, 831939a3d22SErich Keane /*RelativeToPrimary=*/true, 83244ab3805SKrystian Stasiowski /*Pattern=*/nullptr, 833939a3d22SErich Keane /*ForConstraintInstantiation=*/true); 834f07e5162SYounan Zhang // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII. 835f07e5162SYounan Zhang if (isLambdaCallOperator(FD)) 836f07e5162SYounan Zhang return MLTAL; 837babdef27SErich Keane if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) 8388595f2e5SKazu Hirata return std::nullopt; 839babdef27SErich Keane 840babdef27SErich Keane return MLTAL; 841fdf80e86SSaar Raz } 842fdf80e86SSaar Raz 843713562f5SSaar Raz bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, 844713562f5SSaar Raz ConstraintSatisfaction &Satisfaction, 845babdef27SErich Keane SourceLocation UsageLoc, 846babdef27SErich Keane bool ForOverloadResolution) { 847babdef27SErich Keane // Don't check constraints if the function is dependent. Also don't check if 848babdef27SErich Keane // this is a function template specialization, as the call to 8493972ed57SYounan Zhang // CheckinstantiatedFunctionTemplateConstraints after this will check it 850babdef27SErich Keane // better. 851babdef27SErich Keane if (FD->isDependentContext() || 852babdef27SErich Keane FD->getTemplatedKind() == 853babdef27SErich Keane FunctionDecl::TK_FunctionTemplateSpecialization) { 854a424ef99SSaar Raz Satisfaction.IsSatisfied = true; 855a424ef99SSaar Raz return false; 856a424ef99SSaar Raz } 857babdef27SErich Keane 858f9caa123SCorentin Jabot // A lambda conversion operator has the same constraints as the call operator 859f9caa123SCorentin Jabot // and constraints checking relies on whether we are in a lambda call operator 860f9caa123SCorentin Jabot // (and may refer to its parameters), so check the call operator instead. 8613e69e5a1SYounan Zhang // Note that the declarations outside of the lambda should also be 8623e69e5a1SYounan Zhang // considered. Turning on the 'ForOverloadResolution' flag results in the 8633e69e5a1SYounan Zhang // LocalInstantiationScope not looking into its parents, but we can still 8643e69e5a1SYounan Zhang // access Decls from the parents while building a lambda RAII scope later. 865f9caa123SCorentin Jabot if (const auto *MD = dyn_cast<CXXConversionDecl>(FD); 866f9caa123SCorentin Jabot MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD))) 867f9caa123SCorentin Jabot return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(), 868f9caa123SCorentin Jabot Satisfaction, UsageLoc, 8693e69e5a1SYounan Zhang /*ShouldAddDeclsFromParentScope=*/true); 870f9caa123SCorentin Jabot 8716b0b306eSErich Keane DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD); 8726b0b306eSErich Keane 8736b0b306eSErich Keane while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) { 8746b0b306eSErich Keane if (isLambdaCallOperator(CtxToSave)) 8756b0b306eSErich Keane CtxToSave = CtxToSave->getParent()->getParent(); 8766b0b306eSErich Keane else 8776b0b306eSErich Keane CtxToSave = CtxToSave->getNonTransparentContext(); 8786b0b306eSErich Keane } 8796b0b306eSErich Keane 8806b0b306eSErich Keane ContextRAII SavedContext{*this, CtxToSave}; 881548d67a0SSheng LocalInstantiationScope Scope(*this, !ForOverloadResolution); 8826ad0788cSKazu Hirata std::optional<MultiLevelTemplateArgumentList> MLTAL = 883babdef27SErich Keane SetupConstraintCheckingTemplateArgumentsAndScope( 884babdef27SErich Keane const_cast<FunctionDecl *>(FD), {}, Scope); 885babdef27SErich Keane 886a726be38SErich Keane if (!MLTAL) 887a726be38SErich Keane return true; 888a726be38SErich Keane 8896c232441SSaar Raz Qualifiers ThisQuals; 8906c232441SSaar Raz CXXRecordDecl *Record = nullptr; 8916c232441SSaar Raz if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { 8926c232441SSaar Raz ThisQuals = Method->getMethodQualifiers(); 8936c232441SSaar Raz Record = const_cast<CXXRecordDecl *>(Method->getParent()); 8946c232441SSaar Raz } 8956c232441SSaar Raz CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 896158f4f30SCorentin Jabot 8973ed9e9e3SCorentin Jabot LambdaScopeForCallOperatorInstantiationRAII LambdaScope( 898548d67a0SSheng *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope, 899548d67a0SSheng ForOverloadResolution); 900158f4f30SCorentin Jabot 901aeee4ebdSRichard Smith return CheckConstraintSatisfaction( 902aeee4ebdSRichard Smith FD, {FD->getTrailingRequiresClause()}, *MLTAL, 903713562f5SSaar Raz SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), 904aeee4ebdSRichard Smith Satisfaction); 905babdef27SErich Keane } 906babdef27SErich Keane 907babdef27SErich Keane 908babdef27SErich Keane // Figure out the to-translation-unit depth for this function declaration for 909babdef27SErich Keane // the purpose of seeing if they differ by constraints. This isn't the same as 910babdef27SErich Keane // getTemplateDepth, because it includes already instantiated parents. 91144ab3805SKrystian Stasiowski static unsigned 91244ab3805SKrystian Stasiowski CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, 91344ab3805SKrystian Stasiowski bool SkipForSpecialization = false) { 914babdef27SErich Keane MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 9154739a97fSKrystian Stasiowski ND, ND->getLexicalDeclContext(), /*Final=*/false, 9164739a97fSKrystian Stasiowski /*Innermost=*/std::nullopt, 91798191d7cSErich Keane /*RelativeToPrimary=*/true, 91844ab3805SKrystian Stasiowski /*Pattern=*/nullptr, 91944ab3805SKrystian Stasiowski /*ForConstraintInstantiation=*/true, SkipForSpecialization); 9206db007a0SAlexander Shaposhnikov return MLTAL.getNumLevels(); 921babdef27SErich Keane } 922babdef27SErich Keane 923babdef27SErich Keane namespace { 924babdef27SErich Keane class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> { 925babdef27SErich Keane unsigned TemplateDepth = 0; 926babdef27SErich Keane public: 927babdef27SErich Keane using inherited = TreeTransform<AdjustConstraintDepth>; 928babdef27SErich Keane AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth) 929babdef27SErich Keane : inherited(SemaRef), TemplateDepth(TemplateDepth) {} 930326feaafSMatheus Izvekov 931326feaafSMatheus Izvekov using inherited::TransformTemplateTypeParmType; 932babdef27SErich Keane QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, 933326feaafSMatheus Izvekov TemplateTypeParmTypeLoc TL, bool) { 934babdef27SErich Keane const TemplateTypeParmType *T = TL.getTypePtr(); 935babdef27SErich Keane 936babdef27SErich Keane TemplateTypeParmDecl *NewTTPDecl = nullptr; 937babdef27SErich Keane if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) 938babdef27SErich Keane NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( 939babdef27SErich Keane TransformDecl(TL.getNameLoc(), OldTTPDecl)); 940babdef27SErich Keane 941babdef27SErich Keane QualType Result = getSema().Context.getTemplateTypeParmType( 942babdef27SErich Keane T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(), 943babdef27SErich Keane NewTTPDecl); 944babdef27SErich Keane TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); 945babdef27SErich Keane NewTL.setNameLoc(TL.getNameLoc()); 946babdef27SErich Keane return Result; 947babdef27SErich Keane } 948babdef27SErich Keane }; 949babdef27SErich Keane } // namespace 950babdef27SErich Keane 951f5efa749SIlya Biryukov static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( 952f5efa749SIlya Biryukov Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, 9536db007a0SAlexander Shaposhnikov const Expr *ConstrExpr) { 9546db007a0SAlexander Shaposhnikov MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 95598191d7cSErich Keane DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, 9564739a97fSKrystian Stasiowski /*Innermost=*/std::nullopt, 9576db007a0SAlexander Shaposhnikov /*RelativeToPrimary=*/true, 95844ab3805SKrystian Stasiowski /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, 95944ab3805SKrystian Stasiowski /*SkipForSpecialization*/ false); 96098191d7cSErich Keane 9616db007a0SAlexander Shaposhnikov if (MLTAL.getNumSubstitutedLevels() == 0) 9626db007a0SAlexander Shaposhnikov return ConstrExpr; 9636db007a0SAlexander Shaposhnikov 9646db007a0SAlexander Shaposhnikov Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false); 965fbd8f898SErich Keane 966fbd8f898SErich Keane Sema::InstantiatingTemplate Inst( 96798191d7cSErich Keane S, DeclInfo.getLocation(), 968fbd8f898SErich Keane Sema::InstantiatingTemplate::ConstraintNormalization{}, 96998191d7cSErich Keane const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{}); 970fbd8f898SErich Keane if (Inst.isInvalid()) 971fbd8f898SErich Keane return nullptr; 972fbd8f898SErich Keane 97304d20b17SYounan Zhang // Set up a dummy 'instantiation' scope in the case of reference to function 97404d20b17SYounan Zhang // parameters that the surrounding function hasn't been instantiated yet. Note 97504d20b17SYounan Zhang // this may happen while we're comparing two templates' constraint 97604d20b17SYounan Zhang // equivalence. 977463a4f15SYounan Zhang std::optional<LocalInstantiationScope> ScopeForParameters; 978463a4f15SYounan Zhang if (const NamedDecl *ND = DeclInfo.getDecl(); 979463a4f15SYounan Zhang ND && ND->isFunctionOrFunctionTemplate()) { 980227afac3SYounan Zhang ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true); 981463a4f15SYounan Zhang const FunctionDecl *FD = ND->getAsFunction(); 982e6974daaSYounan Zhang for (auto *PVD : FD->parameters()) { 983e6974daaSYounan Zhang if (!PVD->isParameterPack()) { 984463a4f15SYounan Zhang ScopeForParameters->InstantiatedLocal(PVD, PVD); 985e6974daaSYounan Zhang continue; 986e6974daaSYounan Zhang } 987e6974daaSYounan Zhang // This is hacky: we're mapping the parameter pack to a size-of-1 argument 988e6974daaSYounan Zhang // to avoid building SubstTemplateTypeParmPackTypes for 989e6974daaSYounan Zhang // PackExpansionTypes. The SubstTemplateTypeParmPackType node would 990e6974daaSYounan Zhang // otherwise reference the AssociatedDecl of the template arguments, which 991e6974daaSYounan Zhang // is, in this case, the template declaration. 992e6974daaSYounan Zhang // 993e6974daaSYounan Zhang // However, as we are in the process of comparing potential 994e6974daaSYounan Zhang // re-declarations, the canonical declaration is the declaration itself at 995e6974daaSYounan Zhang // this point. So if we didn't expand these packs, we would end up with an 996e6974daaSYounan Zhang // incorrect profile difference because we will be profiling the 997e6974daaSYounan Zhang // canonical types! 998e6974daaSYounan Zhang // 999e6974daaSYounan Zhang // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so 1000e6974daaSYounan Zhang // that we can eliminate the Scope in the cases where the declarations are 1001e6974daaSYounan Zhang // not necessarily instantiated. It would also benefit the noexcept 1002e6974daaSYounan Zhang // specifier comparison. 1003463a4f15SYounan Zhang ScopeForParameters->MakeInstantiatedLocalArgPack(PVD); 1004463a4f15SYounan Zhang ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD); 1005463a4f15SYounan Zhang } 1006e6974daaSYounan Zhang } 100704d20b17SYounan Zhang 10086db007a0SAlexander Shaposhnikov std::optional<Sema::CXXThisScopeRAII> ThisScope; 1009ab70ac60SYounan Zhang 1010ab70ac60SYounan Zhang // See TreeTransform::RebuildTemplateSpecializationType. A context scope is 1011ab70ac60SYounan Zhang // essential for having an injected class as the canonical type for a template 1012ab70ac60SYounan Zhang // specialization type at the rebuilding stage. This guarantees that, for 1013ab70ac60SYounan Zhang // out-of-line definitions, injected class name types and their equivalent 1014ab70ac60SYounan Zhang // template specializations can be profiled to the same value, which makes it 1015ab70ac60SYounan Zhang // possible that e.g. constraints involving C<Class<T>> and C<Class> are 1016ab70ac60SYounan Zhang // perceived identical. 1017ab70ac60SYounan Zhang std::optional<Sema::ContextRAII> ContextScope; 1018358165deSYounan Zhang const DeclContext *DC = [&] { 1019358165deSYounan Zhang if (!DeclInfo.getDecl()) 1020358165deSYounan Zhang return DeclInfo.getDeclContext(); 1021358165deSYounan Zhang return DeclInfo.getDecl()->getFriendObjectKind() 1022358165deSYounan Zhang ? DeclInfo.getLexicalDeclContext() 1023358165deSYounan Zhang : DeclInfo.getDeclContext(); 1024358165deSYounan Zhang }(); 1025358165deSYounan Zhang if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) { 10266db007a0SAlexander Shaposhnikov ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers()); 1027ab70ac60SYounan Zhang ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)), 1028ab70ac60SYounan Zhang /*NewThisContext=*/false); 1029ab70ac60SYounan Zhang } 1030*69d0c4c1SYounan Zhang EnterExpressionEvaluationContext UnevaluatedContext( 1031*69d0c4c1SYounan Zhang S, Sema::ExpressionEvaluationContext::Unevaluated, 1032*69d0c4c1SYounan Zhang Sema::ReuseLambdaContextDecl); 1033f5efa749SIlya Biryukov ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction( 1034f5efa749SIlya Biryukov const_cast<clang::Expr *>(ConstrExpr), MLTAL); 10356db007a0SAlexander Shaposhnikov if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable()) 10366db007a0SAlexander Shaposhnikov return nullptr; 10376db007a0SAlexander Shaposhnikov return SubstConstr.get(); 10386db007a0SAlexander Shaposhnikov } 10396db007a0SAlexander Shaposhnikov 1040babdef27SErich Keane bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, 1041babdef27SErich Keane const Expr *OldConstr, 104298191d7cSErich Keane const TemplateCompareNewDeclInfo &New, 1043babdef27SErich Keane const Expr *NewConstr) { 10446db007a0SAlexander Shaposhnikov if (OldConstr == NewConstr) 10456db007a0SAlexander Shaposhnikov return true; 1046122b9389SAlexander Shaposhnikov // C++ [temp.constr.decl]p4 104798191d7cSErich Keane if (Old && !New.isInvalid() && !New.ContainsDecl(Old) && 104898191d7cSErich Keane Old->getLexicalDeclContext() != New.getLexicalDeclContext()) { 10496db007a0SAlexander Shaposhnikov if (const Expr *SubstConstr = 1050f5efa749SIlya Biryukov SubstituteConstraintExpressionWithoutSatisfaction(*this, Old, 1051f5efa749SIlya Biryukov OldConstr)) 10526db007a0SAlexander Shaposhnikov OldConstr = SubstConstr; 10536db007a0SAlexander Shaposhnikov else 10546db007a0SAlexander Shaposhnikov return false; 10556db007a0SAlexander Shaposhnikov if (const Expr *SubstConstr = 1056f5efa749SIlya Biryukov SubstituteConstraintExpressionWithoutSatisfaction(*this, New, 1057f5efa749SIlya Biryukov NewConstr)) 10586db007a0SAlexander Shaposhnikov NewConstr = SubstConstr; 10596db007a0SAlexander Shaposhnikov else 10606db007a0SAlexander Shaposhnikov return false; 1061babdef27SErich Keane } 1062babdef27SErich Keane 1063babdef27SErich Keane llvm::FoldingSetNodeID ID1, ID2; 1064babdef27SErich Keane OldConstr->Profile(ID1, Context, /*Canonical=*/true); 1065babdef27SErich Keane NewConstr->Profile(ID2, Context, /*Canonical=*/true); 1066babdef27SErich Keane return ID1 == ID2; 1067babdef27SErich Keane } 1068babdef27SErich Keane 1069babdef27SErich Keane bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { 1070babdef27SErich Keane assert(FD->getFriendObjectKind() && "Must be a friend!"); 1071babdef27SErich Keane 1072babdef27SErich Keane // The logic for non-templates is handled in ASTContext::isSameEntity, so we 1073babdef27SErich Keane // don't have to bother checking 'DependsOnEnclosingTemplate' for a 1074babdef27SErich Keane // non-function-template. 107544ab3805SKrystian Stasiowski assert(FD->getDescribedFunctionTemplate() && 107644ab3805SKrystian Stasiowski "Non-function templates don't need to be checked"); 1077babdef27SErich Keane 1078babdef27SErich Keane SmallVector<const Expr *, 3> ACs; 107944ab3805SKrystian Stasiowski FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); 1080babdef27SErich Keane 108144ab3805SKrystian Stasiowski unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD); 1082babdef27SErich Keane for (const Expr *Constraint : ACs) 1083853df5e1SErich Keane if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth, 1084babdef27SErich Keane Constraint)) 1085babdef27SErich Keane return true; 1086babdef27SErich Keane 1087babdef27SErich Keane return false; 1088713562f5SSaar Raz } 1089713562f5SSaar Raz 1090fdf80e86SSaar Raz bool Sema::EnsureTemplateArgumentListConstraints( 1091b2590273SErich Keane TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists, 1092fdf80e86SSaar Raz SourceRange TemplateIDRange) { 1093fdf80e86SSaar Raz ConstraintSatisfaction Satisfaction; 1094fdf80e86SSaar Raz llvm::SmallVector<const Expr *, 3> AssociatedConstraints; 1095fdf80e86SSaar Raz TD->getAssociatedConstraints(AssociatedConstraints); 1096b2590273SErich Keane if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists, 1097fdf80e86SSaar Raz TemplateIDRange, Satisfaction)) 1098fdf80e86SSaar Raz return true; 1099fdf80e86SSaar Raz 1100fdf80e86SSaar Raz if (!Satisfaction.IsSatisfied) { 1101fdf80e86SSaar Raz SmallString<128> TemplateArgString; 1102fdf80e86SSaar Raz TemplateArgString = " "; 1103fdf80e86SSaar Raz TemplateArgString += getTemplateArgumentBindingsText( 1104b2590273SErich Keane TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(), 1105b2590273SErich Keane TemplateArgsLists.getInnermost().size()); 1106fdf80e86SSaar Raz 1107fdf80e86SSaar Raz Diag(TemplateIDRange.getBegin(), 1108fdf80e86SSaar Raz diag::err_template_arg_list_constraints_not_satisfied) 1109fdf80e86SSaar Raz << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD 1110fdf80e86SSaar Raz << TemplateArgString << TemplateIDRange; 1111fdf80e86SSaar Raz DiagnoseUnsatisfiedConstraint(Satisfaction); 1112fdf80e86SSaar Raz return true; 1113fdf80e86SSaar Raz } 1114fdf80e86SSaar Raz return false; 1115fdf80e86SSaar Raz } 1116fdf80e86SSaar Raz 11173972ed57SYounan Zhang bool Sema::CheckInstantiatedFunctionTemplateConstraints( 111894623fb1SErich Keane SourceLocation PointOfInstantiation, FunctionDecl *Decl, 111994623fb1SErich Keane ArrayRef<TemplateArgument> TemplateArgs, 112094623fb1SErich Keane ConstraintSatisfaction &Satisfaction) { 112194623fb1SErich Keane // In most cases we're not going to have constraints, so check for that first. 112294623fb1SErich Keane FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); 112394623fb1SErich Keane // Note - code synthesis context for the constraints check is created 112494623fb1SErich Keane // inside CheckConstraintsSatisfaction. 112594623fb1SErich Keane SmallVector<const Expr *, 3> TemplateAC; 112694623fb1SErich Keane Template->getAssociatedConstraints(TemplateAC); 112794623fb1SErich Keane if (TemplateAC.empty()) { 112894623fb1SErich Keane Satisfaction.IsSatisfied = true; 112994623fb1SErich Keane return false; 113094623fb1SErich Keane } 113194623fb1SErich Keane 113294623fb1SErich Keane // Enter the scope of this instantiation. We don't use 113394623fb1SErich Keane // PushDeclContext because we don't have a scope. 113494623fb1SErich Keane Sema::ContextRAII savedContext(*this, Decl); 113594623fb1SErich Keane LocalInstantiationScope Scope(*this); 113694623fb1SErich Keane 11376ad0788cSKazu Hirata std::optional<MultiLevelTemplateArgumentList> MLTAL = 1138babdef27SErich Keane SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs, 1139babdef27SErich Keane Scope); 1140babdef27SErich Keane 1141babdef27SErich Keane if (!MLTAL) 114294623fb1SErich Keane return true; 1143babdef27SErich Keane 114494623fb1SErich Keane Qualifiers ThisQuals; 114594623fb1SErich Keane CXXRecordDecl *Record = nullptr; 114694623fb1SErich Keane if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { 114794623fb1SErich Keane ThisQuals = Method->getMethodQualifiers(); 114894623fb1SErich Keane Record = Method->getParent(); 114994623fb1SErich Keane } 115098062d8fSCorentin Jabot 11513ed9e9e3SCorentin Jabot CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 11523ed9e9e3SCorentin Jabot LambdaScopeForCallOperatorInstantiationRAII LambdaScope( 11533ed9e9e3SCorentin Jabot *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope); 1154939a3d22SErich Keane 1155babdef27SErich Keane llvm::SmallVector<Expr *, 1> Converted; 1156babdef27SErich Keane return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL, 115794623fb1SErich Keane PointOfInstantiation, Satisfaction); 115894623fb1SErich Keane } 115994623fb1SErich Keane 1160a0f50d73SSaar Raz static void diagnoseUnsatisfiedRequirement(Sema &S, 1161a0f50d73SSaar Raz concepts::ExprRequirement *Req, 1162a0f50d73SSaar Raz bool First) { 1163a0f50d73SSaar Raz assert(!Req->isSatisfied() 1164a0f50d73SSaar Raz && "Diagnose() can only be used on an unsatisfied requirement"); 1165a0f50d73SSaar Raz switch (Req->getSatisfactionStatus()) { 1166a0f50d73SSaar Raz case concepts::ExprRequirement::SS_Dependent: 1167a0f50d73SSaar Raz llvm_unreachable("Diagnosing a dependent requirement"); 1168a0f50d73SSaar Raz break; 1169a0f50d73SSaar Raz case concepts::ExprRequirement::SS_ExprSubstitutionFailure: { 1170a0f50d73SSaar Raz auto *SubstDiag = Req->getExprSubstitutionDiagnostic(); 1171a0f50d73SSaar Raz if (!SubstDiag->DiagMessage.empty()) 1172a0f50d73SSaar Raz S.Diag(SubstDiag->DiagLoc, 1173a0f50d73SSaar Raz diag::note_expr_requirement_expr_substitution_error) 1174a0f50d73SSaar Raz << (int)First << SubstDiag->SubstitutedEntity 1175a0f50d73SSaar Raz << SubstDiag->DiagMessage; 1176a0f50d73SSaar Raz else 1177a0f50d73SSaar Raz S.Diag(SubstDiag->DiagLoc, 1178a0f50d73SSaar Raz diag::note_expr_requirement_expr_unknown_substitution_error) 1179a0f50d73SSaar Raz << (int)First << SubstDiag->SubstitutedEntity; 1180a0f50d73SSaar Raz break; 1181a0f50d73SSaar Raz } 1182a0f50d73SSaar Raz case concepts::ExprRequirement::SS_NoexceptNotMet: 1183a0f50d73SSaar Raz S.Diag(Req->getNoexceptLoc(), 1184a0f50d73SSaar Raz diag::note_expr_requirement_noexcept_not_met) 1185a0f50d73SSaar Raz << (int)First << Req->getExpr(); 1186a0f50d73SSaar Raz break; 1187a0f50d73SSaar Raz case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: { 1188a0f50d73SSaar Raz auto *SubstDiag = 1189a0f50d73SSaar Raz Req->getReturnTypeRequirement().getSubstitutionDiagnostic(); 1190a0f50d73SSaar Raz if (!SubstDiag->DiagMessage.empty()) 1191a0f50d73SSaar Raz S.Diag(SubstDiag->DiagLoc, 1192a0f50d73SSaar Raz diag::note_expr_requirement_type_requirement_substitution_error) 1193a0f50d73SSaar Raz << (int)First << SubstDiag->SubstitutedEntity 1194a0f50d73SSaar Raz << SubstDiag->DiagMessage; 1195a0f50d73SSaar Raz else 1196a0f50d73SSaar Raz S.Diag(SubstDiag->DiagLoc, 1197a0f50d73SSaar Raz diag::note_expr_requirement_type_requirement_unknown_substitution_error) 1198a0f50d73SSaar Raz << (int)First << SubstDiag->SubstitutedEntity; 1199a0f50d73SSaar Raz break; 1200a0f50d73SSaar Raz } 1201a0f50d73SSaar Raz case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { 1202a0f50d73SSaar Raz ConceptSpecializationExpr *ConstraintExpr = 1203a0f50d73SSaar Raz Req->getReturnTypeRequirementSubstitutedConstraintExpr(); 12043ad6dd5dSMatheus Izvekov if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 1205a0f50d73SSaar Raz // A simple case - expr type is the type being constrained and the concept 1206a0f50d73SSaar Raz // was not provided arguments. 12073ad6dd5dSMatheus Izvekov Expr *e = Req->getExpr(); 12083ad6dd5dSMatheus Izvekov S.Diag(e->getBeginLoc(), 1209a0f50d73SSaar Raz diag::note_expr_requirement_constraints_not_satisfied_simple) 12100c7cd4a8SMatheus Izvekov << (int)First << S.Context.getReferenceQualifiedType(e) 1211a0f50d73SSaar Raz << ConstraintExpr->getNamedConcept(); 12123ad6dd5dSMatheus Izvekov } else { 1213a0f50d73SSaar Raz S.Diag(ConstraintExpr->getBeginLoc(), 1214a0f50d73SSaar Raz diag::note_expr_requirement_constraints_not_satisfied) 1215a0f50d73SSaar Raz << (int)First << ConstraintExpr; 12163ad6dd5dSMatheus Izvekov } 1217a0f50d73SSaar Raz S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); 1218a0f50d73SSaar Raz break; 1219a0f50d73SSaar Raz } 1220a0f50d73SSaar Raz case concepts::ExprRequirement::SS_Satisfied: 1221a0f50d73SSaar Raz llvm_unreachable("We checked this above"); 1222a0f50d73SSaar Raz } 1223a0f50d73SSaar Raz } 1224a0f50d73SSaar Raz 1225a0f50d73SSaar Raz static void diagnoseUnsatisfiedRequirement(Sema &S, 1226a0f50d73SSaar Raz concepts::TypeRequirement *Req, 1227a0f50d73SSaar Raz bool First) { 1228a0f50d73SSaar Raz assert(!Req->isSatisfied() 1229a0f50d73SSaar Raz && "Diagnose() can only be used on an unsatisfied requirement"); 1230a0f50d73SSaar Raz switch (Req->getSatisfactionStatus()) { 1231a0f50d73SSaar Raz case concepts::TypeRequirement::SS_Dependent: 1232a0f50d73SSaar Raz llvm_unreachable("Diagnosing a dependent requirement"); 1233a0f50d73SSaar Raz return; 1234a0f50d73SSaar Raz case concepts::TypeRequirement::SS_SubstitutionFailure: { 1235a0f50d73SSaar Raz auto *SubstDiag = Req->getSubstitutionDiagnostic(); 1236a0f50d73SSaar Raz if (!SubstDiag->DiagMessage.empty()) 1237a0f50d73SSaar Raz S.Diag(SubstDiag->DiagLoc, 1238a0f50d73SSaar Raz diag::note_type_requirement_substitution_error) << (int)First 1239a0f50d73SSaar Raz << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage; 1240a0f50d73SSaar Raz else 1241a0f50d73SSaar Raz S.Diag(SubstDiag->DiagLoc, 1242a0f50d73SSaar Raz diag::note_type_requirement_unknown_substitution_error) 1243a0f50d73SSaar Raz << (int)First << SubstDiag->SubstitutedEntity; 1244a0f50d73SSaar Raz return; 1245a0f50d73SSaar Raz } 1246a0f50d73SSaar Raz default: 1247a0f50d73SSaar Raz llvm_unreachable("Unknown satisfaction status"); 1248a0f50d73SSaar Raz return; 1249a0f50d73SSaar Raz } 1250a0f50d73SSaar Raz } 1251b3ce8728SUtkarsh Saxena static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 1252b3ce8728SUtkarsh Saxena Expr *SubstExpr, 1253b3ce8728SUtkarsh Saxena bool First = true); 1254a0f50d73SSaar Raz 1255a0f50d73SSaar Raz static void diagnoseUnsatisfiedRequirement(Sema &S, 1256a0f50d73SSaar Raz concepts::NestedRequirement *Req, 1257a0f50d73SSaar Raz bool First) { 1258b3ce8728SUtkarsh Saxena using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; 1259fb196495SYounan Zhang for (auto &Record : Req->getConstraintSatisfaction()) { 1260fb196495SYounan Zhang if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>()) 1261b3ce8728SUtkarsh Saxena S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error) 1262fb196495SYounan Zhang << (int)First << Req->getInvalidConstraintEntity() 1263fb196495SYounan Zhang << SubstDiag->second; 1264a0f50d73SSaar Raz else 1265fb196495SYounan Zhang diagnoseWellFormedUnsatisfiedConstraintExpr(S, Record.dyn_cast<Expr *>(), 1266fb196495SYounan Zhang First); 1267b3ce8728SUtkarsh Saxena First = false; 1268a0f50d73SSaar Raz } 1269a0f50d73SSaar Raz } 1270a0f50d73SSaar Raz 1271fdf80e86SSaar Raz static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 1272fdf80e86SSaar Raz Expr *SubstExpr, 1273b3ce8728SUtkarsh Saxena bool First) { 1274fdf80e86SSaar Raz SubstExpr = SubstExpr->IgnoreParenImpCasts(); 1275fdf80e86SSaar Raz if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) { 1276fdf80e86SSaar Raz switch (BO->getOpcode()) { 1277fdf80e86SSaar Raz // These two cases will in practice only be reached when using fold 1278fdf80e86SSaar Raz // expressions with || and &&, since otherwise the || and && will have been 1279fdf80e86SSaar Raz // broken down into atomic constraints during satisfaction checking. 1280fdf80e86SSaar Raz case BO_LOr: 1281fdf80e86SSaar Raz // Or evaluated to false - meaning both RHS and LHS evaluated to false. 1282fdf80e86SSaar Raz diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 1283fdf80e86SSaar Raz diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 1284fdf80e86SSaar Raz /*First=*/false); 1285fdf80e86SSaar Raz return; 12862f8ac075SRichard Smith case BO_LAnd: { 12872f8ac075SRichard Smith bool LHSSatisfied = 12882f8ac075SRichard Smith BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 1289fdf80e86SSaar Raz if (LHSSatisfied) { 1290fdf80e86SSaar Raz // LHS is true, so RHS must be false. 1291fdf80e86SSaar Raz diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First); 1292fdf80e86SSaar Raz return; 1293fdf80e86SSaar Raz } 1294fdf80e86SSaar Raz // LHS is false 1295fdf80e86SSaar Raz diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 1296fdf80e86SSaar Raz 1297fdf80e86SSaar Raz // RHS might also be false 12982f8ac075SRichard Smith bool RHSSatisfied = 12992f8ac075SRichard Smith BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 1300fdf80e86SSaar Raz if (!RHSSatisfied) 1301fdf80e86SSaar Raz diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 1302fdf80e86SSaar Raz /*First=*/false); 1303fdf80e86SSaar Raz return; 13042f8ac075SRichard Smith } 1305fdf80e86SSaar Raz case BO_GE: 1306fdf80e86SSaar Raz case BO_LE: 1307fdf80e86SSaar Raz case BO_GT: 1308fdf80e86SSaar Raz case BO_LT: 1309fdf80e86SSaar Raz case BO_EQ: 1310fdf80e86SSaar Raz case BO_NE: 1311fdf80e86SSaar Raz if (BO->getLHS()->getType()->isIntegerType() && 1312fdf80e86SSaar Raz BO->getRHS()->getType()->isIntegerType()) { 1313fdf80e86SSaar Raz Expr::EvalResult SimplifiedLHS; 1314fdf80e86SSaar Raz Expr::EvalResult SimplifiedRHS; 13152f8ac075SRichard Smith BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context, 13162f8ac075SRichard Smith Expr::SE_NoSideEffects, 13172f8ac075SRichard Smith /*InConstantContext=*/true); 13182f8ac075SRichard Smith BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context, 13192f8ac075SRichard Smith Expr::SE_NoSideEffects, 13202f8ac075SRichard Smith /*InConstantContext=*/true); 1321fdf80e86SSaar Raz if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) { 1322fdf80e86SSaar Raz S.Diag(SubstExpr->getBeginLoc(), 1323fdf80e86SSaar Raz diag::note_atomic_constraint_evaluated_to_false_elaborated) 1324fdf80e86SSaar Raz << (int)First << SubstExpr 132561cdaf66SSimon Pilgrim << toString(SimplifiedLHS.Val.getInt(), 10) 1326fdf80e86SSaar Raz << BinaryOperator::getOpcodeStr(BO->getOpcode()) 132761cdaf66SSimon Pilgrim << toString(SimplifiedRHS.Val.getInt(), 10); 1328fdf80e86SSaar Raz return; 1329fdf80e86SSaar Raz } 1330fdf80e86SSaar Raz } 1331fdf80e86SSaar Raz break; 1332fdf80e86SSaar Raz 1333fdf80e86SSaar Raz default: 1334fdf80e86SSaar Raz break; 1335fdf80e86SSaar Raz } 1336fdf80e86SSaar Raz } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) { 1337fdf80e86SSaar Raz if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 1338fdf80e86SSaar Raz S.Diag( 1339fdf80e86SSaar Raz CSE->getSourceRange().getBegin(), 1340fdf80e86SSaar Raz diag:: 1341fdf80e86SSaar Raz note_single_arg_concept_specialization_constraint_evaluated_to_false) 1342fdf80e86SSaar Raz << (int)First 1343fdf80e86SSaar Raz << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument() 1344fdf80e86SSaar Raz << CSE->getNamedConcept(); 1345fdf80e86SSaar Raz } else { 1346fdf80e86SSaar Raz S.Diag(SubstExpr->getSourceRange().getBegin(), 1347fdf80e86SSaar Raz diag::note_concept_specialization_constraint_evaluated_to_false) 1348fdf80e86SSaar Raz << (int)First << CSE; 1349fdf80e86SSaar Raz } 1350fdf80e86SSaar Raz S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction()); 1351fdf80e86SSaar Raz return; 1352a0f50d73SSaar Raz } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) { 13539e0474fbSUtkarsh Saxena // FIXME: RequiresExpr should store dependent diagnostics. 1354a0f50d73SSaar Raz for (concepts::Requirement *Req : RE->getRequirements()) 1355a0f50d73SSaar Raz if (!Req->isDependent() && !Req->isSatisfied()) { 1356a0f50d73SSaar Raz if (auto *E = dyn_cast<concepts::ExprRequirement>(Req)) 1357a0f50d73SSaar Raz diagnoseUnsatisfiedRequirement(S, E, First); 1358a0f50d73SSaar Raz else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req)) 1359a0f50d73SSaar Raz diagnoseUnsatisfiedRequirement(S, T, First); 1360a0f50d73SSaar Raz else 1361a0f50d73SSaar Raz diagnoseUnsatisfiedRequirement( 1362a0f50d73SSaar Raz S, cast<concepts::NestedRequirement>(Req), First); 1363a0f50d73SSaar Raz break; 1364a0f50d73SSaar Raz } 1365a0f50d73SSaar Raz return; 1366a383b3ccSHaojian Wu } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr); 1367a383b3ccSHaojian Wu TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) { 1368a383b3ccSHaojian Wu assert(TTE->getNumArgs() == 2); 1369a383b3ccSHaojian Wu S.Diag(SubstExpr->getSourceRange().getBegin(), 1370a383b3ccSHaojian Wu diag::note_is_deducible_constraint_evaluated_to_false) 1371a383b3ccSHaojian Wu << TTE->getArg(0)->getType() << TTE->getArg(1)->getType(); 1372a383b3ccSHaojian Wu return; 1373fdf80e86SSaar Raz } 1374fdf80e86SSaar Raz 1375fdf80e86SSaar Raz S.Diag(SubstExpr->getSourceRange().getBegin(), 1376fdf80e86SSaar Raz diag::note_atomic_constraint_evaluated_to_false) 1377fdf80e86SSaar Raz << (int)First << SubstExpr; 1378fdf80e86SSaar Raz } 1379fdf80e86SSaar Raz 1380fdf80e86SSaar Raz template <typename SubstitutionDiagnostic> 1381fdf80e86SSaar Raz static void diagnoseUnsatisfiedConstraintExpr( 1382fb196495SYounan Zhang Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record, 1383fdf80e86SSaar Raz bool First = true) { 1384fdf80e86SSaar Raz if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) { 1385fdf80e86SSaar Raz S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed) 1386fdf80e86SSaar Raz << Diag->second; 1387fdf80e86SSaar Raz return; 1388fdf80e86SSaar Raz } 1389fdf80e86SSaar Raz 13901e3e199eSKazu Hirata diagnoseWellFormedUnsatisfiedConstraintExpr(S, cast<Expr *>(Record), First); 1391fdf80e86SSaar Raz } 1392fdf80e86SSaar Raz 1393a0f50d73SSaar Raz void 1394a0f50d73SSaar Raz Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, 1395a0f50d73SSaar Raz bool First) { 1396fdf80e86SSaar Raz assert(!Satisfaction.IsSatisfied && 1397fdf80e86SSaar Raz "Attempted to diagnose a satisfied constraint"); 1398fb196495SYounan Zhang for (auto &Record : Satisfaction.Details) { 1399fb196495SYounan Zhang diagnoseUnsatisfiedConstraintExpr(*this, Record, First); 1400fdf80e86SSaar Raz First = false; 1401fdf80e86SSaar Raz } 1402fdf80e86SSaar Raz } 1403fdf80e86SSaar Raz 1404fdf80e86SSaar Raz void Sema::DiagnoseUnsatisfiedConstraint( 1405a0f50d73SSaar Raz const ASTConstraintSatisfaction &Satisfaction, 1406a0f50d73SSaar Raz bool First) { 1407fdf80e86SSaar Raz assert(!Satisfaction.IsSatisfied && 1408fdf80e86SSaar Raz "Attempted to diagnose a satisfied constraint"); 1409fb196495SYounan Zhang for (auto &Record : Satisfaction) { 1410fb196495SYounan Zhang diagnoseUnsatisfiedConstraintExpr(*this, Record, First); 1411fdf80e86SSaar Raz First = false; 1412fdf80e86SSaar Raz } 1413fdf80e86SSaar Raz } 1414df061c3eSSaar Raz 1415b65b1f32SSaar Raz const NormalizedConstraint * 1416b65b1f32SSaar Raz Sema::getNormalizedAssociatedConstraints( 1417b65b1f32SSaar Raz NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) { 141872ac9071SChuanqi Xu // In case the ConstrainedDecl comes from modules, it is necessary to use 141972ac9071SChuanqi Xu // the canonical decl to avoid different atomic constraints with the 'same' 142072ac9071SChuanqi Xu // declarations. 142172ac9071SChuanqi Xu ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl()); 142272ac9071SChuanqi Xu 1423b65b1f32SSaar Raz auto CacheEntry = NormalizationCache.find(ConstrainedDecl); 1424b65b1f32SSaar Raz if (CacheEntry == NormalizationCache.end()) { 1425b65b1f32SSaar Raz auto Normalized = 1426b65b1f32SSaar Raz NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl, 1427b65b1f32SSaar Raz AssociatedConstraints); 1428b65b1f32SSaar Raz CacheEntry = 1429b65b1f32SSaar Raz NormalizationCache 1430b65b1f32SSaar Raz .try_emplace(ConstrainedDecl, 1431b65b1f32SSaar Raz Normalized 1432b65b1f32SSaar Raz ? new (Context) NormalizedConstraint( 1433b65b1f32SSaar Raz std::move(*Normalized)) 1434b65b1f32SSaar Raz : nullptr) 1435b65b1f32SSaar Raz .first; 1436df061c3eSSaar Raz } 1437b65b1f32SSaar Raz return CacheEntry->second; 1438df061c3eSSaar Raz } 1439df061c3eSSaar Raz 1440b330d800Scor3ntin const NormalizedConstraint *clang::getNormalizedAssociatedConstraints( 1441b330d800Scor3ntin Sema &S, NamedDecl *ConstrainedDecl, 1442b330d800Scor3ntin ArrayRef<const Expr *> AssociatedConstraints) { 1443b330d800Scor3ntin return S.getNormalizedAssociatedConstraints(ConstrainedDecl, 1444b330d800Scor3ntin AssociatedConstraints); 1445b330d800Scor3ntin } 1446b330d800Scor3ntin 1447babdef27SErich Keane static bool 1448babdef27SErich Keane substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1449babdef27SErich Keane ConceptDecl *Concept, 1450babdef27SErich Keane const MultiLevelTemplateArgumentList &MLTAL, 1451df061c3eSSaar Raz const ASTTemplateArgumentListInfo *ArgsAsWritten) { 1452b330d800Scor3ntin 1453b330d800Scor3ntin if (N.isCompound()) { 1454babdef27SErich Keane if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL, 1455df061c3eSSaar Raz ArgsAsWritten)) 1456df061c3eSSaar Raz return true; 1457babdef27SErich Keane return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL, 1458df061c3eSSaar Raz ArgsAsWritten); 1459df061c3eSSaar Raz } 1460b330d800Scor3ntin 1461b330d800Scor3ntin if (N.isFoldExpanded()) { 1462b330d800Scor3ntin Sema::ArgumentPackSubstitutionIndexRAII _(S, -1); 1463b330d800Scor3ntin return substituteParameterMappings( 1464b330d800Scor3ntin S, N.getFoldExpandedConstraint()->Constraint, Concept, MLTAL, 1465b330d800Scor3ntin ArgsAsWritten); 1466b330d800Scor3ntin } 1467b330d800Scor3ntin 1468df061c3eSSaar Raz TemplateParameterList *TemplateParams = Concept->getTemplateParameters(); 1469df061c3eSSaar Raz 1470df061c3eSSaar Raz AtomicConstraint &Atomic = *N.getAtomicConstraint(); 1471df061c3eSSaar Raz TemplateArgumentListInfo SubstArgs; 1472df061c3eSSaar Raz if (!Atomic.ParameterMapping) { 1473df061c3eSSaar Raz llvm::SmallBitVector OccurringIndices(TemplateParams->size()); 1474df061c3eSSaar Raz S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false, 1475df061c3eSSaar Raz /*Depth=*/0, OccurringIndices); 1476ec081141SYuanfang Chen TemplateArgumentLoc *TempArgs = 1477ec081141SYuanfang Chen new (S.Context) TemplateArgumentLoc[OccurringIndices.count()]; 1478b65b1f32SSaar Raz for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) 1479df061c3eSSaar Raz if (OccurringIndices[I]) 1480ec081141SYuanfang Chen new (&(TempArgs)[J++]) 1481ec081141SYuanfang Chen TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc( 1482ec081141SYuanfang Chen TemplateParams->begin()[I], 1483df061c3eSSaar Raz // Here we assume we do not support things like 1484df061c3eSSaar Raz // template<typename A, typename B> 1485df061c3eSSaar Raz // concept C = ...; 1486df061c3eSSaar Raz // 1487df061c3eSSaar Raz // template<typename... Ts> requires C<Ts...> 1488df061c3eSSaar Raz // struct S { }; 1489df061c3eSSaar Raz // The above currently yields a diagnostic. 1490df061c3eSSaar Raz // We still might have default arguments for concept parameters. 1491ec081141SYuanfang Chen ArgsAsWritten->NumTemplateArgs > I 1492ec081141SYuanfang Chen ? ArgsAsWritten->arguments()[I].getLocation() 1493ec081141SYuanfang Chen : SourceLocation())); 1494ec081141SYuanfang Chen Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count()); 1495df061c3eSSaar Raz } 149611b20d7aSHaojian Wu SourceLocation InstLocBegin = 149711b20d7aSHaojian Wu ArgsAsWritten->arguments().empty() 149811b20d7aSHaojian Wu ? ArgsAsWritten->getLAngleLoc() 149911b20d7aSHaojian Wu : ArgsAsWritten->arguments().front().getSourceRange().getBegin(); 150011b20d7aSHaojian Wu SourceLocation InstLocEnd = 150111b20d7aSHaojian Wu ArgsAsWritten->arguments().empty() 150211b20d7aSHaojian Wu ? ArgsAsWritten->getRAngleLoc() 150311b20d7aSHaojian Wu : ArgsAsWritten->arguments().front().getSourceRange().getEnd(); 1504df061c3eSSaar Raz Sema::InstantiatingTemplate Inst( 150511b20d7aSHaojian Wu S, InstLocBegin, 15069e9d98aaSMatheus Izvekov Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, 15079e9d98aaSMatheus Izvekov Atomic.ConstraintDecl, {InstLocBegin, InstLocEnd}); 1508a042fcbeSHaojian Wu if (Inst.isInvalid()) 1509a042fcbeSHaojian Wu return true; 1510258c3aeeSErich Keane if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) 1511df061c3eSSaar Raz return true; 1512ec081141SYuanfang Chen 1513ec081141SYuanfang Chen TemplateArgumentLoc *TempArgs = 1514ec081141SYuanfang Chen new (S.Context) TemplateArgumentLoc[SubstArgs.size()]; 1515df061c3eSSaar Raz std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(), 1516ec081141SYuanfang Chen TempArgs); 1517ec081141SYuanfang Chen Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size()); 1518df061c3eSSaar Raz return false; 1519df061c3eSSaar Raz } 1520df061c3eSSaar Raz 1521babdef27SErich Keane static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1522babdef27SErich Keane const ConceptSpecializationExpr *CSE) { 1523326feaafSMatheus Izvekov MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 152498191d7cSErich Keane CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(), 152500139ae1SMatheus Izvekov /*Final=*/false, CSE->getTemplateArguments(), 1526939a3d22SErich Keane /*RelativeToPrimary=*/true, 152744ab3805SKrystian Stasiowski /*Pattern=*/nullptr, 1528939a3d22SErich Keane /*ForConstraintInstantiation=*/true); 1529babdef27SErich Keane 1530babdef27SErich Keane return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL, 1531babdef27SErich Keane CSE->getTemplateArgsAsWritten()); 1532babdef27SErich Keane } 1533babdef27SErich Keane 1534b330d800Scor3ntin NormalizedConstraint::NormalizedConstraint(ASTContext &C, 1535b330d800Scor3ntin NormalizedConstraint LHS, 1536b330d800Scor3ntin NormalizedConstraint RHS, 1537b330d800Scor3ntin CompoundConstraintKind Kind) 1538b330d800Scor3ntin : Constraint{CompoundConstraint{ 1539b330d800Scor3ntin new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)}, 1540b330d800Scor3ntin Kind}} {} 1541b330d800Scor3ntin 1542b330d800Scor3ntin NormalizedConstraint::NormalizedConstraint(ASTContext &C, 1543b330d800Scor3ntin const NormalizedConstraint &Other) { 1544b330d800Scor3ntin if (Other.isAtomic()) { 1545b330d800Scor3ntin Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint()); 1546b330d800Scor3ntin } else if (Other.isFoldExpanded()) { 1547b330d800Scor3ntin Constraint = new (C) FoldExpandedConstraint( 1548b330d800Scor3ntin Other.getFoldExpandedConstraint()->Kind, 1549b330d800Scor3ntin NormalizedConstraint(C, Other.getFoldExpandedConstraint()->Constraint), 1550b330d800Scor3ntin Other.getFoldExpandedConstraint()->Pattern); 1551b330d800Scor3ntin } else { 1552b330d800Scor3ntin Constraint = CompoundConstraint( 1553b330d800Scor3ntin new (C) 1554b330d800Scor3ntin NormalizedConstraintPair{NormalizedConstraint(C, Other.getLHS()), 1555b330d800Scor3ntin NormalizedConstraint(C, Other.getRHS())}, 1556b330d800Scor3ntin Other.getCompoundKind()); 1557b330d800Scor3ntin } 1558b330d800Scor3ntin } 1559b330d800Scor3ntin 1560b330d800Scor3ntin NormalizedConstraint &NormalizedConstraint::getLHS() const { 1561b330d800Scor3ntin assert(isCompound() && "getLHS called on a non-compound constraint."); 15621e3e199eSKazu Hirata return cast<CompoundConstraint>(Constraint).getPointer()->LHS; 1563b330d800Scor3ntin } 1564b330d800Scor3ntin 1565b330d800Scor3ntin NormalizedConstraint &NormalizedConstraint::getRHS() const { 1566b330d800Scor3ntin assert(isCompound() && "getRHS called on a non-compound constraint."); 15671e3e199eSKazu Hirata return cast<CompoundConstraint>(Constraint).getPointer()->RHS; 1568b330d800Scor3ntin } 1569b330d800Scor3ntin 15706ad0788cSKazu Hirata std::optional<NormalizedConstraint> 1571b65b1f32SSaar Raz NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D, 1572b65b1f32SSaar Raz ArrayRef<const Expr *> E) { 1573b65b1f32SSaar Raz assert(E.size() != 0); 157487aa3182SMatheus Izvekov auto Conjunction = fromConstraintExpr(S, D, E[0]); 157587aa3182SMatheus Izvekov if (!Conjunction) 15768595f2e5SKazu Hirata return std::nullopt; 157787aa3182SMatheus Izvekov for (unsigned I = 1; I < E.size(); ++I) { 1578b65b1f32SSaar Raz auto Next = fromConstraintExpr(S, D, E[I]); 1579b65b1f32SSaar Raz if (!Next) 15808595f2e5SKazu Hirata return std::nullopt; 158187aa3182SMatheus Izvekov *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction), 1582b65b1f32SSaar Raz std::move(*Next), CCK_Conjunction); 1583b65b1f32SSaar Raz } 1584b65b1f32SSaar Raz return Conjunction; 1585b65b1f32SSaar Raz } 1586b65b1f32SSaar Raz 15876ad0788cSKazu Hirata std::optional<NormalizedConstraint> 1588df061c3eSSaar Raz NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) { 1589df061c3eSSaar Raz assert(E != nullptr); 1590df061c3eSSaar Raz 1591df061c3eSSaar Raz // C++ [temp.constr.normal]p1.1 1592df061c3eSSaar Raz // [...] 1593df061c3eSSaar Raz // - The normal form of an expression (E) is the normal form of E. 1594df061c3eSSaar Raz // [...] 1595df061c3eSSaar Raz E = E->IgnoreParenImpCasts(); 1596340eac01SYuanfang Chen 1597340eac01SYuanfang Chen // C++2a [temp.param]p4: 1598340eac01SYuanfang Chen // [...] If T is not a pack, then E is E', otherwise E is (E' && ...). 1599c9447c62SYuanfang Chen // Fold expression is considered atomic constraints per current wording. 1600c9447c62SYuanfang Chen // See http://cplusplus.github.io/concepts-ts/ts-active.html#28 1601340eac01SYuanfang Chen 16026c29073eSRichard Smith if (LogicalBinOp BO = E) { 16036c29073eSRichard Smith auto LHS = fromConstraintExpr(S, D, BO.getLHS()); 1604df061c3eSSaar Raz if (!LHS) 16058595f2e5SKazu Hirata return std::nullopt; 16066c29073eSRichard Smith auto RHS = fromConstraintExpr(S, D, BO.getRHS()); 1607df061c3eSSaar Raz if (!RHS) 16088595f2e5SKazu Hirata return std::nullopt; 1609df061c3eSSaar Raz 16106c29073eSRichard Smith return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS), 16116c29073eSRichard Smith BO.isAnd() ? CCK_Conjunction : CCK_Disjunction); 1612df061c3eSSaar Raz } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) { 1613b65b1f32SSaar Raz const NormalizedConstraint *SubNF; 1614df061c3eSSaar Raz { 1615df061c3eSSaar Raz Sema::InstantiatingTemplate Inst( 1616df061c3eSSaar Raz S, CSE->getExprLoc(), 1617df061c3eSSaar Raz Sema::InstantiatingTemplate::ConstraintNormalization{}, D, 1618df061c3eSSaar Raz CSE->getSourceRange()); 161959902785SHaojian Wu if (Inst.isInvalid()) 162059902785SHaojian Wu return std::nullopt; 1621df061c3eSSaar Raz // C++ [temp.constr.normal]p1.1 1622df061c3eSSaar Raz // [...] 1623df061c3eSSaar Raz // The normal form of an id-expression of the form C<A1, A2, ..., AN>, 1624df061c3eSSaar Raz // where C names a concept, is the normal form of the 1625df061c3eSSaar Raz // constraint-expression of C, after substituting A1, A2, ..., AN for C’s 1626df061c3eSSaar Raz // respective template parameters in the parameter mappings in each atomic 1627df061c3eSSaar Raz // constraint. If any such substitution results in an invalid type or 1628df061c3eSSaar Raz // expression, the program is ill-formed; no diagnostic is required. 1629df061c3eSSaar Raz // [...] 1630b65b1f32SSaar Raz ConceptDecl *CD = CSE->getNamedConcept(); 1631b65b1f32SSaar Raz SubNF = S.getNormalizedAssociatedConstraints(CD, 1632b65b1f32SSaar Raz {CD->getConstraintExpr()}); 1633df061c3eSSaar Raz if (!SubNF) 16348595f2e5SKazu Hirata return std::nullopt; 1635df061c3eSSaar Raz } 1636df061c3eSSaar Raz 16376ad0788cSKazu Hirata std::optional<NormalizedConstraint> New; 1638b65b1f32SSaar Raz New.emplace(S.Context, *SubNF); 1639b65b1f32SSaar Raz 1640babdef27SErich Keane if (substituteParameterMappings(S, *New, CSE)) 16418595f2e5SKazu Hirata return std::nullopt; 1642df061c3eSSaar Raz 1643b65b1f32SSaar Raz return New; 1644b330d800Scor3ntin } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E); 1645b330d800Scor3ntin FE && S.getLangOpts().CPlusPlus26 && 1646b330d800Scor3ntin (FE->getOperator() == BinaryOperatorKind::BO_LAnd || 1647b330d800Scor3ntin FE->getOperator() == BinaryOperatorKind::BO_LOr)) { 1648b330d800Scor3ntin 1649b330d800Scor3ntin // Normalize fold expressions in C++26. 1650b330d800Scor3ntin 1651b330d800Scor3ntin FoldExpandedConstraint::FoldOperatorKind Kind = 1652b330d800Scor3ntin FE->getOperator() == BinaryOperatorKind::BO_LAnd 1653b330d800Scor3ntin ? FoldExpandedConstraint::FoldOperatorKind::And 1654b330d800Scor3ntin : FoldExpandedConstraint::FoldOperatorKind::Or; 1655b330d800Scor3ntin 1656b330d800Scor3ntin if (FE->getInit()) { 1657b330d800Scor3ntin auto LHS = fromConstraintExpr(S, D, FE->getLHS()); 1658b330d800Scor3ntin auto RHS = fromConstraintExpr(S, D, FE->getRHS()); 1659b330d800Scor3ntin if (!LHS || !RHS) 1660b330d800Scor3ntin return std::nullopt; 1661b330d800Scor3ntin 1662b330d800Scor3ntin if (FE->isRightFold()) 1663b330d800Scor3ntin RHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 1664b330d800Scor3ntin Kind, std::move(*RHS), FE->getPattern()}}; 1665b330d800Scor3ntin else 1666b330d800Scor3ntin LHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 1667b330d800Scor3ntin Kind, std::move(*LHS), FE->getPattern()}}; 1668b330d800Scor3ntin 1669b330d800Scor3ntin return NormalizedConstraint( 1670b330d800Scor3ntin S.Context, std::move(*LHS), std::move(*RHS), 1671b330d800Scor3ntin FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction 1672b330d800Scor3ntin : CCK_Disjunction); 1673df061c3eSSaar Raz } 1674b330d800Scor3ntin auto Sub = fromConstraintExpr(S, D, FE->getPattern()); 1675b330d800Scor3ntin if (!Sub) 1676b330d800Scor3ntin return std::nullopt; 1677b330d800Scor3ntin return NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 1678b330d800Scor3ntin Kind, std::move(*Sub), FE->getPattern()}}; 1679b330d800Scor3ntin } 1680b330d800Scor3ntin 16819e9d98aaSMatheus Izvekov return NormalizedConstraint{new (S.Context) AtomicConstraint(E, D)}; 1682df061c3eSSaar Raz } 1683df061c3eSSaar Raz 1684b330d800Scor3ntin bool FoldExpandedConstraint::AreCompatibleForSubsumption( 1685b330d800Scor3ntin const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) { 1686df061c3eSSaar Raz 1687b330d800Scor3ntin // [C++26] [temp.constr.fold] 1688b330d800Scor3ntin // Two fold expanded constraints are compatible for subsumption 1689b330d800Scor3ntin // if their respective constraints both contain an equivalent unexpanded pack. 1690b330d800Scor3ntin 1691b330d800Scor3ntin llvm::SmallVector<UnexpandedParameterPack> APacks, BPacks; 1692b330d800Scor3ntin Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.Pattern), APacks); 1693b330d800Scor3ntin Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks); 1694b330d800Scor3ntin 1695b330d800Scor3ntin for (const UnexpandedParameterPack &APack : APacks) { 1696b330d800Scor3ntin std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack); 1697b330d800Scor3ntin auto it = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) { 1698b330d800Scor3ntin return getDepthAndIndex(BPack) == DepthAndIndex; 1699b330d800Scor3ntin }); 1700b330d800Scor3ntin if (it != BPacks.end()) 1701b330d800Scor3ntin return true; 1702b330d800Scor3ntin } 1703b330d800Scor3ntin return false; 1704b330d800Scor3ntin } 1705b330d800Scor3ntin 1706b330d800Scor3ntin NormalForm clang::makeCNF(const NormalizedConstraint &Normalized) { 1707df061c3eSSaar Raz if (Normalized.isAtomic()) 1708df061c3eSSaar Raz return {{Normalized.getAtomicConstraint()}}; 1709df061c3eSSaar Raz 1710b330d800Scor3ntin else if (Normalized.isFoldExpanded()) 1711b330d800Scor3ntin return {{Normalized.getFoldExpandedConstraint()}}; 1712b330d800Scor3ntin 1713df061c3eSSaar Raz NormalForm LCNF = makeCNF(Normalized.getLHS()); 1714df061c3eSSaar Raz NormalForm RCNF = makeCNF(Normalized.getRHS()); 1715df061c3eSSaar Raz if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) { 1716df061c3eSSaar Raz LCNF.reserve(LCNF.size() + RCNF.size()); 1717df061c3eSSaar Raz while (!RCNF.empty()) 1718df061c3eSSaar Raz LCNF.push_back(RCNF.pop_back_val()); 1719df061c3eSSaar Raz return LCNF; 1720df061c3eSSaar Raz } 1721df061c3eSSaar Raz 1722df061c3eSSaar Raz // Disjunction 1723df061c3eSSaar Raz NormalForm Res; 1724df061c3eSSaar Raz Res.reserve(LCNF.size() * RCNF.size()); 1725df061c3eSSaar Raz for (auto &LDisjunction : LCNF) 1726df061c3eSSaar Raz for (auto &RDisjunction : RCNF) { 1727df061c3eSSaar Raz NormalForm::value_type Combined; 1728df061c3eSSaar Raz Combined.reserve(LDisjunction.size() + RDisjunction.size()); 1729df061c3eSSaar Raz std::copy(LDisjunction.begin(), LDisjunction.end(), 1730df061c3eSSaar Raz std::back_inserter(Combined)); 1731df061c3eSSaar Raz std::copy(RDisjunction.begin(), RDisjunction.end(), 1732df061c3eSSaar Raz std::back_inserter(Combined)); 1733df061c3eSSaar Raz Res.emplace_back(Combined); 1734df061c3eSSaar Raz } 1735df061c3eSSaar Raz return Res; 1736df061c3eSSaar Raz } 1737df061c3eSSaar Raz 1738b330d800Scor3ntin NormalForm clang::makeDNF(const NormalizedConstraint &Normalized) { 1739df061c3eSSaar Raz if (Normalized.isAtomic()) 1740df061c3eSSaar Raz return {{Normalized.getAtomicConstraint()}}; 1741df061c3eSSaar Raz 1742b330d800Scor3ntin else if (Normalized.isFoldExpanded()) 1743b330d800Scor3ntin return {{Normalized.getFoldExpandedConstraint()}}; 1744b330d800Scor3ntin 1745df061c3eSSaar Raz NormalForm LDNF = makeDNF(Normalized.getLHS()); 1746df061c3eSSaar Raz NormalForm RDNF = makeDNF(Normalized.getRHS()); 1747df061c3eSSaar Raz if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) { 1748df061c3eSSaar Raz LDNF.reserve(LDNF.size() + RDNF.size()); 1749df061c3eSSaar Raz while (!RDNF.empty()) 1750df061c3eSSaar Raz LDNF.push_back(RDNF.pop_back_val()); 1751df061c3eSSaar Raz return LDNF; 1752df061c3eSSaar Raz } 1753df061c3eSSaar Raz 1754df061c3eSSaar Raz // Conjunction 1755df061c3eSSaar Raz NormalForm Res; 1756df061c3eSSaar Raz Res.reserve(LDNF.size() * RDNF.size()); 1757df061c3eSSaar Raz for (auto &LConjunction : LDNF) { 1758df061c3eSSaar Raz for (auto &RConjunction : RDNF) { 1759df061c3eSSaar Raz NormalForm::value_type Combined; 1760df061c3eSSaar Raz Combined.reserve(LConjunction.size() + RConjunction.size()); 1761df061c3eSSaar Raz std::copy(LConjunction.begin(), LConjunction.end(), 1762df061c3eSSaar Raz std::back_inserter(Combined)); 1763df061c3eSSaar Raz std::copy(RConjunction.begin(), RConjunction.end(), 1764df061c3eSSaar Raz std::back_inserter(Combined)); 1765df061c3eSSaar Raz Res.emplace_back(Combined); 1766df061c3eSSaar Raz } 1767df061c3eSSaar Raz } 1768df061c3eSSaar Raz return Res; 1769df061c3eSSaar Raz } 1770df061c3eSSaar Raz 1771ae48d1c7SLiming Liu bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, 1772ae48d1c7SLiming Liu MutableArrayRef<const Expr *> AC1, 1773ae48d1c7SLiming Liu NamedDecl *D2, 1774ae48d1c7SLiming Liu MutableArrayRef<const Expr *> AC2, 1775df061c3eSSaar Raz bool &Result) { 1776e18c2c55SYuanfang Chen if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) { 1777e18c2c55SYuanfang Chen auto IsExpectedEntity = [](const FunctionDecl *FD) { 1778e18c2c55SYuanfang Chen FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind(); 1779e18c2c55SYuanfang Chen return Kind == FunctionDecl::TK_NonTemplate || 1780e18c2c55SYuanfang Chen Kind == FunctionDecl::TK_FunctionTemplate; 1781e18c2c55SYuanfang Chen }; 1782e18c2c55SYuanfang Chen const auto *FD2 = dyn_cast<FunctionDecl>(D2); 178321bac595SHaojian Wu (void)IsExpectedEntity; 1784d0a98efbSVictor Komarov (void)FD1; 178521bac595SHaojian Wu (void)FD2; 1786e18c2c55SYuanfang Chen assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) && 1787e18c2c55SYuanfang Chen "use non-instantiated function declaration for constraints partial " 1788e18c2c55SYuanfang Chen "ordering"); 1789e18c2c55SYuanfang Chen } 1790e18c2c55SYuanfang Chen 1791df061c3eSSaar Raz if (AC1.empty()) { 1792df061c3eSSaar Raz Result = AC2.empty(); 1793df061c3eSSaar Raz return false; 1794df061c3eSSaar Raz } 1795df061c3eSSaar Raz if (AC2.empty()) { 1796df061c3eSSaar Raz // TD1 has associated constraints and TD2 does not. 1797df061c3eSSaar Raz Result = true; 1798df061c3eSSaar Raz return false; 1799df061c3eSSaar Raz } 1800df061c3eSSaar Raz 1801df061c3eSSaar Raz std::pair<NamedDecl *, NamedDecl *> Key{D1, D2}; 1802df061c3eSSaar Raz auto CacheEntry = SubsumptionCache.find(Key); 1803df061c3eSSaar Raz if (CacheEntry != SubsumptionCache.end()) { 1804df061c3eSSaar Raz Result = CacheEntry->second; 1805df061c3eSSaar Raz return false; 1806df061c3eSSaar Raz } 1807b65b1f32SSaar Raz 180844ab3805SKrystian Stasiowski unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true); 180944ab3805SKrystian Stasiowski unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true); 1810ae48d1c7SLiming Liu 1811ae48d1c7SLiming Liu for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) { 1812ae48d1c7SLiming Liu if (Depth2 > Depth1) { 1813ae48d1c7SLiming Liu AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1) 1814ae48d1c7SLiming Liu .TransformExpr(const_cast<Expr *>(AC1[I])) 1815ae48d1c7SLiming Liu .get(); 1816ae48d1c7SLiming Liu } else if (Depth1 > Depth2) { 1817ae48d1c7SLiming Liu AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2) 1818ae48d1c7SLiming Liu .TransformExpr(const_cast<Expr *>(AC2[I])) 1819ae48d1c7SLiming Liu .get(); 1820ae48d1c7SLiming Liu } 1821ae48d1c7SLiming Liu } 1822ae48d1c7SLiming Liu 1823b330d800Scor3ntin if (clang::subsumes( 1824b330d800Scor3ntin *this, D1, AC1, D2, AC2, Result, 1825b65b1f32SSaar Raz [this](const AtomicConstraint &A, const AtomicConstraint &B) { 1826b65b1f32SSaar Raz return A.subsumes(Context, B); 1827b65b1f32SSaar Raz })) 1828df061c3eSSaar Raz return true; 1829df061c3eSSaar Raz SubsumptionCache.try_emplace(Key, Result); 1830df061c3eSSaar Raz return false; 1831df061c3eSSaar Raz } 1832b65b1f32SSaar Raz 1833b65b1f32SSaar Raz bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, 1834b65b1f32SSaar Raz ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) { 1835b65b1f32SSaar Raz if (isSFINAEContext()) 1836b65b1f32SSaar Raz // No need to work here because our notes would be discarded. 1837b65b1f32SSaar Raz return false; 1838b65b1f32SSaar Raz 1839b65b1f32SSaar Raz if (AC1.empty() || AC2.empty()) 1840b65b1f32SSaar Raz return false; 1841b65b1f32SSaar Raz 1842b65b1f32SSaar Raz auto NormalExprEvaluator = 1843b65b1f32SSaar Raz [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 1844b65b1f32SSaar Raz return A.subsumes(Context, B); 1845b65b1f32SSaar Raz }; 1846b65b1f32SSaar Raz 1847b65b1f32SSaar Raz const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr; 1848b65b1f32SSaar Raz auto IdenticalExprEvaluator = 1849b65b1f32SSaar Raz [&] (const AtomicConstraint &A, const AtomicConstraint &B) { 1850b65b1f32SSaar Raz if (!A.hasMatchingParameterMapping(Context, B)) 1851b65b1f32SSaar Raz return false; 1852b65b1f32SSaar Raz const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr; 1853b65b1f32SSaar Raz if (EA == EB) 1854b65b1f32SSaar Raz return true; 1855b65b1f32SSaar Raz 1856b65b1f32SSaar Raz // Not the same source level expression - are the expressions 1857b65b1f32SSaar Raz // identical? 1858b65b1f32SSaar Raz llvm::FoldingSetNodeID IDA, IDB; 1859bde305baSNico Weber EA->Profile(IDA, Context, /*Canonical=*/true); 1860bde305baSNico Weber EB->Profile(IDB, Context, /*Canonical=*/true); 1861b65b1f32SSaar Raz if (IDA != IDB) 1862b65b1f32SSaar Raz return false; 1863b65b1f32SSaar Raz 1864b65b1f32SSaar Raz AmbiguousAtomic1 = EA; 1865b65b1f32SSaar Raz AmbiguousAtomic2 = EB; 1866b65b1f32SSaar Raz return true; 1867b65b1f32SSaar Raz }; 1868b65b1f32SSaar Raz 1869b65b1f32SSaar Raz { 1870b65b1f32SSaar Raz // The subsumption checks might cause diagnostics 1871b65b1f32SSaar Raz SFINAETrap Trap(*this); 1872b65b1f32SSaar Raz auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1); 1873b65b1f32SSaar Raz if (!Normalized1) 1874b65b1f32SSaar Raz return false; 1875b65b1f32SSaar Raz const NormalForm DNF1 = makeDNF(*Normalized1); 1876b65b1f32SSaar Raz const NormalForm CNF1 = makeCNF(*Normalized1); 1877b65b1f32SSaar Raz 1878b65b1f32SSaar Raz auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2); 1879b65b1f32SSaar Raz if (!Normalized2) 1880b65b1f32SSaar Raz return false; 1881b65b1f32SSaar Raz const NormalForm DNF2 = makeDNF(*Normalized2); 1882b65b1f32SSaar Raz const NormalForm CNF2 = makeCNF(*Normalized2); 1883b65b1f32SSaar Raz 1884b330d800Scor3ntin bool Is1AtLeastAs2Normally = 1885b330d800Scor3ntin clang::subsumes(DNF1, CNF2, NormalExprEvaluator); 1886b330d800Scor3ntin bool Is2AtLeastAs1Normally = 1887b330d800Scor3ntin clang::subsumes(DNF2, CNF1, NormalExprEvaluator); 1888b330d800Scor3ntin bool Is1AtLeastAs2 = clang::subsumes(DNF1, CNF2, IdenticalExprEvaluator); 1889b330d800Scor3ntin bool Is2AtLeastAs1 = clang::subsumes(DNF2, CNF1, IdenticalExprEvaluator); 1890b65b1f32SSaar Raz if (Is1AtLeastAs2 == Is1AtLeastAs2Normally && 1891b65b1f32SSaar Raz Is2AtLeastAs1 == Is2AtLeastAs1Normally) 1892b65b1f32SSaar Raz // Same result - no ambiguity was caused by identical atomic expressions. 1893b65b1f32SSaar Raz return false; 1894b65b1f32SSaar Raz } 1895b65b1f32SSaar Raz 1896b65b1f32SSaar Raz // A different result! Some ambiguous atomic constraint(s) caused a difference 1897b65b1f32SSaar Raz assert(AmbiguousAtomic1 && AmbiguousAtomic2); 1898b65b1f32SSaar Raz 1899b65b1f32SSaar Raz Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints) 1900b65b1f32SSaar Raz << AmbiguousAtomic1->getSourceRange(); 1901b65b1f32SSaar Raz Diag(AmbiguousAtomic2->getBeginLoc(), 1902b65b1f32SSaar Raz diag::note_ambiguous_atomic_constraints_similar_expression) 1903b65b1f32SSaar Raz << AmbiguousAtomic2->getSourceRange(); 1904b65b1f32SSaar Raz return true; 1905b65b1f32SSaar Raz } 1906a0f50d73SSaar Raz 1907a0f50d73SSaar Raz concepts::ExprRequirement::ExprRequirement( 1908a0f50d73SSaar Raz Expr *E, bool IsSimple, SourceLocation NoexceptLoc, 1909a0f50d73SSaar Raz ReturnTypeRequirement Req, SatisfactionStatus Status, 1910a0f50d73SSaar Raz ConceptSpecializationExpr *SubstitutedConstraintExpr) : 1911a0f50d73SSaar Raz Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, 1912a0f50d73SSaar Raz Status == SS_Dependent && 1913a0f50d73SSaar Raz (E->containsUnexpandedParameterPack() || 1914a0f50d73SSaar Raz Req.containsUnexpandedParameterPack()), 1915a0f50d73SSaar Raz Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc), 1916a0f50d73SSaar Raz TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr), 1917a0f50d73SSaar Raz Status(Status) { 1918a0f50d73SSaar Raz assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 1919a0f50d73SSaar Raz "Simple requirement must not have a return type requirement or a " 1920a0f50d73SSaar Raz "noexcept specification"); 1921a0f50d73SSaar Raz assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == 1922a0f50d73SSaar Raz (SubstitutedConstraintExpr != nullptr)); 1923a0f50d73SSaar Raz } 1924a0f50d73SSaar Raz 1925a0f50d73SSaar Raz concepts::ExprRequirement::ExprRequirement( 1926a0f50d73SSaar Raz SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, 1927a0f50d73SSaar Raz SourceLocation NoexceptLoc, ReturnTypeRequirement Req) : 1928a0f50d73SSaar Raz Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), 1929a0f50d73SSaar Raz Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), 1930a0f50d73SSaar Raz Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), 1931a0f50d73SSaar Raz Status(SS_ExprSubstitutionFailure) { 1932a0f50d73SSaar Raz assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 1933a0f50d73SSaar Raz "Simple requirement must not have a return type requirement or a " 1934a0f50d73SSaar Raz "noexcept specification"); 1935a0f50d73SSaar Raz } 1936a0f50d73SSaar Raz 1937a0f50d73SSaar Raz concepts::ExprRequirement::ReturnTypeRequirement:: 1938a0f50d73SSaar Raz ReturnTypeRequirement(TemplateParameterList *TPL) : 193940446663SKazu Hirata TypeConstraintInfo(TPL, false) { 1940a0f50d73SSaar Raz assert(TPL->size() == 1); 1941a0f50d73SSaar Raz const TypeConstraint *TC = 1942a0f50d73SSaar Raz cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint(); 19430cf4f810SAaron Ballman assert(TC && 19440cf4f810SAaron Ballman "TPL must have a template type parameter with a type constraint"); 1945a0f50d73SSaar Raz auto *Constraint = 194698339f14SSindhu Chittireddy cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint()); 194771886c56SRichard Smith bool Dependent = 194871886c56SRichard Smith Constraint->getTemplateArgsAsWritten() && 194971886c56SRichard Smith TemplateSpecializationType::anyInstantiationDependentTemplateArguments( 195071886c56SRichard Smith Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)); 195140446663SKazu Hirata TypeConstraintInfo.setInt(Dependent ? true : false); 1952a0f50d73SSaar Raz } 1953a0f50d73SSaar Raz 1954a0f50d73SSaar Raz concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) : 195571886c56SRichard Smith Requirement(RK_Type, T->getType()->isInstantiationDependentType(), 1956a0f50d73SSaar Raz T->getType()->containsUnexpandedParameterPack(), 1957a0f50d73SSaar Raz // We reach this ctor with either dependent types (in which 1958a0f50d73SSaar Raz // IsSatisfied doesn't matter) or with non-dependent type in 1959a0f50d73SSaar Raz // which the existence of the type indicates satisfaction. 196071886c56SRichard Smith /*IsSatisfied=*/true), 196171886c56SRichard Smith Value(T), 196271886c56SRichard Smith Status(T->getType()->isInstantiationDependentType() ? SS_Dependent 196371886c56SRichard Smith : SS_Satisfied) {} 19641e146dfbSKazu Hirata 19651e146dfbSKazu Hirata NormalizedConstraint::CompoundConstraintKind 19661e146dfbSKazu Hirata NormalizedConstraint::getCompoundKind() const { 19671e146dfbSKazu Hirata assert(isCompound() && "getCompoundKind on a non-compound constraint.."); 19681e146dfbSKazu Hirata return cast<CompoundConstraint>(Constraint).getInt(); 19691e146dfbSKazu Hirata } 19701e146dfbSKazu Hirata 19711e146dfbSKazu Hirata AtomicConstraint *NormalizedConstraint::getAtomicConstraint() const { 19721e146dfbSKazu Hirata assert(isAtomic() && "getAtomicConstraint called on non-atomic constraint."); 19731e146dfbSKazu Hirata return cast<AtomicConstraint *>(Constraint); 19741e146dfbSKazu Hirata } 19751e146dfbSKazu Hirata 19761e146dfbSKazu Hirata FoldExpandedConstraint * 19771e146dfbSKazu Hirata NormalizedConstraint::getFoldExpandedConstraint() const { 19781e146dfbSKazu Hirata assert(isFoldExpanded() && 19791e146dfbSKazu Hirata "getFoldExpandedConstraint called on non-fold-expanded constraint."); 19801e146dfbSKazu Hirata return cast<FoldExpandedConstraint *>(Constraint); 19811e146dfbSKazu Hirata } 1982