1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===// 2a7dea167SDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric // 9a7dea167SDimitry Andric // This file implements semantic analysis for C++ constraints and concepts. 10a7dea167SDimitry Andric // 11a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 12a7dea167SDimitry Andric 13480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h" 1406c3fb27SDimitry Andric #include "TreeTransform.h" 15bdd1243dSDimitry Andric #include "clang/AST/ASTLambda.h" 16feb5b0c7SDimitry Andric #include "clang/AST/DeclCXX.h" 1755e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h" 18480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 19480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h" 2006c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h" 2106c3fb27SDimitry Andric #include "clang/Sema/Initialization.h" 2206c3fb27SDimitry Andric #include "clang/Sema/Overload.h" 23feb5b0c7SDimitry Andric #include "clang/Sema/ScopeInfo.h" 2406c3fb27SDimitry Andric #include "clang/Sema/Sema.h" 2506c3fb27SDimitry Andric #include "clang/Sema/SemaDiagnostic.h" 2606c3fb27SDimitry Andric #include "clang/Sema/SemaInternal.h" 2706c3fb27SDimitry Andric #include "clang/Sema/Template.h" 2806c3fb27SDimitry Andric #include "clang/Sema/TemplateDeduction.h" 29480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h" 30480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h" 31fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h" 32bdd1243dSDimitry Andric #include <optional> 33fe6060f1SDimitry Andric 34a7dea167SDimitry Andric using namespace clang; 35a7dea167SDimitry Andric using namespace sema; 36a7dea167SDimitry Andric 375ffd83dbSDimitry Andric namespace { 385ffd83dbSDimitry Andric class LogicalBinOp { 39bdd1243dSDimitry Andric SourceLocation Loc; 405ffd83dbSDimitry Andric OverloadedOperatorKind Op = OO_None; 415ffd83dbSDimitry Andric const Expr *LHS = nullptr; 425ffd83dbSDimitry Andric const Expr *RHS = nullptr; 435ffd83dbSDimitry Andric 445ffd83dbSDimitry Andric public: 455ffd83dbSDimitry Andric LogicalBinOp(const Expr *E) { 465ffd83dbSDimitry Andric if (auto *BO = dyn_cast<BinaryOperator>(E)) { 475ffd83dbSDimitry Andric Op = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 485ffd83dbSDimitry Andric LHS = BO->getLHS(); 495ffd83dbSDimitry Andric RHS = BO->getRHS(); 50bdd1243dSDimitry Andric Loc = BO->getExprLoc(); 515ffd83dbSDimitry Andric } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) { 52fe6060f1SDimitry Andric // If OO is not || or && it might not have exactly 2 arguments. 53fe6060f1SDimitry Andric if (OO->getNumArgs() == 2) { 545ffd83dbSDimitry Andric Op = OO->getOperator(); 555ffd83dbSDimitry Andric LHS = OO->getArg(0); 565ffd83dbSDimitry Andric RHS = OO->getArg(1); 57bdd1243dSDimitry Andric Loc = OO->getOperatorLoc(); 585ffd83dbSDimitry Andric } 595ffd83dbSDimitry Andric } 60fe6060f1SDimitry Andric } 615ffd83dbSDimitry Andric 625ffd83dbSDimitry Andric bool isAnd() const { return Op == OO_AmpAmp; } 635ffd83dbSDimitry Andric bool isOr() const { return Op == OO_PipePipe; } 645ffd83dbSDimitry Andric explicit operator bool() const { return isAnd() || isOr(); } 655ffd83dbSDimitry Andric 665ffd83dbSDimitry Andric const Expr *getLHS() const { return LHS; } 675ffd83dbSDimitry Andric const Expr *getRHS() const { return RHS; } 68bdd1243dSDimitry Andric 69bdd1243dSDimitry Andric ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const { 70bdd1243dSDimitry Andric return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS())); 71bdd1243dSDimitry Andric } 72bdd1243dSDimitry Andric 73bdd1243dSDimitry Andric ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS, 74bdd1243dSDimitry Andric ExprResult RHS) const { 75bdd1243dSDimitry Andric assert((isAnd() || isOr()) && "Not the right kind of op?"); 76bdd1243dSDimitry Andric assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?"); 77bdd1243dSDimitry Andric 78bdd1243dSDimitry Andric if (!LHS.isUsable() || !RHS.isUsable()) 79bdd1243dSDimitry Andric return ExprEmpty(); 80bdd1243dSDimitry Andric 81bdd1243dSDimitry Andric // We should just be able to 'normalize' these to the builtin Binary 82bdd1243dSDimitry Andric // Operator, since that is how they are evaluated in constriant checks. 83bdd1243dSDimitry Andric return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(), 84bdd1243dSDimitry Andric BinaryOperator::getOverloadedOpcode(Op), 85bdd1243dSDimitry Andric SemaRef.Context.BoolTy, VK_PRValue, 86bdd1243dSDimitry Andric OK_Ordinary, Loc, FPOptionsOverride{}); 87bdd1243dSDimitry Andric } 885ffd83dbSDimitry Andric }; 895ffd83dbSDimitry Andric } 905ffd83dbSDimitry Andric 915ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression, 925ffd83dbSDimitry Andric Token NextToken, bool *PossibleNonPrimary, 93480093f4SDimitry Andric bool IsTrailingRequiresClause) { 94a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 95a7dea167SDimitry Andric // ..E shall be a constant expression of type bool. 96a7dea167SDimitry Andric 97a7dea167SDimitry Andric ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts(); 98a7dea167SDimitry Andric 995ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpression) { 1005ffd83dbSDimitry Andric return CheckConstraintExpression(BO.getLHS(), NextToken, 101480093f4SDimitry Andric PossibleNonPrimary) && 1025ffd83dbSDimitry Andric CheckConstraintExpression(BO.getRHS(), NextToken, 103480093f4SDimitry Andric PossibleNonPrimary); 104a7dea167SDimitry Andric } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression)) 105480093f4SDimitry Andric return CheckConstraintExpression(C->getSubExpr(), NextToken, 106480093f4SDimitry Andric PossibleNonPrimary); 107a7dea167SDimitry Andric 108a7dea167SDimitry Andric QualType Type = ConstraintExpression->getType(); 109480093f4SDimitry Andric 110480093f4SDimitry Andric auto CheckForNonPrimary = [&] { 11106c3fb27SDimitry Andric if (!PossibleNonPrimary) 11206c3fb27SDimitry Andric return; 11306c3fb27SDimitry Andric 114480093f4SDimitry Andric *PossibleNonPrimary = 115480093f4SDimitry Andric // We have the following case: 116480093f4SDimitry Andric // template<typename> requires func(0) struct S { }; 117480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 118480093f4SDimitry Andric // the function call, and we're only going to parse 'func' as the 119480093f4SDimitry Andric // primary-expression, and complain that it is of non-bool type. 12006c3fb27SDimitry Andric // 12106c3fb27SDimitry Andric // However, if we're in a lambda, this might also be: 12206c3fb27SDimitry Andric // []<typename> requires var () {}; 12306c3fb27SDimitry Andric // Which also looks like a function call due to the lambda parentheses, 12406c3fb27SDimitry Andric // but unlike the first case, isn't an error, so this check is skipped. 125480093f4SDimitry Andric (NextToken.is(tok::l_paren) && 126480093f4SDimitry Andric (IsTrailingRequiresClause || 127480093f4SDimitry Andric (Type->isDependentType() && 12806c3fb27SDimitry Andric isa<UnresolvedLookupExpr>(ConstraintExpression) && 12906c3fb27SDimitry Andric !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) || 130480093f4SDimitry Andric Type->isFunctionType() || 131480093f4SDimitry Andric Type->isSpecificBuiltinType(BuiltinType::Overload))) || 132480093f4SDimitry Andric // We have the following case: 133480093f4SDimitry Andric // template<typename T> requires size_<T> == 0 struct S { }; 134480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 135480093f4SDimitry Andric // the binary operator, and we're only going to parse 'func' as the 136480093f4SDimitry Andric // first operand, and complain that it is of non-bool type. 137480093f4SDimitry Andric getBinOpPrecedence(NextToken.getKind(), 138480093f4SDimitry Andric /*GreaterThanIsOperator=*/true, 139480093f4SDimitry Andric getLangOpts().CPlusPlus11) > prec::LogicalAnd; 140480093f4SDimitry Andric }; 141480093f4SDimitry Andric 142480093f4SDimitry Andric // An atomic constraint! 143480093f4SDimitry Andric if (ConstraintExpression->isTypeDependent()) { 144480093f4SDimitry Andric CheckForNonPrimary(); 145480093f4SDimitry Andric return true; 146480093f4SDimitry Andric } 147480093f4SDimitry Andric 148a7dea167SDimitry Andric if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) { 149a7dea167SDimitry Andric Diag(ConstraintExpression->getExprLoc(), 150a7dea167SDimitry Andric diag::err_non_bool_atomic_constraint) << Type 151a7dea167SDimitry Andric << ConstraintExpression->getSourceRange(); 152480093f4SDimitry Andric CheckForNonPrimary(); 153a7dea167SDimitry Andric return false; 154a7dea167SDimitry Andric } 155480093f4SDimitry Andric 156480093f4SDimitry Andric if (PossibleNonPrimary) 157480093f4SDimitry Andric *PossibleNonPrimary = false; 158a7dea167SDimitry Andric return true; 159a7dea167SDimitry Andric } 160a7dea167SDimitry Andric 161bdd1243dSDimitry Andric namespace { 162bdd1243dSDimitry Andric struct SatisfactionStackRAII { 163bdd1243dSDimitry Andric Sema &SemaRef; 1641ac55f4cSDimitry Andric bool Inserted = false; 1651ac55f4cSDimitry Andric SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND, 16606c3fb27SDimitry Andric const llvm::FoldingSetNodeID &FSNID) 167bdd1243dSDimitry Andric : SemaRef(SemaRef) { 1681ac55f4cSDimitry Andric if (ND) { 1691ac55f4cSDimitry Andric SemaRef.PushSatisfactionStackEntry(ND, FSNID); 1701ac55f4cSDimitry Andric Inserted = true; 171bdd1243dSDimitry Andric } 1721ac55f4cSDimitry Andric } 1731ac55f4cSDimitry Andric ~SatisfactionStackRAII() { 1741ac55f4cSDimitry Andric if (Inserted) 1751ac55f4cSDimitry Andric SemaRef.PopSatisfactionStackEntry(); 1761ac55f4cSDimitry Andric } 177bdd1243dSDimitry Andric }; 178bdd1243dSDimitry Andric } // namespace 179bdd1243dSDimitry Andric 180480093f4SDimitry Andric template <typename AtomicEvaluator> 181bdd1243dSDimitry Andric static ExprResult 182480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, 183480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction, 184480093f4SDimitry Andric AtomicEvaluator &&Evaluator) { 185a7dea167SDimitry Andric ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); 186a7dea167SDimitry Andric 1875ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpr) { 1885f757f3fSDimitry Andric size_t EffectiveDetailEndIndex = Satisfaction.Details.size(); 189bdd1243dSDimitry Andric ExprResult LHSRes = calculateConstraintSatisfaction( 190bdd1243dSDimitry Andric S, BO.getLHS(), Satisfaction, Evaluator); 191bdd1243dSDimitry Andric 192bdd1243dSDimitry Andric if (LHSRes.isInvalid()) 193bdd1243dSDimitry Andric return ExprError(); 194480093f4SDimitry Andric 195480093f4SDimitry Andric bool IsLHSSatisfied = Satisfaction.IsSatisfied; 196480093f4SDimitry Andric 1975ffd83dbSDimitry Andric if (BO.isOr() && IsLHSSatisfied) 198480093f4SDimitry Andric // [temp.constr.op] p3 199480093f4SDimitry Andric // A disjunction is a constraint taking two operands. To determine if 200480093f4SDimitry Andric // a disjunction is satisfied, the satisfaction of the first operand 201480093f4SDimitry Andric // is checked. If that is satisfied, the disjunction is satisfied. 202480093f4SDimitry Andric // Otherwise, the disjunction is satisfied if and only if the second 203480093f4SDimitry Andric // operand is satisfied. 204bdd1243dSDimitry Andric // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 205bdd1243dSDimitry Andric return LHSRes; 206480093f4SDimitry Andric 2075ffd83dbSDimitry Andric if (BO.isAnd() && !IsLHSSatisfied) 208480093f4SDimitry Andric // [temp.constr.op] p2 209480093f4SDimitry Andric // A conjunction is a constraint taking two operands. To determine if 210480093f4SDimitry Andric // a conjunction is satisfied, the satisfaction of the first operand 211480093f4SDimitry Andric // is checked. If that is not satisfied, the conjunction is not 212480093f4SDimitry Andric // satisfied. Otherwise, the conjunction is satisfied if and only if 213480093f4SDimitry Andric // the second operand is satisfied. 214bdd1243dSDimitry Andric // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 215bdd1243dSDimitry Andric return LHSRes; 216480093f4SDimitry Andric 217bdd1243dSDimitry Andric ExprResult RHSRes = calculateConstraintSatisfaction( 2185ffd83dbSDimitry Andric S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator)); 219bdd1243dSDimitry Andric if (RHSRes.isInvalid()) 220bdd1243dSDimitry Andric return ExprError(); 221bdd1243dSDimitry Andric 2225f757f3fSDimitry Andric bool IsRHSSatisfied = Satisfaction.IsSatisfied; 2235f757f3fSDimitry Andric // Current implementation adds diagnostic information about the falsity 2245f757f3fSDimitry Andric // of each false atomic constraint expression when it evaluates them. 2255f757f3fSDimitry Andric // When the evaluation results to `false || true`, the information 2265f757f3fSDimitry Andric // generated during the evaluation of left-hand side is meaningless 2275f757f3fSDimitry Andric // because the whole expression evaluates to true. 2285f757f3fSDimitry Andric // The following code removes the irrelevant diagnostic information. 2295f757f3fSDimitry Andric // FIXME: We should probably delay the addition of diagnostic information 2305f757f3fSDimitry Andric // until we know the entire expression is false. 2315f757f3fSDimitry Andric if (BO.isOr() && IsRHSSatisfied) { 2325f757f3fSDimitry Andric auto EffectiveDetailEnd = Satisfaction.Details.begin(); 2335f757f3fSDimitry Andric std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex); 2345f757f3fSDimitry Andric Satisfaction.Details.erase(EffectiveDetailEnd, 2355f757f3fSDimitry Andric Satisfaction.Details.end()); 2365f757f3fSDimitry Andric } 2375f757f3fSDimitry Andric 238bdd1243dSDimitry Andric return BO.recreateBinOp(S, LHSRes, RHSRes); 239bdd1243dSDimitry Andric } 240bdd1243dSDimitry Andric 241bdd1243dSDimitry Andric if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) { 242bdd1243dSDimitry Andric // These aren't evaluated, so we don't care about cleanups, so we can just 243bdd1243dSDimitry Andric // evaluate these as if the cleanups didn't exist. 244bdd1243dSDimitry Andric return calculateConstraintSatisfaction( 245bdd1243dSDimitry Andric S, C->getSubExpr(), Satisfaction, 246480093f4SDimitry Andric std::forward<AtomicEvaluator>(Evaluator)); 2475ffd83dbSDimitry Andric } 248480093f4SDimitry Andric 249480093f4SDimitry Andric // An atomic constraint expression 250480093f4SDimitry Andric ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr); 251480093f4SDimitry Andric 252480093f4SDimitry Andric if (SubstitutedAtomicExpr.isInvalid()) 253bdd1243dSDimitry Andric return ExprError(); 254480093f4SDimitry Andric 255480093f4SDimitry Andric if (!SubstitutedAtomicExpr.isUsable()) 256480093f4SDimitry Andric // Evaluator has decided satisfaction without yielding an expression. 257bdd1243dSDimitry Andric return ExprEmpty(); 258bdd1243dSDimitry Andric 259bdd1243dSDimitry Andric // We don't have the ability to evaluate this, since it contains a 260bdd1243dSDimitry Andric // RecoveryExpr, so we want to fail overload resolution. Otherwise, 261bdd1243dSDimitry Andric // we'd potentially pick up a different overload, and cause confusing 262bdd1243dSDimitry Andric // diagnostics. SO, add a failure detail that will cause us to make this 263bdd1243dSDimitry Andric // overload set not viable. 264bdd1243dSDimitry Andric if (SubstitutedAtomicExpr.get()->containsErrors()) { 265bdd1243dSDimitry Andric Satisfaction.IsSatisfied = false; 266bdd1243dSDimitry Andric Satisfaction.ContainsErrors = true; 267bdd1243dSDimitry Andric 268bdd1243dSDimitry Andric PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error); 269bdd1243dSDimitry Andric SmallString<128> DiagString; 270bdd1243dSDimitry Andric DiagString = ": "; 271bdd1243dSDimitry Andric Msg.EmitToString(S.getDiagnostics(), DiagString); 272bdd1243dSDimitry Andric unsigned MessageSize = DiagString.size(); 273bdd1243dSDimitry Andric char *Mem = new (S.Context) char[MessageSize]; 274bdd1243dSDimitry Andric memcpy(Mem, DiagString.c_str(), MessageSize); 275bdd1243dSDimitry Andric Satisfaction.Details.emplace_back( 276bdd1243dSDimitry Andric ConstraintExpr, 277bdd1243dSDimitry Andric new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 278bdd1243dSDimitry Andric SubstitutedAtomicExpr.get()->getBeginLoc(), 279bdd1243dSDimitry Andric StringRef(Mem, MessageSize)}); 280bdd1243dSDimitry Andric return SubstitutedAtomicExpr; 281bdd1243dSDimitry Andric } 282a7dea167SDimitry Andric 283a7dea167SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 284480093f4SDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 285a7dea167SDimitry Andric SmallVector<PartialDiagnosticAt, 2> EvaluationDiags; 286a7dea167SDimitry Andric Expr::EvalResult EvalResult; 287a7dea167SDimitry Andric EvalResult.Diag = &EvaluationDiags; 288fe6060f1SDimitry Andric if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult, 289fe6060f1SDimitry Andric S.Context) || 290fe6060f1SDimitry Andric !EvaluationDiags.empty()) { 291a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 292a7dea167SDimitry Andric // ...E shall be a constant expression of type bool. 293480093f4SDimitry Andric S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(), 294a7dea167SDimitry Andric diag::err_non_constant_constraint_expression) 295480093f4SDimitry Andric << SubstitutedAtomicExpr.get()->getSourceRange(); 296a7dea167SDimitry Andric for (const PartialDiagnosticAt &PDiag : EvaluationDiags) 297480093f4SDimitry Andric S.Diag(PDiag.first, PDiag.second); 298bdd1243dSDimitry Andric return ExprError(); 299a7dea167SDimitry Andric } 300a7dea167SDimitry Andric 301fe6060f1SDimitry Andric assert(EvalResult.Val.isInt() && 302fe6060f1SDimitry Andric "evaluating bool expression didn't produce int"); 303480093f4SDimitry Andric Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); 304480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) 305480093f4SDimitry Andric Satisfaction.Details.emplace_back(ConstraintExpr, 306480093f4SDimitry Andric SubstitutedAtomicExpr.get()); 307a7dea167SDimitry Andric 308bdd1243dSDimitry Andric return SubstitutedAtomicExpr; 309bdd1243dSDimitry Andric } 310bdd1243dSDimitry Andric 311bdd1243dSDimitry Andric static bool 3121ac55f4cSDimitry Andric DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, 3131ac55f4cSDimitry Andric const NamedDecl *Templ, const Expr *E, 314bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL) { 315bdd1243dSDimitry Andric E->Profile(ID, S.Context, /*Canonical=*/true); 316bdd1243dSDimitry Andric for (const auto &List : MLTAL) 317bdd1243dSDimitry Andric for (const auto &TemplateArg : List.Args) 318bdd1243dSDimitry Andric TemplateArg.Profile(ID, S.Context); 319bdd1243dSDimitry Andric 320bdd1243dSDimitry Andric // Note that we have to do this with our own collection, because there are 321bdd1243dSDimitry Andric // times where a constraint-expression check can cause us to need to evaluate 322bdd1243dSDimitry Andric // other constriants that are unrelated, such as when evaluating a recovery 323bdd1243dSDimitry Andric // expression, or when trying to determine the constexpr-ness of special 324bdd1243dSDimitry Andric // members. Otherwise we could just use the 325bdd1243dSDimitry Andric // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function. 3261ac55f4cSDimitry Andric if (S.SatisfactionStackContains(Templ, ID)) { 327bdd1243dSDimitry Andric S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self) 328bdd1243dSDimitry Andric << const_cast<Expr *>(E) << E->getSourceRange(); 329bdd1243dSDimitry Andric return true; 330bdd1243dSDimitry Andric } 331bdd1243dSDimitry Andric 332a7dea167SDimitry Andric return false; 333a7dea167SDimitry Andric } 334480093f4SDimitry Andric 335bdd1243dSDimitry Andric static ExprResult calculateConstraintSatisfaction( 336bdd1243dSDimitry Andric Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc, 337bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr, 338bdd1243dSDimitry Andric ConstraintSatisfaction &Satisfaction) { 339480093f4SDimitry Andric return calculateConstraintSatisfaction( 340480093f4SDimitry Andric S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) { 341480093f4SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 342bdd1243dSDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated, 343bdd1243dSDimitry Andric Sema::ReuseLambdaContextDecl); 344480093f4SDimitry Andric 345480093f4SDimitry Andric // Atomic constraint - substitute arguments and check satisfaction. 346480093f4SDimitry Andric ExprResult SubstitutedExpression; 347480093f4SDimitry Andric { 348480093f4SDimitry Andric TemplateDeductionInfo Info(TemplateNameLoc); 349480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(), 35013138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintSubstitution{}, 35113138422SDimitry Andric const_cast<NamedDecl *>(Template), Info, 35213138422SDimitry Andric AtomicExpr->getSourceRange()); 353480093f4SDimitry Andric if (Inst.isInvalid()) 354480093f4SDimitry Andric return ExprError(); 355bdd1243dSDimitry Andric 356bdd1243dSDimitry Andric llvm::FoldingSetNodeID ID; 3571ac55f4cSDimitry Andric if (Template && 3581ac55f4cSDimitry Andric DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) { 359bdd1243dSDimitry Andric Satisfaction.IsSatisfied = false; 360bdd1243dSDimitry Andric Satisfaction.ContainsErrors = true; 361bdd1243dSDimitry Andric return ExprEmpty(); 362bdd1243dSDimitry Andric } 363bdd1243dSDimitry Andric 3641ac55f4cSDimitry Andric SatisfactionStackRAII StackRAII(S, Template, ID); 365bdd1243dSDimitry Andric 366480093f4SDimitry Andric // We do not want error diagnostics escaping here. 367480093f4SDimitry Andric Sema::SFINAETrap Trap(S); 368fe6060f1SDimitry Andric SubstitutedExpression = 369bdd1243dSDimitry Andric S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL); 370bdd1243dSDimitry Andric 371480093f4SDimitry Andric if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) { 372480093f4SDimitry Andric // C++2a [temp.constr.atomic]p1 373480093f4SDimitry Andric // ...If substitution results in an invalid type or expression, the 374480093f4SDimitry Andric // constraint is not satisfied. 375480093f4SDimitry Andric if (!Trap.hasErrorOccurred()) 376349cc55cSDimitry Andric // A non-SFINAE error has occurred as a result of this 377480093f4SDimitry Andric // substitution. 378480093f4SDimitry Andric return ExprError(); 379480093f4SDimitry Andric 380480093f4SDimitry Andric PartialDiagnosticAt SubstDiag{SourceLocation(), 381480093f4SDimitry Andric PartialDiagnostic::NullDiagnostic()}; 382480093f4SDimitry Andric Info.takeSFINAEDiagnostic(SubstDiag); 383480093f4SDimitry Andric // FIXME: Concepts: This is an unfortunate consequence of there 384480093f4SDimitry Andric // being no serialization code for PartialDiagnostics and the fact 385480093f4SDimitry Andric // that serializing them would likely take a lot more storage than 386480093f4SDimitry Andric // just storing them as strings. We would still like, in the 387480093f4SDimitry Andric // future, to serialize the proper PartialDiagnostic as serializing 388480093f4SDimitry Andric // it as a string defeats the purpose of the diagnostic mechanism. 389480093f4SDimitry Andric SmallString<128> DiagString; 390480093f4SDimitry Andric DiagString = ": "; 391480093f4SDimitry Andric SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString); 392480093f4SDimitry Andric unsigned MessageSize = DiagString.size(); 393480093f4SDimitry Andric char *Mem = new (S.Context) char[MessageSize]; 394480093f4SDimitry Andric memcpy(Mem, DiagString.c_str(), MessageSize); 395480093f4SDimitry Andric Satisfaction.Details.emplace_back( 396480093f4SDimitry Andric AtomicExpr, 397480093f4SDimitry Andric new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 398480093f4SDimitry Andric SubstDiag.first, StringRef(Mem, MessageSize)}); 399480093f4SDimitry Andric Satisfaction.IsSatisfied = false; 400480093f4SDimitry Andric return ExprEmpty(); 401480093f4SDimitry Andric } 402480093f4SDimitry Andric } 403480093f4SDimitry Andric 404480093f4SDimitry Andric if (!S.CheckConstraintExpression(SubstitutedExpression.get())) 405480093f4SDimitry Andric return ExprError(); 406480093f4SDimitry Andric 407bdd1243dSDimitry Andric // [temp.constr.atomic]p3: To determine if an atomic constraint is 408bdd1243dSDimitry Andric // satisfied, the parameter mapping and template arguments are first 409bdd1243dSDimitry Andric // substituted into its expression. If substitution results in an 410bdd1243dSDimitry Andric // invalid type or expression, the constraint is not satisfied. 411bdd1243dSDimitry Andric // Otherwise, the lvalue-to-rvalue conversion is performed if necessary, 412bdd1243dSDimitry Andric // and E shall be a constant expression of type bool. 413bdd1243dSDimitry Andric // 414bdd1243dSDimitry Andric // Perform the L to R Value conversion if necessary. We do so for all 415bdd1243dSDimitry Andric // non-PRValue categories, else we fail to extend the lifetime of 416bdd1243dSDimitry Andric // temporaries, and that fails the constant expression check. 417bdd1243dSDimitry Andric if (!SubstitutedExpression.get()->isPRValue()) 418bdd1243dSDimitry Andric SubstitutedExpression = ImplicitCastExpr::Create( 419bdd1243dSDimitry Andric S.Context, SubstitutedExpression.get()->getType(), 420bdd1243dSDimitry Andric CK_LValueToRValue, SubstitutedExpression.get(), 421bdd1243dSDimitry Andric /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride()); 422bdd1243dSDimitry Andric 423480093f4SDimitry Andric return SubstitutedExpression; 424480093f4SDimitry Andric }); 425480093f4SDimitry Andric } 426480093f4SDimitry Andric 427bdd1243dSDimitry Andric static bool CheckConstraintSatisfaction( 428bdd1243dSDimitry Andric Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 429bdd1243dSDimitry Andric llvm::SmallVectorImpl<Expr *> &Converted, 430bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &TemplateArgsLists, 431bdd1243dSDimitry Andric SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { 432480093f4SDimitry Andric if (ConstraintExprs.empty()) { 433480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 434480093f4SDimitry Andric return false; 435480093f4SDimitry Andric } 436480093f4SDimitry Andric 437bdd1243dSDimitry Andric if (TemplateArgsLists.isAnyArgInstantiationDependent()) { 438480093f4SDimitry Andric // No need to check satisfaction for dependent constraint expressions. 439480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 440480093f4SDimitry Andric return false; 441480093f4SDimitry Andric } 442480093f4SDimitry Andric 443bdd1243dSDimitry Andric ArrayRef<TemplateArgument> TemplateArgs = 444bdd1243dSDimitry Andric TemplateArgsLists.getNumSubstitutedLevels() > 0 445bdd1243dSDimitry Andric ? TemplateArgsLists.getOutermost() 446bdd1243dSDimitry Andric : ArrayRef<TemplateArgument> {}; 447480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), 44813138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, 44913138422SDimitry Andric const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); 450480093f4SDimitry Andric if (Inst.isInvalid()) 451480093f4SDimitry Andric return true; 452480093f4SDimitry Andric 453480093f4SDimitry Andric for (const Expr *ConstraintExpr : ConstraintExprs) { 454bdd1243dSDimitry Andric ExprResult Res = calculateConstraintSatisfaction( 455bdd1243dSDimitry Andric S, Template, TemplateIDRange.getBegin(), TemplateArgsLists, 456bdd1243dSDimitry Andric ConstraintExpr, Satisfaction); 457bdd1243dSDimitry Andric if (Res.isInvalid()) 458480093f4SDimitry Andric return true; 459bdd1243dSDimitry Andric 460bdd1243dSDimitry Andric Converted.push_back(Res.get()); 461bdd1243dSDimitry Andric if (!Satisfaction.IsSatisfied) { 462bdd1243dSDimitry Andric // Backfill the 'converted' list with nulls so we can keep the Converted 463bdd1243dSDimitry Andric // and unconverted lists in sync. 464bdd1243dSDimitry Andric Converted.append(ConstraintExprs.size() - Converted.size(), nullptr); 465480093f4SDimitry Andric // [temp.constr.op] p2 466480093f4SDimitry Andric // [...] To determine if a conjunction is satisfied, the satisfaction 467480093f4SDimitry Andric // of the first operand is checked. If that is not satisfied, the 468480093f4SDimitry Andric // conjunction is not satisfied. [...] 469480093f4SDimitry Andric return false; 470480093f4SDimitry Andric } 471bdd1243dSDimitry Andric } 472480093f4SDimitry Andric return false; 473480093f4SDimitry Andric } 474480093f4SDimitry Andric 47555e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction( 47613138422SDimitry Andric const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 477bdd1243dSDimitry Andric llvm::SmallVectorImpl<Expr *> &ConvertedConstraints, 478bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &TemplateArgsLists, 479bdd1243dSDimitry Andric SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) { 48055e4f9d5SDimitry Andric if (ConstraintExprs.empty()) { 48155e4f9d5SDimitry Andric OutSatisfaction.IsSatisfied = true; 48255e4f9d5SDimitry Andric return false; 483480093f4SDimitry Andric } 48481ad6265SDimitry Andric if (!Template) { 485bdd1243dSDimitry Andric return ::CheckConstraintSatisfaction( 486bdd1243dSDimitry Andric *this, nullptr, ConstraintExprs, ConvertedConstraints, 487bdd1243dSDimitry Andric TemplateArgsLists, TemplateIDRange, OutSatisfaction); 48881ad6265SDimitry Andric } 489bdd1243dSDimitry Andric 490bdd1243dSDimitry Andric // A list of the template argument list flattened in a predictible manner for 491bdd1243dSDimitry Andric // the purposes of caching. The ConstraintSatisfaction type is in AST so it 492bdd1243dSDimitry Andric // has no access to the MultiLevelTemplateArgumentList, so this has to happen 493bdd1243dSDimitry Andric // here. 494bdd1243dSDimitry Andric llvm::SmallVector<TemplateArgument, 4> FlattenedArgs; 495bdd1243dSDimitry Andric for (auto List : TemplateArgsLists) 496bdd1243dSDimitry Andric FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(), 497bdd1243dSDimitry Andric List.Args.end()); 498bdd1243dSDimitry Andric 49955e4f9d5SDimitry Andric llvm::FoldingSetNodeID ID; 500bdd1243dSDimitry Andric ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs); 50181ad6265SDimitry Andric void *InsertPos; 50281ad6265SDimitry Andric if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 50381ad6265SDimitry Andric OutSatisfaction = *Cached; 50455e4f9d5SDimitry Andric return false; 50555e4f9d5SDimitry Andric } 506bdd1243dSDimitry Andric 50781ad6265SDimitry Andric auto Satisfaction = 508bdd1243dSDimitry Andric std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs); 50913138422SDimitry Andric if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, 510bdd1243dSDimitry Andric ConvertedConstraints, TemplateArgsLists, 511bdd1243dSDimitry Andric TemplateIDRange, *Satisfaction)) { 512bdd1243dSDimitry Andric OutSatisfaction = *Satisfaction; 51355e4f9d5SDimitry Andric return true; 514480093f4SDimitry Andric } 515bdd1243dSDimitry Andric 516bdd1243dSDimitry Andric if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 517bdd1243dSDimitry Andric // The evaluation of this constraint resulted in us trying to re-evaluate it 518bdd1243dSDimitry Andric // recursively. This isn't really possible, except we try to form a 519bdd1243dSDimitry Andric // RecoveryExpr as a part of the evaluation. If this is the case, just 520bdd1243dSDimitry Andric // return the 'cached' version (which will have the same result), and save 521bdd1243dSDimitry Andric // ourselves the extra-insert. If it ever becomes possible to legitimately 522bdd1243dSDimitry Andric // recursively check a constraint, we should skip checking the 'inner' one 523bdd1243dSDimitry Andric // above, and replace the cached version with this one, as it would be more 524bdd1243dSDimitry Andric // specific. 525bdd1243dSDimitry Andric OutSatisfaction = *Cached; 526bdd1243dSDimitry Andric return false; 527bdd1243dSDimitry Andric } 528bdd1243dSDimitry Andric 529bdd1243dSDimitry Andric // Else we can simply add this satisfaction to the list. 53055e4f9d5SDimitry Andric OutSatisfaction = *Satisfaction; 53181ad6265SDimitry Andric // We cannot use InsertPos here because CheckConstraintSatisfaction might have 53281ad6265SDimitry Andric // invalidated it. 53381ad6265SDimitry Andric // Note that entries of SatisfactionCache are deleted in Sema's destructor. 53481ad6265SDimitry Andric SatisfactionCache.InsertNode(Satisfaction.release()); 53555e4f9d5SDimitry Andric return false; 536480093f4SDimitry Andric } 537480093f4SDimitry Andric 538480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr, 539480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction) { 540480093f4SDimitry Andric return calculateConstraintSatisfaction( 541480093f4SDimitry Andric *this, ConstraintExpr, Satisfaction, 54281ad6265SDimitry Andric [this](const Expr *AtomicExpr) -> ExprResult { 54381ad6265SDimitry Andric // We only do this to immitate lvalue-to-rvalue conversion. 544bdd1243dSDimitry Andric return PerformContextuallyConvertToBool( 545bdd1243dSDimitry Andric const_cast<Expr *>(AtomicExpr)); 546bdd1243dSDimitry Andric }) 547bdd1243dSDimitry Andric .isInvalid(); 548bdd1243dSDimitry Andric } 549bdd1243dSDimitry Andric 55006c3fb27SDimitry Andric bool Sema::addInstantiatedCapturesToScope( 55106c3fb27SDimitry Andric FunctionDecl *Function, const FunctionDecl *PatternDecl, 55206c3fb27SDimitry Andric LocalInstantiationScope &Scope, 55306c3fb27SDimitry Andric const MultiLevelTemplateArgumentList &TemplateArgs) { 55406c3fb27SDimitry Andric const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent(); 55506c3fb27SDimitry Andric const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent(); 55606c3fb27SDimitry Andric 55706c3fb27SDimitry Andric unsigned Instantiated = 0; 55806c3fb27SDimitry Andric 55906c3fb27SDimitry Andric auto AddSingleCapture = [&](const ValueDecl *CapturedPattern, 56006c3fb27SDimitry Andric unsigned Index) { 56106c3fb27SDimitry Andric ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar(); 56206c3fb27SDimitry Andric if (CapturedVar->isInitCapture()) 56306c3fb27SDimitry Andric Scope.InstantiatedLocal(CapturedPattern, CapturedVar); 56406c3fb27SDimitry Andric }; 56506c3fb27SDimitry Andric 56606c3fb27SDimitry Andric for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) { 56706c3fb27SDimitry Andric if (!CapturePattern.capturesVariable()) { 56806c3fb27SDimitry Andric Instantiated++; 56906c3fb27SDimitry Andric continue; 57006c3fb27SDimitry Andric } 57106c3fb27SDimitry Andric const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar(); 57206c3fb27SDimitry Andric if (!CapturedPattern->isParameterPack()) { 57306c3fb27SDimitry Andric AddSingleCapture(CapturedPattern, Instantiated++); 57406c3fb27SDimitry Andric } else { 57506c3fb27SDimitry Andric Scope.MakeInstantiatedLocalArgPack(CapturedPattern); 57606c3fb27SDimitry Andric std::optional<unsigned> NumArgumentsInExpansion = 57706c3fb27SDimitry Andric getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs); 57806c3fb27SDimitry Andric if (!NumArgumentsInExpansion) 57906c3fb27SDimitry Andric continue; 58006c3fb27SDimitry Andric for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) 58106c3fb27SDimitry Andric AddSingleCapture(CapturedPattern, Instantiated++); 58206c3fb27SDimitry Andric } 58306c3fb27SDimitry Andric } 58406c3fb27SDimitry Andric return false; 58506c3fb27SDimitry Andric } 58606c3fb27SDimitry Andric 587bdd1243dSDimitry Andric bool Sema::SetupConstraintScope( 588bdd1243dSDimitry Andric FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 589bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) { 590bdd1243dSDimitry Andric if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { 591bdd1243dSDimitry Andric FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); 592bdd1243dSDimitry Andric InstantiatingTemplate Inst( 593bdd1243dSDimitry Andric *this, FD->getPointOfInstantiation(), 594bdd1243dSDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate, 595bdd1243dSDimitry Andric TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 596bdd1243dSDimitry Andric SourceRange()); 597bdd1243dSDimitry Andric if (Inst.isInvalid()) 598bdd1243dSDimitry Andric return true; 599bdd1243dSDimitry Andric 600bdd1243dSDimitry Andric // addInstantiatedParametersToScope creates a map of 'uninstantiated' to 601bdd1243dSDimitry Andric // 'instantiated' parameters and adds it to the context. For the case where 602bdd1243dSDimitry Andric // this function is a template being instantiated NOW, we also need to add 603bdd1243dSDimitry Andric // the list of current template arguments to the list so that they also can 604bdd1243dSDimitry Andric // be picked out of the map. 605bdd1243dSDimitry Andric if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) { 606bdd1243dSDimitry Andric MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(), 607bdd1243dSDimitry Andric /*Final=*/false); 608bdd1243dSDimitry Andric if (addInstantiatedParametersToScope( 609bdd1243dSDimitry Andric FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs)) 610bdd1243dSDimitry Andric return true; 611bdd1243dSDimitry Andric } 612bdd1243dSDimitry Andric 613bdd1243dSDimitry Andric // If this is a member function, make sure we get the parameters that 614bdd1243dSDimitry Andric // reference the original primary template. 615*b3edf446SDimitry Andric // We walk up the instantiated template chain so that nested lambdas get 616*b3edf446SDimitry Andric // handled properly. 617*b3edf446SDimitry Andric for (FunctionTemplateDecl *FromMemTempl = 618*b3edf446SDimitry Andric PrimaryTemplate->getInstantiatedFromMemberTemplate(); 619*b3edf446SDimitry Andric FromMemTempl; 620*b3edf446SDimitry Andric FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate()) { 621bdd1243dSDimitry Andric if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(), 622bdd1243dSDimitry Andric Scope, MLTAL)) 623bdd1243dSDimitry Andric return true; 624bdd1243dSDimitry Andric } 625bdd1243dSDimitry Andric 626bdd1243dSDimitry Andric return false; 627bdd1243dSDimitry Andric } 628bdd1243dSDimitry Andric 629bdd1243dSDimitry Andric if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || 630bdd1243dSDimitry Andric FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) { 631bdd1243dSDimitry Andric FunctionDecl *InstantiatedFrom = 632bdd1243dSDimitry Andric FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization 633bdd1243dSDimitry Andric ? FD->getInstantiatedFromMemberFunction() 634bdd1243dSDimitry Andric : FD->getInstantiatedFromDecl(); 635bdd1243dSDimitry Andric 636bdd1243dSDimitry Andric InstantiatingTemplate Inst( 637bdd1243dSDimitry Andric *this, FD->getPointOfInstantiation(), 638bdd1243dSDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom, 639bdd1243dSDimitry Andric TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 640bdd1243dSDimitry Andric SourceRange()); 641bdd1243dSDimitry Andric if (Inst.isInvalid()) 642bdd1243dSDimitry Andric return true; 643bdd1243dSDimitry Andric 644bdd1243dSDimitry Andric // Case where this was not a template, but instantiated as a 645bdd1243dSDimitry Andric // child-function. 646bdd1243dSDimitry Andric if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL)) 647bdd1243dSDimitry Andric return true; 648bdd1243dSDimitry Andric } 649bdd1243dSDimitry Andric 650bdd1243dSDimitry Andric return false; 651bdd1243dSDimitry Andric } 652bdd1243dSDimitry Andric 653bdd1243dSDimitry Andric // This function collects all of the template arguments for the purposes of 654bdd1243dSDimitry Andric // constraint-instantiation and checking. 655bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> 656bdd1243dSDimitry Andric Sema::SetupConstraintCheckingTemplateArgumentsAndScope( 657bdd1243dSDimitry Andric FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 658bdd1243dSDimitry Andric LocalInstantiationScope &Scope) { 659bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL; 660bdd1243dSDimitry Andric 661bdd1243dSDimitry Andric // Collect the list of template arguments relative to the 'primary' template. 662bdd1243dSDimitry Andric // We need the entire list, since the constraint is completely uninstantiated 663bdd1243dSDimitry Andric // at this point. 6645f757f3fSDimitry Andric MLTAL = getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), 6655f757f3fSDimitry Andric /*Final=*/false, /*Innermost=*/nullptr, 666bdd1243dSDimitry Andric /*RelativeToPrimary=*/true, 667bdd1243dSDimitry Andric /*Pattern=*/nullptr, 668bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true); 669bdd1243dSDimitry Andric if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) 670bdd1243dSDimitry Andric return std::nullopt; 671bdd1243dSDimitry Andric 672bdd1243dSDimitry Andric return MLTAL; 673480093f4SDimitry Andric } 674480093f4SDimitry Andric 67513138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, 67613138422SDimitry Andric ConstraintSatisfaction &Satisfaction, 677bdd1243dSDimitry Andric SourceLocation UsageLoc, 678bdd1243dSDimitry Andric bool ForOverloadResolution) { 679bdd1243dSDimitry Andric // Don't check constraints if the function is dependent. Also don't check if 680bdd1243dSDimitry Andric // this is a function template specialization, as the call to 681bdd1243dSDimitry Andric // CheckinstantiatedFunctionTemplateConstraints after this will check it 682bdd1243dSDimitry Andric // better. 683bdd1243dSDimitry Andric if (FD->isDependentContext() || 684bdd1243dSDimitry Andric FD->getTemplatedKind() == 685bdd1243dSDimitry Andric FunctionDecl::TK_FunctionTemplateSpecialization) { 68613138422SDimitry Andric Satisfaction.IsSatisfied = true; 68713138422SDimitry Andric return false; 68813138422SDimitry Andric } 689bdd1243dSDimitry Andric 69006c3fb27SDimitry Andric // A lambda conversion operator has the same constraints as the call operator 69106c3fb27SDimitry Andric // and constraints checking relies on whether we are in a lambda call operator 69206c3fb27SDimitry Andric // (and may refer to its parameters), so check the call operator instead. 69306c3fb27SDimitry Andric if (const auto *MD = dyn_cast<CXXConversionDecl>(FD); 69406c3fb27SDimitry Andric MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD))) 69506c3fb27SDimitry Andric return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(), 69606c3fb27SDimitry Andric Satisfaction, UsageLoc, 69706c3fb27SDimitry Andric ForOverloadResolution); 69806c3fb27SDimitry Andric 699bdd1243dSDimitry Andric DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD); 700bdd1243dSDimitry Andric 701bdd1243dSDimitry Andric while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) { 702bdd1243dSDimitry Andric if (isLambdaCallOperator(CtxToSave)) 703bdd1243dSDimitry Andric CtxToSave = CtxToSave->getParent()->getParent(); 704bdd1243dSDimitry Andric else 705bdd1243dSDimitry Andric CtxToSave = CtxToSave->getNonTransparentContext(); 706bdd1243dSDimitry Andric } 707bdd1243dSDimitry Andric 708bdd1243dSDimitry Andric ContextRAII SavedContext{*this, CtxToSave}; 7095f757f3fSDimitry Andric LocalInstantiationScope Scope(*this, !ForOverloadResolution); 710bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> MLTAL = 711bdd1243dSDimitry Andric SetupConstraintCheckingTemplateArgumentsAndScope( 712bdd1243dSDimitry Andric const_cast<FunctionDecl *>(FD), {}, Scope); 713bdd1243dSDimitry Andric 714bdd1243dSDimitry Andric if (!MLTAL) 715bdd1243dSDimitry Andric return true; 716bdd1243dSDimitry Andric 71713138422SDimitry Andric Qualifiers ThisQuals; 71813138422SDimitry Andric CXXRecordDecl *Record = nullptr; 71913138422SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { 72013138422SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 72113138422SDimitry Andric Record = const_cast<CXXRecordDecl *>(Method->getParent()); 72213138422SDimitry Andric } 72313138422SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 724feb5b0c7SDimitry Andric 725feb5b0c7SDimitry Andric LambdaScopeForCallOperatorInstantiationRAII LambdaScope( 7265f757f3fSDimitry Andric *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope, 7275f757f3fSDimitry Andric ForOverloadResolution); 728feb5b0c7SDimitry Andric 72906c3fb27SDimitry Andric return CheckConstraintSatisfaction( 73006c3fb27SDimitry Andric FD, {FD->getTrailingRequiresClause()}, *MLTAL, 73113138422SDimitry Andric SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), 73206c3fb27SDimitry Andric Satisfaction); 733bdd1243dSDimitry Andric } 734bdd1243dSDimitry Andric 735bdd1243dSDimitry Andric 736bdd1243dSDimitry Andric // Figure out the to-translation-unit depth for this function declaration for 737bdd1243dSDimitry Andric // the purpose of seeing if they differ by constraints. This isn't the same as 738bdd1243dSDimitry Andric // getTemplateDepth, because it includes already instantiated parents. 739bdd1243dSDimitry Andric static unsigned 740bdd1243dSDimitry Andric CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, 741bdd1243dSDimitry Andric bool SkipForSpecialization = false) { 742bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 7435f757f3fSDimitry Andric ND, ND->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/nullptr, 7445f757f3fSDimitry Andric /*RelativeToPrimary=*/true, 745bdd1243dSDimitry Andric /*Pattern=*/nullptr, 746bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true, SkipForSpecialization); 74706c3fb27SDimitry Andric return MLTAL.getNumLevels(); 748bdd1243dSDimitry Andric } 749bdd1243dSDimitry Andric 750bdd1243dSDimitry Andric namespace { 751bdd1243dSDimitry Andric class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> { 752bdd1243dSDimitry Andric unsigned TemplateDepth = 0; 753bdd1243dSDimitry Andric public: 754bdd1243dSDimitry Andric using inherited = TreeTransform<AdjustConstraintDepth>; 755bdd1243dSDimitry Andric AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth) 756bdd1243dSDimitry Andric : inherited(SemaRef), TemplateDepth(TemplateDepth) {} 757bdd1243dSDimitry Andric 758bdd1243dSDimitry Andric using inherited::TransformTemplateTypeParmType; 759bdd1243dSDimitry Andric QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, 760bdd1243dSDimitry Andric TemplateTypeParmTypeLoc TL, bool) { 761bdd1243dSDimitry Andric const TemplateTypeParmType *T = TL.getTypePtr(); 762bdd1243dSDimitry Andric 763bdd1243dSDimitry Andric TemplateTypeParmDecl *NewTTPDecl = nullptr; 764bdd1243dSDimitry Andric if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) 765bdd1243dSDimitry Andric NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( 766bdd1243dSDimitry Andric TransformDecl(TL.getNameLoc(), OldTTPDecl)); 767bdd1243dSDimitry Andric 768bdd1243dSDimitry Andric QualType Result = getSema().Context.getTemplateTypeParmType( 769bdd1243dSDimitry Andric T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(), 770bdd1243dSDimitry Andric NewTTPDecl); 771bdd1243dSDimitry Andric TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); 772bdd1243dSDimitry Andric NewTL.setNameLoc(TL.getNameLoc()); 773bdd1243dSDimitry Andric return Result; 774bdd1243dSDimitry Andric } 775bdd1243dSDimitry Andric }; 776bdd1243dSDimitry Andric } // namespace 777bdd1243dSDimitry Andric 7781db9f3b2SDimitry Andric static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( 7791db9f3b2SDimitry Andric Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, 78006c3fb27SDimitry Andric const Expr *ConstrExpr) { 78106c3fb27SDimitry Andric MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 7825f757f3fSDimitry Andric DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, 7835f757f3fSDimitry Andric /*Innermost=*/nullptr, 78406c3fb27SDimitry Andric /*RelativeToPrimary=*/true, 78506c3fb27SDimitry Andric /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, 78606c3fb27SDimitry Andric /*SkipForSpecialization*/ false); 7875f757f3fSDimitry Andric 78806c3fb27SDimitry Andric if (MLTAL.getNumSubstitutedLevels() == 0) 78906c3fb27SDimitry Andric return ConstrExpr; 79006c3fb27SDimitry Andric 79106c3fb27SDimitry Andric Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false); 79206c3fb27SDimitry Andric 79306c3fb27SDimitry Andric Sema::InstantiatingTemplate Inst( 7945f757f3fSDimitry Andric S, DeclInfo.getLocation(), 79506c3fb27SDimitry Andric Sema::InstantiatingTemplate::ConstraintNormalization{}, 7965f757f3fSDimitry Andric const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{}); 79706c3fb27SDimitry Andric if (Inst.isInvalid()) 79806c3fb27SDimitry Andric return nullptr; 79906c3fb27SDimitry Andric 80006c3fb27SDimitry Andric std::optional<Sema::CXXThisScopeRAII> ThisScope; 8015f757f3fSDimitry Andric if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext())) 80206c3fb27SDimitry Andric ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers()); 8031db9f3b2SDimitry Andric ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction( 8041db9f3b2SDimitry Andric const_cast<clang::Expr *>(ConstrExpr), MLTAL); 80506c3fb27SDimitry Andric if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable()) 80606c3fb27SDimitry Andric return nullptr; 80706c3fb27SDimitry Andric return SubstConstr.get(); 80806c3fb27SDimitry Andric } 80906c3fb27SDimitry Andric 810bdd1243dSDimitry Andric bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, 811bdd1243dSDimitry Andric const Expr *OldConstr, 8125f757f3fSDimitry Andric const TemplateCompareNewDeclInfo &New, 813bdd1243dSDimitry Andric const Expr *NewConstr) { 81406c3fb27SDimitry Andric if (OldConstr == NewConstr) 81506c3fb27SDimitry Andric return true; 81606c3fb27SDimitry Andric // C++ [temp.constr.decl]p4 8175f757f3fSDimitry Andric if (Old && !New.isInvalid() && !New.ContainsDecl(Old) && 8185f757f3fSDimitry Andric Old->getLexicalDeclContext() != New.getLexicalDeclContext()) { 81906c3fb27SDimitry Andric if (const Expr *SubstConstr = 8201db9f3b2SDimitry Andric SubstituteConstraintExpressionWithoutSatisfaction(*this, Old, 8211db9f3b2SDimitry Andric OldConstr)) 82206c3fb27SDimitry Andric OldConstr = SubstConstr; 82306c3fb27SDimitry Andric else 82406c3fb27SDimitry Andric return false; 82506c3fb27SDimitry Andric if (const Expr *SubstConstr = 8261db9f3b2SDimitry Andric SubstituteConstraintExpressionWithoutSatisfaction(*this, New, 8271db9f3b2SDimitry Andric NewConstr)) 82806c3fb27SDimitry Andric NewConstr = SubstConstr; 82906c3fb27SDimitry Andric else 83006c3fb27SDimitry Andric return false; 831bdd1243dSDimitry Andric } 832bdd1243dSDimitry Andric 833bdd1243dSDimitry Andric llvm::FoldingSetNodeID ID1, ID2; 834bdd1243dSDimitry Andric OldConstr->Profile(ID1, Context, /*Canonical=*/true); 835bdd1243dSDimitry Andric NewConstr->Profile(ID2, Context, /*Canonical=*/true); 836bdd1243dSDimitry Andric return ID1 == ID2; 837bdd1243dSDimitry Andric } 838bdd1243dSDimitry Andric 839bdd1243dSDimitry Andric bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { 840bdd1243dSDimitry Andric assert(FD->getFriendObjectKind() && "Must be a friend!"); 841bdd1243dSDimitry Andric 842bdd1243dSDimitry Andric // The logic for non-templates is handled in ASTContext::isSameEntity, so we 843bdd1243dSDimitry Andric // don't have to bother checking 'DependsOnEnclosingTemplate' for a 844bdd1243dSDimitry Andric // non-function-template. 845bdd1243dSDimitry Andric assert(FD->getDescribedFunctionTemplate() && 846bdd1243dSDimitry Andric "Non-function templates don't need to be checked"); 847bdd1243dSDimitry Andric 848bdd1243dSDimitry Andric SmallVector<const Expr *, 3> ACs; 849bdd1243dSDimitry Andric FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); 850bdd1243dSDimitry Andric 851bdd1243dSDimitry Andric unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD); 852bdd1243dSDimitry Andric for (const Expr *Constraint : ACs) 853bdd1243dSDimitry Andric if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth, 854bdd1243dSDimitry Andric Constraint)) 855bdd1243dSDimitry Andric return true; 856bdd1243dSDimitry Andric 857bdd1243dSDimitry Andric return false; 85813138422SDimitry Andric } 85913138422SDimitry Andric 860480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints( 861bdd1243dSDimitry Andric TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists, 862480093f4SDimitry Andric SourceRange TemplateIDRange) { 863480093f4SDimitry Andric ConstraintSatisfaction Satisfaction; 864480093f4SDimitry Andric llvm::SmallVector<const Expr *, 3> AssociatedConstraints; 865480093f4SDimitry Andric TD->getAssociatedConstraints(AssociatedConstraints); 866bdd1243dSDimitry Andric if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists, 867480093f4SDimitry Andric TemplateIDRange, Satisfaction)) 868480093f4SDimitry Andric return true; 869480093f4SDimitry Andric 870480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) { 871480093f4SDimitry Andric SmallString<128> TemplateArgString; 872480093f4SDimitry Andric TemplateArgString = " "; 873480093f4SDimitry Andric TemplateArgString += getTemplateArgumentBindingsText( 874bdd1243dSDimitry Andric TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(), 875bdd1243dSDimitry Andric TemplateArgsLists.getInnermost().size()); 876480093f4SDimitry Andric 877480093f4SDimitry Andric Diag(TemplateIDRange.getBegin(), 878480093f4SDimitry Andric diag::err_template_arg_list_constraints_not_satisfied) 879480093f4SDimitry Andric << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD 880480093f4SDimitry Andric << TemplateArgString << TemplateIDRange; 881480093f4SDimitry Andric DiagnoseUnsatisfiedConstraint(Satisfaction); 882480093f4SDimitry Andric return true; 883480093f4SDimitry Andric } 884480093f4SDimitry Andric return false; 885480093f4SDimitry Andric } 886480093f4SDimitry Andric 88781ad6265SDimitry Andric bool Sema::CheckInstantiatedFunctionTemplateConstraints( 88881ad6265SDimitry Andric SourceLocation PointOfInstantiation, FunctionDecl *Decl, 88981ad6265SDimitry Andric ArrayRef<TemplateArgument> TemplateArgs, 89081ad6265SDimitry Andric ConstraintSatisfaction &Satisfaction) { 89181ad6265SDimitry Andric // In most cases we're not going to have constraints, so check for that first. 89281ad6265SDimitry Andric FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); 89381ad6265SDimitry Andric // Note - code synthesis context for the constraints check is created 89481ad6265SDimitry Andric // inside CheckConstraintsSatisfaction. 89581ad6265SDimitry Andric SmallVector<const Expr *, 3> TemplateAC; 89681ad6265SDimitry Andric Template->getAssociatedConstraints(TemplateAC); 89781ad6265SDimitry Andric if (TemplateAC.empty()) { 89881ad6265SDimitry Andric Satisfaction.IsSatisfied = true; 89981ad6265SDimitry Andric return false; 90081ad6265SDimitry Andric } 90181ad6265SDimitry Andric 90281ad6265SDimitry Andric // Enter the scope of this instantiation. We don't use 90381ad6265SDimitry Andric // PushDeclContext because we don't have a scope. 90481ad6265SDimitry Andric Sema::ContextRAII savedContext(*this, Decl); 90581ad6265SDimitry Andric LocalInstantiationScope Scope(*this); 90681ad6265SDimitry Andric 907bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> MLTAL = 908bdd1243dSDimitry Andric SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs, 909bdd1243dSDimitry Andric Scope); 910bdd1243dSDimitry Andric 911bdd1243dSDimitry Andric if (!MLTAL) 91281ad6265SDimitry Andric return true; 913bdd1243dSDimitry Andric 91481ad6265SDimitry Andric Qualifiers ThisQuals; 91581ad6265SDimitry Andric CXXRecordDecl *Record = nullptr; 91681ad6265SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { 91781ad6265SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 91881ad6265SDimitry Andric Record = Method->getParent(); 91981ad6265SDimitry Andric } 920feb5b0c7SDimitry Andric 92181ad6265SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 922feb5b0c7SDimitry Andric LambdaScopeForCallOperatorInstantiationRAII LambdaScope( 923feb5b0c7SDimitry Andric *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope); 924bdd1243dSDimitry Andric 925bdd1243dSDimitry Andric llvm::SmallVector<Expr *, 1> Converted; 926bdd1243dSDimitry Andric return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL, 92781ad6265SDimitry Andric PointOfInstantiation, Satisfaction); 92881ad6265SDimitry Andric } 92981ad6265SDimitry Andric 93055e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 93155e4f9d5SDimitry Andric concepts::ExprRequirement *Req, 93255e4f9d5SDimitry Andric bool First) { 93355e4f9d5SDimitry Andric assert(!Req->isSatisfied() 93455e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 93555e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 93655e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Dependent: 93755e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 93855e4f9d5SDimitry Andric break; 93955e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ExprSubstitutionFailure: { 94055e4f9d5SDimitry Andric auto *SubstDiag = Req->getExprSubstitutionDiagnostic(); 94155e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 94255e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 94355e4f9d5SDimitry Andric diag::note_expr_requirement_expr_substitution_error) 94455e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 94555e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 94655e4f9d5SDimitry Andric else 94755e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 94855e4f9d5SDimitry Andric diag::note_expr_requirement_expr_unknown_substitution_error) 94955e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 95055e4f9d5SDimitry Andric break; 95155e4f9d5SDimitry Andric } 95255e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_NoexceptNotMet: 95355e4f9d5SDimitry Andric S.Diag(Req->getNoexceptLoc(), 95455e4f9d5SDimitry Andric diag::note_expr_requirement_noexcept_not_met) 95555e4f9d5SDimitry Andric << (int)First << Req->getExpr(); 95655e4f9d5SDimitry Andric break; 95755e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: { 95855e4f9d5SDimitry Andric auto *SubstDiag = 95955e4f9d5SDimitry Andric Req->getReturnTypeRequirement().getSubstitutionDiagnostic(); 96055e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 96155e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 96255e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_substitution_error) 96355e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 96455e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 96555e4f9d5SDimitry Andric else 96655e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 96755e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_unknown_substitution_error) 96855e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 96955e4f9d5SDimitry Andric break; 97055e4f9d5SDimitry Andric } 97155e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { 97255e4f9d5SDimitry Andric ConceptSpecializationExpr *ConstraintExpr = 97355e4f9d5SDimitry Andric Req->getReturnTypeRequirementSubstitutedConstraintExpr(); 974fe6060f1SDimitry Andric if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 97555e4f9d5SDimitry Andric // A simple case - expr type is the type being constrained and the concept 97655e4f9d5SDimitry Andric // was not provided arguments. 977fe6060f1SDimitry Andric Expr *e = Req->getExpr(); 978fe6060f1SDimitry Andric S.Diag(e->getBeginLoc(), 97955e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied_simple) 980349cc55cSDimitry Andric << (int)First << S.Context.getReferenceQualifiedType(e) 98155e4f9d5SDimitry Andric << ConstraintExpr->getNamedConcept(); 982fe6060f1SDimitry Andric } else { 98355e4f9d5SDimitry Andric S.Diag(ConstraintExpr->getBeginLoc(), 98455e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied) 98555e4f9d5SDimitry Andric << (int)First << ConstraintExpr; 986fe6060f1SDimitry Andric } 98755e4f9d5SDimitry Andric S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); 98855e4f9d5SDimitry Andric break; 98955e4f9d5SDimitry Andric } 99055e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Satisfied: 99155e4f9d5SDimitry Andric llvm_unreachable("We checked this above"); 99255e4f9d5SDimitry Andric } 99355e4f9d5SDimitry Andric } 99455e4f9d5SDimitry Andric 99555e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 99655e4f9d5SDimitry Andric concepts::TypeRequirement *Req, 99755e4f9d5SDimitry Andric bool First) { 99855e4f9d5SDimitry Andric assert(!Req->isSatisfied() 99955e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 100055e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 100155e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_Dependent: 100255e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 100355e4f9d5SDimitry Andric return; 100455e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_SubstitutionFailure: { 100555e4f9d5SDimitry Andric auto *SubstDiag = Req->getSubstitutionDiagnostic(); 100655e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 100755e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 100855e4f9d5SDimitry Andric diag::note_type_requirement_substitution_error) << (int)First 100955e4f9d5SDimitry Andric << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage; 101055e4f9d5SDimitry Andric else 101155e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 101255e4f9d5SDimitry Andric diag::note_type_requirement_unknown_substitution_error) 101355e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 101455e4f9d5SDimitry Andric return; 101555e4f9d5SDimitry Andric } 101655e4f9d5SDimitry Andric default: 101755e4f9d5SDimitry Andric llvm_unreachable("Unknown satisfaction status"); 101855e4f9d5SDimitry Andric return; 101955e4f9d5SDimitry Andric } 102055e4f9d5SDimitry Andric } 1021bdd1243dSDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 1022bdd1243dSDimitry Andric Expr *SubstExpr, 1023bdd1243dSDimitry Andric bool First = true); 102455e4f9d5SDimitry Andric 102555e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 102655e4f9d5SDimitry Andric concepts::NestedRequirement *Req, 102755e4f9d5SDimitry Andric bool First) { 1028bdd1243dSDimitry Andric using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; 1029bdd1243dSDimitry Andric for (auto &Pair : Req->getConstraintSatisfaction()) { 1030bdd1243dSDimitry Andric if (auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>()) 1031bdd1243dSDimitry Andric S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error) 1032bdd1243dSDimitry Andric << (int)First << Req->getInvalidConstraintEntity() << SubstDiag->second; 103355e4f9d5SDimitry Andric else 1034bdd1243dSDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr( 1035bdd1243dSDimitry Andric S, Pair.second.dyn_cast<Expr *>(), First); 1036bdd1243dSDimitry Andric First = false; 103755e4f9d5SDimitry Andric } 103855e4f9d5SDimitry Andric } 103955e4f9d5SDimitry Andric 1040480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 1041480093f4SDimitry Andric Expr *SubstExpr, 1042bdd1243dSDimitry Andric bool First) { 1043480093f4SDimitry Andric SubstExpr = SubstExpr->IgnoreParenImpCasts(); 1044480093f4SDimitry Andric if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) { 1045480093f4SDimitry Andric switch (BO->getOpcode()) { 1046480093f4SDimitry Andric // These two cases will in practice only be reached when using fold 1047480093f4SDimitry Andric // expressions with || and &&, since otherwise the || and && will have been 1048480093f4SDimitry Andric // broken down into atomic constraints during satisfaction checking. 1049480093f4SDimitry Andric case BO_LOr: 1050480093f4SDimitry Andric // Or evaluated to false - meaning both RHS and LHS evaluated to false. 1051480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 1052480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 1053480093f4SDimitry Andric /*First=*/false); 1054480093f4SDimitry Andric return; 1055fe6060f1SDimitry Andric case BO_LAnd: { 1056fe6060f1SDimitry Andric bool LHSSatisfied = 1057fe6060f1SDimitry Andric BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 1058480093f4SDimitry Andric if (LHSSatisfied) { 1059480093f4SDimitry Andric // LHS is true, so RHS must be false. 1060480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First); 1061480093f4SDimitry Andric return; 1062480093f4SDimitry Andric } 1063480093f4SDimitry Andric // LHS is false 1064480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 1065480093f4SDimitry Andric 1066480093f4SDimitry Andric // RHS might also be false 1067fe6060f1SDimitry Andric bool RHSSatisfied = 1068fe6060f1SDimitry Andric BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 1069480093f4SDimitry Andric if (!RHSSatisfied) 1070480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 1071480093f4SDimitry Andric /*First=*/false); 1072480093f4SDimitry Andric return; 1073fe6060f1SDimitry Andric } 1074480093f4SDimitry Andric case BO_GE: 1075480093f4SDimitry Andric case BO_LE: 1076480093f4SDimitry Andric case BO_GT: 1077480093f4SDimitry Andric case BO_LT: 1078480093f4SDimitry Andric case BO_EQ: 1079480093f4SDimitry Andric case BO_NE: 1080480093f4SDimitry Andric if (BO->getLHS()->getType()->isIntegerType() && 1081480093f4SDimitry Andric BO->getRHS()->getType()->isIntegerType()) { 1082480093f4SDimitry Andric Expr::EvalResult SimplifiedLHS; 1083480093f4SDimitry Andric Expr::EvalResult SimplifiedRHS; 1084fe6060f1SDimitry Andric BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context, 1085fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 1086fe6060f1SDimitry Andric /*InConstantContext=*/true); 1087fe6060f1SDimitry Andric BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context, 1088fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 1089fe6060f1SDimitry Andric /*InConstantContext=*/true); 1090480093f4SDimitry Andric if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) { 1091480093f4SDimitry Andric S.Diag(SubstExpr->getBeginLoc(), 1092480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false_elaborated) 1093480093f4SDimitry Andric << (int)First << SubstExpr 1094fe6060f1SDimitry Andric << toString(SimplifiedLHS.Val.getInt(), 10) 1095480093f4SDimitry Andric << BinaryOperator::getOpcodeStr(BO->getOpcode()) 1096fe6060f1SDimitry Andric << toString(SimplifiedRHS.Val.getInt(), 10); 1097480093f4SDimitry Andric return; 1098480093f4SDimitry Andric } 1099480093f4SDimitry Andric } 1100480093f4SDimitry Andric break; 1101480093f4SDimitry Andric 1102480093f4SDimitry Andric default: 1103480093f4SDimitry Andric break; 1104480093f4SDimitry Andric } 1105480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) { 1106480093f4SDimitry Andric if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 1107480093f4SDimitry Andric S.Diag( 1108480093f4SDimitry Andric CSE->getSourceRange().getBegin(), 1109480093f4SDimitry Andric diag:: 1110480093f4SDimitry Andric note_single_arg_concept_specialization_constraint_evaluated_to_false) 1111480093f4SDimitry Andric << (int)First 1112480093f4SDimitry Andric << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument() 1113480093f4SDimitry Andric << CSE->getNamedConcept(); 1114480093f4SDimitry Andric } else { 1115480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 1116480093f4SDimitry Andric diag::note_concept_specialization_constraint_evaluated_to_false) 1117480093f4SDimitry Andric << (int)First << CSE; 1118480093f4SDimitry Andric } 1119480093f4SDimitry Andric S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction()); 1120480093f4SDimitry Andric return; 112155e4f9d5SDimitry Andric } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) { 1122bdd1243dSDimitry Andric // FIXME: RequiresExpr should store dependent diagnostics. 112355e4f9d5SDimitry Andric for (concepts::Requirement *Req : RE->getRequirements()) 112455e4f9d5SDimitry Andric if (!Req->isDependent() && !Req->isSatisfied()) { 112555e4f9d5SDimitry Andric if (auto *E = dyn_cast<concepts::ExprRequirement>(Req)) 112655e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, E, First); 112755e4f9d5SDimitry Andric else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req)) 112855e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, T, First); 112955e4f9d5SDimitry Andric else 113055e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement( 113155e4f9d5SDimitry Andric S, cast<concepts::NestedRequirement>(Req), First); 113255e4f9d5SDimitry Andric break; 113355e4f9d5SDimitry Andric } 113455e4f9d5SDimitry Andric return; 1135480093f4SDimitry Andric } 1136480093f4SDimitry Andric 1137480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 1138480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false) 1139480093f4SDimitry Andric << (int)First << SubstExpr; 1140480093f4SDimitry Andric } 1141480093f4SDimitry Andric 1142480093f4SDimitry Andric template<typename SubstitutionDiagnostic> 1143480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr( 1144480093f4SDimitry Andric Sema &S, const Expr *E, 1145480093f4SDimitry Andric const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record, 1146480093f4SDimitry Andric bool First = true) { 1147480093f4SDimitry Andric if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){ 1148480093f4SDimitry Andric S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed) 1149480093f4SDimitry Andric << Diag->second; 1150480093f4SDimitry Andric return; 1151480093f4SDimitry Andric } 1152480093f4SDimitry Andric 1153480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, 1154480093f4SDimitry Andric Record.template get<Expr *>(), First); 1155480093f4SDimitry Andric } 1156480093f4SDimitry Andric 115755e4f9d5SDimitry Andric void 115855e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, 115955e4f9d5SDimitry Andric bool First) { 1160480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 1161480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 1162480093f4SDimitry Andric for (auto &Pair : Satisfaction.Details) { 1163480093f4SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); 1164480093f4SDimitry Andric First = false; 1165480093f4SDimitry Andric } 1166480093f4SDimitry Andric } 1167480093f4SDimitry Andric 1168480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint( 116955e4f9d5SDimitry Andric const ASTConstraintSatisfaction &Satisfaction, 117055e4f9d5SDimitry Andric bool First) { 1171480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 1172480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 1173480093f4SDimitry Andric for (auto &Pair : Satisfaction) { 1174480093f4SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); 1175480093f4SDimitry Andric First = false; 1176480093f4SDimitry Andric } 1177480093f4SDimitry Andric } 1178480093f4SDimitry Andric 1179480093f4SDimitry Andric const NormalizedConstraint * 1180480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints( 1181480093f4SDimitry Andric NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) { 118206c3fb27SDimitry Andric // In case the ConstrainedDecl comes from modules, it is necessary to use 118306c3fb27SDimitry Andric // the canonical decl to avoid different atomic constraints with the 'same' 118406c3fb27SDimitry Andric // declarations. 118506c3fb27SDimitry Andric ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl()); 118606c3fb27SDimitry Andric 1187480093f4SDimitry Andric auto CacheEntry = NormalizationCache.find(ConstrainedDecl); 1188480093f4SDimitry Andric if (CacheEntry == NormalizationCache.end()) { 1189480093f4SDimitry Andric auto Normalized = 1190480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl, 1191480093f4SDimitry Andric AssociatedConstraints); 1192480093f4SDimitry Andric CacheEntry = 1193480093f4SDimitry Andric NormalizationCache 1194480093f4SDimitry Andric .try_emplace(ConstrainedDecl, 1195480093f4SDimitry Andric Normalized 1196480093f4SDimitry Andric ? new (Context) NormalizedConstraint( 1197480093f4SDimitry Andric std::move(*Normalized)) 1198480093f4SDimitry Andric : nullptr) 1199480093f4SDimitry Andric .first; 1200480093f4SDimitry Andric } 1201480093f4SDimitry Andric return CacheEntry->second; 1202480093f4SDimitry Andric } 1203480093f4SDimitry Andric 1204bdd1243dSDimitry Andric static bool 1205bdd1243dSDimitry Andric substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1206bdd1243dSDimitry Andric ConceptDecl *Concept, 1207bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL, 1208480093f4SDimitry Andric const ASTTemplateArgumentListInfo *ArgsAsWritten) { 1209480093f4SDimitry Andric if (!N.isAtomic()) { 1210bdd1243dSDimitry Andric if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL, 1211480093f4SDimitry Andric ArgsAsWritten)) 1212480093f4SDimitry Andric return true; 1213bdd1243dSDimitry Andric return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL, 1214480093f4SDimitry Andric ArgsAsWritten); 1215480093f4SDimitry Andric } 1216480093f4SDimitry Andric TemplateParameterList *TemplateParams = Concept->getTemplateParameters(); 1217480093f4SDimitry Andric 1218480093f4SDimitry Andric AtomicConstraint &Atomic = *N.getAtomicConstraint(); 1219480093f4SDimitry Andric TemplateArgumentListInfo SubstArgs; 1220480093f4SDimitry Andric if (!Atomic.ParameterMapping) { 1221480093f4SDimitry Andric llvm::SmallBitVector OccurringIndices(TemplateParams->size()); 1222480093f4SDimitry Andric S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false, 1223480093f4SDimitry Andric /*Depth=*/0, OccurringIndices); 1224bdd1243dSDimitry Andric TemplateArgumentLoc *TempArgs = 1225bdd1243dSDimitry Andric new (S.Context) TemplateArgumentLoc[OccurringIndices.count()]; 1226480093f4SDimitry Andric for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) 1227480093f4SDimitry Andric if (OccurringIndices[I]) 1228bdd1243dSDimitry Andric new (&(TempArgs)[J++]) 1229bdd1243dSDimitry Andric TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc( 1230bdd1243dSDimitry Andric TemplateParams->begin()[I], 1231480093f4SDimitry Andric // Here we assume we do not support things like 1232480093f4SDimitry Andric // template<typename A, typename B> 1233480093f4SDimitry Andric // concept C = ...; 1234480093f4SDimitry Andric // 1235480093f4SDimitry Andric // template<typename... Ts> requires C<Ts...> 1236480093f4SDimitry Andric // struct S { }; 1237480093f4SDimitry Andric // The above currently yields a diagnostic. 1238480093f4SDimitry Andric // We still might have default arguments for concept parameters. 1239bdd1243dSDimitry Andric ArgsAsWritten->NumTemplateArgs > I 1240bdd1243dSDimitry Andric ? ArgsAsWritten->arguments()[I].getLocation() 1241bdd1243dSDimitry Andric : SourceLocation())); 1242bdd1243dSDimitry Andric Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count()); 1243480093f4SDimitry Andric } 1244480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 1245480093f4SDimitry Andric S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(), 1246480093f4SDimitry Andric Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, 12471ac55f4cSDimitry Andric ArgsAsWritten->arguments().front().getSourceRange()); 1248480093f4SDimitry Andric if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) 1249480093f4SDimitry Andric return true; 1250bdd1243dSDimitry Andric 1251bdd1243dSDimitry Andric TemplateArgumentLoc *TempArgs = 1252bdd1243dSDimitry Andric new (S.Context) TemplateArgumentLoc[SubstArgs.size()]; 1253480093f4SDimitry Andric std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(), 1254bdd1243dSDimitry Andric TempArgs); 1255bdd1243dSDimitry Andric Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size()); 1256480093f4SDimitry Andric return false; 1257480093f4SDimitry Andric } 1258480093f4SDimitry Andric 1259bdd1243dSDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1260bdd1243dSDimitry Andric const ConceptSpecializationExpr *CSE) { 1261bdd1243dSDimitry Andric TemplateArgumentList TAL{TemplateArgumentList::OnStack, 1262bdd1243dSDimitry Andric CSE->getTemplateArguments()}; 1263bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 12645f757f3fSDimitry Andric CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(), 12655f757f3fSDimitry Andric /*Final=*/false, &TAL, 1266bdd1243dSDimitry Andric /*RelativeToPrimary=*/true, 1267bdd1243dSDimitry Andric /*Pattern=*/nullptr, 1268bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true); 1269bdd1243dSDimitry Andric 1270bdd1243dSDimitry Andric return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL, 1271bdd1243dSDimitry Andric CSE->getTemplateArgsAsWritten()); 1272bdd1243dSDimitry Andric } 1273bdd1243dSDimitry Andric 1274bdd1243dSDimitry Andric std::optional<NormalizedConstraint> 1275480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D, 1276480093f4SDimitry Andric ArrayRef<const Expr *> E) { 1277480093f4SDimitry Andric assert(E.size() != 0); 12786e75b2fbSDimitry Andric auto Conjunction = fromConstraintExpr(S, D, E[0]); 12796e75b2fbSDimitry Andric if (!Conjunction) 1280bdd1243dSDimitry Andric return std::nullopt; 12816e75b2fbSDimitry Andric for (unsigned I = 1; I < E.size(); ++I) { 1282480093f4SDimitry Andric auto Next = fromConstraintExpr(S, D, E[I]); 1283480093f4SDimitry Andric if (!Next) 1284bdd1243dSDimitry Andric return std::nullopt; 12856e75b2fbSDimitry Andric *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction), 1286480093f4SDimitry Andric std::move(*Next), CCK_Conjunction); 1287480093f4SDimitry Andric } 1288480093f4SDimitry Andric return Conjunction; 1289480093f4SDimitry Andric } 1290480093f4SDimitry Andric 1291bdd1243dSDimitry Andric std::optional<NormalizedConstraint> 1292480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) { 1293480093f4SDimitry Andric assert(E != nullptr); 1294480093f4SDimitry Andric 1295480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 1296480093f4SDimitry Andric // [...] 1297480093f4SDimitry Andric // - The normal form of an expression (E) is the normal form of E. 1298480093f4SDimitry Andric // [...] 1299480093f4SDimitry Andric E = E->IgnoreParenImpCasts(); 1300bdd1243dSDimitry Andric 1301bdd1243dSDimitry Andric // C++2a [temp.param]p4: 1302bdd1243dSDimitry Andric // [...] If T is not a pack, then E is E', otherwise E is (E' && ...). 1303bdd1243dSDimitry Andric // Fold expression is considered atomic constraints per current wording. 1304bdd1243dSDimitry Andric // See http://cplusplus.github.io/concepts-ts/ts-active.html#28 1305bdd1243dSDimitry Andric 13065ffd83dbSDimitry Andric if (LogicalBinOp BO = E) { 13075ffd83dbSDimitry Andric auto LHS = fromConstraintExpr(S, D, BO.getLHS()); 1308480093f4SDimitry Andric if (!LHS) 1309bdd1243dSDimitry Andric return std::nullopt; 13105ffd83dbSDimitry Andric auto RHS = fromConstraintExpr(S, D, BO.getRHS()); 1311480093f4SDimitry Andric if (!RHS) 1312bdd1243dSDimitry Andric return std::nullopt; 1313480093f4SDimitry Andric 13145ffd83dbSDimitry Andric return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS), 13155ffd83dbSDimitry Andric BO.isAnd() ? CCK_Conjunction : CCK_Disjunction); 1316480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) { 1317480093f4SDimitry Andric const NormalizedConstraint *SubNF; 1318480093f4SDimitry Andric { 1319480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 1320480093f4SDimitry Andric S, CSE->getExprLoc(), 1321480093f4SDimitry Andric Sema::InstantiatingTemplate::ConstraintNormalization{}, D, 1322480093f4SDimitry Andric CSE->getSourceRange()); 1323480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 1324480093f4SDimitry Andric // [...] 1325480093f4SDimitry Andric // The normal form of an id-expression of the form C<A1, A2, ..., AN>, 1326480093f4SDimitry Andric // where C names a concept, is the normal form of the 1327480093f4SDimitry Andric // constraint-expression of C, after substituting A1, A2, ..., AN for C’s 1328480093f4SDimitry Andric // respective template parameters in the parameter mappings in each atomic 1329480093f4SDimitry Andric // constraint. If any such substitution results in an invalid type or 1330480093f4SDimitry Andric // expression, the program is ill-formed; no diagnostic is required. 1331480093f4SDimitry Andric // [...] 1332480093f4SDimitry Andric ConceptDecl *CD = CSE->getNamedConcept(); 1333480093f4SDimitry Andric SubNF = S.getNormalizedAssociatedConstraints(CD, 1334480093f4SDimitry Andric {CD->getConstraintExpr()}); 1335480093f4SDimitry Andric if (!SubNF) 1336bdd1243dSDimitry Andric return std::nullopt; 1337480093f4SDimitry Andric } 1338480093f4SDimitry Andric 1339bdd1243dSDimitry Andric std::optional<NormalizedConstraint> New; 1340480093f4SDimitry Andric New.emplace(S.Context, *SubNF); 1341480093f4SDimitry Andric 1342bdd1243dSDimitry Andric if (substituteParameterMappings(S, *New, CSE)) 1343bdd1243dSDimitry Andric return std::nullopt; 1344480093f4SDimitry Andric 1345480093f4SDimitry Andric return New; 1346480093f4SDimitry Andric } 1347480093f4SDimitry Andric return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)}; 1348480093f4SDimitry Andric } 1349480093f4SDimitry Andric 1350480093f4SDimitry Andric using NormalForm = 1351480093f4SDimitry Andric llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>; 1352480093f4SDimitry Andric 1353480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) { 1354480093f4SDimitry Andric if (Normalized.isAtomic()) 1355480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 1356480093f4SDimitry Andric 1357480093f4SDimitry Andric NormalForm LCNF = makeCNF(Normalized.getLHS()); 1358480093f4SDimitry Andric NormalForm RCNF = makeCNF(Normalized.getRHS()); 1359480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) { 1360480093f4SDimitry Andric LCNF.reserve(LCNF.size() + RCNF.size()); 1361480093f4SDimitry Andric while (!RCNF.empty()) 1362480093f4SDimitry Andric LCNF.push_back(RCNF.pop_back_val()); 1363480093f4SDimitry Andric return LCNF; 1364480093f4SDimitry Andric } 1365480093f4SDimitry Andric 1366480093f4SDimitry Andric // Disjunction 1367480093f4SDimitry Andric NormalForm Res; 1368480093f4SDimitry Andric Res.reserve(LCNF.size() * RCNF.size()); 1369480093f4SDimitry Andric for (auto &LDisjunction : LCNF) 1370480093f4SDimitry Andric for (auto &RDisjunction : RCNF) { 1371480093f4SDimitry Andric NormalForm::value_type Combined; 1372480093f4SDimitry Andric Combined.reserve(LDisjunction.size() + RDisjunction.size()); 1373480093f4SDimitry Andric std::copy(LDisjunction.begin(), LDisjunction.end(), 1374480093f4SDimitry Andric std::back_inserter(Combined)); 1375480093f4SDimitry Andric std::copy(RDisjunction.begin(), RDisjunction.end(), 1376480093f4SDimitry Andric std::back_inserter(Combined)); 1377480093f4SDimitry Andric Res.emplace_back(Combined); 1378480093f4SDimitry Andric } 1379480093f4SDimitry Andric return Res; 1380480093f4SDimitry Andric } 1381480093f4SDimitry Andric 1382480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) { 1383480093f4SDimitry Andric if (Normalized.isAtomic()) 1384480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 1385480093f4SDimitry Andric 1386480093f4SDimitry Andric NormalForm LDNF = makeDNF(Normalized.getLHS()); 1387480093f4SDimitry Andric NormalForm RDNF = makeDNF(Normalized.getRHS()); 1388480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) { 1389480093f4SDimitry Andric LDNF.reserve(LDNF.size() + RDNF.size()); 1390480093f4SDimitry Andric while (!RDNF.empty()) 1391480093f4SDimitry Andric LDNF.push_back(RDNF.pop_back_val()); 1392480093f4SDimitry Andric return LDNF; 1393480093f4SDimitry Andric } 1394480093f4SDimitry Andric 1395480093f4SDimitry Andric // Conjunction 1396480093f4SDimitry Andric NormalForm Res; 1397480093f4SDimitry Andric Res.reserve(LDNF.size() * RDNF.size()); 1398480093f4SDimitry Andric for (auto &LConjunction : LDNF) { 1399480093f4SDimitry Andric for (auto &RConjunction : RDNF) { 1400480093f4SDimitry Andric NormalForm::value_type Combined; 1401480093f4SDimitry Andric Combined.reserve(LConjunction.size() + RConjunction.size()); 1402480093f4SDimitry Andric std::copy(LConjunction.begin(), LConjunction.end(), 1403480093f4SDimitry Andric std::back_inserter(Combined)); 1404480093f4SDimitry Andric std::copy(RConjunction.begin(), RConjunction.end(), 1405480093f4SDimitry Andric std::back_inserter(Combined)); 1406480093f4SDimitry Andric Res.emplace_back(Combined); 1407480093f4SDimitry Andric } 1408480093f4SDimitry Andric } 1409480093f4SDimitry Andric return Res; 1410480093f4SDimitry Andric } 1411480093f4SDimitry Andric 1412480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator> 141306c3fb27SDimitry Andric static bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF, 1414480093f4SDimitry Andric AtomicSubsumptionEvaluator E) { 1415480093f4SDimitry Andric // C++ [temp.constr.order] p2 1416480093f4SDimitry Andric // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the 1417480093f4SDimitry Andric // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in 1418480093f4SDimitry Andric // the conjuctive normal form of Q, where [...] 1419480093f4SDimitry Andric for (const auto &Pi : PDNF) { 1420480093f4SDimitry Andric for (const auto &Qj : QCNF) { 1421480093f4SDimitry Andric // C++ [temp.constr.order] p2 1422480093f4SDimitry Andric // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if 1423480093f4SDimitry Andric // and only if there exists an atomic constraint Pia in Pi for which 1424480093f4SDimitry Andric // there exists an atomic constraint, Qjb, in Qj such that Pia 1425480093f4SDimitry Andric // subsumes Qjb. 1426480093f4SDimitry Andric bool Found = false; 1427480093f4SDimitry Andric for (const AtomicConstraint *Pia : Pi) { 1428480093f4SDimitry Andric for (const AtomicConstraint *Qjb : Qj) { 1429480093f4SDimitry Andric if (E(*Pia, *Qjb)) { 1430480093f4SDimitry Andric Found = true; 1431480093f4SDimitry Andric break; 1432480093f4SDimitry Andric } 1433480093f4SDimitry Andric } 1434480093f4SDimitry Andric if (Found) 1435480093f4SDimitry Andric break; 1436480093f4SDimitry Andric } 1437480093f4SDimitry Andric if (!Found) 1438480093f4SDimitry Andric return false; 1439480093f4SDimitry Andric } 1440480093f4SDimitry Andric } 1441480093f4SDimitry Andric return true; 1442480093f4SDimitry Andric } 1443480093f4SDimitry Andric 1444480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator> 1445480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P, 1446480093f4SDimitry Andric NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes, 1447480093f4SDimitry Andric AtomicSubsumptionEvaluator E) { 1448480093f4SDimitry Andric // C++ [temp.constr.order] p2 1449480093f4SDimitry Andric // In order to determine if a constraint P subsumes a constraint Q, P is 1450480093f4SDimitry Andric // transformed into disjunctive normal form, and Q is transformed into 1451480093f4SDimitry Andric // conjunctive normal form. [...] 1452480093f4SDimitry Andric auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P); 1453480093f4SDimitry Andric if (!PNormalized) 1454480093f4SDimitry Andric return true; 1455480093f4SDimitry Andric const NormalForm PDNF = makeDNF(*PNormalized); 1456480093f4SDimitry Andric 1457480093f4SDimitry Andric auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q); 1458480093f4SDimitry Andric if (!QNormalized) 1459480093f4SDimitry Andric return true; 1460480093f4SDimitry Andric const NormalForm QCNF = makeCNF(*QNormalized); 1461480093f4SDimitry Andric 1462480093f4SDimitry Andric Subsumes = subsumes(PDNF, QCNF, E); 1463480093f4SDimitry Andric return false; 1464480093f4SDimitry Andric } 1465480093f4SDimitry Andric 1466bdd1243dSDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, 1467bdd1243dSDimitry Andric MutableArrayRef<const Expr *> AC1, 1468bdd1243dSDimitry Andric NamedDecl *D2, 1469bdd1243dSDimitry Andric MutableArrayRef<const Expr *> AC2, 1470480093f4SDimitry Andric bool &Result) { 1471bdd1243dSDimitry Andric if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) { 1472bdd1243dSDimitry Andric auto IsExpectedEntity = [](const FunctionDecl *FD) { 1473bdd1243dSDimitry Andric FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind(); 1474bdd1243dSDimitry Andric return Kind == FunctionDecl::TK_NonTemplate || 1475bdd1243dSDimitry Andric Kind == FunctionDecl::TK_FunctionTemplate; 1476bdd1243dSDimitry Andric }; 1477bdd1243dSDimitry Andric const auto *FD2 = dyn_cast<FunctionDecl>(D2); 1478bdd1243dSDimitry Andric (void)IsExpectedEntity; 1479bdd1243dSDimitry Andric (void)FD1; 1480bdd1243dSDimitry Andric (void)FD2; 1481bdd1243dSDimitry Andric assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) && 1482bdd1243dSDimitry Andric "use non-instantiated function declaration for constraints partial " 1483bdd1243dSDimitry Andric "ordering"); 1484bdd1243dSDimitry Andric } 1485bdd1243dSDimitry Andric 1486480093f4SDimitry Andric if (AC1.empty()) { 1487480093f4SDimitry Andric Result = AC2.empty(); 1488480093f4SDimitry Andric return false; 1489480093f4SDimitry Andric } 1490480093f4SDimitry Andric if (AC2.empty()) { 1491480093f4SDimitry Andric // TD1 has associated constraints and TD2 does not. 1492480093f4SDimitry Andric Result = true; 1493480093f4SDimitry Andric return false; 1494480093f4SDimitry Andric } 1495480093f4SDimitry Andric 1496480093f4SDimitry Andric std::pair<NamedDecl *, NamedDecl *> Key{D1, D2}; 1497480093f4SDimitry Andric auto CacheEntry = SubsumptionCache.find(Key); 1498480093f4SDimitry Andric if (CacheEntry != SubsumptionCache.end()) { 1499480093f4SDimitry Andric Result = CacheEntry->second; 1500480093f4SDimitry Andric return false; 1501480093f4SDimitry Andric } 1502480093f4SDimitry Andric 1503bdd1243dSDimitry Andric unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true); 1504bdd1243dSDimitry Andric unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true); 1505bdd1243dSDimitry Andric 1506bdd1243dSDimitry Andric for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) { 1507bdd1243dSDimitry Andric if (Depth2 > Depth1) { 1508bdd1243dSDimitry Andric AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1) 1509bdd1243dSDimitry Andric .TransformExpr(const_cast<Expr *>(AC1[I])) 1510bdd1243dSDimitry Andric .get(); 1511bdd1243dSDimitry Andric } else if (Depth1 > Depth2) { 1512bdd1243dSDimitry Andric AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2) 1513bdd1243dSDimitry Andric .TransformExpr(const_cast<Expr *>(AC2[I])) 1514bdd1243dSDimitry Andric .get(); 1515bdd1243dSDimitry Andric } 1516bdd1243dSDimitry Andric } 1517bdd1243dSDimitry Andric 1518480093f4SDimitry Andric if (subsumes(*this, D1, AC1, D2, AC2, Result, 1519480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 1520480093f4SDimitry Andric return A.subsumes(Context, B); 1521480093f4SDimitry Andric })) 1522480093f4SDimitry Andric return true; 1523480093f4SDimitry Andric SubsumptionCache.try_emplace(Key, Result); 1524480093f4SDimitry Andric return false; 1525480093f4SDimitry Andric } 1526480093f4SDimitry Andric 1527480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, 1528480093f4SDimitry Andric ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) { 1529480093f4SDimitry Andric if (isSFINAEContext()) 1530480093f4SDimitry Andric // No need to work here because our notes would be discarded. 1531480093f4SDimitry Andric return false; 1532480093f4SDimitry Andric 1533480093f4SDimitry Andric if (AC1.empty() || AC2.empty()) 1534480093f4SDimitry Andric return false; 1535480093f4SDimitry Andric 1536480093f4SDimitry Andric auto NormalExprEvaluator = 1537480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 1538480093f4SDimitry Andric return A.subsumes(Context, B); 1539480093f4SDimitry Andric }; 1540480093f4SDimitry Andric 1541480093f4SDimitry Andric const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr; 1542480093f4SDimitry Andric auto IdenticalExprEvaluator = 1543480093f4SDimitry Andric [&] (const AtomicConstraint &A, const AtomicConstraint &B) { 1544480093f4SDimitry Andric if (!A.hasMatchingParameterMapping(Context, B)) 1545480093f4SDimitry Andric return false; 1546480093f4SDimitry Andric const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr; 1547480093f4SDimitry Andric if (EA == EB) 1548480093f4SDimitry Andric return true; 1549480093f4SDimitry Andric 1550480093f4SDimitry Andric // Not the same source level expression - are the expressions 1551480093f4SDimitry Andric // identical? 1552480093f4SDimitry Andric llvm::FoldingSetNodeID IDA, IDB; 1553349cc55cSDimitry Andric EA->Profile(IDA, Context, /*Canonical=*/true); 1554349cc55cSDimitry Andric EB->Profile(IDB, Context, /*Canonical=*/true); 1555480093f4SDimitry Andric if (IDA != IDB) 1556480093f4SDimitry Andric return false; 1557480093f4SDimitry Andric 1558480093f4SDimitry Andric AmbiguousAtomic1 = EA; 1559480093f4SDimitry Andric AmbiguousAtomic2 = EB; 1560480093f4SDimitry Andric return true; 1561480093f4SDimitry Andric }; 1562480093f4SDimitry Andric 1563480093f4SDimitry Andric { 1564480093f4SDimitry Andric // The subsumption checks might cause diagnostics 1565480093f4SDimitry Andric SFINAETrap Trap(*this); 1566480093f4SDimitry Andric auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1); 1567480093f4SDimitry Andric if (!Normalized1) 1568480093f4SDimitry Andric return false; 1569480093f4SDimitry Andric const NormalForm DNF1 = makeDNF(*Normalized1); 1570480093f4SDimitry Andric const NormalForm CNF1 = makeCNF(*Normalized1); 1571480093f4SDimitry Andric 1572480093f4SDimitry Andric auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2); 1573480093f4SDimitry Andric if (!Normalized2) 1574480093f4SDimitry Andric return false; 1575480093f4SDimitry Andric const NormalForm DNF2 = makeDNF(*Normalized2); 1576480093f4SDimitry Andric const NormalForm CNF2 = makeCNF(*Normalized2); 1577480093f4SDimitry Andric 1578480093f4SDimitry Andric bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator); 1579480093f4SDimitry Andric bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator); 1580480093f4SDimitry Andric bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator); 1581480093f4SDimitry Andric bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator); 1582480093f4SDimitry Andric if (Is1AtLeastAs2 == Is1AtLeastAs2Normally && 1583480093f4SDimitry Andric Is2AtLeastAs1 == Is2AtLeastAs1Normally) 1584480093f4SDimitry Andric // Same result - no ambiguity was caused by identical atomic expressions. 1585480093f4SDimitry Andric return false; 1586480093f4SDimitry Andric } 1587480093f4SDimitry Andric 1588480093f4SDimitry Andric // A different result! Some ambiguous atomic constraint(s) caused a difference 1589480093f4SDimitry Andric assert(AmbiguousAtomic1 && AmbiguousAtomic2); 1590480093f4SDimitry Andric 1591480093f4SDimitry Andric Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints) 1592480093f4SDimitry Andric << AmbiguousAtomic1->getSourceRange(); 1593480093f4SDimitry Andric Diag(AmbiguousAtomic2->getBeginLoc(), 1594480093f4SDimitry Andric diag::note_ambiguous_atomic_constraints_similar_expression) 1595480093f4SDimitry Andric << AmbiguousAtomic2->getSourceRange(); 1596480093f4SDimitry Andric return true; 1597480093f4SDimitry Andric } 159855e4f9d5SDimitry Andric 159955e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 160055e4f9d5SDimitry Andric Expr *E, bool IsSimple, SourceLocation NoexceptLoc, 160155e4f9d5SDimitry Andric ReturnTypeRequirement Req, SatisfactionStatus Status, 160255e4f9d5SDimitry Andric ConceptSpecializationExpr *SubstitutedConstraintExpr) : 160355e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, 160455e4f9d5SDimitry Andric Status == SS_Dependent && 160555e4f9d5SDimitry Andric (E->containsUnexpandedParameterPack() || 160655e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack()), 160755e4f9d5SDimitry Andric Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc), 160855e4f9d5SDimitry Andric TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr), 160955e4f9d5SDimitry Andric Status(Status) { 161055e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 161155e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 161255e4f9d5SDimitry Andric "noexcept specification"); 161355e4f9d5SDimitry Andric assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == 161455e4f9d5SDimitry Andric (SubstitutedConstraintExpr != nullptr)); 161555e4f9d5SDimitry Andric } 161655e4f9d5SDimitry Andric 161755e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 161855e4f9d5SDimitry Andric SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, 161955e4f9d5SDimitry Andric SourceLocation NoexceptLoc, ReturnTypeRequirement Req) : 162055e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), 162155e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), 162255e4f9d5SDimitry Andric Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), 162355e4f9d5SDimitry Andric Status(SS_ExprSubstitutionFailure) { 162455e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 162555e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 162655e4f9d5SDimitry Andric "noexcept specification"); 162755e4f9d5SDimitry Andric } 162855e4f9d5SDimitry Andric 162955e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement:: 163055e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) : 163104eeddc0SDimitry Andric TypeConstraintInfo(TPL, false) { 163255e4f9d5SDimitry Andric assert(TPL->size() == 1); 163355e4f9d5SDimitry Andric const TypeConstraint *TC = 163455e4f9d5SDimitry Andric cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint(); 163555e4f9d5SDimitry Andric assert(TC && 163655e4f9d5SDimitry Andric "TPL must have a template type parameter with a type constraint"); 163755e4f9d5SDimitry Andric auto *Constraint = 1638349cc55cSDimitry Andric cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint()); 1639e8d8bef9SDimitry Andric bool Dependent = 1640e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten() && 1641e8d8bef9SDimitry Andric TemplateSpecializationType::anyInstantiationDependentTemplateArguments( 1642e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)); 164304eeddc0SDimitry Andric TypeConstraintInfo.setInt(Dependent ? true : false); 164455e4f9d5SDimitry Andric } 164555e4f9d5SDimitry Andric 164655e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) : 1647e8d8bef9SDimitry Andric Requirement(RK_Type, T->getType()->isInstantiationDependentType(), 164855e4f9d5SDimitry Andric T->getType()->containsUnexpandedParameterPack(), 164955e4f9d5SDimitry Andric // We reach this ctor with either dependent types (in which 165055e4f9d5SDimitry Andric // IsSatisfied doesn't matter) or with non-dependent type in 165155e4f9d5SDimitry Andric // which the existence of the type indicates satisfaction. 1652e8d8bef9SDimitry Andric /*IsSatisfied=*/true), 1653e8d8bef9SDimitry Andric Value(T), 1654e8d8bef9SDimitry Andric Status(T->getType()->isInstantiationDependentType() ? SS_Dependent 1655e8d8bef9SDimitry Andric : SS_Satisfied) {} 1656