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 13*bdd1243dSDimitry Andric #include "TreeTransform.h" 14480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h" 15a7dea167SDimitry Andric #include "clang/Sema/Sema.h" 16480093f4SDimitry Andric #include "clang/Sema/SemaInternal.h" 17a7dea167SDimitry Andric #include "clang/Sema/SemaDiagnostic.h" 18a7dea167SDimitry Andric #include "clang/Sema/TemplateDeduction.h" 19a7dea167SDimitry Andric #include "clang/Sema/Template.h" 2055e4f9d5SDimitry Andric #include "clang/Sema/Overload.h" 2155e4f9d5SDimitry Andric #include "clang/Sema/Initialization.h" 22*bdd1243dSDimitry Andric #include "clang/AST/ASTLambda.h" 2355e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h" 24480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 25480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h" 26480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h" 27480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h" 28fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h" 29*bdd1243dSDimitry Andric #include <optional> 30fe6060f1SDimitry Andric 31a7dea167SDimitry Andric using namespace clang; 32a7dea167SDimitry Andric using namespace sema; 33a7dea167SDimitry Andric 345ffd83dbSDimitry Andric namespace { 355ffd83dbSDimitry Andric class LogicalBinOp { 36*bdd1243dSDimitry Andric SourceLocation Loc; 375ffd83dbSDimitry Andric OverloadedOperatorKind Op = OO_None; 385ffd83dbSDimitry Andric const Expr *LHS = nullptr; 395ffd83dbSDimitry Andric const Expr *RHS = nullptr; 405ffd83dbSDimitry Andric 415ffd83dbSDimitry Andric public: 425ffd83dbSDimitry Andric LogicalBinOp(const Expr *E) { 435ffd83dbSDimitry Andric if (auto *BO = dyn_cast<BinaryOperator>(E)) { 445ffd83dbSDimitry Andric Op = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 455ffd83dbSDimitry Andric LHS = BO->getLHS(); 465ffd83dbSDimitry Andric RHS = BO->getRHS(); 47*bdd1243dSDimitry Andric Loc = BO->getExprLoc(); 485ffd83dbSDimitry Andric } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) { 49fe6060f1SDimitry Andric // If OO is not || or && it might not have exactly 2 arguments. 50fe6060f1SDimitry Andric if (OO->getNumArgs() == 2) { 515ffd83dbSDimitry Andric Op = OO->getOperator(); 525ffd83dbSDimitry Andric LHS = OO->getArg(0); 535ffd83dbSDimitry Andric RHS = OO->getArg(1); 54*bdd1243dSDimitry Andric Loc = OO->getOperatorLoc(); 555ffd83dbSDimitry Andric } 565ffd83dbSDimitry Andric } 57fe6060f1SDimitry Andric } 585ffd83dbSDimitry Andric 595ffd83dbSDimitry Andric bool isAnd() const { return Op == OO_AmpAmp; } 605ffd83dbSDimitry Andric bool isOr() const { return Op == OO_PipePipe; } 615ffd83dbSDimitry Andric explicit operator bool() const { return isAnd() || isOr(); } 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andric const Expr *getLHS() const { return LHS; } 645ffd83dbSDimitry Andric const Expr *getRHS() const { return RHS; } 65*bdd1243dSDimitry Andric 66*bdd1243dSDimitry Andric ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const { 67*bdd1243dSDimitry Andric return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS())); 68*bdd1243dSDimitry Andric } 69*bdd1243dSDimitry Andric 70*bdd1243dSDimitry Andric ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS, 71*bdd1243dSDimitry Andric ExprResult RHS) const { 72*bdd1243dSDimitry Andric assert((isAnd() || isOr()) && "Not the right kind of op?"); 73*bdd1243dSDimitry Andric assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?"); 74*bdd1243dSDimitry Andric 75*bdd1243dSDimitry Andric if (!LHS.isUsable() || !RHS.isUsable()) 76*bdd1243dSDimitry Andric return ExprEmpty(); 77*bdd1243dSDimitry Andric 78*bdd1243dSDimitry Andric // We should just be able to 'normalize' these to the builtin Binary 79*bdd1243dSDimitry Andric // Operator, since that is how they are evaluated in constriant checks. 80*bdd1243dSDimitry Andric return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(), 81*bdd1243dSDimitry Andric BinaryOperator::getOverloadedOpcode(Op), 82*bdd1243dSDimitry Andric SemaRef.Context.BoolTy, VK_PRValue, 83*bdd1243dSDimitry Andric OK_Ordinary, Loc, FPOptionsOverride{}); 84*bdd1243dSDimitry Andric } 855ffd83dbSDimitry Andric }; 865ffd83dbSDimitry Andric } 875ffd83dbSDimitry Andric 885ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression, 895ffd83dbSDimitry Andric Token NextToken, bool *PossibleNonPrimary, 90480093f4SDimitry Andric bool IsTrailingRequiresClause) { 91a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 92a7dea167SDimitry Andric // ..E shall be a constant expression of type bool. 93a7dea167SDimitry Andric 94a7dea167SDimitry Andric ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts(); 95a7dea167SDimitry Andric 965ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpression) { 975ffd83dbSDimitry Andric return CheckConstraintExpression(BO.getLHS(), NextToken, 98480093f4SDimitry Andric PossibleNonPrimary) && 995ffd83dbSDimitry Andric CheckConstraintExpression(BO.getRHS(), NextToken, 100480093f4SDimitry Andric PossibleNonPrimary); 101a7dea167SDimitry Andric } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression)) 102480093f4SDimitry Andric return CheckConstraintExpression(C->getSubExpr(), NextToken, 103480093f4SDimitry Andric PossibleNonPrimary); 104a7dea167SDimitry Andric 105a7dea167SDimitry Andric QualType Type = ConstraintExpression->getType(); 106480093f4SDimitry Andric 107480093f4SDimitry Andric auto CheckForNonPrimary = [&] { 108480093f4SDimitry Andric if (PossibleNonPrimary) 109480093f4SDimitry Andric *PossibleNonPrimary = 110480093f4SDimitry Andric // We have the following case: 111480093f4SDimitry Andric // template<typename> requires func(0) struct S { }; 112480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 113480093f4SDimitry Andric // the function call, and we're only going to parse 'func' as the 114480093f4SDimitry Andric // primary-expression, and complain that it is of non-bool type. 115480093f4SDimitry Andric (NextToken.is(tok::l_paren) && 116480093f4SDimitry Andric (IsTrailingRequiresClause || 117480093f4SDimitry Andric (Type->isDependentType() && 1185ffd83dbSDimitry Andric isa<UnresolvedLookupExpr>(ConstraintExpression)) || 119480093f4SDimitry Andric Type->isFunctionType() || 120480093f4SDimitry Andric Type->isSpecificBuiltinType(BuiltinType::Overload))) || 121480093f4SDimitry Andric // We have the following case: 122480093f4SDimitry Andric // template<typename T> requires size_<T> == 0 struct S { }; 123480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 124480093f4SDimitry Andric // the binary operator, and we're only going to parse 'func' as the 125480093f4SDimitry Andric // first operand, and complain that it is of non-bool type. 126480093f4SDimitry Andric getBinOpPrecedence(NextToken.getKind(), 127480093f4SDimitry Andric /*GreaterThanIsOperator=*/true, 128480093f4SDimitry Andric getLangOpts().CPlusPlus11) > prec::LogicalAnd; 129480093f4SDimitry Andric }; 130480093f4SDimitry Andric 131480093f4SDimitry Andric // An atomic constraint! 132480093f4SDimitry Andric if (ConstraintExpression->isTypeDependent()) { 133480093f4SDimitry Andric CheckForNonPrimary(); 134480093f4SDimitry Andric return true; 135480093f4SDimitry Andric } 136480093f4SDimitry Andric 137a7dea167SDimitry Andric if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) { 138a7dea167SDimitry Andric Diag(ConstraintExpression->getExprLoc(), 139a7dea167SDimitry Andric diag::err_non_bool_atomic_constraint) << Type 140a7dea167SDimitry Andric << ConstraintExpression->getSourceRange(); 141480093f4SDimitry Andric CheckForNonPrimary(); 142a7dea167SDimitry Andric return false; 143a7dea167SDimitry Andric } 144480093f4SDimitry Andric 145480093f4SDimitry Andric if (PossibleNonPrimary) 146480093f4SDimitry Andric *PossibleNonPrimary = false; 147a7dea167SDimitry Andric return true; 148a7dea167SDimitry Andric } 149a7dea167SDimitry Andric 150*bdd1243dSDimitry Andric namespace { 151*bdd1243dSDimitry Andric struct SatisfactionStackRAII { 152*bdd1243dSDimitry Andric Sema &SemaRef; 153*bdd1243dSDimitry Andric SatisfactionStackRAII(Sema &SemaRef, llvm::FoldingSetNodeID FSNID) 154*bdd1243dSDimitry Andric : SemaRef(SemaRef) { 155*bdd1243dSDimitry Andric SemaRef.PushSatisfactionStackEntry(FSNID); 156*bdd1243dSDimitry Andric } 157*bdd1243dSDimitry Andric ~SatisfactionStackRAII() { SemaRef.PopSatisfactionStackEntry(); } 158*bdd1243dSDimitry Andric }; 159*bdd1243dSDimitry Andric } // namespace 160*bdd1243dSDimitry Andric 161480093f4SDimitry Andric template <typename AtomicEvaluator> 162*bdd1243dSDimitry Andric static ExprResult 163480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, 164480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction, 165480093f4SDimitry Andric AtomicEvaluator &&Evaluator) { 166a7dea167SDimitry Andric ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); 167a7dea167SDimitry Andric 1685ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpr) { 169*bdd1243dSDimitry Andric ExprResult LHSRes = calculateConstraintSatisfaction( 170*bdd1243dSDimitry Andric S, BO.getLHS(), Satisfaction, Evaluator); 171*bdd1243dSDimitry Andric 172*bdd1243dSDimitry Andric if (LHSRes.isInvalid()) 173*bdd1243dSDimitry Andric return ExprError(); 174480093f4SDimitry Andric 175480093f4SDimitry Andric bool IsLHSSatisfied = Satisfaction.IsSatisfied; 176480093f4SDimitry Andric 1775ffd83dbSDimitry Andric if (BO.isOr() && IsLHSSatisfied) 178480093f4SDimitry Andric // [temp.constr.op] p3 179480093f4SDimitry Andric // A disjunction is a constraint taking two operands. To determine if 180480093f4SDimitry Andric // a disjunction is satisfied, the satisfaction of the first operand 181480093f4SDimitry Andric // is checked. If that is satisfied, the disjunction is satisfied. 182480093f4SDimitry Andric // Otherwise, the disjunction is satisfied if and only if the second 183480093f4SDimitry Andric // operand is satisfied. 184*bdd1243dSDimitry Andric // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 185*bdd1243dSDimitry Andric return LHSRes; 186480093f4SDimitry Andric 1875ffd83dbSDimitry Andric if (BO.isAnd() && !IsLHSSatisfied) 188480093f4SDimitry Andric // [temp.constr.op] p2 189480093f4SDimitry Andric // A conjunction is a constraint taking two operands. To determine if 190480093f4SDimitry Andric // a conjunction is satisfied, the satisfaction of the first operand 191480093f4SDimitry Andric // is checked. If that is not satisfied, the conjunction is not 192480093f4SDimitry Andric // satisfied. Otherwise, the conjunction is satisfied if and only if 193480093f4SDimitry Andric // the second operand is satisfied. 194*bdd1243dSDimitry Andric // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 195*bdd1243dSDimitry Andric return LHSRes; 196480093f4SDimitry Andric 197*bdd1243dSDimitry Andric ExprResult RHSRes = calculateConstraintSatisfaction( 1985ffd83dbSDimitry Andric S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator)); 199*bdd1243dSDimitry Andric if (RHSRes.isInvalid()) 200*bdd1243dSDimitry Andric return ExprError(); 201*bdd1243dSDimitry Andric 202*bdd1243dSDimitry Andric return BO.recreateBinOp(S, LHSRes, RHSRes); 203*bdd1243dSDimitry Andric } 204*bdd1243dSDimitry Andric 205*bdd1243dSDimitry Andric if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) { 206*bdd1243dSDimitry Andric // These aren't evaluated, so we don't care about cleanups, so we can just 207*bdd1243dSDimitry Andric // evaluate these as if the cleanups didn't exist. 208*bdd1243dSDimitry Andric return calculateConstraintSatisfaction( 209*bdd1243dSDimitry Andric S, C->getSubExpr(), Satisfaction, 210480093f4SDimitry Andric std::forward<AtomicEvaluator>(Evaluator)); 2115ffd83dbSDimitry Andric } 212480093f4SDimitry Andric 213480093f4SDimitry Andric // An atomic constraint expression 214480093f4SDimitry Andric ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr); 215480093f4SDimitry Andric 216480093f4SDimitry Andric if (SubstitutedAtomicExpr.isInvalid()) 217*bdd1243dSDimitry Andric return ExprError(); 218480093f4SDimitry Andric 219480093f4SDimitry Andric if (!SubstitutedAtomicExpr.isUsable()) 220480093f4SDimitry Andric // Evaluator has decided satisfaction without yielding an expression. 221*bdd1243dSDimitry Andric return ExprEmpty(); 222*bdd1243dSDimitry Andric 223*bdd1243dSDimitry Andric // We don't have the ability to evaluate this, since it contains a 224*bdd1243dSDimitry Andric // RecoveryExpr, so we want to fail overload resolution. Otherwise, 225*bdd1243dSDimitry Andric // we'd potentially pick up a different overload, and cause confusing 226*bdd1243dSDimitry Andric // diagnostics. SO, add a failure detail that will cause us to make this 227*bdd1243dSDimitry Andric // overload set not viable. 228*bdd1243dSDimitry Andric if (SubstitutedAtomicExpr.get()->containsErrors()) { 229*bdd1243dSDimitry Andric Satisfaction.IsSatisfied = false; 230*bdd1243dSDimitry Andric Satisfaction.ContainsErrors = true; 231*bdd1243dSDimitry Andric 232*bdd1243dSDimitry Andric PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error); 233*bdd1243dSDimitry Andric SmallString<128> DiagString; 234*bdd1243dSDimitry Andric DiagString = ": "; 235*bdd1243dSDimitry Andric Msg.EmitToString(S.getDiagnostics(), DiagString); 236*bdd1243dSDimitry Andric unsigned MessageSize = DiagString.size(); 237*bdd1243dSDimitry Andric char *Mem = new (S.Context) char[MessageSize]; 238*bdd1243dSDimitry Andric memcpy(Mem, DiagString.c_str(), MessageSize); 239*bdd1243dSDimitry Andric Satisfaction.Details.emplace_back( 240*bdd1243dSDimitry Andric ConstraintExpr, 241*bdd1243dSDimitry Andric new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 242*bdd1243dSDimitry Andric SubstitutedAtomicExpr.get()->getBeginLoc(), 243*bdd1243dSDimitry Andric StringRef(Mem, MessageSize)}); 244*bdd1243dSDimitry Andric return SubstitutedAtomicExpr; 245*bdd1243dSDimitry Andric } 246a7dea167SDimitry Andric 247a7dea167SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 248480093f4SDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 249a7dea167SDimitry Andric SmallVector<PartialDiagnosticAt, 2> EvaluationDiags; 250a7dea167SDimitry Andric Expr::EvalResult EvalResult; 251a7dea167SDimitry Andric EvalResult.Diag = &EvaluationDiags; 252fe6060f1SDimitry Andric if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult, 253fe6060f1SDimitry Andric S.Context) || 254fe6060f1SDimitry Andric !EvaluationDiags.empty()) { 255a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 256a7dea167SDimitry Andric // ...E shall be a constant expression of type bool. 257480093f4SDimitry Andric S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(), 258a7dea167SDimitry Andric diag::err_non_constant_constraint_expression) 259480093f4SDimitry Andric << SubstitutedAtomicExpr.get()->getSourceRange(); 260a7dea167SDimitry Andric for (const PartialDiagnosticAt &PDiag : EvaluationDiags) 261480093f4SDimitry Andric S.Diag(PDiag.first, PDiag.second); 262*bdd1243dSDimitry Andric return ExprError(); 263a7dea167SDimitry Andric } 264a7dea167SDimitry Andric 265fe6060f1SDimitry Andric assert(EvalResult.Val.isInt() && 266fe6060f1SDimitry Andric "evaluating bool expression didn't produce int"); 267480093f4SDimitry Andric Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); 268480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) 269480093f4SDimitry Andric Satisfaction.Details.emplace_back(ConstraintExpr, 270480093f4SDimitry Andric SubstitutedAtomicExpr.get()); 271a7dea167SDimitry Andric 272*bdd1243dSDimitry Andric return SubstitutedAtomicExpr; 273*bdd1243dSDimitry Andric } 274*bdd1243dSDimitry Andric 275*bdd1243dSDimitry Andric static bool 276*bdd1243dSDimitry Andric DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const Expr *E, 277*bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL) { 278*bdd1243dSDimitry Andric E->Profile(ID, S.Context, /*Canonical=*/true); 279*bdd1243dSDimitry Andric for (const auto &List : MLTAL) 280*bdd1243dSDimitry Andric for (const auto &TemplateArg : List.Args) 281*bdd1243dSDimitry Andric TemplateArg.Profile(ID, S.Context); 282*bdd1243dSDimitry Andric 283*bdd1243dSDimitry Andric // Note that we have to do this with our own collection, because there are 284*bdd1243dSDimitry Andric // times where a constraint-expression check can cause us to need to evaluate 285*bdd1243dSDimitry Andric // other constriants that are unrelated, such as when evaluating a recovery 286*bdd1243dSDimitry Andric // expression, or when trying to determine the constexpr-ness of special 287*bdd1243dSDimitry Andric // members. Otherwise we could just use the 288*bdd1243dSDimitry Andric // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function. 289*bdd1243dSDimitry Andric if (S.SatisfactionStackContains(ID)) { 290*bdd1243dSDimitry Andric S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self) 291*bdd1243dSDimitry Andric << const_cast<Expr *>(E) << E->getSourceRange(); 292*bdd1243dSDimitry Andric return true; 293*bdd1243dSDimitry Andric } 294*bdd1243dSDimitry Andric 295a7dea167SDimitry Andric return false; 296a7dea167SDimitry Andric } 297480093f4SDimitry Andric 298*bdd1243dSDimitry Andric static ExprResult calculateConstraintSatisfaction( 299*bdd1243dSDimitry Andric Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc, 300*bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr, 301*bdd1243dSDimitry Andric ConstraintSatisfaction &Satisfaction) { 302480093f4SDimitry Andric return calculateConstraintSatisfaction( 303480093f4SDimitry Andric S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) { 304480093f4SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 305*bdd1243dSDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated, 306*bdd1243dSDimitry Andric Sema::ReuseLambdaContextDecl); 307480093f4SDimitry Andric 308480093f4SDimitry Andric // Atomic constraint - substitute arguments and check satisfaction. 309480093f4SDimitry Andric ExprResult SubstitutedExpression; 310480093f4SDimitry Andric { 311480093f4SDimitry Andric TemplateDeductionInfo Info(TemplateNameLoc); 312480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(), 31313138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintSubstitution{}, 31413138422SDimitry Andric const_cast<NamedDecl *>(Template), Info, 31513138422SDimitry Andric AtomicExpr->getSourceRange()); 316480093f4SDimitry Andric if (Inst.isInvalid()) 317480093f4SDimitry Andric return ExprError(); 318*bdd1243dSDimitry Andric 319*bdd1243dSDimitry Andric llvm::FoldingSetNodeID ID; 320*bdd1243dSDimitry Andric if (DiagRecursiveConstraintEval(S, ID, AtomicExpr, MLTAL)) { 321*bdd1243dSDimitry Andric Satisfaction.IsSatisfied = false; 322*bdd1243dSDimitry Andric Satisfaction.ContainsErrors = true; 323*bdd1243dSDimitry Andric return ExprEmpty(); 324*bdd1243dSDimitry Andric } 325*bdd1243dSDimitry Andric 326*bdd1243dSDimitry Andric SatisfactionStackRAII StackRAII(S, ID); 327*bdd1243dSDimitry Andric 328480093f4SDimitry Andric // We do not want error diagnostics escaping here. 329480093f4SDimitry Andric Sema::SFINAETrap Trap(S); 330fe6060f1SDimitry Andric SubstitutedExpression = 331*bdd1243dSDimitry Andric S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL); 332*bdd1243dSDimitry Andric 333480093f4SDimitry Andric if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) { 334480093f4SDimitry Andric // C++2a [temp.constr.atomic]p1 335480093f4SDimitry Andric // ...If substitution results in an invalid type or expression, the 336480093f4SDimitry Andric // constraint is not satisfied. 337480093f4SDimitry Andric if (!Trap.hasErrorOccurred()) 338349cc55cSDimitry Andric // A non-SFINAE error has occurred as a result of this 339480093f4SDimitry Andric // substitution. 340480093f4SDimitry Andric return ExprError(); 341480093f4SDimitry Andric 342480093f4SDimitry Andric PartialDiagnosticAt SubstDiag{SourceLocation(), 343480093f4SDimitry Andric PartialDiagnostic::NullDiagnostic()}; 344480093f4SDimitry Andric Info.takeSFINAEDiagnostic(SubstDiag); 345480093f4SDimitry Andric // FIXME: Concepts: This is an unfortunate consequence of there 346480093f4SDimitry Andric // being no serialization code for PartialDiagnostics and the fact 347480093f4SDimitry Andric // that serializing them would likely take a lot more storage than 348480093f4SDimitry Andric // just storing them as strings. We would still like, in the 349480093f4SDimitry Andric // future, to serialize the proper PartialDiagnostic as serializing 350480093f4SDimitry Andric // it as a string defeats the purpose of the diagnostic mechanism. 351480093f4SDimitry Andric SmallString<128> DiagString; 352480093f4SDimitry Andric DiagString = ": "; 353480093f4SDimitry Andric SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString); 354480093f4SDimitry Andric unsigned MessageSize = DiagString.size(); 355480093f4SDimitry Andric char *Mem = new (S.Context) char[MessageSize]; 356480093f4SDimitry Andric memcpy(Mem, DiagString.c_str(), MessageSize); 357480093f4SDimitry Andric Satisfaction.Details.emplace_back( 358480093f4SDimitry Andric AtomicExpr, 359480093f4SDimitry Andric new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 360480093f4SDimitry Andric SubstDiag.first, StringRef(Mem, MessageSize)}); 361480093f4SDimitry Andric Satisfaction.IsSatisfied = false; 362480093f4SDimitry Andric return ExprEmpty(); 363480093f4SDimitry Andric } 364480093f4SDimitry Andric } 365480093f4SDimitry Andric 366480093f4SDimitry Andric if (!S.CheckConstraintExpression(SubstitutedExpression.get())) 367480093f4SDimitry Andric return ExprError(); 368480093f4SDimitry Andric 369*bdd1243dSDimitry Andric // [temp.constr.atomic]p3: To determine if an atomic constraint is 370*bdd1243dSDimitry Andric // satisfied, the parameter mapping and template arguments are first 371*bdd1243dSDimitry Andric // substituted into its expression. If substitution results in an 372*bdd1243dSDimitry Andric // invalid type or expression, the constraint is not satisfied. 373*bdd1243dSDimitry Andric // Otherwise, the lvalue-to-rvalue conversion is performed if necessary, 374*bdd1243dSDimitry Andric // and E shall be a constant expression of type bool. 375*bdd1243dSDimitry Andric // 376*bdd1243dSDimitry Andric // Perform the L to R Value conversion if necessary. We do so for all 377*bdd1243dSDimitry Andric // non-PRValue categories, else we fail to extend the lifetime of 378*bdd1243dSDimitry Andric // temporaries, and that fails the constant expression check. 379*bdd1243dSDimitry Andric if (!SubstitutedExpression.get()->isPRValue()) 380*bdd1243dSDimitry Andric SubstitutedExpression = ImplicitCastExpr::Create( 381*bdd1243dSDimitry Andric S.Context, SubstitutedExpression.get()->getType(), 382*bdd1243dSDimitry Andric CK_LValueToRValue, SubstitutedExpression.get(), 383*bdd1243dSDimitry Andric /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride()); 384*bdd1243dSDimitry Andric 385480093f4SDimitry Andric return SubstitutedExpression; 386480093f4SDimitry Andric }); 387480093f4SDimitry Andric } 388480093f4SDimitry Andric 389*bdd1243dSDimitry Andric static bool CheckConstraintSatisfaction( 390*bdd1243dSDimitry Andric Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 391*bdd1243dSDimitry Andric llvm::SmallVectorImpl<Expr *> &Converted, 392*bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &TemplateArgsLists, 393*bdd1243dSDimitry Andric SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { 394480093f4SDimitry Andric if (ConstraintExprs.empty()) { 395480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 396480093f4SDimitry Andric return false; 397480093f4SDimitry Andric } 398480093f4SDimitry Andric 399*bdd1243dSDimitry Andric if (TemplateArgsLists.isAnyArgInstantiationDependent()) { 400480093f4SDimitry Andric // No need to check satisfaction for dependent constraint expressions. 401480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 402480093f4SDimitry Andric return false; 403480093f4SDimitry Andric } 404480093f4SDimitry Andric 405*bdd1243dSDimitry Andric ArrayRef<TemplateArgument> TemplateArgs = 406*bdd1243dSDimitry Andric TemplateArgsLists.getNumSubstitutedLevels() > 0 407*bdd1243dSDimitry Andric ? TemplateArgsLists.getOutermost() 408*bdd1243dSDimitry Andric : ArrayRef<TemplateArgument> {}; 409480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), 41013138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, 41113138422SDimitry Andric const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); 412480093f4SDimitry Andric if (Inst.isInvalid()) 413480093f4SDimitry Andric return true; 414480093f4SDimitry Andric 415480093f4SDimitry Andric for (const Expr *ConstraintExpr : ConstraintExprs) { 416*bdd1243dSDimitry Andric ExprResult Res = calculateConstraintSatisfaction( 417*bdd1243dSDimitry Andric S, Template, TemplateIDRange.getBegin(), TemplateArgsLists, 418*bdd1243dSDimitry Andric ConstraintExpr, Satisfaction); 419*bdd1243dSDimitry Andric if (Res.isInvalid()) 420480093f4SDimitry Andric return true; 421*bdd1243dSDimitry Andric 422*bdd1243dSDimitry Andric Converted.push_back(Res.get()); 423*bdd1243dSDimitry Andric if (!Satisfaction.IsSatisfied) { 424*bdd1243dSDimitry Andric // Backfill the 'converted' list with nulls so we can keep the Converted 425*bdd1243dSDimitry Andric // and unconverted lists in sync. 426*bdd1243dSDimitry Andric Converted.append(ConstraintExprs.size() - Converted.size(), nullptr); 427480093f4SDimitry Andric // [temp.constr.op] p2 428480093f4SDimitry Andric // [...] To determine if a conjunction is satisfied, the satisfaction 429480093f4SDimitry Andric // of the first operand is checked. If that is not satisfied, the 430480093f4SDimitry Andric // conjunction is not satisfied. [...] 431480093f4SDimitry Andric return false; 432480093f4SDimitry Andric } 433*bdd1243dSDimitry Andric } 434480093f4SDimitry Andric return false; 435480093f4SDimitry Andric } 436480093f4SDimitry Andric 43755e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction( 43813138422SDimitry Andric const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 439*bdd1243dSDimitry Andric llvm::SmallVectorImpl<Expr *> &ConvertedConstraints, 440*bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &TemplateArgsLists, 441*bdd1243dSDimitry Andric SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) { 44255e4f9d5SDimitry Andric if (ConstraintExprs.empty()) { 44355e4f9d5SDimitry Andric OutSatisfaction.IsSatisfied = true; 44455e4f9d5SDimitry Andric return false; 445480093f4SDimitry Andric } 44681ad6265SDimitry Andric if (!Template) { 447*bdd1243dSDimitry Andric return ::CheckConstraintSatisfaction( 448*bdd1243dSDimitry Andric *this, nullptr, ConstraintExprs, ConvertedConstraints, 449*bdd1243dSDimitry Andric TemplateArgsLists, TemplateIDRange, OutSatisfaction); 45081ad6265SDimitry Andric } 451*bdd1243dSDimitry Andric 452*bdd1243dSDimitry Andric // A list of the template argument list flattened in a predictible manner for 453*bdd1243dSDimitry Andric // the purposes of caching. The ConstraintSatisfaction type is in AST so it 454*bdd1243dSDimitry Andric // has no access to the MultiLevelTemplateArgumentList, so this has to happen 455*bdd1243dSDimitry Andric // here. 456*bdd1243dSDimitry Andric llvm::SmallVector<TemplateArgument, 4> FlattenedArgs; 457*bdd1243dSDimitry Andric for (auto List : TemplateArgsLists) 458*bdd1243dSDimitry Andric FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(), 459*bdd1243dSDimitry Andric List.Args.end()); 460*bdd1243dSDimitry Andric 46155e4f9d5SDimitry Andric llvm::FoldingSetNodeID ID; 462*bdd1243dSDimitry Andric ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs); 46381ad6265SDimitry Andric void *InsertPos; 46481ad6265SDimitry Andric if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 46581ad6265SDimitry Andric OutSatisfaction = *Cached; 46655e4f9d5SDimitry Andric return false; 46755e4f9d5SDimitry Andric } 468*bdd1243dSDimitry Andric 46981ad6265SDimitry Andric auto Satisfaction = 470*bdd1243dSDimitry Andric std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs); 47113138422SDimitry Andric if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, 472*bdd1243dSDimitry Andric ConvertedConstraints, TemplateArgsLists, 473*bdd1243dSDimitry Andric TemplateIDRange, *Satisfaction)) { 474*bdd1243dSDimitry Andric OutSatisfaction = *Satisfaction; 47555e4f9d5SDimitry Andric return true; 476480093f4SDimitry Andric } 477*bdd1243dSDimitry Andric 478*bdd1243dSDimitry Andric if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 479*bdd1243dSDimitry Andric // The evaluation of this constraint resulted in us trying to re-evaluate it 480*bdd1243dSDimitry Andric // recursively. This isn't really possible, except we try to form a 481*bdd1243dSDimitry Andric // RecoveryExpr as a part of the evaluation. If this is the case, just 482*bdd1243dSDimitry Andric // return the 'cached' version (which will have the same result), and save 483*bdd1243dSDimitry Andric // ourselves the extra-insert. If it ever becomes possible to legitimately 484*bdd1243dSDimitry Andric // recursively check a constraint, we should skip checking the 'inner' one 485*bdd1243dSDimitry Andric // above, and replace the cached version with this one, as it would be more 486*bdd1243dSDimitry Andric // specific. 487*bdd1243dSDimitry Andric OutSatisfaction = *Cached; 488*bdd1243dSDimitry Andric return false; 489*bdd1243dSDimitry Andric } 490*bdd1243dSDimitry Andric 491*bdd1243dSDimitry Andric // Else we can simply add this satisfaction to the list. 49255e4f9d5SDimitry Andric OutSatisfaction = *Satisfaction; 49381ad6265SDimitry Andric // We cannot use InsertPos here because CheckConstraintSatisfaction might have 49481ad6265SDimitry Andric // invalidated it. 49581ad6265SDimitry Andric // Note that entries of SatisfactionCache are deleted in Sema's destructor. 49681ad6265SDimitry Andric SatisfactionCache.InsertNode(Satisfaction.release()); 49755e4f9d5SDimitry Andric return false; 498480093f4SDimitry Andric } 499480093f4SDimitry Andric 500480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr, 501480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction) { 502480093f4SDimitry Andric return calculateConstraintSatisfaction( 503480093f4SDimitry Andric *this, ConstraintExpr, Satisfaction, 50481ad6265SDimitry Andric [this](const Expr *AtomicExpr) -> ExprResult { 50581ad6265SDimitry Andric // We only do this to immitate lvalue-to-rvalue conversion. 506*bdd1243dSDimitry Andric return PerformContextuallyConvertToBool( 507*bdd1243dSDimitry Andric const_cast<Expr *>(AtomicExpr)); 508*bdd1243dSDimitry Andric }) 509*bdd1243dSDimitry Andric .isInvalid(); 510*bdd1243dSDimitry Andric } 511*bdd1243dSDimitry Andric 512*bdd1243dSDimitry Andric bool Sema::SetupConstraintScope( 513*bdd1243dSDimitry Andric FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 514*bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) { 515*bdd1243dSDimitry Andric if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { 516*bdd1243dSDimitry Andric FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); 517*bdd1243dSDimitry Andric InstantiatingTemplate Inst( 518*bdd1243dSDimitry Andric *this, FD->getPointOfInstantiation(), 519*bdd1243dSDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate, 520*bdd1243dSDimitry Andric TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 521*bdd1243dSDimitry Andric SourceRange()); 522*bdd1243dSDimitry Andric if (Inst.isInvalid()) 523*bdd1243dSDimitry Andric return true; 524*bdd1243dSDimitry Andric 525*bdd1243dSDimitry Andric // addInstantiatedParametersToScope creates a map of 'uninstantiated' to 526*bdd1243dSDimitry Andric // 'instantiated' parameters and adds it to the context. For the case where 527*bdd1243dSDimitry Andric // this function is a template being instantiated NOW, we also need to add 528*bdd1243dSDimitry Andric // the list of current template arguments to the list so that they also can 529*bdd1243dSDimitry Andric // be picked out of the map. 530*bdd1243dSDimitry Andric if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) { 531*bdd1243dSDimitry Andric MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(), 532*bdd1243dSDimitry Andric /*Final=*/false); 533*bdd1243dSDimitry Andric if (addInstantiatedParametersToScope( 534*bdd1243dSDimitry Andric FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs)) 535*bdd1243dSDimitry Andric return true; 536*bdd1243dSDimitry Andric } 537*bdd1243dSDimitry Andric 538*bdd1243dSDimitry Andric // If this is a member function, make sure we get the parameters that 539*bdd1243dSDimitry Andric // reference the original primary template. 540*bdd1243dSDimitry Andric if (const auto *FromMemTempl = 541*bdd1243dSDimitry Andric PrimaryTemplate->getInstantiatedFromMemberTemplate()) { 542*bdd1243dSDimitry Andric if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(), 543*bdd1243dSDimitry Andric Scope, MLTAL)) 544*bdd1243dSDimitry Andric return true; 545*bdd1243dSDimitry Andric } 546*bdd1243dSDimitry Andric 547*bdd1243dSDimitry Andric return false; 548*bdd1243dSDimitry Andric } 549*bdd1243dSDimitry Andric 550*bdd1243dSDimitry Andric if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || 551*bdd1243dSDimitry Andric FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) { 552*bdd1243dSDimitry Andric FunctionDecl *InstantiatedFrom = 553*bdd1243dSDimitry Andric FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization 554*bdd1243dSDimitry Andric ? FD->getInstantiatedFromMemberFunction() 555*bdd1243dSDimitry Andric : FD->getInstantiatedFromDecl(); 556*bdd1243dSDimitry Andric 557*bdd1243dSDimitry Andric InstantiatingTemplate Inst( 558*bdd1243dSDimitry Andric *this, FD->getPointOfInstantiation(), 559*bdd1243dSDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom, 560*bdd1243dSDimitry Andric TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 561*bdd1243dSDimitry Andric SourceRange()); 562*bdd1243dSDimitry Andric if (Inst.isInvalid()) 563*bdd1243dSDimitry Andric return true; 564*bdd1243dSDimitry Andric 565*bdd1243dSDimitry Andric // Case where this was not a template, but instantiated as a 566*bdd1243dSDimitry Andric // child-function. 567*bdd1243dSDimitry Andric if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL)) 568*bdd1243dSDimitry Andric return true; 569*bdd1243dSDimitry Andric } 570*bdd1243dSDimitry Andric 571*bdd1243dSDimitry Andric return false; 572*bdd1243dSDimitry Andric } 573*bdd1243dSDimitry Andric 574*bdd1243dSDimitry Andric // This function collects all of the template arguments for the purposes of 575*bdd1243dSDimitry Andric // constraint-instantiation and checking. 576*bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> 577*bdd1243dSDimitry Andric Sema::SetupConstraintCheckingTemplateArgumentsAndScope( 578*bdd1243dSDimitry Andric FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 579*bdd1243dSDimitry Andric LocalInstantiationScope &Scope) { 580*bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL; 581*bdd1243dSDimitry Andric 582*bdd1243dSDimitry Andric // Collect the list of template arguments relative to the 'primary' template. 583*bdd1243dSDimitry Andric // We need the entire list, since the constraint is completely uninstantiated 584*bdd1243dSDimitry Andric // at this point. 585*bdd1243dSDimitry Andric MLTAL = 586*bdd1243dSDimitry Andric getTemplateInstantiationArgs(FD, /*Final=*/false, /*Innermost=*/nullptr, 587*bdd1243dSDimitry Andric /*RelativeToPrimary=*/true, 588*bdd1243dSDimitry Andric /*Pattern=*/nullptr, 589*bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true); 590*bdd1243dSDimitry Andric if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) 591*bdd1243dSDimitry Andric return std::nullopt; 592*bdd1243dSDimitry Andric 593*bdd1243dSDimitry Andric return MLTAL; 594480093f4SDimitry Andric } 595480093f4SDimitry Andric 59613138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, 59713138422SDimitry Andric ConstraintSatisfaction &Satisfaction, 598*bdd1243dSDimitry Andric SourceLocation UsageLoc, 599*bdd1243dSDimitry Andric bool ForOverloadResolution) { 600*bdd1243dSDimitry Andric // Don't check constraints if the function is dependent. Also don't check if 601*bdd1243dSDimitry Andric // this is a function template specialization, as the call to 602*bdd1243dSDimitry Andric // CheckinstantiatedFunctionTemplateConstraints after this will check it 603*bdd1243dSDimitry Andric // better. 604*bdd1243dSDimitry Andric if (FD->isDependentContext() || 605*bdd1243dSDimitry Andric FD->getTemplatedKind() == 606*bdd1243dSDimitry Andric FunctionDecl::TK_FunctionTemplateSpecialization) { 60713138422SDimitry Andric Satisfaction.IsSatisfied = true; 60813138422SDimitry Andric return false; 60913138422SDimitry Andric } 610*bdd1243dSDimitry Andric 611*bdd1243dSDimitry Andric DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD); 612*bdd1243dSDimitry Andric 613*bdd1243dSDimitry Andric while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) { 614*bdd1243dSDimitry Andric if (isLambdaCallOperator(CtxToSave)) 615*bdd1243dSDimitry Andric CtxToSave = CtxToSave->getParent()->getParent(); 616*bdd1243dSDimitry Andric else 617*bdd1243dSDimitry Andric CtxToSave = CtxToSave->getNonTransparentContext(); 618*bdd1243dSDimitry Andric } 619*bdd1243dSDimitry Andric 620*bdd1243dSDimitry Andric ContextRAII SavedContext{*this, CtxToSave}; 621*bdd1243dSDimitry Andric LocalInstantiationScope Scope(*this, !ForOverloadResolution || 622*bdd1243dSDimitry Andric isLambdaCallOperator(FD)); 623*bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> MLTAL = 624*bdd1243dSDimitry Andric SetupConstraintCheckingTemplateArgumentsAndScope( 625*bdd1243dSDimitry Andric const_cast<FunctionDecl *>(FD), {}, Scope); 626*bdd1243dSDimitry Andric 627*bdd1243dSDimitry Andric if (!MLTAL) 628*bdd1243dSDimitry Andric return true; 629*bdd1243dSDimitry Andric 63013138422SDimitry Andric Qualifiers ThisQuals; 63113138422SDimitry Andric CXXRecordDecl *Record = nullptr; 63213138422SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { 63313138422SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 63413138422SDimitry Andric Record = const_cast<CXXRecordDecl *>(Method->getParent()); 63513138422SDimitry Andric } 63613138422SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 63713138422SDimitry Andric // We substitute with empty arguments in order to rebuild the atomic 63813138422SDimitry Andric // constraint in a constant-evaluated context. 63913138422SDimitry Andric // FIXME: Should this be a dedicated TreeTransform? 640*bdd1243dSDimitry Andric const Expr *RC = FD->getTrailingRequiresClause(); 641*bdd1243dSDimitry Andric llvm::SmallVector<Expr *, 1> Converted; 642*bdd1243dSDimitry Andric 643*bdd1243dSDimitry Andric if (CheckConstraintSatisfaction( 644*bdd1243dSDimitry Andric FD, {RC}, Converted, *MLTAL, 64513138422SDimitry Andric SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), 646*bdd1243dSDimitry Andric Satisfaction)) 647*bdd1243dSDimitry Andric return true; 648*bdd1243dSDimitry Andric 649*bdd1243dSDimitry Andric // FIXME: we need to do this for the function constraints for 650*bdd1243dSDimitry Andric // comparison of constraints to work, but do we also need to do it for 651*bdd1243dSDimitry Andric // CheckInstantiatedFunctionConstraints? That one is more difficult, but we 652*bdd1243dSDimitry Andric // seem to always just pick up the constraints from the primary template. 653*bdd1243dSDimitry Andric assert(Converted.size() <= 1 && "Got more expressions converted?"); 654*bdd1243dSDimitry Andric if (!Converted.empty() && Converted[0] != nullptr) 655*bdd1243dSDimitry Andric const_cast<FunctionDecl *>(FD)->setTrailingRequiresClause(Converted[0]); 656*bdd1243dSDimitry Andric return false; 657*bdd1243dSDimitry Andric } 658*bdd1243dSDimitry Andric 659*bdd1243dSDimitry Andric 660*bdd1243dSDimitry Andric // Figure out the to-translation-unit depth for this function declaration for 661*bdd1243dSDimitry Andric // the purpose of seeing if they differ by constraints. This isn't the same as 662*bdd1243dSDimitry Andric // getTemplateDepth, because it includes already instantiated parents. 663*bdd1243dSDimitry Andric static unsigned 664*bdd1243dSDimitry Andric CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, 665*bdd1243dSDimitry Andric bool SkipForSpecialization = false) { 666*bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 667*bdd1243dSDimitry Andric ND, /*Final=*/false, /*Innermost=*/nullptr, /*RelativeToPrimary=*/true, 668*bdd1243dSDimitry Andric /*Pattern=*/nullptr, 669*bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true, SkipForSpecialization); 670*bdd1243dSDimitry Andric return MLTAL.getNumSubstitutedLevels(); 671*bdd1243dSDimitry Andric } 672*bdd1243dSDimitry Andric 673*bdd1243dSDimitry Andric namespace { 674*bdd1243dSDimitry Andric class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> { 675*bdd1243dSDimitry Andric unsigned TemplateDepth = 0; 676*bdd1243dSDimitry Andric public: 677*bdd1243dSDimitry Andric using inherited = TreeTransform<AdjustConstraintDepth>; 678*bdd1243dSDimitry Andric AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth) 679*bdd1243dSDimitry Andric : inherited(SemaRef), TemplateDepth(TemplateDepth) {} 680*bdd1243dSDimitry Andric 681*bdd1243dSDimitry Andric using inherited::TransformTemplateTypeParmType; 682*bdd1243dSDimitry Andric QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, 683*bdd1243dSDimitry Andric TemplateTypeParmTypeLoc TL, bool) { 684*bdd1243dSDimitry Andric const TemplateTypeParmType *T = TL.getTypePtr(); 685*bdd1243dSDimitry Andric 686*bdd1243dSDimitry Andric TemplateTypeParmDecl *NewTTPDecl = nullptr; 687*bdd1243dSDimitry Andric if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) 688*bdd1243dSDimitry Andric NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( 689*bdd1243dSDimitry Andric TransformDecl(TL.getNameLoc(), OldTTPDecl)); 690*bdd1243dSDimitry Andric 691*bdd1243dSDimitry Andric QualType Result = getSema().Context.getTemplateTypeParmType( 692*bdd1243dSDimitry Andric T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(), 693*bdd1243dSDimitry Andric NewTTPDecl); 694*bdd1243dSDimitry Andric TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); 695*bdd1243dSDimitry Andric NewTL.setNameLoc(TL.getNameLoc()); 696*bdd1243dSDimitry Andric return Result; 697*bdd1243dSDimitry Andric } 698*bdd1243dSDimitry Andric }; 699*bdd1243dSDimitry Andric } // namespace 700*bdd1243dSDimitry Andric 701*bdd1243dSDimitry Andric bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, 702*bdd1243dSDimitry Andric const Expr *OldConstr, 703*bdd1243dSDimitry Andric const NamedDecl *New, 704*bdd1243dSDimitry Andric const Expr *NewConstr) { 705*bdd1243dSDimitry Andric if (Old && New && Old != New) { 706*bdd1243dSDimitry Andric unsigned Depth1 = CalculateTemplateDepthForConstraints( 707*bdd1243dSDimitry Andric *this, Old); 708*bdd1243dSDimitry Andric unsigned Depth2 = CalculateTemplateDepthForConstraints( 709*bdd1243dSDimitry Andric *this, New); 710*bdd1243dSDimitry Andric 711*bdd1243dSDimitry Andric // Adjust the 'shallowest' verison of this to increase the depth to match 712*bdd1243dSDimitry Andric // the 'other'. 713*bdd1243dSDimitry Andric if (Depth2 > Depth1) { 714*bdd1243dSDimitry Andric OldConstr = AdjustConstraintDepth(*this, Depth2 - Depth1) 715*bdd1243dSDimitry Andric .TransformExpr(const_cast<Expr *>(OldConstr)) 716*bdd1243dSDimitry Andric .get(); 717*bdd1243dSDimitry Andric } else if (Depth1 > Depth2) { 718*bdd1243dSDimitry Andric NewConstr = AdjustConstraintDepth(*this, Depth1 - Depth2) 719*bdd1243dSDimitry Andric .TransformExpr(const_cast<Expr *>(NewConstr)) 720*bdd1243dSDimitry Andric .get(); 721*bdd1243dSDimitry Andric } 722*bdd1243dSDimitry Andric } 723*bdd1243dSDimitry Andric 724*bdd1243dSDimitry Andric llvm::FoldingSetNodeID ID1, ID2; 725*bdd1243dSDimitry Andric OldConstr->Profile(ID1, Context, /*Canonical=*/true); 726*bdd1243dSDimitry Andric NewConstr->Profile(ID2, Context, /*Canonical=*/true); 727*bdd1243dSDimitry Andric return ID1 == ID2; 728*bdd1243dSDimitry Andric } 729*bdd1243dSDimitry Andric 730*bdd1243dSDimitry Andric bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { 731*bdd1243dSDimitry Andric assert(FD->getFriendObjectKind() && "Must be a friend!"); 732*bdd1243dSDimitry Andric 733*bdd1243dSDimitry Andric // The logic for non-templates is handled in ASTContext::isSameEntity, so we 734*bdd1243dSDimitry Andric // don't have to bother checking 'DependsOnEnclosingTemplate' for a 735*bdd1243dSDimitry Andric // non-function-template. 736*bdd1243dSDimitry Andric assert(FD->getDescribedFunctionTemplate() && 737*bdd1243dSDimitry Andric "Non-function templates don't need to be checked"); 738*bdd1243dSDimitry Andric 739*bdd1243dSDimitry Andric SmallVector<const Expr *, 3> ACs; 740*bdd1243dSDimitry Andric FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); 741*bdd1243dSDimitry Andric 742*bdd1243dSDimitry Andric unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD); 743*bdd1243dSDimitry Andric for (const Expr *Constraint : ACs) 744*bdd1243dSDimitry Andric if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth, 745*bdd1243dSDimitry Andric Constraint)) 746*bdd1243dSDimitry Andric return true; 747*bdd1243dSDimitry Andric 748*bdd1243dSDimitry Andric return false; 74913138422SDimitry Andric } 75013138422SDimitry Andric 751480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints( 752*bdd1243dSDimitry Andric TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists, 753480093f4SDimitry Andric SourceRange TemplateIDRange) { 754480093f4SDimitry Andric ConstraintSatisfaction Satisfaction; 755480093f4SDimitry Andric llvm::SmallVector<const Expr *, 3> AssociatedConstraints; 756480093f4SDimitry Andric TD->getAssociatedConstraints(AssociatedConstraints); 757*bdd1243dSDimitry Andric if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists, 758480093f4SDimitry Andric TemplateIDRange, Satisfaction)) 759480093f4SDimitry Andric return true; 760480093f4SDimitry Andric 761480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) { 762480093f4SDimitry Andric SmallString<128> TemplateArgString; 763480093f4SDimitry Andric TemplateArgString = " "; 764480093f4SDimitry Andric TemplateArgString += getTemplateArgumentBindingsText( 765*bdd1243dSDimitry Andric TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(), 766*bdd1243dSDimitry Andric TemplateArgsLists.getInnermost().size()); 767480093f4SDimitry Andric 768480093f4SDimitry Andric Diag(TemplateIDRange.getBegin(), 769480093f4SDimitry Andric diag::err_template_arg_list_constraints_not_satisfied) 770480093f4SDimitry Andric << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD 771480093f4SDimitry Andric << TemplateArgString << TemplateIDRange; 772480093f4SDimitry Andric DiagnoseUnsatisfiedConstraint(Satisfaction); 773480093f4SDimitry Andric return true; 774480093f4SDimitry Andric } 775480093f4SDimitry Andric return false; 776480093f4SDimitry Andric } 777480093f4SDimitry Andric 77881ad6265SDimitry Andric bool Sema::CheckInstantiatedFunctionTemplateConstraints( 77981ad6265SDimitry Andric SourceLocation PointOfInstantiation, FunctionDecl *Decl, 78081ad6265SDimitry Andric ArrayRef<TemplateArgument> TemplateArgs, 78181ad6265SDimitry Andric ConstraintSatisfaction &Satisfaction) { 78281ad6265SDimitry Andric // In most cases we're not going to have constraints, so check for that first. 78381ad6265SDimitry Andric FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); 78481ad6265SDimitry Andric // Note - code synthesis context for the constraints check is created 78581ad6265SDimitry Andric // inside CheckConstraintsSatisfaction. 78681ad6265SDimitry Andric SmallVector<const Expr *, 3> TemplateAC; 78781ad6265SDimitry Andric Template->getAssociatedConstraints(TemplateAC); 78881ad6265SDimitry Andric if (TemplateAC.empty()) { 78981ad6265SDimitry Andric Satisfaction.IsSatisfied = true; 79081ad6265SDimitry Andric return false; 79181ad6265SDimitry Andric } 79281ad6265SDimitry Andric 79381ad6265SDimitry Andric // Enter the scope of this instantiation. We don't use 79481ad6265SDimitry Andric // PushDeclContext because we don't have a scope. 79581ad6265SDimitry Andric Sema::ContextRAII savedContext(*this, Decl); 79681ad6265SDimitry Andric LocalInstantiationScope Scope(*this); 79781ad6265SDimitry Andric 798*bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList> MLTAL = 799*bdd1243dSDimitry Andric SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs, 800*bdd1243dSDimitry Andric Scope); 801*bdd1243dSDimitry Andric 802*bdd1243dSDimitry Andric if (!MLTAL) 80381ad6265SDimitry Andric return true; 804*bdd1243dSDimitry Andric 80581ad6265SDimitry Andric Qualifiers ThisQuals; 80681ad6265SDimitry Andric CXXRecordDecl *Record = nullptr; 80781ad6265SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { 80881ad6265SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 80981ad6265SDimitry Andric Record = Method->getParent(); 81081ad6265SDimitry Andric } 81181ad6265SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 812*bdd1243dSDimitry Andric FunctionScopeRAII FuncScope(*this); 813*bdd1243dSDimitry Andric if (isLambdaCallOperator(Decl)) 814*bdd1243dSDimitry Andric PushLambdaScope(); 815*bdd1243dSDimitry Andric else 816*bdd1243dSDimitry Andric FuncScope.disable(); 817*bdd1243dSDimitry Andric 818*bdd1243dSDimitry Andric llvm::SmallVector<Expr *, 1> Converted; 819*bdd1243dSDimitry Andric return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL, 82081ad6265SDimitry Andric PointOfInstantiation, Satisfaction); 82181ad6265SDimitry Andric } 82281ad6265SDimitry Andric 82355e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 82455e4f9d5SDimitry Andric concepts::ExprRequirement *Req, 82555e4f9d5SDimitry Andric bool First) { 82655e4f9d5SDimitry Andric assert(!Req->isSatisfied() 82755e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 82855e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 82955e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Dependent: 83055e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 83155e4f9d5SDimitry Andric break; 83255e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ExprSubstitutionFailure: { 83355e4f9d5SDimitry Andric auto *SubstDiag = Req->getExprSubstitutionDiagnostic(); 83455e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 83555e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 83655e4f9d5SDimitry Andric diag::note_expr_requirement_expr_substitution_error) 83755e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 83855e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 83955e4f9d5SDimitry Andric else 84055e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 84155e4f9d5SDimitry Andric diag::note_expr_requirement_expr_unknown_substitution_error) 84255e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 84355e4f9d5SDimitry Andric break; 84455e4f9d5SDimitry Andric } 84555e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_NoexceptNotMet: 84655e4f9d5SDimitry Andric S.Diag(Req->getNoexceptLoc(), 84755e4f9d5SDimitry Andric diag::note_expr_requirement_noexcept_not_met) 84855e4f9d5SDimitry Andric << (int)First << Req->getExpr(); 84955e4f9d5SDimitry Andric break; 85055e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: { 85155e4f9d5SDimitry Andric auto *SubstDiag = 85255e4f9d5SDimitry Andric Req->getReturnTypeRequirement().getSubstitutionDiagnostic(); 85355e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 85455e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 85555e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_substitution_error) 85655e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 85755e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 85855e4f9d5SDimitry Andric else 85955e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 86055e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_unknown_substitution_error) 86155e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 86255e4f9d5SDimitry Andric break; 86355e4f9d5SDimitry Andric } 86455e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { 86555e4f9d5SDimitry Andric ConceptSpecializationExpr *ConstraintExpr = 86655e4f9d5SDimitry Andric Req->getReturnTypeRequirementSubstitutedConstraintExpr(); 867fe6060f1SDimitry Andric if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 86855e4f9d5SDimitry Andric // A simple case - expr type is the type being constrained and the concept 86955e4f9d5SDimitry Andric // was not provided arguments. 870fe6060f1SDimitry Andric Expr *e = Req->getExpr(); 871fe6060f1SDimitry Andric S.Diag(e->getBeginLoc(), 87255e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied_simple) 873349cc55cSDimitry Andric << (int)First << S.Context.getReferenceQualifiedType(e) 87455e4f9d5SDimitry Andric << ConstraintExpr->getNamedConcept(); 875fe6060f1SDimitry Andric } else { 87655e4f9d5SDimitry Andric S.Diag(ConstraintExpr->getBeginLoc(), 87755e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied) 87855e4f9d5SDimitry Andric << (int)First << ConstraintExpr; 879fe6060f1SDimitry Andric } 88055e4f9d5SDimitry Andric S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); 88155e4f9d5SDimitry Andric break; 88255e4f9d5SDimitry Andric } 88355e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Satisfied: 88455e4f9d5SDimitry Andric llvm_unreachable("We checked this above"); 88555e4f9d5SDimitry Andric } 88655e4f9d5SDimitry Andric } 88755e4f9d5SDimitry Andric 88855e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 88955e4f9d5SDimitry Andric concepts::TypeRequirement *Req, 89055e4f9d5SDimitry Andric bool First) { 89155e4f9d5SDimitry Andric assert(!Req->isSatisfied() 89255e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 89355e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 89455e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_Dependent: 89555e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 89655e4f9d5SDimitry Andric return; 89755e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_SubstitutionFailure: { 89855e4f9d5SDimitry Andric auto *SubstDiag = Req->getSubstitutionDiagnostic(); 89955e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 90055e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 90155e4f9d5SDimitry Andric diag::note_type_requirement_substitution_error) << (int)First 90255e4f9d5SDimitry Andric << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage; 90355e4f9d5SDimitry Andric else 90455e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 90555e4f9d5SDimitry Andric diag::note_type_requirement_unknown_substitution_error) 90655e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 90755e4f9d5SDimitry Andric return; 90855e4f9d5SDimitry Andric } 90955e4f9d5SDimitry Andric default: 91055e4f9d5SDimitry Andric llvm_unreachable("Unknown satisfaction status"); 91155e4f9d5SDimitry Andric return; 91255e4f9d5SDimitry Andric } 91355e4f9d5SDimitry Andric } 914*bdd1243dSDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 915*bdd1243dSDimitry Andric Expr *SubstExpr, 916*bdd1243dSDimitry Andric bool First = true); 91755e4f9d5SDimitry Andric 91855e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 91955e4f9d5SDimitry Andric concepts::NestedRequirement *Req, 92055e4f9d5SDimitry Andric bool First) { 921*bdd1243dSDimitry Andric using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; 922*bdd1243dSDimitry Andric for (auto &Pair : Req->getConstraintSatisfaction()) { 923*bdd1243dSDimitry Andric if (auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>()) 924*bdd1243dSDimitry Andric S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error) 925*bdd1243dSDimitry Andric << (int)First << Req->getInvalidConstraintEntity() << SubstDiag->second; 92655e4f9d5SDimitry Andric else 927*bdd1243dSDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr( 928*bdd1243dSDimitry Andric S, Pair.second.dyn_cast<Expr *>(), First); 929*bdd1243dSDimitry Andric First = false; 93055e4f9d5SDimitry Andric } 93155e4f9d5SDimitry Andric } 93255e4f9d5SDimitry Andric 933480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 934480093f4SDimitry Andric Expr *SubstExpr, 935*bdd1243dSDimitry Andric bool First) { 936480093f4SDimitry Andric SubstExpr = SubstExpr->IgnoreParenImpCasts(); 937480093f4SDimitry Andric if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) { 938480093f4SDimitry Andric switch (BO->getOpcode()) { 939480093f4SDimitry Andric // These two cases will in practice only be reached when using fold 940480093f4SDimitry Andric // expressions with || and &&, since otherwise the || and && will have been 941480093f4SDimitry Andric // broken down into atomic constraints during satisfaction checking. 942480093f4SDimitry Andric case BO_LOr: 943480093f4SDimitry Andric // Or evaluated to false - meaning both RHS and LHS evaluated to false. 944480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 945480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 946480093f4SDimitry Andric /*First=*/false); 947480093f4SDimitry Andric return; 948fe6060f1SDimitry Andric case BO_LAnd: { 949fe6060f1SDimitry Andric bool LHSSatisfied = 950fe6060f1SDimitry Andric BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 951480093f4SDimitry Andric if (LHSSatisfied) { 952480093f4SDimitry Andric // LHS is true, so RHS must be false. 953480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First); 954480093f4SDimitry Andric return; 955480093f4SDimitry Andric } 956480093f4SDimitry Andric // LHS is false 957480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 958480093f4SDimitry Andric 959480093f4SDimitry Andric // RHS might also be false 960fe6060f1SDimitry Andric bool RHSSatisfied = 961fe6060f1SDimitry Andric BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 962480093f4SDimitry Andric if (!RHSSatisfied) 963480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 964480093f4SDimitry Andric /*First=*/false); 965480093f4SDimitry Andric return; 966fe6060f1SDimitry Andric } 967480093f4SDimitry Andric case BO_GE: 968480093f4SDimitry Andric case BO_LE: 969480093f4SDimitry Andric case BO_GT: 970480093f4SDimitry Andric case BO_LT: 971480093f4SDimitry Andric case BO_EQ: 972480093f4SDimitry Andric case BO_NE: 973480093f4SDimitry Andric if (BO->getLHS()->getType()->isIntegerType() && 974480093f4SDimitry Andric BO->getRHS()->getType()->isIntegerType()) { 975480093f4SDimitry Andric Expr::EvalResult SimplifiedLHS; 976480093f4SDimitry Andric Expr::EvalResult SimplifiedRHS; 977fe6060f1SDimitry Andric BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context, 978fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 979fe6060f1SDimitry Andric /*InConstantContext=*/true); 980fe6060f1SDimitry Andric BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context, 981fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 982fe6060f1SDimitry Andric /*InConstantContext=*/true); 983480093f4SDimitry Andric if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) { 984480093f4SDimitry Andric S.Diag(SubstExpr->getBeginLoc(), 985480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false_elaborated) 986480093f4SDimitry Andric << (int)First << SubstExpr 987fe6060f1SDimitry Andric << toString(SimplifiedLHS.Val.getInt(), 10) 988480093f4SDimitry Andric << BinaryOperator::getOpcodeStr(BO->getOpcode()) 989fe6060f1SDimitry Andric << toString(SimplifiedRHS.Val.getInt(), 10); 990480093f4SDimitry Andric return; 991480093f4SDimitry Andric } 992480093f4SDimitry Andric } 993480093f4SDimitry Andric break; 994480093f4SDimitry Andric 995480093f4SDimitry Andric default: 996480093f4SDimitry Andric break; 997480093f4SDimitry Andric } 998480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) { 999480093f4SDimitry Andric if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 1000480093f4SDimitry Andric S.Diag( 1001480093f4SDimitry Andric CSE->getSourceRange().getBegin(), 1002480093f4SDimitry Andric diag:: 1003480093f4SDimitry Andric note_single_arg_concept_specialization_constraint_evaluated_to_false) 1004480093f4SDimitry Andric << (int)First 1005480093f4SDimitry Andric << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument() 1006480093f4SDimitry Andric << CSE->getNamedConcept(); 1007480093f4SDimitry Andric } else { 1008480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 1009480093f4SDimitry Andric diag::note_concept_specialization_constraint_evaluated_to_false) 1010480093f4SDimitry Andric << (int)First << CSE; 1011480093f4SDimitry Andric } 1012480093f4SDimitry Andric S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction()); 1013480093f4SDimitry Andric return; 101455e4f9d5SDimitry Andric } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) { 1015*bdd1243dSDimitry Andric // FIXME: RequiresExpr should store dependent diagnostics. 101655e4f9d5SDimitry Andric for (concepts::Requirement *Req : RE->getRequirements()) 101755e4f9d5SDimitry Andric if (!Req->isDependent() && !Req->isSatisfied()) { 101855e4f9d5SDimitry Andric if (auto *E = dyn_cast<concepts::ExprRequirement>(Req)) 101955e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, E, First); 102055e4f9d5SDimitry Andric else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req)) 102155e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, T, First); 102255e4f9d5SDimitry Andric else 102355e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement( 102455e4f9d5SDimitry Andric S, cast<concepts::NestedRequirement>(Req), First); 102555e4f9d5SDimitry Andric break; 102655e4f9d5SDimitry Andric } 102755e4f9d5SDimitry Andric return; 1028480093f4SDimitry Andric } 1029480093f4SDimitry Andric 1030480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 1031480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false) 1032480093f4SDimitry Andric << (int)First << SubstExpr; 1033480093f4SDimitry Andric } 1034480093f4SDimitry Andric 1035480093f4SDimitry Andric template<typename SubstitutionDiagnostic> 1036480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr( 1037480093f4SDimitry Andric Sema &S, const Expr *E, 1038480093f4SDimitry Andric const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record, 1039480093f4SDimitry Andric bool First = true) { 1040480093f4SDimitry Andric if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){ 1041480093f4SDimitry Andric S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed) 1042480093f4SDimitry Andric << Diag->second; 1043480093f4SDimitry Andric return; 1044480093f4SDimitry Andric } 1045480093f4SDimitry Andric 1046480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, 1047480093f4SDimitry Andric Record.template get<Expr *>(), First); 1048480093f4SDimitry Andric } 1049480093f4SDimitry Andric 105055e4f9d5SDimitry Andric void 105155e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, 105255e4f9d5SDimitry Andric bool First) { 1053480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 1054480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 1055480093f4SDimitry Andric for (auto &Pair : Satisfaction.Details) { 1056480093f4SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); 1057480093f4SDimitry Andric First = false; 1058480093f4SDimitry Andric } 1059480093f4SDimitry Andric } 1060480093f4SDimitry Andric 1061480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint( 106255e4f9d5SDimitry Andric const ASTConstraintSatisfaction &Satisfaction, 106355e4f9d5SDimitry Andric bool First) { 1064480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 1065480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 1066480093f4SDimitry Andric for (auto &Pair : Satisfaction) { 1067480093f4SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); 1068480093f4SDimitry Andric First = false; 1069480093f4SDimitry Andric } 1070480093f4SDimitry Andric } 1071480093f4SDimitry Andric 1072480093f4SDimitry Andric const NormalizedConstraint * 1073480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints( 1074480093f4SDimitry Andric NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) { 1075480093f4SDimitry Andric auto CacheEntry = NormalizationCache.find(ConstrainedDecl); 1076480093f4SDimitry Andric if (CacheEntry == NormalizationCache.end()) { 1077480093f4SDimitry Andric auto Normalized = 1078480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl, 1079480093f4SDimitry Andric AssociatedConstraints); 1080480093f4SDimitry Andric CacheEntry = 1081480093f4SDimitry Andric NormalizationCache 1082480093f4SDimitry Andric .try_emplace(ConstrainedDecl, 1083480093f4SDimitry Andric Normalized 1084480093f4SDimitry Andric ? new (Context) NormalizedConstraint( 1085480093f4SDimitry Andric std::move(*Normalized)) 1086480093f4SDimitry Andric : nullptr) 1087480093f4SDimitry Andric .first; 1088480093f4SDimitry Andric } 1089480093f4SDimitry Andric return CacheEntry->second; 1090480093f4SDimitry Andric } 1091480093f4SDimitry Andric 1092*bdd1243dSDimitry Andric static bool 1093*bdd1243dSDimitry Andric substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1094*bdd1243dSDimitry Andric ConceptDecl *Concept, 1095*bdd1243dSDimitry Andric const MultiLevelTemplateArgumentList &MLTAL, 1096480093f4SDimitry Andric const ASTTemplateArgumentListInfo *ArgsAsWritten) { 1097480093f4SDimitry Andric if (!N.isAtomic()) { 1098*bdd1243dSDimitry Andric if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL, 1099480093f4SDimitry Andric ArgsAsWritten)) 1100480093f4SDimitry Andric return true; 1101*bdd1243dSDimitry Andric return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL, 1102480093f4SDimitry Andric ArgsAsWritten); 1103480093f4SDimitry Andric } 1104480093f4SDimitry Andric TemplateParameterList *TemplateParams = Concept->getTemplateParameters(); 1105480093f4SDimitry Andric 1106480093f4SDimitry Andric AtomicConstraint &Atomic = *N.getAtomicConstraint(); 1107480093f4SDimitry Andric TemplateArgumentListInfo SubstArgs; 1108480093f4SDimitry Andric if (!Atomic.ParameterMapping) { 1109480093f4SDimitry Andric llvm::SmallBitVector OccurringIndices(TemplateParams->size()); 1110480093f4SDimitry Andric S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false, 1111480093f4SDimitry Andric /*Depth=*/0, OccurringIndices); 1112*bdd1243dSDimitry Andric TemplateArgumentLoc *TempArgs = 1113*bdd1243dSDimitry Andric new (S.Context) TemplateArgumentLoc[OccurringIndices.count()]; 1114480093f4SDimitry Andric for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) 1115480093f4SDimitry Andric if (OccurringIndices[I]) 1116*bdd1243dSDimitry Andric new (&(TempArgs)[J++]) 1117*bdd1243dSDimitry Andric TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc( 1118*bdd1243dSDimitry Andric TemplateParams->begin()[I], 1119480093f4SDimitry Andric // Here we assume we do not support things like 1120480093f4SDimitry Andric // template<typename A, typename B> 1121480093f4SDimitry Andric // concept C = ...; 1122480093f4SDimitry Andric // 1123480093f4SDimitry Andric // template<typename... Ts> requires C<Ts...> 1124480093f4SDimitry Andric // struct S { }; 1125480093f4SDimitry Andric // The above currently yields a diagnostic. 1126480093f4SDimitry Andric // We still might have default arguments for concept parameters. 1127*bdd1243dSDimitry Andric ArgsAsWritten->NumTemplateArgs > I 1128*bdd1243dSDimitry Andric ? ArgsAsWritten->arguments()[I].getLocation() 1129*bdd1243dSDimitry Andric : SourceLocation())); 1130*bdd1243dSDimitry Andric Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count()); 1131480093f4SDimitry Andric } 1132480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 1133480093f4SDimitry Andric S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(), 1134480093f4SDimitry Andric Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, 1135480093f4SDimitry Andric SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(), 1136480093f4SDimitry Andric ArgsAsWritten->arguments().back().getSourceRange().getEnd())); 1137480093f4SDimitry Andric if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) 1138480093f4SDimitry Andric return true; 1139*bdd1243dSDimitry Andric 1140*bdd1243dSDimitry Andric TemplateArgumentLoc *TempArgs = 1141*bdd1243dSDimitry Andric new (S.Context) TemplateArgumentLoc[SubstArgs.size()]; 1142480093f4SDimitry Andric std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(), 1143*bdd1243dSDimitry Andric TempArgs); 1144*bdd1243dSDimitry Andric Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size()); 1145480093f4SDimitry Andric return false; 1146480093f4SDimitry Andric } 1147480093f4SDimitry Andric 1148*bdd1243dSDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1149*bdd1243dSDimitry Andric const ConceptSpecializationExpr *CSE) { 1150*bdd1243dSDimitry Andric TemplateArgumentList TAL{TemplateArgumentList::OnStack, 1151*bdd1243dSDimitry Andric CSE->getTemplateArguments()}; 1152*bdd1243dSDimitry Andric MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 1153*bdd1243dSDimitry Andric CSE->getNamedConcept(), /*Final=*/false, &TAL, 1154*bdd1243dSDimitry Andric /*RelativeToPrimary=*/true, 1155*bdd1243dSDimitry Andric /*Pattern=*/nullptr, 1156*bdd1243dSDimitry Andric /*ForConstraintInstantiation=*/true); 1157*bdd1243dSDimitry Andric 1158*bdd1243dSDimitry Andric return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL, 1159*bdd1243dSDimitry Andric CSE->getTemplateArgsAsWritten()); 1160*bdd1243dSDimitry Andric } 1161*bdd1243dSDimitry Andric 1162*bdd1243dSDimitry Andric std::optional<NormalizedConstraint> 1163480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D, 1164480093f4SDimitry Andric ArrayRef<const Expr *> E) { 1165480093f4SDimitry Andric assert(E.size() != 0); 11666e75b2fbSDimitry Andric auto Conjunction = fromConstraintExpr(S, D, E[0]); 11676e75b2fbSDimitry Andric if (!Conjunction) 1168*bdd1243dSDimitry Andric return std::nullopt; 11696e75b2fbSDimitry Andric for (unsigned I = 1; I < E.size(); ++I) { 1170480093f4SDimitry Andric auto Next = fromConstraintExpr(S, D, E[I]); 1171480093f4SDimitry Andric if (!Next) 1172*bdd1243dSDimitry Andric return std::nullopt; 11736e75b2fbSDimitry Andric *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction), 1174480093f4SDimitry Andric std::move(*Next), CCK_Conjunction); 1175480093f4SDimitry Andric } 1176480093f4SDimitry Andric return Conjunction; 1177480093f4SDimitry Andric } 1178480093f4SDimitry Andric 1179*bdd1243dSDimitry Andric std::optional<NormalizedConstraint> 1180480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) { 1181480093f4SDimitry Andric assert(E != nullptr); 1182480093f4SDimitry Andric 1183480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 1184480093f4SDimitry Andric // [...] 1185480093f4SDimitry Andric // - The normal form of an expression (E) is the normal form of E. 1186480093f4SDimitry Andric // [...] 1187480093f4SDimitry Andric E = E->IgnoreParenImpCasts(); 1188*bdd1243dSDimitry Andric 1189*bdd1243dSDimitry Andric // C++2a [temp.param]p4: 1190*bdd1243dSDimitry Andric // [...] If T is not a pack, then E is E', otherwise E is (E' && ...). 1191*bdd1243dSDimitry Andric // Fold expression is considered atomic constraints per current wording. 1192*bdd1243dSDimitry Andric // See http://cplusplus.github.io/concepts-ts/ts-active.html#28 1193*bdd1243dSDimitry Andric 11945ffd83dbSDimitry Andric if (LogicalBinOp BO = E) { 11955ffd83dbSDimitry Andric auto LHS = fromConstraintExpr(S, D, BO.getLHS()); 1196480093f4SDimitry Andric if (!LHS) 1197*bdd1243dSDimitry Andric return std::nullopt; 11985ffd83dbSDimitry Andric auto RHS = fromConstraintExpr(S, D, BO.getRHS()); 1199480093f4SDimitry Andric if (!RHS) 1200*bdd1243dSDimitry Andric return std::nullopt; 1201480093f4SDimitry Andric 12025ffd83dbSDimitry Andric return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS), 12035ffd83dbSDimitry Andric BO.isAnd() ? CCK_Conjunction : CCK_Disjunction); 1204480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) { 1205480093f4SDimitry Andric const NormalizedConstraint *SubNF; 1206480093f4SDimitry Andric { 1207480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 1208480093f4SDimitry Andric S, CSE->getExprLoc(), 1209480093f4SDimitry Andric Sema::InstantiatingTemplate::ConstraintNormalization{}, D, 1210480093f4SDimitry Andric CSE->getSourceRange()); 1211480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 1212480093f4SDimitry Andric // [...] 1213480093f4SDimitry Andric // The normal form of an id-expression of the form C<A1, A2, ..., AN>, 1214480093f4SDimitry Andric // where C names a concept, is the normal form of the 1215480093f4SDimitry Andric // constraint-expression of C, after substituting A1, A2, ..., AN for C’s 1216480093f4SDimitry Andric // respective template parameters in the parameter mappings in each atomic 1217480093f4SDimitry Andric // constraint. If any such substitution results in an invalid type or 1218480093f4SDimitry Andric // expression, the program is ill-formed; no diagnostic is required. 1219480093f4SDimitry Andric // [...] 1220480093f4SDimitry Andric ConceptDecl *CD = CSE->getNamedConcept(); 1221480093f4SDimitry Andric SubNF = S.getNormalizedAssociatedConstraints(CD, 1222480093f4SDimitry Andric {CD->getConstraintExpr()}); 1223480093f4SDimitry Andric if (!SubNF) 1224*bdd1243dSDimitry Andric return std::nullopt; 1225480093f4SDimitry Andric } 1226480093f4SDimitry Andric 1227*bdd1243dSDimitry Andric std::optional<NormalizedConstraint> New; 1228480093f4SDimitry Andric New.emplace(S.Context, *SubNF); 1229480093f4SDimitry Andric 1230*bdd1243dSDimitry Andric if (substituteParameterMappings(S, *New, CSE)) 1231*bdd1243dSDimitry Andric return std::nullopt; 1232480093f4SDimitry Andric 1233480093f4SDimitry Andric return New; 1234480093f4SDimitry Andric } 1235480093f4SDimitry Andric return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)}; 1236480093f4SDimitry Andric } 1237480093f4SDimitry Andric 1238480093f4SDimitry Andric using NormalForm = 1239480093f4SDimitry Andric llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>; 1240480093f4SDimitry Andric 1241480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) { 1242480093f4SDimitry Andric if (Normalized.isAtomic()) 1243480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 1244480093f4SDimitry Andric 1245480093f4SDimitry Andric NormalForm LCNF = makeCNF(Normalized.getLHS()); 1246480093f4SDimitry Andric NormalForm RCNF = makeCNF(Normalized.getRHS()); 1247480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) { 1248480093f4SDimitry Andric LCNF.reserve(LCNF.size() + RCNF.size()); 1249480093f4SDimitry Andric while (!RCNF.empty()) 1250480093f4SDimitry Andric LCNF.push_back(RCNF.pop_back_val()); 1251480093f4SDimitry Andric return LCNF; 1252480093f4SDimitry Andric } 1253480093f4SDimitry Andric 1254480093f4SDimitry Andric // Disjunction 1255480093f4SDimitry Andric NormalForm Res; 1256480093f4SDimitry Andric Res.reserve(LCNF.size() * RCNF.size()); 1257480093f4SDimitry Andric for (auto &LDisjunction : LCNF) 1258480093f4SDimitry Andric for (auto &RDisjunction : RCNF) { 1259480093f4SDimitry Andric NormalForm::value_type Combined; 1260480093f4SDimitry Andric Combined.reserve(LDisjunction.size() + RDisjunction.size()); 1261480093f4SDimitry Andric std::copy(LDisjunction.begin(), LDisjunction.end(), 1262480093f4SDimitry Andric std::back_inserter(Combined)); 1263480093f4SDimitry Andric std::copy(RDisjunction.begin(), RDisjunction.end(), 1264480093f4SDimitry Andric std::back_inserter(Combined)); 1265480093f4SDimitry Andric Res.emplace_back(Combined); 1266480093f4SDimitry Andric } 1267480093f4SDimitry Andric return Res; 1268480093f4SDimitry Andric } 1269480093f4SDimitry Andric 1270480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) { 1271480093f4SDimitry Andric if (Normalized.isAtomic()) 1272480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 1273480093f4SDimitry Andric 1274480093f4SDimitry Andric NormalForm LDNF = makeDNF(Normalized.getLHS()); 1275480093f4SDimitry Andric NormalForm RDNF = makeDNF(Normalized.getRHS()); 1276480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) { 1277480093f4SDimitry Andric LDNF.reserve(LDNF.size() + RDNF.size()); 1278480093f4SDimitry Andric while (!RDNF.empty()) 1279480093f4SDimitry Andric LDNF.push_back(RDNF.pop_back_val()); 1280480093f4SDimitry Andric return LDNF; 1281480093f4SDimitry Andric } 1282480093f4SDimitry Andric 1283480093f4SDimitry Andric // Conjunction 1284480093f4SDimitry Andric NormalForm Res; 1285480093f4SDimitry Andric Res.reserve(LDNF.size() * RDNF.size()); 1286480093f4SDimitry Andric for (auto &LConjunction : LDNF) { 1287480093f4SDimitry Andric for (auto &RConjunction : RDNF) { 1288480093f4SDimitry Andric NormalForm::value_type Combined; 1289480093f4SDimitry Andric Combined.reserve(LConjunction.size() + RConjunction.size()); 1290480093f4SDimitry Andric std::copy(LConjunction.begin(), LConjunction.end(), 1291480093f4SDimitry Andric std::back_inserter(Combined)); 1292480093f4SDimitry Andric std::copy(RConjunction.begin(), RConjunction.end(), 1293480093f4SDimitry Andric std::back_inserter(Combined)); 1294480093f4SDimitry Andric Res.emplace_back(Combined); 1295480093f4SDimitry Andric } 1296480093f4SDimitry Andric } 1297480093f4SDimitry Andric return Res; 1298480093f4SDimitry Andric } 1299480093f4SDimitry Andric 1300480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator> 1301480093f4SDimitry Andric static bool subsumes(NormalForm PDNF, NormalForm QCNF, 1302480093f4SDimitry Andric AtomicSubsumptionEvaluator E) { 1303480093f4SDimitry Andric // C++ [temp.constr.order] p2 1304480093f4SDimitry Andric // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the 1305480093f4SDimitry Andric // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in 1306480093f4SDimitry Andric // the conjuctive normal form of Q, where [...] 1307480093f4SDimitry Andric for (const auto &Pi : PDNF) { 1308480093f4SDimitry Andric for (const auto &Qj : QCNF) { 1309480093f4SDimitry Andric // C++ [temp.constr.order] p2 1310480093f4SDimitry Andric // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if 1311480093f4SDimitry Andric // and only if there exists an atomic constraint Pia in Pi for which 1312480093f4SDimitry Andric // there exists an atomic constraint, Qjb, in Qj such that Pia 1313480093f4SDimitry Andric // subsumes Qjb. 1314480093f4SDimitry Andric bool Found = false; 1315480093f4SDimitry Andric for (const AtomicConstraint *Pia : Pi) { 1316480093f4SDimitry Andric for (const AtomicConstraint *Qjb : Qj) { 1317480093f4SDimitry Andric if (E(*Pia, *Qjb)) { 1318480093f4SDimitry Andric Found = true; 1319480093f4SDimitry Andric break; 1320480093f4SDimitry Andric } 1321480093f4SDimitry Andric } 1322480093f4SDimitry Andric if (Found) 1323480093f4SDimitry Andric break; 1324480093f4SDimitry Andric } 1325480093f4SDimitry Andric if (!Found) 1326480093f4SDimitry Andric return false; 1327480093f4SDimitry Andric } 1328480093f4SDimitry Andric } 1329480093f4SDimitry Andric return true; 1330480093f4SDimitry Andric } 1331480093f4SDimitry Andric 1332480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator> 1333480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P, 1334480093f4SDimitry Andric NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes, 1335480093f4SDimitry Andric AtomicSubsumptionEvaluator E) { 1336480093f4SDimitry Andric // C++ [temp.constr.order] p2 1337480093f4SDimitry Andric // In order to determine if a constraint P subsumes a constraint Q, P is 1338480093f4SDimitry Andric // transformed into disjunctive normal form, and Q is transformed into 1339480093f4SDimitry Andric // conjunctive normal form. [...] 1340480093f4SDimitry Andric auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P); 1341480093f4SDimitry Andric if (!PNormalized) 1342480093f4SDimitry Andric return true; 1343480093f4SDimitry Andric const NormalForm PDNF = makeDNF(*PNormalized); 1344480093f4SDimitry Andric 1345480093f4SDimitry Andric auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q); 1346480093f4SDimitry Andric if (!QNormalized) 1347480093f4SDimitry Andric return true; 1348480093f4SDimitry Andric const NormalForm QCNF = makeCNF(*QNormalized); 1349480093f4SDimitry Andric 1350480093f4SDimitry Andric Subsumes = subsumes(PDNF, QCNF, E); 1351480093f4SDimitry Andric return false; 1352480093f4SDimitry Andric } 1353480093f4SDimitry Andric 1354*bdd1243dSDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, 1355*bdd1243dSDimitry Andric MutableArrayRef<const Expr *> AC1, 1356*bdd1243dSDimitry Andric NamedDecl *D2, 1357*bdd1243dSDimitry Andric MutableArrayRef<const Expr *> AC2, 1358480093f4SDimitry Andric bool &Result) { 1359*bdd1243dSDimitry Andric if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) { 1360*bdd1243dSDimitry Andric auto IsExpectedEntity = [](const FunctionDecl *FD) { 1361*bdd1243dSDimitry Andric FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind(); 1362*bdd1243dSDimitry Andric return Kind == FunctionDecl::TK_NonTemplate || 1363*bdd1243dSDimitry Andric Kind == FunctionDecl::TK_FunctionTemplate; 1364*bdd1243dSDimitry Andric }; 1365*bdd1243dSDimitry Andric const auto *FD2 = dyn_cast<FunctionDecl>(D2); 1366*bdd1243dSDimitry Andric (void)IsExpectedEntity; 1367*bdd1243dSDimitry Andric (void)FD1; 1368*bdd1243dSDimitry Andric (void)FD2; 1369*bdd1243dSDimitry Andric assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) && 1370*bdd1243dSDimitry Andric "use non-instantiated function declaration for constraints partial " 1371*bdd1243dSDimitry Andric "ordering"); 1372*bdd1243dSDimitry Andric } 1373*bdd1243dSDimitry Andric 1374480093f4SDimitry Andric if (AC1.empty()) { 1375480093f4SDimitry Andric Result = AC2.empty(); 1376480093f4SDimitry Andric return false; 1377480093f4SDimitry Andric } 1378480093f4SDimitry Andric if (AC2.empty()) { 1379480093f4SDimitry Andric // TD1 has associated constraints and TD2 does not. 1380480093f4SDimitry Andric Result = true; 1381480093f4SDimitry Andric return false; 1382480093f4SDimitry Andric } 1383480093f4SDimitry Andric 1384480093f4SDimitry Andric std::pair<NamedDecl *, NamedDecl *> Key{D1, D2}; 1385480093f4SDimitry Andric auto CacheEntry = SubsumptionCache.find(Key); 1386480093f4SDimitry Andric if (CacheEntry != SubsumptionCache.end()) { 1387480093f4SDimitry Andric Result = CacheEntry->second; 1388480093f4SDimitry Andric return false; 1389480093f4SDimitry Andric } 1390480093f4SDimitry Andric 1391*bdd1243dSDimitry Andric unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true); 1392*bdd1243dSDimitry Andric unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true); 1393*bdd1243dSDimitry Andric 1394*bdd1243dSDimitry Andric for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) { 1395*bdd1243dSDimitry Andric if (Depth2 > Depth1) { 1396*bdd1243dSDimitry Andric AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1) 1397*bdd1243dSDimitry Andric .TransformExpr(const_cast<Expr *>(AC1[I])) 1398*bdd1243dSDimitry Andric .get(); 1399*bdd1243dSDimitry Andric } else if (Depth1 > Depth2) { 1400*bdd1243dSDimitry Andric AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2) 1401*bdd1243dSDimitry Andric .TransformExpr(const_cast<Expr *>(AC2[I])) 1402*bdd1243dSDimitry Andric .get(); 1403*bdd1243dSDimitry Andric } 1404*bdd1243dSDimitry Andric } 1405*bdd1243dSDimitry Andric 1406480093f4SDimitry Andric if (subsumes(*this, D1, AC1, D2, AC2, Result, 1407480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 1408480093f4SDimitry Andric return A.subsumes(Context, B); 1409480093f4SDimitry Andric })) 1410480093f4SDimitry Andric return true; 1411480093f4SDimitry Andric SubsumptionCache.try_emplace(Key, Result); 1412480093f4SDimitry Andric return false; 1413480093f4SDimitry Andric } 1414480093f4SDimitry Andric 1415480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, 1416480093f4SDimitry Andric ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) { 1417480093f4SDimitry Andric if (isSFINAEContext()) 1418480093f4SDimitry Andric // No need to work here because our notes would be discarded. 1419480093f4SDimitry Andric return false; 1420480093f4SDimitry Andric 1421480093f4SDimitry Andric if (AC1.empty() || AC2.empty()) 1422480093f4SDimitry Andric return false; 1423480093f4SDimitry Andric 1424480093f4SDimitry Andric auto NormalExprEvaluator = 1425480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 1426480093f4SDimitry Andric return A.subsumes(Context, B); 1427480093f4SDimitry Andric }; 1428480093f4SDimitry Andric 1429480093f4SDimitry Andric const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr; 1430480093f4SDimitry Andric auto IdenticalExprEvaluator = 1431480093f4SDimitry Andric [&] (const AtomicConstraint &A, const AtomicConstraint &B) { 1432480093f4SDimitry Andric if (!A.hasMatchingParameterMapping(Context, B)) 1433480093f4SDimitry Andric return false; 1434480093f4SDimitry Andric const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr; 1435480093f4SDimitry Andric if (EA == EB) 1436480093f4SDimitry Andric return true; 1437480093f4SDimitry Andric 1438480093f4SDimitry Andric // Not the same source level expression - are the expressions 1439480093f4SDimitry Andric // identical? 1440480093f4SDimitry Andric llvm::FoldingSetNodeID IDA, IDB; 1441349cc55cSDimitry Andric EA->Profile(IDA, Context, /*Canonical=*/true); 1442349cc55cSDimitry Andric EB->Profile(IDB, Context, /*Canonical=*/true); 1443480093f4SDimitry Andric if (IDA != IDB) 1444480093f4SDimitry Andric return false; 1445480093f4SDimitry Andric 1446480093f4SDimitry Andric AmbiguousAtomic1 = EA; 1447480093f4SDimitry Andric AmbiguousAtomic2 = EB; 1448480093f4SDimitry Andric return true; 1449480093f4SDimitry Andric }; 1450480093f4SDimitry Andric 1451480093f4SDimitry Andric { 1452480093f4SDimitry Andric // The subsumption checks might cause diagnostics 1453480093f4SDimitry Andric SFINAETrap Trap(*this); 1454480093f4SDimitry Andric auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1); 1455480093f4SDimitry Andric if (!Normalized1) 1456480093f4SDimitry Andric return false; 1457480093f4SDimitry Andric const NormalForm DNF1 = makeDNF(*Normalized1); 1458480093f4SDimitry Andric const NormalForm CNF1 = makeCNF(*Normalized1); 1459480093f4SDimitry Andric 1460480093f4SDimitry Andric auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2); 1461480093f4SDimitry Andric if (!Normalized2) 1462480093f4SDimitry Andric return false; 1463480093f4SDimitry Andric const NormalForm DNF2 = makeDNF(*Normalized2); 1464480093f4SDimitry Andric const NormalForm CNF2 = makeCNF(*Normalized2); 1465480093f4SDimitry Andric 1466480093f4SDimitry Andric bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator); 1467480093f4SDimitry Andric bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator); 1468480093f4SDimitry Andric bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator); 1469480093f4SDimitry Andric bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator); 1470480093f4SDimitry Andric if (Is1AtLeastAs2 == Is1AtLeastAs2Normally && 1471480093f4SDimitry Andric Is2AtLeastAs1 == Is2AtLeastAs1Normally) 1472480093f4SDimitry Andric // Same result - no ambiguity was caused by identical atomic expressions. 1473480093f4SDimitry Andric return false; 1474480093f4SDimitry Andric } 1475480093f4SDimitry Andric 1476480093f4SDimitry Andric // A different result! Some ambiguous atomic constraint(s) caused a difference 1477480093f4SDimitry Andric assert(AmbiguousAtomic1 && AmbiguousAtomic2); 1478480093f4SDimitry Andric 1479480093f4SDimitry Andric Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints) 1480480093f4SDimitry Andric << AmbiguousAtomic1->getSourceRange(); 1481480093f4SDimitry Andric Diag(AmbiguousAtomic2->getBeginLoc(), 1482480093f4SDimitry Andric diag::note_ambiguous_atomic_constraints_similar_expression) 1483480093f4SDimitry Andric << AmbiguousAtomic2->getSourceRange(); 1484480093f4SDimitry Andric return true; 1485480093f4SDimitry Andric } 148655e4f9d5SDimitry Andric 148755e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 148855e4f9d5SDimitry Andric Expr *E, bool IsSimple, SourceLocation NoexceptLoc, 148955e4f9d5SDimitry Andric ReturnTypeRequirement Req, SatisfactionStatus Status, 149055e4f9d5SDimitry Andric ConceptSpecializationExpr *SubstitutedConstraintExpr) : 149155e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, 149255e4f9d5SDimitry Andric Status == SS_Dependent && 149355e4f9d5SDimitry Andric (E->containsUnexpandedParameterPack() || 149455e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack()), 149555e4f9d5SDimitry Andric Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc), 149655e4f9d5SDimitry Andric TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr), 149755e4f9d5SDimitry Andric Status(Status) { 149855e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 149955e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 150055e4f9d5SDimitry Andric "noexcept specification"); 150155e4f9d5SDimitry Andric assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == 150255e4f9d5SDimitry Andric (SubstitutedConstraintExpr != nullptr)); 150355e4f9d5SDimitry Andric } 150455e4f9d5SDimitry Andric 150555e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 150655e4f9d5SDimitry Andric SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, 150755e4f9d5SDimitry Andric SourceLocation NoexceptLoc, ReturnTypeRequirement Req) : 150855e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), 150955e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), 151055e4f9d5SDimitry Andric Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), 151155e4f9d5SDimitry Andric Status(SS_ExprSubstitutionFailure) { 151255e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 151355e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 151455e4f9d5SDimitry Andric "noexcept specification"); 151555e4f9d5SDimitry Andric } 151655e4f9d5SDimitry Andric 151755e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement:: 151855e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) : 151904eeddc0SDimitry Andric TypeConstraintInfo(TPL, false) { 152055e4f9d5SDimitry Andric assert(TPL->size() == 1); 152155e4f9d5SDimitry Andric const TypeConstraint *TC = 152255e4f9d5SDimitry Andric cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint(); 152355e4f9d5SDimitry Andric assert(TC && 152455e4f9d5SDimitry Andric "TPL must have a template type parameter with a type constraint"); 152555e4f9d5SDimitry Andric auto *Constraint = 1526349cc55cSDimitry Andric cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint()); 1527e8d8bef9SDimitry Andric bool Dependent = 1528e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten() && 1529e8d8bef9SDimitry Andric TemplateSpecializationType::anyInstantiationDependentTemplateArguments( 1530e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)); 153104eeddc0SDimitry Andric TypeConstraintInfo.setInt(Dependent ? true : false); 153255e4f9d5SDimitry Andric } 153355e4f9d5SDimitry Andric 153455e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) : 1535e8d8bef9SDimitry Andric Requirement(RK_Type, T->getType()->isInstantiationDependentType(), 153655e4f9d5SDimitry Andric T->getType()->containsUnexpandedParameterPack(), 153755e4f9d5SDimitry Andric // We reach this ctor with either dependent types (in which 153855e4f9d5SDimitry Andric // IsSatisfied doesn't matter) or with non-dependent type in 153955e4f9d5SDimitry Andric // which the existence of the type indicates satisfaction. 1540e8d8bef9SDimitry Andric /*IsSatisfied=*/true), 1541e8d8bef9SDimitry Andric Value(T), 1542e8d8bef9SDimitry Andric Status(T->getType()->isInstantiationDependentType() ? SS_Dependent 1543e8d8bef9SDimitry Andric : SS_Satisfied) {} 1544