1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===// 2a7dea167SDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric // 9a7dea167SDimitry Andric // This file implements semantic analysis for C++ constraints and concepts. 10a7dea167SDimitry Andric // 11a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 12a7dea167SDimitry Andric 13480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h" 14a7dea167SDimitry Andric #include "clang/Sema/Sema.h" 15480093f4SDimitry Andric #include "clang/Sema/SemaInternal.h" 16a7dea167SDimitry Andric #include "clang/Sema/SemaDiagnostic.h" 17a7dea167SDimitry Andric #include "clang/Sema/TemplateDeduction.h" 18a7dea167SDimitry Andric #include "clang/Sema/Template.h" 1955e4f9d5SDimitry Andric #include "clang/Sema/Overload.h" 2055e4f9d5SDimitry Andric #include "clang/Sema/Initialization.h" 2155e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h" 22480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 23480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h" 24480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h" 25480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h" 26fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h" 27fe6060f1SDimitry Andric 28a7dea167SDimitry Andric using namespace clang; 29a7dea167SDimitry Andric using namespace sema; 30a7dea167SDimitry Andric 315ffd83dbSDimitry Andric namespace { 325ffd83dbSDimitry Andric class LogicalBinOp { 335ffd83dbSDimitry Andric OverloadedOperatorKind Op = OO_None; 345ffd83dbSDimitry Andric const Expr *LHS = nullptr; 355ffd83dbSDimitry Andric const Expr *RHS = nullptr; 365ffd83dbSDimitry Andric 375ffd83dbSDimitry Andric public: 385ffd83dbSDimitry Andric LogicalBinOp(const Expr *E) { 395ffd83dbSDimitry Andric if (auto *BO = dyn_cast<BinaryOperator>(E)) { 405ffd83dbSDimitry Andric Op = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 415ffd83dbSDimitry Andric LHS = BO->getLHS(); 425ffd83dbSDimitry Andric RHS = BO->getRHS(); 435ffd83dbSDimitry Andric } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) { 44fe6060f1SDimitry Andric // If OO is not || or && it might not have exactly 2 arguments. 45fe6060f1SDimitry Andric if (OO->getNumArgs() == 2) { 465ffd83dbSDimitry Andric Op = OO->getOperator(); 475ffd83dbSDimitry Andric LHS = OO->getArg(0); 485ffd83dbSDimitry Andric RHS = OO->getArg(1); 495ffd83dbSDimitry Andric } 505ffd83dbSDimitry Andric } 51fe6060f1SDimitry Andric } 525ffd83dbSDimitry Andric 535ffd83dbSDimitry Andric bool isAnd() const { return Op == OO_AmpAmp; } 545ffd83dbSDimitry Andric bool isOr() const { return Op == OO_PipePipe; } 555ffd83dbSDimitry Andric explicit operator bool() const { return isAnd() || isOr(); } 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric const Expr *getLHS() const { return LHS; } 585ffd83dbSDimitry Andric const Expr *getRHS() const { return RHS; } 595ffd83dbSDimitry Andric }; 605ffd83dbSDimitry Andric } 615ffd83dbSDimitry Andric 625ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression, 635ffd83dbSDimitry Andric Token NextToken, bool *PossibleNonPrimary, 64480093f4SDimitry Andric bool IsTrailingRequiresClause) { 65a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 66a7dea167SDimitry Andric // ..E shall be a constant expression of type bool. 67a7dea167SDimitry Andric 68a7dea167SDimitry Andric ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts(); 69a7dea167SDimitry Andric 705ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpression) { 715ffd83dbSDimitry Andric return CheckConstraintExpression(BO.getLHS(), NextToken, 72480093f4SDimitry Andric PossibleNonPrimary) && 735ffd83dbSDimitry Andric CheckConstraintExpression(BO.getRHS(), NextToken, 74480093f4SDimitry Andric PossibleNonPrimary); 75a7dea167SDimitry Andric } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression)) 76480093f4SDimitry Andric return CheckConstraintExpression(C->getSubExpr(), NextToken, 77480093f4SDimitry Andric PossibleNonPrimary); 78a7dea167SDimitry Andric 79a7dea167SDimitry Andric QualType Type = ConstraintExpression->getType(); 80480093f4SDimitry Andric 81480093f4SDimitry Andric auto CheckForNonPrimary = [&] { 82480093f4SDimitry Andric if (PossibleNonPrimary) 83480093f4SDimitry Andric *PossibleNonPrimary = 84480093f4SDimitry Andric // We have the following case: 85480093f4SDimitry Andric // template<typename> requires func(0) struct S { }; 86480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 87480093f4SDimitry Andric // the function call, and we're only going to parse 'func' as the 88480093f4SDimitry Andric // primary-expression, and complain that it is of non-bool type. 89480093f4SDimitry Andric (NextToken.is(tok::l_paren) && 90480093f4SDimitry Andric (IsTrailingRequiresClause || 91480093f4SDimitry Andric (Type->isDependentType() && 925ffd83dbSDimitry Andric isa<UnresolvedLookupExpr>(ConstraintExpression)) || 93480093f4SDimitry Andric Type->isFunctionType() || 94480093f4SDimitry Andric Type->isSpecificBuiltinType(BuiltinType::Overload))) || 95480093f4SDimitry Andric // We have the following case: 96480093f4SDimitry Andric // template<typename T> requires size_<T> == 0 struct S { }; 97480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 98480093f4SDimitry Andric // the binary operator, and we're only going to parse 'func' as the 99480093f4SDimitry Andric // first operand, and complain that it is of non-bool type. 100480093f4SDimitry Andric getBinOpPrecedence(NextToken.getKind(), 101480093f4SDimitry Andric /*GreaterThanIsOperator=*/true, 102480093f4SDimitry Andric getLangOpts().CPlusPlus11) > prec::LogicalAnd; 103480093f4SDimitry Andric }; 104480093f4SDimitry Andric 105480093f4SDimitry Andric // An atomic constraint! 106480093f4SDimitry Andric if (ConstraintExpression->isTypeDependent()) { 107480093f4SDimitry Andric CheckForNonPrimary(); 108480093f4SDimitry Andric return true; 109480093f4SDimitry Andric } 110480093f4SDimitry Andric 111a7dea167SDimitry Andric if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) { 112a7dea167SDimitry Andric Diag(ConstraintExpression->getExprLoc(), 113a7dea167SDimitry Andric diag::err_non_bool_atomic_constraint) << Type 114a7dea167SDimitry Andric << ConstraintExpression->getSourceRange(); 115480093f4SDimitry Andric CheckForNonPrimary(); 116a7dea167SDimitry Andric return false; 117a7dea167SDimitry Andric } 118480093f4SDimitry Andric 119480093f4SDimitry Andric if (PossibleNonPrimary) 120480093f4SDimitry Andric *PossibleNonPrimary = false; 121a7dea167SDimitry Andric return true; 122a7dea167SDimitry Andric } 123a7dea167SDimitry Andric 124480093f4SDimitry Andric template <typename AtomicEvaluator> 125480093f4SDimitry Andric static bool 126480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, 127480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction, 128480093f4SDimitry Andric AtomicEvaluator &&Evaluator) { 129a7dea167SDimitry Andric ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); 130a7dea167SDimitry Andric 1315ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpr) { 1325ffd83dbSDimitry Andric if (calculateConstraintSatisfaction(S, BO.getLHS(), Satisfaction, 133480093f4SDimitry Andric Evaluator)) 134a7dea167SDimitry Andric return true; 135480093f4SDimitry Andric 136480093f4SDimitry Andric bool IsLHSSatisfied = Satisfaction.IsSatisfied; 137480093f4SDimitry Andric 1385ffd83dbSDimitry Andric if (BO.isOr() && IsLHSSatisfied) 139480093f4SDimitry Andric // [temp.constr.op] p3 140480093f4SDimitry Andric // A disjunction is a constraint taking two operands. To determine if 141480093f4SDimitry Andric // a disjunction is satisfied, the satisfaction of the first operand 142480093f4SDimitry Andric // is checked. If that is satisfied, the disjunction is satisfied. 143480093f4SDimitry Andric // Otherwise, the disjunction is satisfied if and only if the second 144480093f4SDimitry Andric // operand is satisfied. 145a7dea167SDimitry Andric return false; 146480093f4SDimitry Andric 1475ffd83dbSDimitry Andric if (BO.isAnd() && !IsLHSSatisfied) 148480093f4SDimitry Andric // [temp.constr.op] p2 149480093f4SDimitry Andric // A conjunction is a constraint taking two operands. To determine if 150480093f4SDimitry Andric // a conjunction is satisfied, the satisfaction of the first operand 151480093f4SDimitry Andric // is checked. If that is not satisfied, the conjunction is not 152480093f4SDimitry Andric // satisfied. Otherwise, the conjunction is satisfied if and only if 153480093f4SDimitry Andric // the second operand is satisfied. 154a7dea167SDimitry Andric return false; 155480093f4SDimitry Andric 1565ffd83dbSDimitry Andric return calculateConstraintSatisfaction( 1575ffd83dbSDimitry Andric S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator)); 1585ffd83dbSDimitry Andric } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) { 159480093f4SDimitry Andric return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction, 160480093f4SDimitry Andric std::forward<AtomicEvaluator>(Evaluator)); 1615ffd83dbSDimitry Andric } 162480093f4SDimitry Andric 163480093f4SDimitry Andric // An atomic constraint expression 164480093f4SDimitry Andric ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr); 165480093f4SDimitry Andric 166480093f4SDimitry Andric if (SubstitutedAtomicExpr.isInvalid()) 167480093f4SDimitry Andric return true; 168480093f4SDimitry Andric 169480093f4SDimitry Andric if (!SubstitutedAtomicExpr.isUsable()) 170480093f4SDimitry Andric // Evaluator has decided satisfaction without yielding an expression. 171480093f4SDimitry Andric return false; 172a7dea167SDimitry Andric 173a7dea167SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 174480093f4SDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 175a7dea167SDimitry Andric SmallVector<PartialDiagnosticAt, 2> EvaluationDiags; 176a7dea167SDimitry Andric Expr::EvalResult EvalResult; 177a7dea167SDimitry Andric EvalResult.Diag = &EvaluationDiags; 178fe6060f1SDimitry Andric if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult, 179fe6060f1SDimitry Andric S.Context) || 180fe6060f1SDimitry Andric !EvaluationDiags.empty()) { 181a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 182a7dea167SDimitry Andric // ...E shall be a constant expression of type bool. 183480093f4SDimitry Andric S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(), 184a7dea167SDimitry Andric diag::err_non_constant_constraint_expression) 185480093f4SDimitry Andric << SubstitutedAtomicExpr.get()->getSourceRange(); 186a7dea167SDimitry Andric for (const PartialDiagnosticAt &PDiag : EvaluationDiags) 187480093f4SDimitry Andric S.Diag(PDiag.first, PDiag.second); 188a7dea167SDimitry Andric return true; 189a7dea167SDimitry Andric } 190a7dea167SDimitry Andric 191fe6060f1SDimitry Andric assert(EvalResult.Val.isInt() && 192fe6060f1SDimitry Andric "evaluating bool expression didn't produce int"); 193480093f4SDimitry Andric Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); 194480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) 195480093f4SDimitry Andric Satisfaction.Details.emplace_back(ConstraintExpr, 196480093f4SDimitry Andric SubstitutedAtomicExpr.get()); 197a7dea167SDimitry Andric 198a7dea167SDimitry Andric return false; 199a7dea167SDimitry Andric } 200480093f4SDimitry Andric 201480093f4SDimitry Andric static bool calculateConstraintSatisfaction( 20213138422SDimitry Andric Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, 203480093f4SDimitry Andric SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL, 204480093f4SDimitry Andric const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) { 205480093f4SDimitry Andric return calculateConstraintSatisfaction( 206480093f4SDimitry Andric S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) { 207480093f4SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 208480093f4SDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 209480093f4SDimitry Andric 210480093f4SDimitry Andric // Atomic constraint - substitute arguments and check satisfaction. 211480093f4SDimitry Andric ExprResult SubstitutedExpression; 212480093f4SDimitry Andric { 213480093f4SDimitry Andric TemplateDeductionInfo Info(TemplateNameLoc); 214480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(), 21513138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintSubstitution{}, 21613138422SDimitry Andric const_cast<NamedDecl *>(Template), Info, 21713138422SDimitry Andric AtomicExpr->getSourceRange()); 218480093f4SDimitry Andric if (Inst.isInvalid()) 219480093f4SDimitry Andric return ExprError(); 220480093f4SDimitry Andric // We do not want error diagnostics escaping here. 221480093f4SDimitry Andric Sema::SFINAETrap Trap(S); 222480093f4SDimitry Andric SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr), 223480093f4SDimitry Andric MLTAL); 224fe6060f1SDimitry Andric // Substitution might have stripped off a contextual conversion to 225fe6060f1SDimitry Andric // bool if this is the operand of an '&&' or '||'. For example, we 226fe6060f1SDimitry Andric // might lose an lvalue-to-rvalue conversion here. If so, put it back 227fe6060f1SDimitry Andric // before we try to evaluate. 228fe6060f1SDimitry Andric if (!SubstitutedExpression.isInvalid()) 229fe6060f1SDimitry Andric SubstitutedExpression = 230fe6060f1SDimitry Andric S.PerformContextuallyConvertToBool(SubstitutedExpression.get()); 231480093f4SDimitry Andric if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) { 232480093f4SDimitry Andric // C++2a [temp.constr.atomic]p1 233480093f4SDimitry Andric // ...If substitution results in an invalid type or expression, the 234480093f4SDimitry Andric // constraint is not satisfied. 235480093f4SDimitry Andric if (!Trap.hasErrorOccurred()) 236349cc55cSDimitry Andric // A non-SFINAE error has occurred as a result of this 237480093f4SDimitry Andric // substitution. 238480093f4SDimitry Andric return ExprError(); 239480093f4SDimitry Andric 240480093f4SDimitry Andric PartialDiagnosticAt SubstDiag{SourceLocation(), 241480093f4SDimitry Andric PartialDiagnostic::NullDiagnostic()}; 242480093f4SDimitry Andric Info.takeSFINAEDiagnostic(SubstDiag); 243480093f4SDimitry Andric // FIXME: Concepts: This is an unfortunate consequence of there 244480093f4SDimitry Andric // being no serialization code for PartialDiagnostics and the fact 245480093f4SDimitry Andric // that serializing them would likely take a lot more storage than 246480093f4SDimitry Andric // just storing them as strings. We would still like, in the 247480093f4SDimitry Andric // future, to serialize the proper PartialDiagnostic as serializing 248480093f4SDimitry Andric // it as a string defeats the purpose of the diagnostic mechanism. 249480093f4SDimitry Andric SmallString<128> DiagString; 250480093f4SDimitry Andric DiagString = ": "; 251480093f4SDimitry Andric SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString); 252480093f4SDimitry Andric unsigned MessageSize = DiagString.size(); 253480093f4SDimitry Andric char *Mem = new (S.Context) char[MessageSize]; 254480093f4SDimitry Andric memcpy(Mem, DiagString.c_str(), MessageSize); 255480093f4SDimitry Andric Satisfaction.Details.emplace_back( 256480093f4SDimitry Andric AtomicExpr, 257480093f4SDimitry Andric new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 258480093f4SDimitry Andric SubstDiag.first, StringRef(Mem, MessageSize)}); 259480093f4SDimitry Andric Satisfaction.IsSatisfied = false; 260480093f4SDimitry Andric return ExprEmpty(); 261480093f4SDimitry Andric } 262480093f4SDimitry Andric } 263480093f4SDimitry Andric 264480093f4SDimitry Andric if (!S.CheckConstraintExpression(SubstitutedExpression.get())) 265480093f4SDimitry Andric return ExprError(); 266480093f4SDimitry Andric 267480093f4SDimitry Andric return SubstitutedExpression; 268480093f4SDimitry Andric }); 269480093f4SDimitry Andric } 270480093f4SDimitry Andric 27113138422SDimitry Andric static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, 272480093f4SDimitry Andric ArrayRef<const Expr *> ConstraintExprs, 273480093f4SDimitry Andric ArrayRef<TemplateArgument> TemplateArgs, 274480093f4SDimitry Andric SourceRange TemplateIDRange, 275480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction) { 276480093f4SDimitry Andric if (ConstraintExprs.empty()) { 277480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 278480093f4SDimitry Andric return false; 279480093f4SDimitry Andric } 280480093f4SDimitry Andric 281480093f4SDimitry Andric for (auto& Arg : TemplateArgs) 282480093f4SDimitry Andric if (Arg.isInstantiationDependent()) { 283480093f4SDimitry Andric // No need to check satisfaction for dependent constraint expressions. 284480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 285480093f4SDimitry Andric return false; 286480093f4SDimitry Andric } 287480093f4SDimitry Andric 288480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), 28913138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, 29013138422SDimitry Andric const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); 291480093f4SDimitry Andric if (Inst.isInvalid()) 292480093f4SDimitry Andric return true; 293480093f4SDimitry Andric 294480093f4SDimitry Andric MultiLevelTemplateArgumentList MLTAL; 295480093f4SDimitry Andric MLTAL.addOuterTemplateArguments(TemplateArgs); 296480093f4SDimitry Andric 297480093f4SDimitry Andric for (const Expr *ConstraintExpr : ConstraintExprs) { 298480093f4SDimitry Andric if (calculateConstraintSatisfaction(S, Template, TemplateArgs, 299480093f4SDimitry Andric TemplateIDRange.getBegin(), MLTAL, 300480093f4SDimitry Andric ConstraintExpr, Satisfaction)) 301480093f4SDimitry Andric return true; 302480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) 303480093f4SDimitry Andric // [temp.constr.op] p2 304480093f4SDimitry Andric // [...] To determine if a conjunction is satisfied, the satisfaction 305480093f4SDimitry Andric // of the first operand is checked. If that is not satisfied, the 306480093f4SDimitry Andric // conjunction is not satisfied. [...] 307480093f4SDimitry Andric return false; 308480093f4SDimitry Andric } 309480093f4SDimitry Andric return false; 310480093f4SDimitry Andric } 311480093f4SDimitry Andric 31255e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction( 31313138422SDimitry Andric const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 31455e4f9d5SDimitry Andric ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange, 31555e4f9d5SDimitry Andric ConstraintSatisfaction &OutSatisfaction) { 31655e4f9d5SDimitry Andric if (ConstraintExprs.empty()) { 31755e4f9d5SDimitry Andric OutSatisfaction.IsSatisfied = true; 31855e4f9d5SDimitry Andric return false; 319480093f4SDimitry Andric } 320*81ad6265SDimitry Andric if (!Template) { 321*81ad6265SDimitry Andric return ::CheckConstraintSatisfaction(*this, nullptr, ConstraintExprs, 322*81ad6265SDimitry Andric TemplateArgs, TemplateIDRange, 323*81ad6265SDimitry Andric OutSatisfaction); 324*81ad6265SDimitry Andric } 32555e4f9d5SDimitry Andric llvm::FoldingSetNodeID ID; 32655e4f9d5SDimitry Andric ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs); 327*81ad6265SDimitry Andric void *InsertPos; 328*81ad6265SDimitry Andric if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 329*81ad6265SDimitry Andric OutSatisfaction = *Cached; 33055e4f9d5SDimitry Andric return false; 33155e4f9d5SDimitry Andric } 332*81ad6265SDimitry Andric auto Satisfaction = 333*81ad6265SDimitry Andric std::make_unique<ConstraintSatisfaction>(Template, TemplateArgs); 33413138422SDimitry Andric if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, 335480093f4SDimitry Andric TemplateArgs, TemplateIDRange, 33613138422SDimitry Andric *Satisfaction)) { 33755e4f9d5SDimitry Andric return true; 338480093f4SDimitry Andric } 33955e4f9d5SDimitry Andric OutSatisfaction = *Satisfaction; 340*81ad6265SDimitry Andric // We cannot use InsertPos here because CheckConstraintSatisfaction might have 341*81ad6265SDimitry Andric // invalidated it. 342*81ad6265SDimitry Andric // Note that entries of SatisfactionCache are deleted in Sema's destructor. 343*81ad6265SDimitry Andric SatisfactionCache.InsertNode(Satisfaction.release()); 34455e4f9d5SDimitry Andric return false; 345480093f4SDimitry Andric } 346480093f4SDimitry Andric 347480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr, 348480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction) { 349480093f4SDimitry Andric return calculateConstraintSatisfaction( 350480093f4SDimitry Andric *this, ConstraintExpr, Satisfaction, 351*81ad6265SDimitry Andric [this](const Expr *AtomicExpr) -> ExprResult { 352*81ad6265SDimitry Andric // We only do this to immitate lvalue-to-rvalue conversion. 353*81ad6265SDimitry Andric return PerformContextuallyConvertToBool(const_cast<Expr *>(AtomicExpr)); 354480093f4SDimitry Andric }); 355480093f4SDimitry Andric } 356480093f4SDimitry Andric 35713138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, 35813138422SDimitry Andric ConstraintSatisfaction &Satisfaction, 35913138422SDimitry Andric SourceLocation UsageLoc) { 36013138422SDimitry Andric const Expr *RC = FD->getTrailingRequiresClause(); 36113138422SDimitry Andric if (RC->isInstantiationDependent()) { 36213138422SDimitry Andric Satisfaction.IsSatisfied = true; 36313138422SDimitry Andric return false; 36413138422SDimitry Andric } 36513138422SDimitry Andric Qualifiers ThisQuals; 36613138422SDimitry Andric CXXRecordDecl *Record = nullptr; 36713138422SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { 36813138422SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 36913138422SDimitry Andric Record = const_cast<CXXRecordDecl *>(Method->getParent()); 37013138422SDimitry Andric } 37113138422SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 37213138422SDimitry Andric // We substitute with empty arguments in order to rebuild the atomic 37313138422SDimitry Andric // constraint in a constant-evaluated context. 37413138422SDimitry Andric // FIXME: Should this be a dedicated TreeTransform? 37513138422SDimitry Andric return CheckConstraintSatisfaction( 37613138422SDimitry Andric FD, {RC}, /*TemplateArgs=*/{}, 37713138422SDimitry Andric SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), 37813138422SDimitry Andric Satisfaction); 37913138422SDimitry Andric } 38013138422SDimitry Andric 381480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints( 382480093f4SDimitry Andric TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs, 383480093f4SDimitry Andric SourceRange TemplateIDRange) { 384480093f4SDimitry Andric ConstraintSatisfaction Satisfaction; 385480093f4SDimitry Andric llvm::SmallVector<const Expr *, 3> AssociatedConstraints; 386480093f4SDimitry Andric TD->getAssociatedConstraints(AssociatedConstraints); 387480093f4SDimitry Andric if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs, 388480093f4SDimitry Andric TemplateIDRange, Satisfaction)) 389480093f4SDimitry Andric return true; 390480093f4SDimitry Andric 391480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) { 392480093f4SDimitry Andric SmallString<128> TemplateArgString; 393480093f4SDimitry Andric TemplateArgString = " "; 394480093f4SDimitry Andric TemplateArgString += getTemplateArgumentBindingsText( 395480093f4SDimitry Andric TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size()); 396480093f4SDimitry Andric 397480093f4SDimitry Andric Diag(TemplateIDRange.getBegin(), 398480093f4SDimitry Andric diag::err_template_arg_list_constraints_not_satisfied) 399480093f4SDimitry Andric << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD 400480093f4SDimitry Andric << TemplateArgString << TemplateIDRange; 401480093f4SDimitry Andric DiagnoseUnsatisfiedConstraint(Satisfaction); 402480093f4SDimitry Andric return true; 403480093f4SDimitry Andric } 404480093f4SDimitry Andric return false; 405480093f4SDimitry Andric } 406480093f4SDimitry Andric 407*81ad6265SDimitry Andric bool Sema::CheckInstantiatedFunctionTemplateConstraints( 408*81ad6265SDimitry Andric SourceLocation PointOfInstantiation, FunctionDecl *Decl, 409*81ad6265SDimitry Andric ArrayRef<TemplateArgument> TemplateArgs, 410*81ad6265SDimitry Andric ConstraintSatisfaction &Satisfaction) { 411*81ad6265SDimitry Andric // In most cases we're not going to have constraints, so check for that first. 412*81ad6265SDimitry Andric FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); 413*81ad6265SDimitry Andric // Note - code synthesis context for the constraints check is created 414*81ad6265SDimitry Andric // inside CheckConstraintsSatisfaction. 415*81ad6265SDimitry Andric SmallVector<const Expr *, 3> TemplateAC; 416*81ad6265SDimitry Andric Template->getAssociatedConstraints(TemplateAC); 417*81ad6265SDimitry Andric if (TemplateAC.empty()) { 418*81ad6265SDimitry Andric Satisfaction.IsSatisfied = true; 419*81ad6265SDimitry Andric return false; 420*81ad6265SDimitry Andric } 421*81ad6265SDimitry Andric 422*81ad6265SDimitry Andric // Enter the scope of this instantiation. We don't use 423*81ad6265SDimitry Andric // PushDeclContext because we don't have a scope. 424*81ad6265SDimitry Andric Sema::ContextRAII savedContext(*this, Decl); 425*81ad6265SDimitry Andric LocalInstantiationScope Scope(*this); 426*81ad6265SDimitry Andric 427*81ad6265SDimitry Andric // If this is not an explicit specialization - we need to get the instantiated 428*81ad6265SDimitry Andric // version of the template arguments and add them to scope for the 429*81ad6265SDimitry Andric // substitution. 430*81ad6265SDimitry Andric if (Decl->isTemplateInstantiation()) { 431*81ad6265SDimitry Andric InstantiatingTemplate Inst(*this, Decl->getPointOfInstantiation(), 432*81ad6265SDimitry Andric InstantiatingTemplate::ConstraintsCheck{}, Decl->getPrimaryTemplate(), 433*81ad6265SDimitry Andric TemplateArgs, SourceRange()); 434*81ad6265SDimitry Andric if (Inst.isInvalid()) 435*81ad6265SDimitry Andric return true; 436*81ad6265SDimitry Andric MultiLevelTemplateArgumentList MLTAL( 437*81ad6265SDimitry Andric *Decl->getTemplateSpecializationArgs()); 438*81ad6265SDimitry Andric if (addInstantiatedParametersToScope( 439*81ad6265SDimitry Andric Decl, Decl->getPrimaryTemplate()->getTemplatedDecl(), Scope, MLTAL)) 440*81ad6265SDimitry Andric return true; 441*81ad6265SDimitry Andric } 442*81ad6265SDimitry Andric Qualifiers ThisQuals; 443*81ad6265SDimitry Andric CXXRecordDecl *Record = nullptr; 444*81ad6265SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { 445*81ad6265SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 446*81ad6265SDimitry Andric Record = Method->getParent(); 447*81ad6265SDimitry Andric } 448*81ad6265SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 449*81ad6265SDimitry Andric return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs, 450*81ad6265SDimitry Andric PointOfInstantiation, Satisfaction); 451*81ad6265SDimitry Andric } 452*81ad6265SDimitry Andric 45355e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 45455e4f9d5SDimitry Andric concepts::ExprRequirement *Req, 45555e4f9d5SDimitry Andric bool First) { 45655e4f9d5SDimitry Andric assert(!Req->isSatisfied() 45755e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 45855e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 45955e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Dependent: 46055e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 46155e4f9d5SDimitry Andric break; 46255e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ExprSubstitutionFailure: { 46355e4f9d5SDimitry Andric auto *SubstDiag = Req->getExprSubstitutionDiagnostic(); 46455e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 46555e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 46655e4f9d5SDimitry Andric diag::note_expr_requirement_expr_substitution_error) 46755e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 46855e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 46955e4f9d5SDimitry Andric else 47055e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 47155e4f9d5SDimitry Andric diag::note_expr_requirement_expr_unknown_substitution_error) 47255e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 47355e4f9d5SDimitry Andric break; 47455e4f9d5SDimitry Andric } 47555e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_NoexceptNotMet: 47655e4f9d5SDimitry Andric S.Diag(Req->getNoexceptLoc(), 47755e4f9d5SDimitry Andric diag::note_expr_requirement_noexcept_not_met) 47855e4f9d5SDimitry Andric << (int)First << Req->getExpr(); 47955e4f9d5SDimitry Andric break; 48055e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: { 48155e4f9d5SDimitry Andric auto *SubstDiag = 48255e4f9d5SDimitry Andric Req->getReturnTypeRequirement().getSubstitutionDiagnostic(); 48355e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 48455e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 48555e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_substitution_error) 48655e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 48755e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 48855e4f9d5SDimitry Andric else 48955e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 49055e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_unknown_substitution_error) 49155e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 49255e4f9d5SDimitry Andric break; 49355e4f9d5SDimitry Andric } 49455e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { 49555e4f9d5SDimitry Andric ConceptSpecializationExpr *ConstraintExpr = 49655e4f9d5SDimitry Andric Req->getReturnTypeRequirementSubstitutedConstraintExpr(); 497fe6060f1SDimitry Andric if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 49855e4f9d5SDimitry Andric // A simple case - expr type is the type being constrained and the concept 49955e4f9d5SDimitry Andric // was not provided arguments. 500fe6060f1SDimitry Andric Expr *e = Req->getExpr(); 501fe6060f1SDimitry Andric S.Diag(e->getBeginLoc(), 50255e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied_simple) 503349cc55cSDimitry Andric << (int)First << S.Context.getReferenceQualifiedType(e) 50455e4f9d5SDimitry Andric << ConstraintExpr->getNamedConcept(); 505fe6060f1SDimitry Andric } else { 50655e4f9d5SDimitry Andric S.Diag(ConstraintExpr->getBeginLoc(), 50755e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied) 50855e4f9d5SDimitry Andric << (int)First << ConstraintExpr; 509fe6060f1SDimitry Andric } 51055e4f9d5SDimitry Andric S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); 51155e4f9d5SDimitry Andric break; 51255e4f9d5SDimitry Andric } 51355e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Satisfied: 51455e4f9d5SDimitry Andric llvm_unreachable("We checked this above"); 51555e4f9d5SDimitry Andric } 51655e4f9d5SDimitry Andric } 51755e4f9d5SDimitry Andric 51855e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 51955e4f9d5SDimitry Andric concepts::TypeRequirement *Req, 52055e4f9d5SDimitry Andric bool First) { 52155e4f9d5SDimitry Andric assert(!Req->isSatisfied() 52255e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 52355e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 52455e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_Dependent: 52555e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 52655e4f9d5SDimitry Andric return; 52755e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_SubstitutionFailure: { 52855e4f9d5SDimitry Andric auto *SubstDiag = Req->getSubstitutionDiagnostic(); 52955e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 53055e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 53155e4f9d5SDimitry Andric diag::note_type_requirement_substitution_error) << (int)First 53255e4f9d5SDimitry Andric << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage; 53355e4f9d5SDimitry Andric else 53455e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 53555e4f9d5SDimitry Andric diag::note_type_requirement_unknown_substitution_error) 53655e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 53755e4f9d5SDimitry Andric return; 53855e4f9d5SDimitry Andric } 53955e4f9d5SDimitry Andric default: 54055e4f9d5SDimitry Andric llvm_unreachable("Unknown satisfaction status"); 54155e4f9d5SDimitry Andric return; 54255e4f9d5SDimitry Andric } 54355e4f9d5SDimitry Andric } 54455e4f9d5SDimitry Andric 54555e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 54655e4f9d5SDimitry Andric concepts::NestedRequirement *Req, 54755e4f9d5SDimitry Andric bool First) { 54855e4f9d5SDimitry Andric if (Req->isSubstitutionFailure()) { 54955e4f9d5SDimitry Andric concepts::Requirement::SubstitutionDiagnostic *SubstDiag = 55055e4f9d5SDimitry Andric Req->getSubstitutionDiagnostic(); 55155e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 55255e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 55355e4f9d5SDimitry Andric diag::note_nested_requirement_substitution_error) 55455e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 55555e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 55655e4f9d5SDimitry Andric else 55755e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 55855e4f9d5SDimitry Andric diag::note_nested_requirement_unknown_substitution_error) 55955e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 56055e4f9d5SDimitry Andric return; 56155e4f9d5SDimitry Andric } 56255e4f9d5SDimitry Andric S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First); 56355e4f9d5SDimitry Andric } 56455e4f9d5SDimitry Andric 56555e4f9d5SDimitry Andric 566480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 567480093f4SDimitry Andric Expr *SubstExpr, 568480093f4SDimitry Andric bool First = true) { 569480093f4SDimitry Andric SubstExpr = SubstExpr->IgnoreParenImpCasts(); 570480093f4SDimitry Andric if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) { 571480093f4SDimitry Andric switch (BO->getOpcode()) { 572480093f4SDimitry Andric // These two cases will in practice only be reached when using fold 573480093f4SDimitry Andric // expressions with || and &&, since otherwise the || and && will have been 574480093f4SDimitry Andric // broken down into atomic constraints during satisfaction checking. 575480093f4SDimitry Andric case BO_LOr: 576480093f4SDimitry Andric // Or evaluated to false - meaning both RHS and LHS evaluated to false. 577480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 578480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 579480093f4SDimitry Andric /*First=*/false); 580480093f4SDimitry Andric return; 581fe6060f1SDimitry Andric case BO_LAnd: { 582fe6060f1SDimitry Andric bool LHSSatisfied = 583fe6060f1SDimitry Andric BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 584480093f4SDimitry Andric if (LHSSatisfied) { 585480093f4SDimitry Andric // LHS is true, so RHS must be false. 586480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First); 587480093f4SDimitry Andric return; 588480093f4SDimitry Andric } 589480093f4SDimitry Andric // LHS is false 590480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 591480093f4SDimitry Andric 592480093f4SDimitry Andric // RHS might also be false 593fe6060f1SDimitry Andric bool RHSSatisfied = 594fe6060f1SDimitry Andric BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 595480093f4SDimitry Andric if (!RHSSatisfied) 596480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 597480093f4SDimitry Andric /*First=*/false); 598480093f4SDimitry Andric return; 599fe6060f1SDimitry Andric } 600480093f4SDimitry Andric case BO_GE: 601480093f4SDimitry Andric case BO_LE: 602480093f4SDimitry Andric case BO_GT: 603480093f4SDimitry Andric case BO_LT: 604480093f4SDimitry Andric case BO_EQ: 605480093f4SDimitry Andric case BO_NE: 606480093f4SDimitry Andric if (BO->getLHS()->getType()->isIntegerType() && 607480093f4SDimitry Andric BO->getRHS()->getType()->isIntegerType()) { 608480093f4SDimitry Andric Expr::EvalResult SimplifiedLHS; 609480093f4SDimitry Andric Expr::EvalResult SimplifiedRHS; 610fe6060f1SDimitry Andric BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context, 611fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 612fe6060f1SDimitry Andric /*InConstantContext=*/true); 613fe6060f1SDimitry Andric BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context, 614fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 615fe6060f1SDimitry Andric /*InConstantContext=*/true); 616480093f4SDimitry Andric if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) { 617480093f4SDimitry Andric S.Diag(SubstExpr->getBeginLoc(), 618480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false_elaborated) 619480093f4SDimitry Andric << (int)First << SubstExpr 620fe6060f1SDimitry Andric << toString(SimplifiedLHS.Val.getInt(), 10) 621480093f4SDimitry Andric << BinaryOperator::getOpcodeStr(BO->getOpcode()) 622fe6060f1SDimitry Andric << toString(SimplifiedRHS.Val.getInt(), 10); 623480093f4SDimitry Andric return; 624480093f4SDimitry Andric } 625480093f4SDimitry Andric } 626480093f4SDimitry Andric break; 627480093f4SDimitry Andric 628480093f4SDimitry Andric default: 629480093f4SDimitry Andric break; 630480093f4SDimitry Andric } 631480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) { 632480093f4SDimitry Andric if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 633480093f4SDimitry Andric S.Diag( 634480093f4SDimitry Andric CSE->getSourceRange().getBegin(), 635480093f4SDimitry Andric diag:: 636480093f4SDimitry Andric note_single_arg_concept_specialization_constraint_evaluated_to_false) 637480093f4SDimitry Andric << (int)First 638480093f4SDimitry Andric << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument() 639480093f4SDimitry Andric << CSE->getNamedConcept(); 640480093f4SDimitry Andric } else { 641480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 642480093f4SDimitry Andric diag::note_concept_specialization_constraint_evaluated_to_false) 643480093f4SDimitry Andric << (int)First << CSE; 644480093f4SDimitry Andric } 645480093f4SDimitry Andric S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction()); 646480093f4SDimitry Andric return; 64755e4f9d5SDimitry Andric } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) { 64855e4f9d5SDimitry Andric for (concepts::Requirement *Req : RE->getRequirements()) 64955e4f9d5SDimitry Andric if (!Req->isDependent() && !Req->isSatisfied()) { 65055e4f9d5SDimitry Andric if (auto *E = dyn_cast<concepts::ExprRequirement>(Req)) 65155e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, E, First); 65255e4f9d5SDimitry Andric else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req)) 65355e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, T, First); 65455e4f9d5SDimitry Andric else 65555e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement( 65655e4f9d5SDimitry Andric S, cast<concepts::NestedRequirement>(Req), First); 65755e4f9d5SDimitry Andric break; 65855e4f9d5SDimitry Andric } 65955e4f9d5SDimitry Andric return; 660480093f4SDimitry Andric } 661480093f4SDimitry Andric 662480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 663480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false) 664480093f4SDimitry Andric << (int)First << SubstExpr; 665480093f4SDimitry Andric } 666480093f4SDimitry Andric 667480093f4SDimitry Andric template<typename SubstitutionDiagnostic> 668480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr( 669480093f4SDimitry Andric Sema &S, const Expr *E, 670480093f4SDimitry Andric const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record, 671480093f4SDimitry Andric bool First = true) { 672480093f4SDimitry Andric if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){ 673480093f4SDimitry Andric S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed) 674480093f4SDimitry Andric << Diag->second; 675480093f4SDimitry Andric return; 676480093f4SDimitry Andric } 677480093f4SDimitry Andric 678480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, 679480093f4SDimitry Andric Record.template get<Expr *>(), First); 680480093f4SDimitry Andric } 681480093f4SDimitry Andric 68255e4f9d5SDimitry Andric void 68355e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, 68455e4f9d5SDimitry Andric bool First) { 685480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 686480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 687480093f4SDimitry Andric for (auto &Pair : Satisfaction.Details) { 688480093f4SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); 689480093f4SDimitry Andric First = false; 690480093f4SDimitry Andric } 691480093f4SDimitry Andric } 692480093f4SDimitry Andric 693480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint( 69455e4f9d5SDimitry Andric const ASTConstraintSatisfaction &Satisfaction, 69555e4f9d5SDimitry Andric bool First) { 696480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 697480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 698480093f4SDimitry Andric for (auto &Pair : Satisfaction) { 699480093f4SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); 700480093f4SDimitry Andric First = false; 701480093f4SDimitry Andric } 702480093f4SDimitry Andric } 703480093f4SDimitry Andric 704480093f4SDimitry Andric const NormalizedConstraint * 705480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints( 706480093f4SDimitry Andric NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) { 707480093f4SDimitry Andric auto CacheEntry = NormalizationCache.find(ConstrainedDecl); 708480093f4SDimitry Andric if (CacheEntry == NormalizationCache.end()) { 709480093f4SDimitry Andric auto Normalized = 710480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl, 711480093f4SDimitry Andric AssociatedConstraints); 712480093f4SDimitry Andric CacheEntry = 713480093f4SDimitry Andric NormalizationCache 714480093f4SDimitry Andric .try_emplace(ConstrainedDecl, 715480093f4SDimitry Andric Normalized 716480093f4SDimitry Andric ? new (Context) NormalizedConstraint( 717480093f4SDimitry Andric std::move(*Normalized)) 718480093f4SDimitry Andric : nullptr) 719480093f4SDimitry Andric .first; 720480093f4SDimitry Andric } 721480093f4SDimitry Andric return CacheEntry->second; 722480093f4SDimitry Andric } 723480093f4SDimitry Andric 724480093f4SDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, 725480093f4SDimitry Andric ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs, 726480093f4SDimitry Andric const ASTTemplateArgumentListInfo *ArgsAsWritten) { 727480093f4SDimitry Andric if (!N.isAtomic()) { 728480093f4SDimitry Andric if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs, 729480093f4SDimitry Andric ArgsAsWritten)) 730480093f4SDimitry Andric return true; 731480093f4SDimitry Andric return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs, 732480093f4SDimitry Andric ArgsAsWritten); 733480093f4SDimitry Andric } 734480093f4SDimitry Andric TemplateParameterList *TemplateParams = Concept->getTemplateParameters(); 735480093f4SDimitry Andric 736480093f4SDimitry Andric AtomicConstraint &Atomic = *N.getAtomicConstraint(); 737480093f4SDimitry Andric TemplateArgumentListInfo SubstArgs; 738480093f4SDimitry Andric MultiLevelTemplateArgumentList MLTAL; 739480093f4SDimitry Andric MLTAL.addOuterTemplateArguments(TemplateArgs); 740480093f4SDimitry Andric if (!Atomic.ParameterMapping) { 741480093f4SDimitry Andric llvm::SmallBitVector OccurringIndices(TemplateParams->size()); 742480093f4SDimitry Andric S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false, 743480093f4SDimitry Andric /*Depth=*/0, OccurringIndices); 744480093f4SDimitry Andric Atomic.ParameterMapping.emplace( 745480093f4SDimitry Andric MutableArrayRef<TemplateArgumentLoc>( 746480093f4SDimitry Andric new (S.Context) TemplateArgumentLoc[OccurringIndices.count()], 747480093f4SDimitry Andric OccurringIndices.count())); 748480093f4SDimitry Andric for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) 749480093f4SDimitry Andric if (OccurringIndices[I]) 750480093f4SDimitry Andric new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc( 751480093f4SDimitry Andric S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I], 752480093f4SDimitry Andric // Here we assume we do not support things like 753480093f4SDimitry Andric // template<typename A, typename B> 754480093f4SDimitry Andric // concept C = ...; 755480093f4SDimitry Andric // 756480093f4SDimitry Andric // template<typename... Ts> requires C<Ts...> 757480093f4SDimitry Andric // struct S { }; 758480093f4SDimitry Andric // The above currently yields a diagnostic. 759480093f4SDimitry Andric // We still might have default arguments for concept parameters. 760480093f4SDimitry Andric ArgsAsWritten->NumTemplateArgs > I ? 761480093f4SDimitry Andric ArgsAsWritten->arguments()[I].getLocation() : 762480093f4SDimitry Andric SourceLocation())); 763480093f4SDimitry Andric } 764480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 765480093f4SDimitry Andric S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(), 766480093f4SDimitry Andric Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, 767480093f4SDimitry Andric SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(), 768480093f4SDimitry Andric ArgsAsWritten->arguments().back().getSourceRange().getEnd())); 769480093f4SDimitry Andric if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) 770480093f4SDimitry Andric return true; 77113138422SDimitry Andric Atomic.ParameterMapping.emplace( 77213138422SDimitry Andric MutableArrayRef<TemplateArgumentLoc>( 77313138422SDimitry Andric new (S.Context) TemplateArgumentLoc[SubstArgs.size()], 77413138422SDimitry Andric SubstArgs.size())); 775480093f4SDimitry Andric std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(), 776480093f4SDimitry Andric N.getAtomicConstraint()->ParameterMapping->begin()); 777480093f4SDimitry Andric return false; 778480093f4SDimitry Andric } 779480093f4SDimitry Andric 780480093f4SDimitry Andric Optional<NormalizedConstraint> 781480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D, 782480093f4SDimitry Andric ArrayRef<const Expr *> E) { 783480093f4SDimitry Andric assert(E.size() != 0); 7846e75b2fbSDimitry Andric auto Conjunction = fromConstraintExpr(S, D, E[0]); 7856e75b2fbSDimitry Andric if (!Conjunction) 786480093f4SDimitry Andric return None; 7876e75b2fbSDimitry Andric for (unsigned I = 1; I < E.size(); ++I) { 788480093f4SDimitry Andric auto Next = fromConstraintExpr(S, D, E[I]); 789480093f4SDimitry Andric if (!Next) 7906e75b2fbSDimitry Andric return None; 7916e75b2fbSDimitry Andric *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction), 792480093f4SDimitry Andric std::move(*Next), CCK_Conjunction); 793480093f4SDimitry Andric } 794480093f4SDimitry Andric return Conjunction; 795480093f4SDimitry Andric } 796480093f4SDimitry Andric 797480093f4SDimitry Andric llvm::Optional<NormalizedConstraint> 798480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) { 799480093f4SDimitry Andric assert(E != nullptr); 800480093f4SDimitry Andric 801480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 802480093f4SDimitry Andric // [...] 803480093f4SDimitry Andric // - The normal form of an expression (E) is the normal form of E. 804480093f4SDimitry Andric // [...] 805480093f4SDimitry Andric E = E->IgnoreParenImpCasts(); 8065ffd83dbSDimitry Andric if (LogicalBinOp BO = E) { 8075ffd83dbSDimitry Andric auto LHS = fromConstraintExpr(S, D, BO.getLHS()); 808480093f4SDimitry Andric if (!LHS) 809480093f4SDimitry Andric return None; 8105ffd83dbSDimitry Andric auto RHS = fromConstraintExpr(S, D, BO.getRHS()); 811480093f4SDimitry Andric if (!RHS) 812480093f4SDimitry Andric return None; 813480093f4SDimitry Andric 8145ffd83dbSDimitry Andric return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS), 8155ffd83dbSDimitry Andric BO.isAnd() ? CCK_Conjunction : CCK_Disjunction); 816480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) { 817480093f4SDimitry Andric const NormalizedConstraint *SubNF; 818480093f4SDimitry Andric { 819480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 820480093f4SDimitry Andric S, CSE->getExprLoc(), 821480093f4SDimitry Andric Sema::InstantiatingTemplate::ConstraintNormalization{}, D, 822480093f4SDimitry Andric CSE->getSourceRange()); 823480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 824480093f4SDimitry Andric // [...] 825480093f4SDimitry Andric // The normal form of an id-expression of the form C<A1, A2, ..., AN>, 826480093f4SDimitry Andric // where C names a concept, is the normal form of the 827480093f4SDimitry Andric // constraint-expression of C, after substituting A1, A2, ..., AN for C’s 828480093f4SDimitry Andric // respective template parameters in the parameter mappings in each atomic 829480093f4SDimitry Andric // constraint. If any such substitution results in an invalid type or 830480093f4SDimitry Andric // expression, the program is ill-formed; no diagnostic is required. 831480093f4SDimitry Andric // [...] 832480093f4SDimitry Andric ConceptDecl *CD = CSE->getNamedConcept(); 833480093f4SDimitry Andric SubNF = S.getNormalizedAssociatedConstraints(CD, 834480093f4SDimitry Andric {CD->getConstraintExpr()}); 835480093f4SDimitry Andric if (!SubNF) 836480093f4SDimitry Andric return None; 837480093f4SDimitry Andric } 838480093f4SDimitry Andric 839480093f4SDimitry Andric Optional<NormalizedConstraint> New; 840480093f4SDimitry Andric New.emplace(S.Context, *SubNF); 841480093f4SDimitry Andric 842480093f4SDimitry Andric if (substituteParameterMappings( 843480093f4SDimitry Andric S, *New, CSE->getNamedConcept(), 844480093f4SDimitry Andric CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten())) 845480093f4SDimitry Andric return None; 846480093f4SDimitry Andric 847480093f4SDimitry Andric return New; 848480093f4SDimitry Andric } 849480093f4SDimitry Andric return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)}; 850480093f4SDimitry Andric } 851480093f4SDimitry Andric 852480093f4SDimitry Andric using NormalForm = 853480093f4SDimitry Andric llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>; 854480093f4SDimitry Andric 855480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) { 856480093f4SDimitry Andric if (Normalized.isAtomic()) 857480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 858480093f4SDimitry Andric 859480093f4SDimitry Andric NormalForm LCNF = makeCNF(Normalized.getLHS()); 860480093f4SDimitry Andric NormalForm RCNF = makeCNF(Normalized.getRHS()); 861480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) { 862480093f4SDimitry Andric LCNF.reserve(LCNF.size() + RCNF.size()); 863480093f4SDimitry Andric while (!RCNF.empty()) 864480093f4SDimitry Andric LCNF.push_back(RCNF.pop_back_val()); 865480093f4SDimitry Andric return LCNF; 866480093f4SDimitry Andric } 867480093f4SDimitry Andric 868480093f4SDimitry Andric // Disjunction 869480093f4SDimitry Andric NormalForm Res; 870480093f4SDimitry Andric Res.reserve(LCNF.size() * RCNF.size()); 871480093f4SDimitry Andric for (auto &LDisjunction : LCNF) 872480093f4SDimitry Andric for (auto &RDisjunction : RCNF) { 873480093f4SDimitry Andric NormalForm::value_type Combined; 874480093f4SDimitry Andric Combined.reserve(LDisjunction.size() + RDisjunction.size()); 875480093f4SDimitry Andric std::copy(LDisjunction.begin(), LDisjunction.end(), 876480093f4SDimitry Andric std::back_inserter(Combined)); 877480093f4SDimitry Andric std::copy(RDisjunction.begin(), RDisjunction.end(), 878480093f4SDimitry Andric std::back_inserter(Combined)); 879480093f4SDimitry Andric Res.emplace_back(Combined); 880480093f4SDimitry Andric } 881480093f4SDimitry Andric return Res; 882480093f4SDimitry Andric } 883480093f4SDimitry Andric 884480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) { 885480093f4SDimitry Andric if (Normalized.isAtomic()) 886480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 887480093f4SDimitry Andric 888480093f4SDimitry Andric NormalForm LDNF = makeDNF(Normalized.getLHS()); 889480093f4SDimitry Andric NormalForm RDNF = makeDNF(Normalized.getRHS()); 890480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) { 891480093f4SDimitry Andric LDNF.reserve(LDNF.size() + RDNF.size()); 892480093f4SDimitry Andric while (!RDNF.empty()) 893480093f4SDimitry Andric LDNF.push_back(RDNF.pop_back_val()); 894480093f4SDimitry Andric return LDNF; 895480093f4SDimitry Andric } 896480093f4SDimitry Andric 897480093f4SDimitry Andric // Conjunction 898480093f4SDimitry Andric NormalForm Res; 899480093f4SDimitry Andric Res.reserve(LDNF.size() * RDNF.size()); 900480093f4SDimitry Andric for (auto &LConjunction : LDNF) { 901480093f4SDimitry Andric for (auto &RConjunction : RDNF) { 902480093f4SDimitry Andric NormalForm::value_type Combined; 903480093f4SDimitry Andric Combined.reserve(LConjunction.size() + RConjunction.size()); 904480093f4SDimitry Andric std::copy(LConjunction.begin(), LConjunction.end(), 905480093f4SDimitry Andric std::back_inserter(Combined)); 906480093f4SDimitry Andric std::copy(RConjunction.begin(), RConjunction.end(), 907480093f4SDimitry Andric std::back_inserter(Combined)); 908480093f4SDimitry Andric Res.emplace_back(Combined); 909480093f4SDimitry Andric } 910480093f4SDimitry Andric } 911480093f4SDimitry Andric return Res; 912480093f4SDimitry Andric } 913480093f4SDimitry Andric 914480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator> 915480093f4SDimitry Andric static bool subsumes(NormalForm PDNF, NormalForm QCNF, 916480093f4SDimitry Andric AtomicSubsumptionEvaluator E) { 917480093f4SDimitry Andric // C++ [temp.constr.order] p2 918480093f4SDimitry Andric // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the 919480093f4SDimitry Andric // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in 920480093f4SDimitry Andric // the conjuctive normal form of Q, where [...] 921480093f4SDimitry Andric for (const auto &Pi : PDNF) { 922480093f4SDimitry Andric for (const auto &Qj : QCNF) { 923480093f4SDimitry Andric // C++ [temp.constr.order] p2 924480093f4SDimitry Andric // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if 925480093f4SDimitry Andric // and only if there exists an atomic constraint Pia in Pi for which 926480093f4SDimitry Andric // there exists an atomic constraint, Qjb, in Qj such that Pia 927480093f4SDimitry Andric // subsumes Qjb. 928480093f4SDimitry Andric bool Found = false; 929480093f4SDimitry Andric for (const AtomicConstraint *Pia : Pi) { 930480093f4SDimitry Andric for (const AtomicConstraint *Qjb : Qj) { 931480093f4SDimitry Andric if (E(*Pia, *Qjb)) { 932480093f4SDimitry Andric Found = true; 933480093f4SDimitry Andric break; 934480093f4SDimitry Andric } 935480093f4SDimitry Andric } 936480093f4SDimitry Andric if (Found) 937480093f4SDimitry Andric break; 938480093f4SDimitry Andric } 939480093f4SDimitry Andric if (!Found) 940480093f4SDimitry Andric return false; 941480093f4SDimitry Andric } 942480093f4SDimitry Andric } 943480093f4SDimitry Andric return true; 944480093f4SDimitry Andric } 945480093f4SDimitry Andric 946480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator> 947480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P, 948480093f4SDimitry Andric NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes, 949480093f4SDimitry Andric AtomicSubsumptionEvaluator E) { 950480093f4SDimitry Andric // C++ [temp.constr.order] p2 951480093f4SDimitry Andric // In order to determine if a constraint P subsumes a constraint Q, P is 952480093f4SDimitry Andric // transformed into disjunctive normal form, and Q is transformed into 953480093f4SDimitry Andric // conjunctive normal form. [...] 954480093f4SDimitry Andric auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P); 955480093f4SDimitry Andric if (!PNormalized) 956480093f4SDimitry Andric return true; 957480093f4SDimitry Andric const NormalForm PDNF = makeDNF(*PNormalized); 958480093f4SDimitry Andric 959480093f4SDimitry Andric auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q); 960480093f4SDimitry Andric if (!QNormalized) 961480093f4SDimitry Andric return true; 962480093f4SDimitry Andric const NormalForm QCNF = makeCNF(*QNormalized); 963480093f4SDimitry Andric 964480093f4SDimitry Andric Subsumes = subsumes(PDNF, QCNF, E); 965480093f4SDimitry Andric return false; 966480093f4SDimitry Andric } 967480093f4SDimitry Andric 968480093f4SDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1, 969480093f4SDimitry Andric NamedDecl *D2, ArrayRef<const Expr *> AC2, 970480093f4SDimitry Andric bool &Result) { 971480093f4SDimitry Andric if (AC1.empty()) { 972480093f4SDimitry Andric Result = AC2.empty(); 973480093f4SDimitry Andric return false; 974480093f4SDimitry Andric } 975480093f4SDimitry Andric if (AC2.empty()) { 976480093f4SDimitry Andric // TD1 has associated constraints and TD2 does not. 977480093f4SDimitry Andric Result = true; 978480093f4SDimitry Andric return false; 979480093f4SDimitry Andric } 980480093f4SDimitry Andric 981480093f4SDimitry Andric std::pair<NamedDecl *, NamedDecl *> Key{D1, D2}; 982480093f4SDimitry Andric auto CacheEntry = SubsumptionCache.find(Key); 983480093f4SDimitry Andric if (CacheEntry != SubsumptionCache.end()) { 984480093f4SDimitry Andric Result = CacheEntry->second; 985480093f4SDimitry Andric return false; 986480093f4SDimitry Andric } 987480093f4SDimitry Andric 988480093f4SDimitry Andric if (subsumes(*this, D1, AC1, D2, AC2, Result, 989480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 990480093f4SDimitry Andric return A.subsumes(Context, B); 991480093f4SDimitry Andric })) 992480093f4SDimitry Andric return true; 993480093f4SDimitry Andric SubsumptionCache.try_emplace(Key, Result); 994480093f4SDimitry Andric return false; 995480093f4SDimitry Andric } 996480093f4SDimitry Andric 997480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, 998480093f4SDimitry Andric ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) { 999480093f4SDimitry Andric if (isSFINAEContext()) 1000480093f4SDimitry Andric // No need to work here because our notes would be discarded. 1001480093f4SDimitry Andric return false; 1002480093f4SDimitry Andric 1003480093f4SDimitry Andric if (AC1.empty() || AC2.empty()) 1004480093f4SDimitry Andric return false; 1005480093f4SDimitry Andric 1006480093f4SDimitry Andric auto NormalExprEvaluator = 1007480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 1008480093f4SDimitry Andric return A.subsumes(Context, B); 1009480093f4SDimitry Andric }; 1010480093f4SDimitry Andric 1011480093f4SDimitry Andric const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr; 1012480093f4SDimitry Andric auto IdenticalExprEvaluator = 1013480093f4SDimitry Andric [&] (const AtomicConstraint &A, const AtomicConstraint &B) { 1014480093f4SDimitry Andric if (!A.hasMatchingParameterMapping(Context, B)) 1015480093f4SDimitry Andric return false; 1016480093f4SDimitry Andric const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr; 1017480093f4SDimitry Andric if (EA == EB) 1018480093f4SDimitry Andric return true; 1019480093f4SDimitry Andric 1020480093f4SDimitry Andric // Not the same source level expression - are the expressions 1021480093f4SDimitry Andric // identical? 1022480093f4SDimitry Andric llvm::FoldingSetNodeID IDA, IDB; 1023349cc55cSDimitry Andric EA->Profile(IDA, Context, /*Canonical=*/true); 1024349cc55cSDimitry Andric EB->Profile(IDB, Context, /*Canonical=*/true); 1025480093f4SDimitry Andric if (IDA != IDB) 1026480093f4SDimitry Andric return false; 1027480093f4SDimitry Andric 1028480093f4SDimitry Andric AmbiguousAtomic1 = EA; 1029480093f4SDimitry Andric AmbiguousAtomic2 = EB; 1030480093f4SDimitry Andric return true; 1031480093f4SDimitry Andric }; 1032480093f4SDimitry Andric 1033480093f4SDimitry Andric { 1034480093f4SDimitry Andric // The subsumption checks might cause diagnostics 1035480093f4SDimitry Andric SFINAETrap Trap(*this); 1036480093f4SDimitry Andric auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1); 1037480093f4SDimitry Andric if (!Normalized1) 1038480093f4SDimitry Andric return false; 1039480093f4SDimitry Andric const NormalForm DNF1 = makeDNF(*Normalized1); 1040480093f4SDimitry Andric const NormalForm CNF1 = makeCNF(*Normalized1); 1041480093f4SDimitry Andric 1042480093f4SDimitry Andric auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2); 1043480093f4SDimitry Andric if (!Normalized2) 1044480093f4SDimitry Andric return false; 1045480093f4SDimitry Andric const NormalForm DNF2 = makeDNF(*Normalized2); 1046480093f4SDimitry Andric const NormalForm CNF2 = makeCNF(*Normalized2); 1047480093f4SDimitry Andric 1048480093f4SDimitry Andric bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator); 1049480093f4SDimitry Andric bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator); 1050480093f4SDimitry Andric bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator); 1051480093f4SDimitry Andric bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator); 1052480093f4SDimitry Andric if (Is1AtLeastAs2 == Is1AtLeastAs2Normally && 1053480093f4SDimitry Andric Is2AtLeastAs1 == Is2AtLeastAs1Normally) 1054480093f4SDimitry Andric // Same result - no ambiguity was caused by identical atomic expressions. 1055480093f4SDimitry Andric return false; 1056480093f4SDimitry Andric } 1057480093f4SDimitry Andric 1058480093f4SDimitry Andric // A different result! Some ambiguous atomic constraint(s) caused a difference 1059480093f4SDimitry Andric assert(AmbiguousAtomic1 && AmbiguousAtomic2); 1060480093f4SDimitry Andric 1061480093f4SDimitry Andric Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints) 1062480093f4SDimitry Andric << AmbiguousAtomic1->getSourceRange(); 1063480093f4SDimitry Andric Diag(AmbiguousAtomic2->getBeginLoc(), 1064480093f4SDimitry Andric diag::note_ambiguous_atomic_constraints_similar_expression) 1065480093f4SDimitry Andric << AmbiguousAtomic2->getSourceRange(); 1066480093f4SDimitry Andric return true; 1067480093f4SDimitry Andric } 106855e4f9d5SDimitry Andric 106955e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 107055e4f9d5SDimitry Andric Expr *E, bool IsSimple, SourceLocation NoexceptLoc, 107155e4f9d5SDimitry Andric ReturnTypeRequirement Req, SatisfactionStatus Status, 107255e4f9d5SDimitry Andric ConceptSpecializationExpr *SubstitutedConstraintExpr) : 107355e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, 107455e4f9d5SDimitry Andric Status == SS_Dependent && 107555e4f9d5SDimitry Andric (E->containsUnexpandedParameterPack() || 107655e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack()), 107755e4f9d5SDimitry Andric Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc), 107855e4f9d5SDimitry Andric TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr), 107955e4f9d5SDimitry Andric Status(Status) { 108055e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 108155e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 108255e4f9d5SDimitry Andric "noexcept specification"); 108355e4f9d5SDimitry Andric assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == 108455e4f9d5SDimitry Andric (SubstitutedConstraintExpr != nullptr)); 108555e4f9d5SDimitry Andric } 108655e4f9d5SDimitry Andric 108755e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 108855e4f9d5SDimitry Andric SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, 108955e4f9d5SDimitry Andric SourceLocation NoexceptLoc, ReturnTypeRequirement Req) : 109055e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), 109155e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), 109255e4f9d5SDimitry Andric Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), 109355e4f9d5SDimitry Andric Status(SS_ExprSubstitutionFailure) { 109455e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 109555e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 109655e4f9d5SDimitry Andric "noexcept specification"); 109755e4f9d5SDimitry Andric } 109855e4f9d5SDimitry Andric 109955e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement:: 110055e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) : 110104eeddc0SDimitry Andric TypeConstraintInfo(TPL, false) { 110255e4f9d5SDimitry Andric assert(TPL->size() == 1); 110355e4f9d5SDimitry Andric const TypeConstraint *TC = 110455e4f9d5SDimitry Andric cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint(); 110555e4f9d5SDimitry Andric assert(TC && 110655e4f9d5SDimitry Andric "TPL must have a template type parameter with a type constraint"); 110755e4f9d5SDimitry Andric auto *Constraint = 1108349cc55cSDimitry Andric cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint()); 1109e8d8bef9SDimitry Andric bool Dependent = 1110e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten() && 1111e8d8bef9SDimitry Andric TemplateSpecializationType::anyInstantiationDependentTemplateArguments( 1112e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)); 111304eeddc0SDimitry Andric TypeConstraintInfo.setInt(Dependent ? true : false); 111455e4f9d5SDimitry Andric } 111555e4f9d5SDimitry Andric 111655e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) : 1117e8d8bef9SDimitry Andric Requirement(RK_Type, T->getType()->isInstantiationDependentType(), 111855e4f9d5SDimitry Andric T->getType()->containsUnexpandedParameterPack(), 111955e4f9d5SDimitry Andric // We reach this ctor with either dependent types (in which 112055e4f9d5SDimitry Andric // IsSatisfied doesn't matter) or with non-dependent type in 112155e4f9d5SDimitry Andric // which the existence of the type indicates satisfaction. 1122e8d8bef9SDimitry Andric /*IsSatisfied=*/true), 1123e8d8bef9SDimitry Andric Value(T), 1124e8d8bef9SDimitry Andric Status(T->getType()->isInstantiationDependentType() ? SS_Dependent 1125e8d8bef9SDimitry Andric : SS_Satisfied) {} 1126