1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // The LLVM Compiler Infrastructure 4a7dea167SDimitry Andric // 5a7dea167SDimitry Andric // This file is distributed under the University of Illinois Open Source 6a7dea167SDimitry Andric // License. See LICENSE.TXT for details. 7a7dea167SDimitry Andric // 8a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 9a7dea167SDimitry Andric // 10a7dea167SDimitry Andric // This file implements semantic analysis for C++ constraints and concepts. 11a7dea167SDimitry Andric // 12a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 13a7dea167SDimitry Andric 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" 2255e4f9d5SDimitry Andric #include "clang/Sema/SemaInternal.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" 29fe6060f1SDimitry Andric 30a7dea167SDimitry Andric using namespace clang; 31a7dea167SDimitry Andric using namespace sema; 32a7dea167SDimitry Andric 335ffd83dbSDimitry Andric namespace { 345ffd83dbSDimitry Andric class LogicalBinOp { 355ffd83dbSDimitry Andric OverloadedOperatorKind Op = OO_None; 365ffd83dbSDimitry Andric const Expr *LHS = nullptr; 375ffd83dbSDimitry Andric const Expr *RHS = nullptr; 385ffd83dbSDimitry Andric 395ffd83dbSDimitry Andric public: 405ffd83dbSDimitry Andric LogicalBinOp(const Expr *E) { 415ffd83dbSDimitry Andric if (auto *BO = dyn_cast<BinaryOperator>(E)) { 425ffd83dbSDimitry Andric Op = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 435ffd83dbSDimitry Andric LHS = BO->getLHS(); 445ffd83dbSDimitry Andric RHS = BO->getRHS(); 455ffd83dbSDimitry Andric } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) { 46fe6060f1SDimitry Andric // If OO is not || or && it might not have exactly 2 arguments. 47fe6060f1SDimitry Andric if (OO->getNumArgs() == 2) { 485ffd83dbSDimitry Andric Op = OO->getOperator(); 495ffd83dbSDimitry Andric LHS = OO->getArg(0); 505ffd83dbSDimitry Andric RHS = OO->getArg(1); 515ffd83dbSDimitry Andric } 525ffd83dbSDimitry Andric } 53fe6060f1SDimitry Andric } 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric bool isAnd() const { return Op == OO_AmpAmp; } 565ffd83dbSDimitry Andric bool isOr() const { return Op == OO_PipePipe; } 575ffd83dbSDimitry Andric explicit operator bool() const { return isAnd() || isOr(); } 585ffd83dbSDimitry Andric 595ffd83dbSDimitry Andric const Expr *getLHS() const { return LHS; } 605ffd83dbSDimitry Andric const Expr *getRHS() const { return RHS; } 615ffd83dbSDimitry Andric }; 625ffd83dbSDimitry Andric } 635ffd83dbSDimitry Andric 645ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression, 655ffd83dbSDimitry Andric Token NextToken, bool *PossibleNonPrimary, 66480093f4SDimitry Andric bool IsTrailingRequiresClause) { 67a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 68a7dea167SDimitry Andric // ..E shall be a constant expression of type bool. 69a7dea167SDimitry Andric 70a7dea167SDimitry Andric ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts(); 71a7dea167SDimitry Andric 725ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpression) { 735ffd83dbSDimitry Andric return CheckConstraintExpression(BO.getLHS(), NextToken, 74480093f4SDimitry Andric PossibleNonPrimary) && 755ffd83dbSDimitry Andric CheckConstraintExpression(BO.getRHS(), NextToken, 76480093f4SDimitry Andric PossibleNonPrimary); 77a7dea167SDimitry Andric } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression)) 78480093f4SDimitry Andric return CheckConstraintExpression(C->getSubExpr(), NextToken, 79480093f4SDimitry Andric PossibleNonPrimary); 80a7dea167SDimitry Andric 81a7dea167SDimitry Andric QualType Type = ConstraintExpression->getType(); 82480093f4SDimitry Andric 83480093f4SDimitry Andric auto CheckForNonPrimary = [&] { 84480093f4SDimitry Andric if (PossibleNonPrimary) 85480093f4SDimitry Andric *PossibleNonPrimary = 86480093f4SDimitry Andric // We have the following case: 87480093f4SDimitry Andric // template<typename> requires func(0) struct S { }; 88480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 89480093f4SDimitry Andric // the function call, and we're only going to parse 'func' as the 90480093f4SDimitry Andric // primary-expression, and complain that it is of non-bool type. 91480093f4SDimitry Andric (NextToken.is(tok::l_paren) && 92480093f4SDimitry Andric (IsTrailingRequiresClause || 93480093f4SDimitry Andric (Type->isDependentType() && 945ffd83dbSDimitry Andric isa<UnresolvedLookupExpr>(ConstraintExpression)) || 95480093f4SDimitry Andric Type->isFunctionType() || 96480093f4SDimitry Andric Type->isSpecificBuiltinType(BuiltinType::Overload))) || 97480093f4SDimitry Andric // We have the following case: 98480093f4SDimitry Andric // template<typename T> requires size_<T> == 0 struct S { }; 99480093f4SDimitry Andric // The user probably isn't aware of the parentheses required around 100480093f4SDimitry Andric // the binary operator, and we're only going to parse 'func' as the 101480093f4SDimitry Andric // first operand, and complain that it is of non-bool type. 102480093f4SDimitry Andric getBinOpPrecedence(NextToken.getKind(), 103480093f4SDimitry Andric /*GreaterThanIsOperator=*/true, 104480093f4SDimitry Andric getLangOpts().CPlusPlus11) > prec::LogicalAnd; 105480093f4SDimitry Andric }; 106480093f4SDimitry Andric 107480093f4SDimitry Andric // An atomic constraint! 108480093f4SDimitry Andric if (ConstraintExpression->isTypeDependent()) { 109480093f4SDimitry Andric CheckForNonPrimary(); 110480093f4SDimitry Andric return true; 111480093f4SDimitry Andric } 112480093f4SDimitry Andric 113a7dea167SDimitry Andric if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) { 114a7dea167SDimitry Andric Diag(ConstraintExpression->getExprLoc(), 115a7dea167SDimitry Andric diag::err_non_bool_atomic_constraint) << Type 116a7dea167SDimitry Andric << ConstraintExpression->getSourceRange(); 117480093f4SDimitry Andric CheckForNonPrimary(); 118a7dea167SDimitry Andric return false; 119a7dea167SDimitry Andric } 120480093f4SDimitry Andric 121480093f4SDimitry Andric if (PossibleNonPrimary) 122480093f4SDimitry Andric *PossibleNonPrimary = false; 123a7dea167SDimitry Andric return true; 124a7dea167SDimitry Andric } 125a7dea167SDimitry Andric 126480093f4SDimitry Andric template <typename AtomicEvaluator> 127480093f4SDimitry Andric static bool 128480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, 129480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction, 130480093f4SDimitry Andric AtomicEvaluator &&Evaluator) { 131a7dea167SDimitry Andric ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); 132a7dea167SDimitry Andric 1335ffd83dbSDimitry Andric if (LogicalBinOp BO = ConstraintExpr) { 1345ffd83dbSDimitry Andric if (calculateConstraintSatisfaction(S, BO.getLHS(), Satisfaction, 135480093f4SDimitry Andric Evaluator)) 136a7dea167SDimitry Andric return true; 137480093f4SDimitry Andric 138480093f4SDimitry Andric bool IsLHSSatisfied = Satisfaction.IsSatisfied; 139480093f4SDimitry Andric 1405ffd83dbSDimitry Andric if (BO.isOr() && IsLHSSatisfied) 141480093f4SDimitry Andric // [temp.constr.op] p3 142480093f4SDimitry Andric // A disjunction is a constraint taking two operands. To determine if 143480093f4SDimitry Andric // a disjunction is satisfied, the satisfaction of the first operand 144480093f4SDimitry Andric // is checked. If that is satisfied, the disjunction is satisfied. 145480093f4SDimitry Andric // Otherwise, the disjunction is satisfied if and only if the second 146480093f4SDimitry Andric // operand is satisfied. 147a7dea167SDimitry Andric return false; 148480093f4SDimitry Andric 1495ffd83dbSDimitry Andric if (BO.isAnd() && !IsLHSSatisfied) 150480093f4SDimitry Andric // [temp.constr.op] p2 151480093f4SDimitry Andric // A conjunction is a constraint taking two operands. To determine if 152480093f4SDimitry Andric // a conjunction is satisfied, the satisfaction of the first operand 153480093f4SDimitry Andric // is checked. If that is not satisfied, the conjunction is not 154480093f4SDimitry Andric // satisfied. Otherwise, the conjunction is satisfied if and only if 155480093f4SDimitry Andric // the second operand is satisfied. 156a7dea167SDimitry Andric return false; 157480093f4SDimitry Andric 1585ffd83dbSDimitry Andric return calculateConstraintSatisfaction( 1595ffd83dbSDimitry Andric S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator)); 1605ffd83dbSDimitry Andric } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) { 161480093f4SDimitry Andric return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction, 162480093f4SDimitry Andric std::forward<AtomicEvaluator>(Evaluator)); 1635ffd83dbSDimitry Andric } 164480093f4SDimitry Andric 165480093f4SDimitry Andric // An atomic constraint expression 166480093f4SDimitry Andric ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr); 167480093f4SDimitry Andric 168480093f4SDimitry Andric if (SubstitutedAtomicExpr.isInvalid()) 169480093f4SDimitry Andric return true; 170480093f4SDimitry Andric 171480093f4SDimitry Andric if (!SubstitutedAtomicExpr.isUsable()) 172480093f4SDimitry Andric // Evaluator has decided satisfaction without yielding an expression. 173480093f4SDimitry Andric return false; 174a7dea167SDimitry Andric 175a7dea167SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 176480093f4SDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 177a7dea167SDimitry Andric SmallVector<PartialDiagnosticAt, 2> EvaluationDiags; 178a7dea167SDimitry Andric Expr::EvalResult EvalResult; 179a7dea167SDimitry Andric EvalResult.Diag = &EvaluationDiags; 180fe6060f1SDimitry Andric if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult, 181fe6060f1SDimitry Andric S.Context) || 182fe6060f1SDimitry Andric !EvaluationDiags.empty()) { 183a7dea167SDimitry Andric // C++2a [temp.constr.atomic]p1 184a7dea167SDimitry Andric // ...E shall be a constant expression of type bool. 185480093f4SDimitry Andric S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(), 186a7dea167SDimitry Andric diag::err_non_constant_constraint_expression) 187480093f4SDimitry Andric << SubstitutedAtomicExpr.get()->getSourceRange(); 188a7dea167SDimitry Andric for (const PartialDiagnosticAt &PDiag : EvaluationDiags) 189480093f4SDimitry Andric S.Diag(PDiag.first, PDiag.second); 190a7dea167SDimitry Andric return true; 191a7dea167SDimitry Andric } 192a7dea167SDimitry Andric 193fe6060f1SDimitry Andric assert(EvalResult.Val.isInt() && 194fe6060f1SDimitry Andric "evaluating bool expression didn't produce int"); 195480093f4SDimitry Andric Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); 196480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) 197480093f4SDimitry Andric Satisfaction.Details.emplace_back(ConstraintExpr, 198480093f4SDimitry Andric SubstitutedAtomicExpr.get()); 199a7dea167SDimitry Andric 200a7dea167SDimitry Andric return false; 201a7dea167SDimitry Andric } 202480093f4SDimitry Andric 203480093f4SDimitry Andric static bool calculateConstraintSatisfaction( 20413138422SDimitry Andric Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, 205480093f4SDimitry Andric SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL, 206480093f4SDimitry Andric const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) { 207480093f4SDimitry Andric return calculateConstraintSatisfaction( 208480093f4SDimitry Andric S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) { 209480093f4SDimitry Andric EnterExpressionEvaluationContext ConstantEvaluated( 210480093f4SDimitry Andric S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 211480093f4SDimitry Andric 212480093f4SDimitry Andric // Atomic constraint - substitute arguments and check satisfaction. 213480093f4SDimitry Andric ExprResult SubstitutedExpression; 214480093f4SDimitry Andric { 215480093f4SDimitry Andric TemplateDeductionInfo Info(TemplateNameLoc); 216480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(), 21713138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintSubstitution{}, 21813138422SDimitry Andric const_cast<NamedDecl *>(Template), Info, 21913138422SDimitry Andric AtomicExpr->getSourceRange()); 220480093f4SDimitry Andric if (Inst.isInvalid()) 221480093f4SDimitry Andric return ExprError(); 222480093f4SDimitry Andric // We do not want error diagnostics escaping here. 223480093f4SDimitry Andric Sema::SFINAETrap Trap(S); 224480093f4SDimitry Andric SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr), 225480093f4SDimitry Andric MLTAL); 226fe6060f1SDimitry Andric // Substitution might have stripped off a contextual conversion to 227fe6060f1SDimitry Andric // bool if this is the operand of an '&&' or '||'. For example, we 228fe6060f1SDimitry Andric // might lose an lvalue-to-rvalue conversion here. If so, put it back 229fe6060f1SDimitry Andric // before we try to evaluate. 230fe6060f1SDimitry Andric if (!SubstitutedExpression.isInvalid()) 231fe6060f1SDimitry Andric SubstitutedExpression = 232fe6060f1SDimitry Andric S.PerformContextuallyConvertToBool(SubstitutedExpression.get()); 233480093f4SDimitry Andric if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) { 234480093f4SDimitry Andric // C++2a [temp.constr.atomic]p1 235480093f4SDimitry Andric // ...If substitution results in an invalid type or expression, the 236480093f4SDimitry Andric // constraint is not satisfied. 237480093f4SDimitry Andric if (!Trap.hasErrorOccurred()) 238480093f4SDimitry Andric // A non-SFINAE error has occured as a result of this 239480093f4SDimitry Andric // substitution. 240480093f4SDimitry Andric return ExprError(); 241480093f4SDimitry Andric 242480093f4SDimitry Andric PartialDiagnosticAt SubstDiag{SourceLocation(), 243480093f4SDimitry Andric PartialDiagnostic::NullDiagnostic()}; 244480093f4SDimitry Andric Info.takeSFINAEDiagnostic(SubstDiag); 245480093f4SDimitry Andric // FIXME: Concepts: This is an unfortunate consequence of there 246480093f4SDimitry Andric // being no serialization code for PartialDiagnostics and the fact 247480093f4SDimitry Andric // that serializing them would likely take a lot more storage than 248480093f4SDimitry Andric // just storing them as strings. We would still like, in the 249480093f4SDimitry Andric // future, to serialize the proper PartialDiagnostic as serializing 250480093f4SDimitry Andric // it as a string defeats the purpose of the diagnostic mechanism. 251480093f4SDimitry Andric SmallString<128> DiagString; 252480093f4SDimitry Andric DiagString = ": "; 253480093f4SDimitry Andric SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString); 254480093f4SDimitry Andric unsigned MessageSize = DiagString.size(); 255480093f4SDimitry Andric char *Mem = new (S.Context) char[MessageSize]; 256480093f4SDimitry Andric memcpy(Mem, DiagString.c_str(), MessageSize); 257480093f4SDimitry Andric Satisfaction.Details.emplace_back( 258480093f4SDimitry Andric AtomicExpr, 259480093f4SDimitry Andric new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 260480093f4SDimitry Andric SubstDiag.first, StringRef(Mem, MessageSize)}); 261480093f4SDimitry Andric Satisfaction.IsSatisfied = false; 262480093f4SDimitry Andric return ExprEmpty(); 263480093f4SDimitry Andric } 264480093f4SDimitry Andric } 265480093f4SDimitry Andric 266480093f4SDimitry Andric if (!S.CheckConstraintExpression(SubstitutedExpression.get())) 267480093f4SDimitry Andric return ExprError(); 268480093f4SDimitry Andric 269480093f4SDimitry Andric return SubstitutedExpression; 270480093f4SDimitry Andric }); 271480093f4SDimitry Andric } 272480093f4SDimitry Andric 27313138422SDimitry Andric static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, 274480093f4SDimitry Andric ArrayRef<const Expr *> ConstraintExprs, 275480093f4SDimitry Andric ArrayRef<TemplateArgument> TemplateArgs, 276480093f4SDimitry Andric SourceRange TemplateIDRange, 277480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction) { 278480093f4SDimitry Andric if (ConstraintExprs.empty()) { 279480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 280480093f4SDimitry Andric return false; 281480093f4SDimitry Andric } 282480093f4SDimitry Andric 283480093f4SDimitry Andric for (auto& Arg : TemplateArgs) 284480093f4SDimitry Andric if (Arg.isInstantiationDependent()) { 285480093f4SDimitry Andric // No need to check satisfaction for dependent constraint expressions. 286480093f4SDimitry Andric Satisfaction.IsSatisfied = true; 287480093f4SDimitry Andric return false; 288480093f4SDimitry Andric } 289480093f4SDimitry Andric 290480093f4SDimitry Andric Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), 29113138422SDimitry Andric Sema::InstantiatingTemplate::ConstraintsCheck{}, 29213138422SDimitry Andric const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); 293480093f4SDimitry Andric if (Inst.isInvalid()) 294480093f4SDimitry Andric return true; 295480093f4SDimitry Andric 296480093f4SDimitry Andric MultiLevelTemplateArgumentList MLTAL; 297480093f4SDimitry Andric MLTAL.addOuterTemplateArguments(TemplateArgs); 298480093f4SDimitry Andric 299480093f4SDimitry Andric for (const Expr *ConstraintExpr : ConstraintExprs) { 300480093f4SDimitry Andric if (calculateConstraintSatisfaction(S, Template, TemplateArgs, 301480093f4SDimitry Andric TemplateIDRange.getBegin(), MLTAL, 302480093f4SDimitry Andric ConstraintExpr, Satisfaction)) 303480093f4SDimitry Andric return true; 304480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) 305480093f4SDimitry Andric // [temp.constr.op] p2 306480093f4SDimitry Andric // [...] To determine if a conjunction is satisfied, the satisfaction 307480093f4SDimitry Andric // of the first operand is checked. If that is not satisfied, the 308480093f4SDimitry Andric // conjunction is not satisfied. [...] 309480093f4SDimitry Andric return false; 310480093f4SDimitry Andric } 311480093f4SDimitry Andric return false; 312480093f4SDimitry Andric } 313480093f4SDimitry Andric 31455e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction( 31513138422SDimitry Andric const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, 31655e4f9d5SDimitry Andric ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange, 31755e4f9d5SDimitry Andric ConstraintSatisfaction &OutSatisfaction) { 31855e4f9d5SDimitry Andric if (ConstraintExprs.empty()) { 31955e4f9d5SDimitry Andric OutSatisfaction.IsSatisfied = true; 32055e4f9d5SDimitry Andric return false; 321480093f4SDimitry Andric } 322480093f4SDimitry Andric 32355e4f9d5SDimitry Andric llvm::FoldingSetNodeID ID; 32455e4f9d5SDimitry Andric void *InsertPos; 32555e4f9d5SDimitry Andric ConstraintSatisfaction *Satisfaction = nullptr; 32613138422SDimitry Andric bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template; 32713138422SDimitry Andric if (ShouldCache) { 32855e4f9d5SDimitry Andric ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs); 32955e4f9d5SDimitry Andric Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos); 33055e4f9d5SDimitry Andric if (Satisfaction) { 33155e4f9d5SDimitry Andric OutSatisfaction = *Satisfaction; 33255e4f9d5SDimitry Andric return false; 33355e4f9d5SDimitry Andric } 33455e4f9d5SDimitry Andric Satisfaction = new ConstraintSatisfaction(Template, TemplateArgs); 33555e4f9d5SDimitry Andric } else { 33655e4f9d5SDimitry Andric Satisfaction = &OutSatisfaction; 33755e4f9d5SDimitry Andric } 33813138422SDimitry Andric if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, 339480093f4SDimitry Andric TemplateArgs, TemplateIDRange, 34013138422SDimitry Andric *Satisfaction)) { 34113138422SDimitry Andric if (ShouldCache) 34255e4f9d5SDimitry Andric delete Satisfaction; 34355e4f9d5SDimitry Andric return true; 344480093f4SDimitry Andric } 345480093f4SDimitry Andric 34613138422SDimitry Andric if (ShouldCache) { 34755e4f9d5SDimitry Andric // We cannot use InsertNode here because CheckConstraintSatisfaction might 34855e4f9d5SDimitry Andric // have invalidated it. 34955e4f9d5SDimitry Andric SatisfactionCache.InsertNode(Satisfaction); 35055e4f9d5SDimitry Andric OutSatisfaction = *Satisfaction; 35155e4f9d5SDimitry Andric } 35255e4f9d5SDimitry Andric return false; 353480093f4SDimitry Andric } 354480093f4SDimitry Andric 355480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr, 356480093f4SDimitry Andric ConstraintSatisfaction &Satisfaction) { 357480093f4SDimitry Andric return calculateConstraintSatisfaction( 358480093f4SDimitry Andric *this, ConstraintExpr, Satisfaction, 359480093f4SDimitry Andric [](const Expr *AtomicExpr) -> ExprResult { 360480093f4SDimitry Andric return ExprResult(const_cast<Expr *>(AtomicExpr)); 361480093f4SDimitry Andric }); 362480093f4SDimitry Andric } 363480093f4SDimitry Andric 36413138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, 36513138422SDimitry Andric ConstraintSatisfaction &Satisfaction, 36613138422SDimitry Andric SourceLocation UsageLoc) { 36713138422SDimitry Andric const Expr *RC = FD->getTrailingRequiresClause(); 36813138422SDimitry Andric if (RC->isInstantiationDependent()) { 36913138422SDimitry Andric Satisfaction.IsSatisfied = true; 37013138422SDimitry Andric return false; 37113138422SDimitry Andric } 37213138422SDimitry Andric Qualifiers ThisQuals; 37313138422SDimitry Andric CXXRecordDecl *Record = nullptr; 37413138422SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { 37513138422SDimitry Andric ThisQuals = Method->getMethodQualifiers(); 37613138422SDimitry Andric Record = const_cast<CXXRecordDecl *>(Method->getParent()); 37713138422SDimitry Andric } 37813138422SDimitry Andric CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 37913138422SDimitry Andric // We substitute with empty arguments in order to rebuild the atomic 38013138422SDimitry Andric // constraint in a constant-evaluated context. 38113138422SDimitry Andric // FIXME: Should this be a dedicated TreeTransform? 38213138422SDimitry Andric return CheckConstraintSatisfaction( 38313138422SDimitry Andric FD, {RC}, /*TemplateArgs=*/{}, 38413138422SDimitry Andric SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), 38513138422SDimitry Andric Satisfaction); 38613138422SDimitry Andric } 38713138422SDimitry Andric 388480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints( 389480093f4SDimitry Andric TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs, 390480093f4SDimitry Andric SourceRange TemplateIDRange) { 391480093f4SDimitry Andric ConstraintSatisfaction Satisfaction; 392480093f4SDimitry Andric llvm::SmallVector<const Expr *, 3> AssociatedConstraints; 393480093f4SDimitry Andric TD->getAssociatedConstraints(AssociatedConstraints); 394480093f4SDimitry Andric if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs, 395480093f4SDimitry Andric TemplateIDRange, Satisfaction)) 396480093f4SDimitry Andric return true; 397480093f4SDimitry Andric 398480093f4SDimitry Andric if (!Satisfaction.IsSatisfied) { 399480093f4SDimitry Andric SmallString<128> TemplateArgString; 400480093f4SDimitry Andric TemplateArgString = " "; 401480093f4SDimitry Andric TemplateArgString += getTemplateArgumentBindingsText( 402480093f4SDimitry Andric TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size()); 403480093f4SDimitry Andric 404480093f4SDimitry Andric Diag(TemplateIDRange.getBegin(), 405480093f4SDimitry Andric diag::err_template_arg_list_constraints_not_satisfied) 406480093f4SDimitry Andric << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD 407480093f4SDimitry Andric << TemplateArgString << TemplateIDRange; 408480093f4SDimitry Andric DiagnoseUnsatisfiedConstraint(Satisfaction); 409480093f4SDimitry Andric return true; 410480093f4SDimitry Andric } 411480093f4SDimitry Andric return false; 412480093f4SDimitry Andric } 413480093f4SDimitry Andric 41455e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 41555e4f9d5SDimitry Andric concepts::ExprRequirement *Req, 41655e4f9d5SDimitry Andric bool First) { 41755e4f9d5SDimitry Andric assert(!Req->isSatisfied() 41855e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 41955e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 42055e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Dependent: 42155e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 42255e4f9d5SDimitry Andric break; 42355e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ExprSubstitutionFailure: { 42455e4f9d5SDimitry Andric auto *SubstDiag = Req->getExprSubstitutionDiagnostic(); 42555e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 42655e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 42755e4f9d5SDimitry Andric diag::note_expr_requirement_expr_substitution_error) 42855e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 42955e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 43055e4f9d5SDimitry Andric else 43155e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 43255e4f9d5SDimitry Andric diag::note_expr_requirement_expr_unknown_substitution_error) 43355e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 43455e4f9d5SDimitry Andric break; 43555e4f9d5SDimitry Andric } 43655e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_NoexceptNotMet: 43755e4f9d5SDimitry Andric S.Diag(Req->getNoexceptLoc(), 43855e4f9d5SDimitry Andric diag::note_expr_requirement_noexcept_not_met) 43955e4f9d5SDimitry Andric << (int)First << Req->getExpr(); 44055e4f9d5SDimitry Andric break; 44155e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: { 44255e4f9d5SDimitry Andric auto *SubstDiag = 44355e4f9d5SDimitry Andric Req->getReturnTypeRequirement().getSubstitutionDiagnostic(); 44455e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 44555e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 44655e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_substitution_error) 44755e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 44855e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 44955e4f9d5SDimitry Andric else 45055e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 45155e4f9d5SDimitry Andric diag::note_expr_requirement_type_requirement_unknown_substitution_error) 45255e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 45355e4f9d5SDimitry Andric break; 45455e4f9d5SDimitry Andric } 45555e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { 45655e4f9d5SDimitry Andric ConceptSpecializationExpr *ConstraintExpr = 45755e4f9d5SDimitry Andric Req->getReturnTypeRequirementSubstitutedConstraintExpr(); 458fe6060f1SDimitry Andric if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 45955e4f9d5SDimitry Andric // A simple case - expr type is the type being constrained and the concept 46055e4f9d5SDimitry Andric // was not provided arguments. 461fe6060f1SDimitry Andric Expr *e = Req->getExpr(); 462fe6060f1SDimitry Andric S.Diag(e->getBeginLoc(), 46355e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied_simple) 464fe6060f1SDimitry Andric << (int)First << S.getDecltypeForParenthesizedExpr(e) 46555e4f9d5SDimitry Andric << ConstraintExpr->getNamedConcept(); 466fe6060f1SDimitry Andric } else { 46755e4f9d5SDimitry Andric S.Diag(ConstraintExpr->getBeginLoc(), 46855e4f9d5SDimitry Andric diag::note_expr_requirement_constraints_not_satisfied) 46955e4f9d5SDimitry Andric << (int)First << ConstraintExpr; 470fe6060f1SDimitry Andric } 47155e4f9d5SDimitry Andric S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); 47255e4f9d5SDimitry Andric break; 47355e4f9d5SDimitry Andric } 47455e4f9d5SDimitry Andric case concepts::ExprRequirement::SS_Satisfied: 47555e4f9d5SDimitry Andric llvm_unreachable("We checked this above"); 47655e4f9d5SDimitry Andric } 47755e4f9d5SDimitry Andric } 47855e4f9d5SDimitry Andric 47955e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 48055e4f9d5SDimitry Andric concepts::TypeRequirement *Req, 48155e4f9d5SDimitry Andric bool First) { 48255e4f9d5SDimitry Andric assert(!Req->isSatisfied() 48355e4f9d5SDimitry Andric && "Diagnose() can only be used on an unsatisfied requirement"); 48455e4f9d5SDimitry Andric switch (Req->getSatisfactionStatus()) { 48555e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_Dependent: 48655e4f9d5SDimitry Andric llvm_unreachable("Diagnosing a dependent requirement"); 48755e4f9d5SDimitry Andric return; 48855e4f9d5SDimitry Andric case concepts::TypeRequirement::SS_SubstitutionFailure: { 48955e4f9d5SDimitry Andric auto *SubstDiag = Req->getSubstitutionDiagnostic(); 49055e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 49155e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 49255e4f9d5SDimitry Andric diag::note_type_requirement_substitution_error) << (int)First 49355e4f9d5SDimitry Andric << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage; 49455e4f9d5SDimitry Andric else 49555e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 49655e4f9d5SDimitry Andric diag::note_type_requirement_unknown_substitution_error) 49755e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 49855e4f9d5SDimitry Andric return; 49955e4f9d5SDimitry Andric } 50055e4f9d5SDimitry Andric default: 50155e4f9d5SDimitry Andric llvm_unreachable("Unknown satisfaction status"); 50255e4f9d5SDimitry Andric return; 50355e4f9d5SDimitry Andric } 50455e4f9d5SDimitry Andric } 50555e4f9d5SDimitry Andric 50655e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S, 50755e4f9d5SDimitry Andric concepts::NestedRequirement *Req, 50855e4f9d5SDimitry Andric bool First) { 50955e4f9d5SDimitry Andric if (Req->isSubstitutionFailure()) { 51055e4f9d5SDimitry Andric concepts::Requirement::SubstitutionDiagnostic *SubstDiag = 51155e4f9d5SDimitry Andric Req->getSubstitutionDiagnostic(); 51255e4f9d5SDimitry Andric if (!SubstDiag->DiagMessage.empty()) 51355e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 51455e4f9d5SDimitry Andric diag::note_nested_requirement_substitution_error) 51555e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity 51655e4f9d5SDimitry Andric << SubstDiag->DiagMessage; 51755e4f9d5SDimitry Andric else 51855e4f9d5SDimitry Andric S.Diag(SubstDiag->DiagLoc, 51955e4f9d5SDimitry Andric diag::note_nested_requirement_unknown_substitution_error) 52055e4f9d5SDimitry Andric << (int)First << SubstDiag->SubstitutedEntity; 52155e4f9d5SDimitry Andric return; 52255e4f9d5SDimitry Andric } 52355e4f9d5SDimitry Andric S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First); 52455e4f9d5SDimitry Andric } 52555e4f9d5SDimitry Andric 52655e4f9d5SDimitry Andric 527480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 528480093f4SDimitry Andric Expr *SubstExpr, 529480093f4SDimitry Andric bool First = true) { 530480093f4SDimitry Andric SubstExpr = SubstExpr->IgnoreParenImpCasts(); 531480093f4SDimitry Andric if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) { 532480093f4SDimitry Andric switch (BO->getOpcode()) { 533480093f4SDimitry Andric // These two cases will in practice only be reached when using fold 534480093f4SDimitry Andric // expressions with || and &&, since otherwise the || and && will have been 535480093f4SDimitry Andric // broken down into atomic constraints during satisfaction checking. 536480093f4SDimitry Andric case BO_LOr: 537480093f4SDimitry Andric // Or evaluated to false - meaning both RHS and LHS evaluated to false. 538480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 539480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 540480093f4SDimitry Andric /*First=*/false); 541480093f4SDimitry Andric return; 542fe6060f1SDimitry Andric case BO_LAnd: { 543fe6060f1SDimitry Andric bool LHSSatisfied = 544fe6060f1SDimitry Andric BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 545480093f4SDimitry Andric if (LHSSatisfied) { 546480093f4SDimitry Andric // LHS is true, so RHS must be false. 547480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First); 548480093f4SDimitry Andric return; 549480093f4SDimitry Andric } 550480093f4SDimitry Andric // LHS is false 551480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 552480093f4SDimitry Andric 553480093f4SDimitry Andric // RHS might also be false 554fe6060f1SDimitry Andric bool RHSSatisfied = 555fe6060f1SDimitry Andric BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 556480093f4SDimitry Andric if (!RHSSatisfied) 557480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 558480093f4SDimitry Andric /*First=*/false); 559480093f4SDimitry Andric return; 560fe6060f1SDimitry Andric } 561480093f4SDimitry Andric case BO_GE: 562480093f4SDimitry Andric case BO_LE: 563480093f4SDimitry Andric case BO_GT: 564480093f4SDimitry Andric case BO_LT: 565480093f4SDimitry Andric case BO_EQ: 566480093f4SDimitry Andric case BO_NE: 567480093f4SDimitry Andric if (BO->getLHS()->getType()->isIntegerType() && 568480093f4SDimitry Andric BO->getRHS()->getType()->isIntegerType()) { 569480093f4SDimitry Andric Expr::EvalResult SimplifiedLHS; 570480093f4SDimitry Andric Expr::EvalResult SimplifiedRHS; 571fe6060f1SDimitry Andric BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context, 572fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 573fe6060f1SDimitry Andric /*InConstantContext=*/true); 574fe6060f1SDimitry Andric BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context, 575fe6060f1SDimitry Andric Expr::SE_NoSideEffects, 576fe6060f1SDimitry Andric /*InConstantContext=*/true); 577480093f4SDimitry Andric if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) { 578480093f4SDimitry Andric S.Diag(SubstExpr->getBeginLoc(), 579480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false_elaborated) 580480093f4SDimitry Andric << (int)First << SubstExpr 581fe6060f1SDimitry Andric << toString(SimplifiedLHS.Val.getInt(), 10) 582480093f4SDimitry Andric << BinaryOperator::getOpcodeStr(BO->getOpcode()) 583fe6060f1SDimitry Andric << toString(SimplifiedRHS.Val.getInt(), 10); 584480093f4SDimitry Andric return; 585480093f4SDimitry Andric } 586480093f4SDimitry Andric } 587480093f4SDimitry Andric break; 588480093f4SDimitry Andric 589480093f4SDimitry Andric default: 590480093f4SDimitry Andric break; 591480093f4SDimitry Andric } 592480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) { 593480093f4SDimitry Andric if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 594480093f4SDimitry Andric S.Diag( 595480093f4SDimitry Andric CSE->getSourceRange().getBegin(), 596480093f4SDimitry Andric diag:: 597480093f4SDimitry Andric note_single_arg_concept_specialization_constraint_evaluated_to_false) 598480093f4SDimitry Andric << (int)First 599480093f4SDimitry Andric << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument() 600480093f4SDimitry Andric << CSE->getNamedConcept(); 601480093f4SDimitry Andric } else { 602480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 603480093f4SDimitry Andric diag::note_concept_specialization_constraint_evaluated_to_false) 604480093f4SDimitry Andric << (int)First << CSE; 605480093f4SDimitry Andric } 606480093f4SDimitry Andric S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction()); 607480093f4SDimitry Andric return; 60855e4f9d5SDimitry Andric } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) { 60955e4f9d5SDimitry Andric for (concepts::Requirement *Req : RE->getRequirements()) 61055e4f9d5SDimitry Andric if (!Req->isDependent() && !Req->isSatisfied()) { 61155e4f9d5SDimitry Andric if (auto *E = dyn_cast<concepts::ExprRequirement>(Req)) 61255e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, E, First); 61355e4f9d5SDimitry Andric else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req)) 61455e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement(S, T, First); 61555e4f9d5SDimitry Andric else 61655e4f9d5SDimitry Andric diagnoseUnsatisfiedRequirement( 61755e4f9d5SDimitry Andric S, cast<concepts::NestedRequirement>(Req), First); 61855e4f9d5SDimitry Andric break; 61955e4f9d5SDimitry Andric } 62055e4f9d5SDimitry Andric return; 621480093f4SDimitry Andric } 622480093f4SDimitry Andric 623480093f4SDimitry Andric S.Diag(SubstExpr->getSourceRange().getBegin(), 624480093f4SDimitry Andric diag::note_atomic_constraint_evaluated_to_false) 625480093f4SDimitry Andric << (int)First << SubstExpr; 626480093f4SDimitry Andric } 627480093f4SDimitry Andric 628480093f4SDimitry Andric template<typename SubstitutionDiagnostic> 629480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr( 630480093f4SDimitry Andric Sema &S, const Expr *E, 631480093f4SDimitry Andric const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record, 632480093f4SDimitry Andric bool First = true) { 633480093f4SDimitry Andric if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){ 634480093f4SDimitry Andric S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed) 635480093f4SDimitry Andric << Diag->second; 636480093f4SDimitry Andric return; 637480093f4SDimitry Andric } 638480093f4SDimitry Andric 639480093f4SDimitry Andric diagnoseWellFormedUnsatisfiedConstraintExpr(S, 640480093f4SDimitry Andric Record.template get<Expr *>(), First); 641480093f4SDimitry Andric } 642480093f4SDimitry Andric 64355e4f9d5SDimitry Andric void 64455e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, 64555e4f9d5SDimitry Andric bool First) { 646480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 647480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 648480093f4SDimitry Andric for (auto &Pair : Satisfaction.Details) { 649480093f4SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); 650480093f4SDimitry Andric First = false; 651480093f4SDimitry Andric } 652480093f4SDimitry Andric } 653480093f4SDimitry Andric 654480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint( 65555e4f9d5SDimitry Andric const ASTConstraintSatisfaction &Satisfaction, 65655e4f9d5SDimitry Andric bool First) { 657480093f4SDimitry Andric assert(!Satisfaction.IsSatisfied && 658480093f4SDimitry Andric "Attempted to diagnose a satisfied constraint"); 659480093f4SDimitry Andric for (auto &Pair : Satisfaction) { 660480093f4SDimitry Andric diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); 661480093f4SDimitry Andric First = false; 662480093f4SDimitry Andric } 663480093f4SDimitry Andric } 664480093f4SDimitry Andric 665480093f4SDimitry Andric const NormalizedConstraint * 666480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints( 667480093f4SDimitry Andric NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) { 668480093f4SDimitry Andric auto CacheEntry = NormalizationCache.find(ConstrainedDecl); 669480093f4SDimitry Andric if (CacheEntry == NormalizationCache.end()) { 670480093f4SDimitry Andric auto Normalized = 671480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl, 672480093f4SDimitry Andric AssociatedConstraints); 673480093f4SDimitry Andric CacheEntry = 674480093f4SDimitry Andric NormalizationCache 675480093f4SDimitry Andric .try_emplace(ConstrainedDecl, 676480093f4SDimitry Andric Normalized 677480093f4SDimitry Andric ? new (Context) NormalizedConstraint( 678480093f4SDimitry Andric std::move(*Normalized)) 679480093f4SDimitry Andric : nullptr) 680480093f4SDimitry Andric .first; 681480093f4SDimitry Andric } 682480093f4SDimitry Andric return CacheEntry->second; 683480093f4SDimitry Andric } 684480093f4SDimitry Andric 685480093f4SDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, 686480093f4SDimitry Andric ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs, 687480093f4SDimitry Andric const ASTTemplateArgumentListInfo *ArgsAsWritten) { 688480093f4SDimitry Andric if (!N.isAtomic()) { 689480093f4SDimitry Andric if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs, 690480093f4SDimitry Andric ArgsAsWritten)) 691480093f4SDimitry Andric return true; 692480093f4SDimitry Andric return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs, 693480093f4SDimitry Andric ArgsAsWritten); 694480093f4SDimitry Andric } 695480093f4SDimitry Andric TemplateParameterList *TemplateParams = Concept->getTemplateParameters(); 696480093f4SDimitry Andric 697480093f4SDimitry Andric AtomicConstraint &Atomic = *N.getAtomicConstraint(); 698480093f4SDimitry Andric TemplateArgumentListInfo SubstArgs; 699480093f4SDimitry Andric MultiLevelTemplateArgumentList MLTAL; 700480093f4SDimitry Andric MLTAL.addOuterTemplateArguments(TemplateArgs); 701480093f4SDimitry Andric if (!Atomic.ParameterMapping) { 702480093f4SDimitry Andric llvm::SmallBitVector OccurringIndices(TemplateParams->size()); 703480093f4SDimitry Andric S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false, 704480093f4SDimitry Andric /*Depth=*/0, OccurringIndices); 705480093f4SDimitry Andric Atomic.ParameterMapping.emplace( 706480093f4SDimitry Andric MutableArrayRef<TemplateArgumentLoc>( 707480093f4SDimitry Andric new (S.Context) TemplateArgumentLoc[OccurringIndices.count()], 708480093f4SDimitry Andric OccurringIndices.count())); 709480093f4SDimitry Andric for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) 710480093f4SDimitry Andric if (OccurringIndices[I]) 711480093f4SDimitry Andric new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc( 712480093f4SDimitry Andric S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I], 713480093f4SDimitry Andric // Here we assume we do not support things like 714480093f4SDimitry Andric // template<typename A, typename B> 715480093f4SDimitry Andric // concept C = ...; 716480093f4SDimitry Andric // 717480093f4SDimitry Andric // template<typename... Ts> requires C<Ts...> 718480093f4SDimitry Andric // struct S { }; 719480093f4SDimitry Andric // The above currently yields a diagnostic. 720480093f4SDimitry Andric // We still might have default arguments for concept parameters. 721480093f4SDimitry Andric ArgsAsWritten->NumTemplateArgs > I ? 722480093f4SDimitry Andric ArgsAsWritten->arguments()[I].getLocation() : 723480093f4SDimitry Andric SourceLocation())); 724480093f4SDimitry Andric } 725480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 726480093f4SDimitry Andric S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(), 727480093f4SDimitry Andric Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, 728480093f4SDimitry Andric SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(), 729480093f4SDimitry Andric ArgsAsWritten->arguments().back().getSourceRange().getEnd())); 730480093f4SDimitry Andric if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) 731480093f4SDimitry Andric return true; 73213138422SDimitry Andric Atomic.ParameterMapping.emplace( 73313138422SDimitry Andric MutableArrayRef<TemplateArgumentLoc>( 73413138422SDimitry Andric new (S.Context) TemplateArgumentLoc[SubstArgs.size()], 73513138422SDimitry Andric SubstArgs.size())); 736480093f4SDimitry Andric std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(), 737480093f4SDimitry Andric N.getAtomicConstraint()->ParameterMapping->begin()); 738480093f4SDimitry Andric return false; 739480093f4SDimitry Andric } 740480093f4SDimitry Andric 741480093f4SDimitry Andric Optional<NormalizedConstraint> 742480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D, 743480093f4SDimitry Andric ArrayRef<const Expr *> E) { 744480093f4SDimitry Andric assert(E.size() != 0); 745*6e75b2fbSDimitry Andric auto Conjunction = fromConstraintExpr(S, D, E[0]); 746*6e75b2fbSDimitry Andric if (!Conjunction) 747480093f4SDimitry Andric return None; 748*6e75b2fbSDimitry Andric for (unsigned I = 1; I < E.size(); ++I) { 749480093f4SDimitry Andric auto Next = fromConstraintExpr(S, D, E[I]); 750480093f4SDimitry Andric if (!Next) 751*6e75b2fbSDimitry Andric return None; 752*6e75b2fbSDimitry Andric *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction), 753480093f4SDimitry Andric std::move(*Next), CCK_Conjunction); 754480093f4SDimitry Andric } 755480093f4SDimitry Andric return Conjunction; 756480093f4SDimitry Andric } 757480093f4SDimitry Andric 758480093f4SDimitry Andric llvm::Optional<NormalizedConstraint> 759480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) { 760480093f4SDimitry Andric assert(E != nullptr); 761480093f4SDimitry Andric 762480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 763480093f4SDimitry Andric // [...] 764480093f4SDimitry Andric // - The normal form of an expression (E) is the normal form of E. 765480093f4SDimitry Andric // [...] 766480093f4SDimitry Andric E = E->IgnoreParenImpCasts(); 7675ffd83dbSDimitry Andric if (LogicalBinOp BO = E) { 7685ffd83dbSDimitry Andric auto LHS = fromConstraintExpr(S, D, BO.getLHS()); 769480093f4SDimitry Andric if (!LHS) 770480093f4SDimitry Andric return None; 7715ffd83dbSDimitry Andric auto RHS = fromConstraintExpr(S, D, BO.getRHS()); 772480093f4SDimitry Andric if (!RHS) 773480093f4SDimitry Andric return None; 774480093f4SDimitry Andric 7755ffd83dbSDimitry Andric return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS), 7765ffd83dbSDimitry Andric BO.isAnd() ? CCK_Conjunction : CCK_Disjunction); 777480093f4SDimitry Andric } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) { 778480093f4SDimitry Andric const NormalizedConstraint *SubNF; 779480093f4SDimitry Andric { 780480093f4SDimitry Andric Sema::InstantiatingTemplate Inst( 781480093f4SDimitry Andric S, CSE->getExprLoc(), 782480093f4SDimitry Andric Sema::InstantiatingTemplate::ConstraintNormalization{}, D, 783480093f4SDimitry Andric CSE->getSourceRange()); 784480093f4SDimitry Andric // C++ [temp.constr.normal]p1.1 785480093f4SDimitry Andric // [...] 786480093f4SDimitry Andric // The normal form of an id-expression of the form C<A1, A2, ..., AN>, 787480093f4SDimitry Andric // where C names a concept, is the normal form of the 788480093f4SDimitry Andric // constraint-expression of C, after substituting A1, A2, ..., AN for C’s 789480093f4SDimitry Andric // respective template parameters in the parameter mappings in each atomic 790480093f4SDimitry Andric // constraint. If any such substitution results in an invalid type or 791480093f4SDimitry Andric // expression, the program is ill-formed; no diagnostic is required. 792480093f4SDimitry Andric // [...] 793480093f4SDimitry Andric ConceptDecl *CD = CSE->getNamedConcept(); 794480093f4SDimitry Andric SubNF = S.getNormalizedAssociatedConstraints(CD, 795480093f4SDimitry Andric {CD->getConstraintExpr()}); 796480093f4SDimitry Andric if (!SubNF) 797480093f4SDimitry Andric return None; 798480093f4SDimitry Andric } 799480093f4SDimitry Andric 800480093f4SDimitry Andric Optional<NormalizedConstraint> New; 801480093f4SDimitry Andric New.emplace(S.Context, *SubNF); 802480093f4SDimitry Andric 803480093f4SDimitry Andric if (substituteParameterMappings( 804480093f4SDimitry Andric S, *New, CSE->getNamedConcept(), 805480093f4SDimitry Andric CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten())) 806480093f4SDimitry Andric return None; 807480093f4SDimitry Andric 808480093f4SDimitry Andric return New; 809480093f4SDimitry Andric } 810480093f4SDimitry Andric return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)}; 811480093f4SDimitry Andric } 812480093f4SDimitry Andric 813480093f4SDimitry Andric using NormalForm = 814480093f4SDimitry Andric llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>; 815480093f4SDimitry Andric 816480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) { 817480093f4SDimitry Andric if (Normalized.isAtomic()) 818480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 819480093f4SDimitry Andric 820480093f4SDimitry Andric NormalForm LCNF = makeCNF(Normalized.getLHS()); 821480093f4SDimitry Andric NormalForm RCNF = makeCNF(Normalized.getRHS()); 822480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) { 823480093f4SDimitry Andric LCNF.reserve(LCNF.size() + RCNF.size()); 824480093f4SDimitry Andric while (!RCNF.empty()) 825480093f4SDimitry Andric LCNF.push_back(RCNF.pop_back_val()); 826480093f4SDimitry Andric return LCNF; 827480093f4SDimitry Andric } 828480093f4SDimitry Andric 829480093f4SDimitry Andric // Disjunction 830480093f4SDimitry Andric NormalForm Res; 831480093f4SDimitry Andric Res.reserve(LCNF.size() * RCNF.size()); 832480093f4SDimitry Andric for (auto &LDisjunction : LCNF) 833480093f4SDimitry Andric for (auto &RDisjunction : RCNF) { 834480093f4SDimitry Andric NormalForm::value_type Combined; 835480093f4SDimitry Andric Combined.reserve(LDisjunction.size() + RDisjunction.size()); 836480093f4SDimitry Andric std::copy(LDisjunction.begin(), LDisjunction.end(), 837480093f4SDimitry Andric std::back_inserter(Combined)); 838480093f4SDimitry Andric std::copy(RDisjunction.begin(), RDisjunction.end(), 839480093f4SDimitry Andric std::back_inserter(Combined)); 840480093f4SDimitry Andric Res.emplace_back(Combined); 841480093f4SDimitry Andric } 842480093f4SDimitry Andric return Res; 843480093f4SDimitry Andric } 844480093f4SDimitry Andric 845480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) { 846480093f4SDimitry Andric if (Normalized.isAtomic()) 847480093f4SDimitry Andric return {{Normalized.getAtomicConstraint()}}; 848480093f4SDimitry Andric 849480093f4SDimitry Andric NormalForm LDNF = makeDNF(Normalized.getLHS()); 850480093f4SDimitry Andric NormalForm RDNF = makeDNF(Normalized.getRHS()); 851480093f4SDimitry Andric if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) { 852480093f4SDimitry Andric LDNF.reserve(LDNF.size() + RDNF.size()); 853480093f4SDimitry Andric while (!RDNF.empty()) 854480093f4SDimitry Andric LDNF.push_back(RDNF.pop_back_val()); 855480093f4SDimitry Andric return LDNF; 856480093f4SDimitry Andric } 857480093f4SDimitry Andric 858480093f4SDimitry Andric // Conjunction 859480093f4SDimitry Andric NormalForm Res; 860480093f4SDimitry Andric Res.reserve(LDNF.size() * RDNF.size()); 861480093f4SDimitry Andric for (auto &LConjunction : LDNF) { 862480093f4SDimitry Andric for (auto &RConjunction : RDNF) { 863480093f4SDimitry Andric NormalForm::value_type Combined; 864480093f4SDimitry Andric Combined.reserve(LConjunction.size() + RConjunction.size()); 865480093f4SDimitry Andric std::copy(LConjunction.begin(), LConjunction.end(), 866480093f4SDimitry Andric std::back_inserter(Combined)); 867480093f4SDimitry Andric std::copy(RConjunction.begin(), RConjunction.end(), 868480093f4SDimitry Andric std::back_inserter(Combined)); 869480093f4SDimitry Andric Res.emplace_back(Combined); 870480093f4SDimitry Andric } 871480093f4SDimitry Andric } 872480093f4SDimitry Andric return Res; 873480093f4SDimitry Andric } 874480093f4SDimitry Andric 875480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator> 876480093f4SDimitry Andric static bool subsumes(NormalForm PDNF, NormalForm QCNF, 877480093f4SDimitry Andric AtomicSubsumptionEvaluator E) { 878480093f4SDimitry Andric // C++ [temp.constr.order] p2 879480093f4SDimitry Andric // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the 880480093f4SDimitry Andric // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in 881480093f4SDimitry Andric // the conjuctive normal form of Q, where [...] 882480093f4SDimitry Andric for (const auto &Pi : PDNF) { 883480093f4SDimitry Andric for (const auto &Qj : QCNF) { 884480093f4SDimitry Andric // C++ [temp.constr.order] p2 885480093f4SDimitry Andric // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if 886480093f4SDimitry Andric // and only if there exists an atomic constraint Pia in Pi for which 887480093f4SDimitry Andric // there exists an atomic constraint, Qjb, in Qj such that Pia 888480093f4SDimitry Andric // subsumes Qjb. 889480093f4SDimitry Andric bool Found = false; 890480093f4SDimitry Andric for (const AtomicConstraint *Pia : Pi) { 891480093f4SDimitry Andric for (const AtomicConstraint *Qjb : Qj) { 892480093f4SDimitry Andric if (E(*Pia, *Qjb)) { 893480093f4SDimitry Andric Found = true; 894480093f4SDimitry Andric break; 895480093f4SDimitry Andric } 896480093f4SDimitry Andric } 897480093f4SDimitry Andric if (Found) 898480093f4SDimitry Andric break; 899480093f4SDimitry Andric } 900480093f4SDimitry Andric if (!Found) 901480093f4SDimitry Andric return false; 902480093f4SDimitry Andric } 903480093f4SDimitry Andric } 904480093f4SDimitry Andric return true; 905480093f4SDimitry Andric } 906480093f4SDimitry Andric 907480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator> 908480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P, 909480093f4SDimitry Andric NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes, 910480093f4SDimitry Andric AtomicSubsumptionEvaluator E) { 911480093f4SDimitry Andric // C++ [temp.constr.order] p2 912480093f4SDimitry Andric // In order to determine if a constraint P subsumes a constraint Q, P is 913480093f4SDimitry Andric // transformed into disjunctive normal form, and Q is transformed into 914480093f4SDimitry Andric // conjunctive normal form. [...] 915480093f4SDimitry Andric auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P); 916480093f4SDimitry Andric if (!PNormalized) 917480093f4SDimitry Andric return true; 918480093f4SDimitry Andric const NormalForm PDNF = makeDNF(*PNormalized); 919480093f4SDimitry Andric 920480093f4SDimitry Andric auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q); 921480093f4SDimitry Andric if (!QNormalized) 922480093f4SDimitry Andric return true; 923480093f4SDimitry Andric const NormalForm QCNF = makeCNF(*QNormalized); 924480093f4SDimitry Andric 925480093f4SDimitry Andric Subsumes = subsumes(PDNF, QCNF, E); 926480093f4SDimitry Andric return false; 927480093f4SDimitry Andric } 928480093f4SDimitry Andric 929480093f4SDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1, 930480093f4SDimitry Andric NamedDecl *D2, ArrayRef<const Expr *> AC2, 931480093f4SDimitry Andric bool &Result) { 932480093f4SDimitry Andric if (AC1.empty()) { 933480093f4SDimitry Andric Result = AC2.empty(); 934480093f4SDimitry Andric return false; 935480093f4SDimitry Andric } 936480093f4SDimitry Andric if (AC2.empty()) { 937480093f4SDimitry Andric // TD1 has associated constraints and TD2 does not. 938480093f4SDimitry Andric Result = true; 939480093f4SDimitry Andric return false; 940480093f4SDimitry Andric } 941480093f4SDimitry Andric 942480093f4SDimitry Andric std::pair<NamedDecl *, NamedDecl *> Key{D1, D2}; 943480093f4SDimitry Andric auto CacheEntry = SubsumptionCache.find(Key); 944480093f4SDimitry Andric if (CacheEntry != SubsumptionCache.end()) { 945480093f4SDimitry Andric Result = CacheEntry->second; 946480093f4SDimitry Andric return false; 947480093f4SDimitry Andric } 948480093f4SDimitry Andric 949480093f4SDimitry Andric if (subsumes(*this, D1, AC1, D2, AC2, Result, 950480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 951480093f4SDimitry Andric return A.subsumes(Context, B); 952480093f4SDimitry Andric })) 953480093f4SDimitry Andric return true; 954480093f4SDimitry Andric SubsumptionCache.try_emplace(Key, Result); 955480093f4SDimitry Andric return false; 956480093f4SDimitry Andric } 957480093f4SDimitry Andric 958480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, 959480093f4SDimitry Andric ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) { 960480093f4SDimitry Andric if (isSFINAEContext()) 961480093f4SDimitry Andric // No need to work here because our notes would be discarded. 962480093f4SDimitry Andric return false; 963480093f4SDimitry Andric 964480093f4SDimitry Andric if (AC1.empty() || AC2.empty()) 965480093f4SDimitry Andric return false; 966480093f4SDimitry Andric 967480093f4SDimitry Andric auto NormalExprEvaluator = 968480093f4SDimitry Andric [this] (const AtomicConstraint &A, const AtomicConstraint &B) { 969480093f4SDimitry Andric return A.subsumes(Context, B); 970480093f4SDimitry Andric }; 971480093f4SDimitry Andric 972480093f4SDimitry Andric const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr; 973480093f4SDimitry Andric auto IdenticalExprEvaluator = 974480093f4SDimitry Andric [&] (const AtomicConstraint &A, const AtomicConstraint &B) { 975480093f4SDimitry Andric if (!A.hasMatchingParameterMapping(Context, B)) 976480093f4SDimitry Andric return false; 977480093f4SDimitry Andric const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr; 978480093f4SDimitry Andric if (EA == EB) 979480093f4SDimitry Andric return true; 980480093f4SDimitry Andric 981480093f4SDimitry Andric // Not the same source level expression - are the expressions 982480093f4SDimitry Andric // identical? 983480093f4SDimitry Andric llvm::FoldingSetNodeID IDA, IDB; 984480093f4SDimitry Andric EA->Profile(IDA, Context, /*Cannonical=*/true); 985480093f4SDimitry Andric EB->Profile(IDB, Context, /*Cannonical=*/true); 986480093f4SDimitry Andric if (IDA != IDB) 987480093f4SDimitry Andric return false; 988480093f4SDimitry Andric 989480093f4SDimitry Andric AmbiguousAtomic1 = EA; 990480093f4SDimitry Andric AmbiguousAtomic2 = EB; 991480093f4SDimitry Andric return true; 992480093f4SDimitry Andric }; 993480093f4SDimitry Andric 994480093f4SDimitry Andric { 995480093f4SDimitry Andric // The subsumption checks might cause diagnostics 996480093f4SDimitry Andric SFINAETrap Trap(*this); 997480093f4SDimitry Andric auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1); 998480093f4SDimitry Andric if (!Normalized1) 999480093f4SDimitry Andric return false; 1000480093f4SDimitry Andric const NormalForm DNF1 = makeDNF(*Normalized1); 1001480093f4SDimitry Andric const NormalForm CNF1 = makeCNF(*Normalized1); 1002480093f4SDimitry Andric 1003480093f4SDimitry Andric auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2); 1004480093f4SDimitry Andric if (!Normalized2) 1005480093f4SDimitry Andric return false; 1006480093f4SDimitry Andric const NormalForm DNF2 = makeDNF(*Normalized2); 1007480093f4SDimitry Andric const NormalForm CNF2 = makeCNF(*Normalized2); 1008480093f4SDimitry Andric 1009480093f4SDimitry Andric bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator); 1010480093f4SDimitry Andric bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator); 1011480093f4SDimitry Andric bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator); 1012480093f4SDimitry Andric bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator); 1013480093f4SDimitry Andric if (Is1AtLeastAs2 == Is1AtLeastAs2Normally && 1014480093f4SDimitry Andric Is2AtLeastAs1 == Is2AtLeastAs1Normally) 1015480093f4SDimitry Andric // Same result - no ambiguity was caused by identical atomic expressions. 1016480093f4SDimitry Andric return false; 1017480093f4SDimitry Andric } 1018480093f4SDimitry Andric 1019480093f4SDimitry Andric // A different result! Some ambiguous atomic constraint(s) caused a difference 1020480093f4SDimitry Andric assert(AmbiguousAtomic1 && AmbiguousAtomic2); 1021480093f4SDimitry Andric 1022480093f4SDimitry Andric Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints) 1023480093f4SDimitry Andric << AmbiguousAtomic1->getSourceRange(); 1024480093f4SDimitry Andric Diag(AmbiguousAtomic2->getBeginLoc(), 1025480093f4SDimitry Andric diag::note_ambiguous_atomic_constraints_similar_expression) 1026480093f4SDimitry Andric << AmbiguousAtomic2->getSourceRange(); 1027480093f4SDimitry Andric return true; 1028480093f4SDimitry Andric } 102955e4f9d5SDimitry Andric 103055e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 103155e4f9d5SDimitry Andric Expr *E, bool IsSimple, SourceLocation NoexceptLoc, 103255e4f9d5SDimitry Andric ReturnTypeRequirement Req, SatisfactionStatus Status, 103355e4f9d5SDimitry Andric ConceptSpecializationExpr *SubstitutedConstraintExpr) : 103455e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, 103555e4f9d5SDimitry Andric Status == SS_Dependent && 103655e4f9d5SDimitry Andric (E->containsUnexpandedParameterPack() || 103755e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack()), 103855e4f9d5SDimitry Andric Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc), 103955e4f9d5SDimitry Andric TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr), 104055e4f9d5SDimitry Andric Status(Status) { 104155e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 104255e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 104355e4f9d5SDimitry Andric "noexcept specification"); 104455e4f9d5SDimitry Andric assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == 104555e4f9d5SDimitry Andric (SubstitutedConstraintExpr != nullptr)); 104655e4f9d5SDimitry Andric } 104755e4f9d5SDimitry Andric 104855e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement( 104955e4f9d5SDimitry Andric SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, 105055e4f9d5SDimitry Andric SourceLocation NoexceptLoc, ReturnTypeRequirement Req) : 105155e4f9d5SDimitry Andric Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), 105255e4f9d5SDimitry Andric Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), 105355e4f9d5SDimitry Andric Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), 105455e4f9d5SDimitry Andric Status(SS_ExprSubstitutionFailure) { 105555e4f9d5SDimitry Andric assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 105655e4f9d5SDimitry Andric "Simple requirement must not have a return type requirement or a " 105755e4f9d5SDimitry Andric "noexcept specification"); 105855e4f9d5SDimitry Andric } 105955e4f9d5SDimitry Andric 106055e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement:: 106155e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) : 106255e4f9d5SDimitry Andric TypeConstraintInfo(TPL, 0) { 106355e4f9d5SDimitry Andric assert(TPL->size() == 1); 106455e4f9d5SDimitry Andric const TypeConstraint *TC = 106555e4f9d5SDimitry Andric cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint(); 106655e4f9d5SDimitry Andric assert(TC && 106755e4f9d5SDimitry Andric "TPL must have a template type parameter with a type constraint"); 106855e4f9d5SDimitry Andric auto *Constraint = 106955e4f9d5SDimitry Andric cast_or_null<ConceptSpecializationExpr>( 107055e4f9d5SDimitry Andric TC->getImmediatelyDeclaredConstraint()); 1071e8d8bef9SDimitry Andric bool Dependent = 1072e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten() && 1073e8d8bef9SDimitry Andric TemplateSpecializationType::anyInstantiationDependentTemplateArguments( 1074e8d8bef9SDimitry Andric Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)); 107555e4f9d5SDimitry Andric TypeConstraintInfo.setInt(Dependent ? 1 : 0); 107655e4f9d5SDimitry Andric } 107755e4f9d5SDimitry Andric 107855e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) : 1079e8d8bef9SDimitry Andric Requirement(RK_Type, T->getType()->isInstantiationDependentType(), 108055e4f9d5SDimitry Andric T->getType()->containsUnexpandedParameterPack(), 108155e4f9d5SDimitry Andric // We reach this ctor with either dependent types (in which 108255e4f9d5SDimitry Andric // IsSatisfied doesn't matter) or with non-dependent type in 108355e4f9d5SDimitry Andric // which the existence of the type indicates satisfaction. 1084e8d8bef9SDimitry Andric /*IsSatisfied=*/true), 1085e8d8bef9SDimitry Andric Value(T), 1086e8d8bef9SDimitry Andric Status(T->getType()->isInstantiationDependentType() ? SS_Dependent 1087e8d8bef9SDimitry Andric : SS_Satisfied) {} 1088