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