Path: blob/main/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp
35233 views
//===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements semantic analysis for C++ constraints and concepts.9//10//===----------------------------------------------------------------------===//1112#include "clang/Sema/SemaConcept.h"13#include "TreeTransform.h"14#include "clang/AST/ASTLambda.h"15#include "clang/AST/DeclCXX.h"16#include "clang/AST/ExprConcepts.h"17#include "clang/AST/RecursiveASTVisitor.h"18#include "clang/Basic/OperatorPrecedence.h"19#include "clang/Sema/EnterExpressionEvaluationContext.h"20#include "clang/Sema/Initialization.h"21#include "clang/Sema/Overload.h"22#include "clang/Sema/ScopeInfo.h"23#include "clang/Sema/Sema.h"24#include "clang/Sema/SemaDiagnostic.h"25#include "clang/Sema/SemaInternal.h"26#include "clang/Sema/Template.h"27#include "clang/Sema/TemplateDeduction.h"28#include "llvm/ADT/DenseMap.h"29#include "llvm/ADT/PointerUnion.h"30#include "llvm/ADT/StringExtras.h"31#include <optional>3233using namespace clang;34using namespace sema;3536namespace {37class LogicalBinOp {38SourceLocation Loc;39OverloadedOperatorKind Op = OO_None;40const Expr *LHS = nullptr;41const Expr *RHS = nullptr;4243public:44LogicalBinOp(const Expr *E) {45if (auto *BO = dyn_cast<BinaryOperator>(E)) {46Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());47LHS = BO->getLHS();48RHS = BO->getRHS();49Loc = BO->getExprLoc();50} else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {51// If OO is not || or && it might not have exactly 2 arguments.52if (OO->getNumArgs() == 2) {53Op = OO->getOperator();54LHS = OO->getArg(0);55RHS = OO->getArg(1);56Loc = OO->getOperatorLoc();57}58}59}6061bool isAnd() const { return Op == OO_AmpAmp; }62bool isOr() const { return Op == OO_PipePipe; }63explicit operator bool() const { return isAnd() || isOr(); }6465const Expr *getLHS() const { return LHS; }66const Expr *getRHS() const { return RHS; }67OverloadedOperatorKind getOp() const { return Op; }6869ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {70return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));71}7273ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,74ExprResult RHS) const {75assert((isAnd() || isOr()) && "Not the right kind of op?");76assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");7778if (!LHS.isUsable() || !RHS.isUsable())79return ExprEmpty();8081// We should just be able to 'normalize' these to the builtin Binary82// Operator, since that is how they are evaluated in constriant checks.83return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),84BinaryOperator::getOverloadedOpcode(Op),85SemaRef.Context.BoolTy, VK_PRValue,86OK_Ordinary, Loc, FPOptionsOverride{});87}88};89}9091bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,92Token NextToken, bool *PossibleNonPrimary,93bool IsTrailingRequiresClause) {94// C++2a [temp.constr.atomic]p195// ..E shall be a constant expression of type bool.9697ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();9899if (LogicalBinOp BO = ConstraintExpression) {100return CheckConstraintExpression(BO.getLHS(), NextToken,101PossibleNonPrimary) &&102CheckConstraintExpression(BO.getRHS(), NextToken,103PossibleNonPrimary);104} else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))105return CheckConstraintExpression(C->getSubExpr(), NextToken,106PossibleNonPrimary);107108QualType Type = ConstraintExpression->getType();109110auto CheckForNonPrimary = [&] {111if (!PossibleNonPrimary)112return;113114*PossibleNonPrimary =115// We have the following case:116// template<typename> requires func(0) struct S { };117// The user probably isn't aware of the parentheses required around118// the function call, and we're only going to parse 'func' as the119// primary-expression, and complain that it is of non-bool type.120//121// However, if we're in a lambda, this might also be:122// []<typename> requires var () {};123// Which also looks like a function call due to the lambda parentheses,124// but unlike the first case, isn't an error, so this check is skipped.125(NextToken.is(tok::l_paren) &&126(IsTrailingRequiresClause ||127(Type->isDependentType() &&128isa<UnresolvedLookupExpr>(ConstraintExpression) &&129!dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||130Type->isFunctionType() ||131Type->isSpecificBuiltinType(BuiltinType::Overload))) ||132// We have the following case:133// template<typename T> requires size_<T> == 0 struct S { };134// The user probably isn't aware of the parentheses required around135// the binary operator, and we're only going to parse 'func' as the136// first operand, and complain that it is of non-bool type.137getBinOpPrecedence(NextToken.getKind(),138/*GreaterThanIsOperator=*/true,139getLangOpts().CPlusPlus11) > prec::LogicalAnd;140};141142// An atomic constraint!143if (ConstraintExpression->isTypeDependent()) {144CheckForNonPrimary();145return true;146}147148if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {149Diag(ConstraintExpression->getExprLoc(),150diag::err_non_bool_atomic_constraint) << Type151<< ConstraintExpression->getSourceRange();152CheckForNonPrimary();153return false;154}155156if (PossibleNonPrimary)157*PossibleNonPrimary = false;158return true;159}160161namespace {162struct SatisfactionStackRAII {163Sema &SemaRef;164bool Inserted = false;165SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,166const llvm::FoldingSetNodeID &FSNID)167: SemaRef(SemaRef) {168if (ND) {169SemaRef.PushSatisfactionStackEntry(ND, FSNID);170Inserted = true;171}172}173~SatisfactionStackRAII() {174if (Inserted)175SemaRef.PopSatisfactionStackEntry();176}177};178} // namespace179180template <typename ConstraintEvaluator>181static ExprResult182calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,183ConstraintSatisfaction &Satisfaction,184const ConstraintEvaluator &Evaluator);185186template <typename ConstraintEvaluator>187static ExprResult188calculateConstraintSatisfaction(Sema &S, const Expr *LHS,189OverloadedOperatorKind Op, const Expr *RHS,190ConstraintSatisfaction &Satisfaction,191const ConstraintEvaluator &Evaluator) {192size_t EffectiveDetailEndIndex = Satisfaction.Details.size();193194ExprResult LHSRes =195calculateConstraintSatisfaction(S, LHS, Satisfaction, Evaluator);196197if (LHSRes.isInvalid())198return ExprError();199200bool IsLHSSatisfied = Satisfaction.IsSatisfied;201202if (Op == clang::OO_PipePipe && IsLHSSatisfied)203// [temp.constr.op] p3204// A disjunction is a constraint taking two operands. To determine if205// a disjunction is satisfied, the satisfaction of the first operand206// is checked. If that is satisfied, the disjunction is satisfied.207// Otherwise, the disjunction is satisfied if and only if the second208// operand is satisfied.209// LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.210return LHSRes;211212if (Op == clang::OO_AmpAmp && !IsLHSSatisfied)213// [temp.constr.op] p2214// A conjunction is a constraint taking two operands. To determine if215// a conjunction is satisfied, the satisfaction of the first operand216// is checked. If that is not satisfied, the conjunction is not217// satisfied. Otherwise, the conjunction is satisfied if and only if218// the second operand is satisfied.219// LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.220return LHSRes;221222ExprResult RHSRes =223calculateConstraintSatisfaction(S, RHS, Satisfaction, Evaluator);224if (RHSRes.isInvalid())225return ExprError();226227bool IsRHSSatisfied = Satisfaction.IsSatisfied;228// Current implementation adds diagnostic information about the falsity229// of each false atomic constraint expression when it evaluates them.230// When the evaluation results to `false || true`, the information231// generated during the evaluation of left-hand side is meaningless232// because the whole expression evaluates to true.233// The following code removes the irrelevant diagnostic information.234// FIXME: We should probably delay the addition of diagnostic information235// until we know the entire expression is false.236if (Op == clang::OO_PipePipe && IsRHSSatisfied) {237auto EffectiveDetailEnd = Satisfaction.Details.begin();238std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);239Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end());240}241242if (!LHSRes.isUsable() || !RHSRes.isUsable())243return ExprEmpty();244245return BinaryOperator::Create(S.Context, LHSRes.get(), RHSRes.get(),246BinaryOperator::getOverloadedOpcode(Op),247S.Context.BoolTy, VK_PRValue, OK_Ordinary,248LHS->getBeginLoc(), FPOptionsOverride{});249}250251template <typename ConstraintEvaluator>252static ExprResult253calculateConstraintSatisfaction(Sema &S, const CXXFoldExpr *FE,254ConstraintSatisfaction &Satisfaction,255const ConstraintEvaluator &Evaluator) {256bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd;257size_t EffectiveDetailEndIndex = Satisfaction.Details.size();258259ExprResult Out;260if (FE->isLeftFold() && FE->getInit()) {261Out = calculateConstraintSatisfaction(S, FE->getInit(), Satisfaction,262Evaluator);263if (Out.isInvalid())264return ExprError();265266// If the first clause of a conjunction is not satisfied,267// or if the first clause of a disjection is satisfied,268// we have established satisfaction of the whole constraint269// and we should not continue further.270if (Conjunction != Satisfaction.IsSatisfied)271return Out;272}273std::optional<unsigned> NumExpansions =274Evaluator.EvaluateFoldExpandedConstraintSize(FE);275if (!NumExpansions)276return ExprError();277for (unsigned I = 0; I < *NumExpansions; I++) {278Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I);279ExprResult Res = calculateConstraintSatisfaction(S, FE->getPattern(),280Satisfaction, Evaluator);281if (Res.isInvalid())282return ExprError();283bool IsRHSSatisfied = Satisfaction.IsSatisfied;284if (!Conjunction && IsRHSSatisfied) {285auto EffectiveDetailEnd = Satisfaction.Details.begin();286std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);287Satisfaction.Details.erase(EffectiveDetailEnd,288Satisfaction.Details.end());289}290if (Out.isUnset())291Out = Res;292else if (!Res.isUnset()) {293Out = BinaryOperator::Create(294S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,295VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{});296}297if (Conjunction != IsRHSSatisfied)298return Out;299}300301if (FE->isRightFold() && FE->getInit()) {302ExprResult Res = calculateConstraintSatisfaction(S, FE->getInit(),303Satisfaction, Evaluator);304if (Out.isInvalid())305return ExprError();306307if (Out.isUnset())308Out = Res;309else if (!Res.isUnset()) {310Out = BinaryOperator::Create(311S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,312VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{});313}314}315316if (Out.isUnset()) {317Satisfaction.IsSatisfied = Conjunction;318Out = S.BuildEmptyCXXFoldExpr(FE->getBeginLoc(), FE->getOperator());319}320return Out;321}322323template <typename ConstraintEvaluator>324static ExprResult325calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,326ConstraintSatisfaction &Satisfaction,327const ConstraintEvaluator &Evaluator) {328ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();329330if (LogicalBinOp BO = ConstraintExpr)331return calculateConstraintSatisfaction(332S, BO.getLHS(), BO.getOp(), BO.getRHS(), Satisfaction, Evaluator);333334if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {335// These aren't evaluated, so we don't care about cleanups, so we can just336// evaluate these as if the cleanups didn't exist.337return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,338Evaluator);339}340341if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr);342FE && S.getLangOpts().CPlusPlus26 &&343(FE->getOperator() == BinaryOperatorKind::BO_LAnd ||344FE->getOperator() == BinaryOperatorKind::BO_LOr)) {345return calculateConstraintSatisfaction(S, FE, Satisfaction, Evaluator);346}347348// An atomic constraint expression349ExprResult SubstitutedAtomicExpr =350Evaluator.EvaluateAtomicConstraint(ConstraintExpr);351352if (SubstitutedAtomicExpr.isInvalid())353return ExprError();354355if (!SubstitutedAtomicExpr.isUsable())356// Evaluator has decided satisfaction without yielding an expression.357return ExprEmpty();358359// We don't have the ability to evaluate this, since it contains a360// RecoveryExpr, so we want to fail overload resolution. Otherwise,361// we'd potentially pick up a different overload, and cause confusing362// diagnostics. SO, add a failure detail that will cause us to make this363// overload set not viable.364if (SubstitutedAtomicExpr.get()->containsErrors()) {365Satisfaction.IsSatisfied = false;366Satisfaction.ContainsErrors = true;367368PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);369SmallString<128> DiagString;370DiagString = ": ";371Msg.EmitToString(S.getDiagnostics(), DiagString);372unsigned MessageSize = DiagString.size();373char *Mem = new (S.Context) char[MessageSize];374memcpy(Mem, DiagString.c_str(), MessageSize);375Satisfaction.Details.emplace_back(376new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{377SubstitutedAtomicExpr.get()->getBeginLoc(),378StringRef(Mem, MessageSize)});379return SubstitutedAtomicExpr;380}381382EnterExpressionEvaluationContext ConstantEvaluated(383S, Sema::ExpressionEvaluationContext::ConstantEvaluated);384SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;385Expr::EvalResult EvalResult;386EvalResult.Diag = &EvaluationDiags;387if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,388S.Context) ||389!EvaluationDiags.empty()) {390// C++2a [temp.constr.atomic]p1391// ...E shall be a constant expression of type bool.392S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),393diag::err_non_constant_constraint_expression)394<< SubstitutedAtomicExpr.get()->getSourceRange();395for (const PartialDiagnosticAt &PDiag : EvaluationDiags)396S.Diag(PDiag.first, PDiag.second);397return ExprError();398}399400assert(EvalResult.Val.isInt() &&401"evaluating bool expression didn't produce int");402Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();403if (!Satisfaction.IsSatisfied)404Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());405406return SubstitutedAtomicExpr;407}408409static bool410DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,411const NamedDecl *Templ, const Expr *E,412const MultiLevelTemplateArgumentList &MLTAL) {413E->Profile(ID, S.Context, /*Canonical=*/true);414for (const auto &List : MLTAL)415for (const auto &TemplateArg : List.Args)416TemplateArg.Profile(ID, S.Context);417418// Note that we have to do this with our own collection, because there are419// times where a constraint-expression check can cause us to need to evaluate420// other constriants that are unrelated, such as when evaluating a recovery421// expression, or when trying to determine the constexpr-ness of special422// members. Otherwise we could just use the423// Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.424if (S.SatisfactionStackContains(Templ, ID)) {425S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)426<< const_cast<Expr *>(E) << E->getSourceRange();427return true;428}429430return false;431}432433static ExprResult calculateConstraintSatisfaction(434Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,435const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,436ConstraintSatisfaction &Satisfaction) {437438struct ConstraintEvaluator {439Sema &S;440const NamedDecl *Template;441SourceLocation TemplateNameLoc;442const MultiLevelTemplateArgumentList &MLTAL;443ConstraintSatisfaction &Satisfaction;444445ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const {446EnterExpressionEvaluationContext ConstantEvaluated(447S, Sema::ExpressionEvaluationContext::ConstantEvaluated,448Sema::ReuseLambdaContextDecl);449450// Atomic constraint - substitute arguments and check satisfaction.451ExprResult SubstitutedExpression;452{453TemplateDeductionInfo Info(TemplateNameLoc);454Sema::InstantiatingTemplate Inst(455S, AtomicExpr->getBeginLoc(),456Sema::InstantiatingTemplate::ConstraintSubstitution{},457const_cast<NamedDecl *>(Template), Info,458AtomicExpr->getSourceRange());459if (Inst.isInvalid())460return ExprError();461462llvm::FoldingSetNodeID ID;463if (Template &&464DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {465Satisfaction.IsSatisfied = false;466Satisfaction.ContainsErrors = true;467return ExprEmpty();468}469470SatisfactionStackRAII StackRAII(S, Template, ID);471472// We do not want error diagnostics escaping here.473Sema::SFINAETrap Trap(S);474SubstitutedExpression =475S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);476477if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {478// C++2a [temp.constr.atomic]p1479// ...If substitution results in an invalid type or expression, the480// constraint is not satisfied.481if (!Trap.hasErrorOccurred())482// A non-SFINAE error has occurred as a result of this483// substitution.484return ExprError();485486PartialDiagnosticAt SubstDiag{SourceLocation(),487PartialDiagnostic::NullDiagnostic()};488Info.takeSFINAEDiagnostic(SubstDiag);489// FIXME: Concepts: This is an unfortunate consequence of there490// being no serialization code for PartialDiagnostics and the fact491// that serializing them would likely take a lot more storage than492// just storing them as strings. We would still like, in the493// future, to serialize the proper PartialDiagnostic as serializing494// it as a string defeats the purpose of the diagnostic mechanism.495SmallString<128> DiagString;496DiagString = ": ";497SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);498unsigned MessageSize = DiagString.size();499char *Mem = new (S.Context) char[MessageSize];500memcpy(Mem, DiagString.c_str(), MessageSize);501Satisfaction.Details.emplace_back(502new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{503SubstDiag.first, StringRef(Mem, MessageSize)});504Satisfaction.IsSatisfied = false;505return ExprEmpty();506}507}508509if (!S.CheckConstraintExpression(SubstitutedExpression.get()))510return ExprError();511512// [temp.constr.atomic]p3: To determine if an atomic constraint is513// satisfied, the parameter mapping and template arguments are first514// substituted into its expression. If substitution results in an515// invalid type or expression, the constraint is not satisfied.516// Otherwise, the lvalue-to-rvalue conversion is performed if necessary,517// and E shall be a constant expression of type bool.518//519// Perform the L to R Value conversion if necessary. We do so for all520// non-PRValue categories, else we fail to extend the lifetime of521// temporaries, and that fails the constant expression check.522if (!SubstitutedExpression.get()->isPRValue())523SubstitutedExpression = ImplicitCastExpr::Create(524S.Context, SubstitutedExpression.get()->getType(),525CK_LValueToRValue, SubstitutedExpression.get(),526/*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());527528return SubstitutedExpression;529}530531std::optional<unsigned>532EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {533534// We should ignore errors in the presence of packs of different size.535Sema::SFINAETrap Trap(S);536537Expr *Pattern = FE->getPattern();538539SmallVector<UnexpandedParameterPack, 2> Unexpanded;540S.collectUnexpandedParameterPacks(Pattern, Unexpanded);541assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");542bool Expand = true;543bool RetainExpansion = false;544std::optional<unsigned> OrigNumExpansions = FE->getNumExpansions(),545NumExpansions = OrigNumExpansions;546if (S.CheckParameterPacksForExpansion(547FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded,548MLTAL, Expand, RetainExpansion, NumExpansions) ||549!Expand || RetainExpansion)550return std::nullopt;551552if (NumExpansions && S.getLangOpts().BracketDepth < NumExpansions) {553S.Diag(FE->getEllipsisLoc(),554clang::diag::err_fold_expression_limit_exceeded)555<< *NumExpansions << S.getLangOpts().BracketDepth556<< FE->getSourceRange();557S.Diag(FE->getEllipsisLoc(), diag::note_bracket_depth);558return std::nullopt;559}560return NumExpansions;561}562};563564return calculateConstraintSatisfaction(565S, ConstraintExpr, Satisfaction,566ConstraintEvaluator{S, Template, TemplateNameLoc, MLTAL, Satisfaction});567}568569static bool CheckConstraintSatisfaction(570Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,571llvm::SmallVectorImpl<Expr *> &Converted,572const MultiLevelTemplateArgumentList &TemplateArgsLists,573SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {574if (ConstraintExprs.empty()) {575Satisfaction.IsSatisfied = true;576return false;577}578579if (TemplateArgsLists.isAnyArgInstantiationDependent()) {580// No need to check satisfaction for dependent constraint expressions.581Satisfaction.IsSatisfied = true;582return false;583}584585ArrayRef<TemplateArgument> TemplateArgs =586TemplateArgsLists.getNumSubstitutedLevels() > 0587? TemplateArgsLists.getOutermost()588: ArrayRef<TemplateArgument> {};589Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),590Sema::InstantiatingTemplate::ConstraintsCheck{},591const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);592if (Inst.isInvalid())593return true;594595for (const Expr *ConstraintExpr : ConstraintExprs) {596ExprResult Res = calculateConstraintSatisfaction(597S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,598ConstraintExpr, Satisfaction);599if (Res.isInvalid())600return true;601602Converted.push_back(Res.get());603if (!Satisfaction.IsSatisfied) {604// Backfill the 'converted' list with nulls so we can keep the Converted605// and unconverted lists in sync.606Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);607// [temp.constr.op] p2608// [...] To determine if a conjunction is satisfied, the satisfaction609// of the first operand is checked. If that is not satisfied, the610// conjunction is not satisfied. [...]611return false;612}613}614return false;615}616617bool Sema::CheckConstraintSatisfaction(618const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,619llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,620const MultiLevelTemplateArgumentList &TemplateArgsLists,621SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {622if (ConstraintExprs.empty()) {623OutSatisfaction.IsSatisfied = true;624return false;625}626if (!Template) {627return ::CheckConstraintSatisfaction(628*this, nullptr, ConstraintExprs, ConvertedConstraints,629TemplateArgsLists, TemplateIDRange, OutSatisfaction);630}631// Invalid templates could make their way here. Substituting them could result632// in dependent expressions.633if (Template->isInvalidDecl()) {634OutSatisfaction.IsSatisfied = false;635return true;636}637638// A list of the template argument list flattened in a predictible manner for639// the purposes of caching. The ConstraintSatisfaction type is in AST so it640// has no access to the MultiLevelTemplateArgumentList, so this has to happen641// here.642llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;643for (auto List : TemplateArgsLists)644FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),645List.Args.end());646647llvm::FoldingSetNodeID ID;648ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);649void *InsertPos;650if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {651OutSatisfaction = *Cached;652return false;653}654655auto Satisfaction =656std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);657if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,658ConvertedConstraints, TemplateArgsLists,659TemplateIDRange, *Satisfaction)) {660OutSatisfaction = *Satisfaction;661return true;662}663664if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {665// The evaluation of this constraint resulted in us trying to re-evaluate it666// recursively. This isn't really possible, except we try to form a667// RecoveryExpr as a part of the evaluation. If this is the case, just668// return the 'cached' version (which will have the same result), and save669// ourselves the extra-insert. If it ever becomes possible to legitimately670// recursively check a constraint, we should skip checking the 'inner' one671// above, and replace the cached version with this one, as it would be more672// specific.673OutSatisfaction = *Cached;674return false;675}676677// Else we can simply add this satisfaction to the list.678OutSatisfaction = *Satisfaction;679// We cannot use InsertPos here because CheckConstraintSatisfaction might have680// invalidated it.681// Note that entries of SatisfactionCache are deleted in Sema's destructor.682SatisfactionCache.InsertNode(Satisfaction.release());683return false;684}685686bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,687ConstraintSatisfaction &Satisfaction) {688689struct ConstraintEvaluator {690Sema &S;691ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const {692return S.PerformContextuallyConvertToBool(const_cast<Expr *>(AtomicExpr));693}694695std::optional<unsigned>696EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {697return 0;698}699};700701return calculateConstraintSatisfaction(*this, ConstraintExpr, Satisfaction,702ConstraintEvaluator{*this})703.isInvalid();704}705706bool Sema::addInstantiatedCapturesToScope(707FunctionDecl *Function, const FunctionDecl *PatternDecl,708LocalInstantiationScope &Scope,709const MultiLevelTemplateArgumentList &TemplateArgs) {710const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();711const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();712713unsigned Instantiated = 0;714715auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,716unsigned Index) {717ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();718if (CapturedVar->isInitCapture())719Scope.InstantiatedLocal(CapturedPattern, CapturedVar);720};721722for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {723if (!CapturePattern.capturesVariable()) {724Instantiated++;725continue;726}727const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();728if (!CapturedPattern->isParameterPack()) {729AddSingleCapture(CapturedPattern, Instantiated++);730} else {731Scope.MakeInstantiatedLocalArgPack(CapturedPattern);732std::optional<unsigned> NumArgumentsInExpansion =733getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);734if (!NumArgumentsInExpansion)735continue;736for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)737AddSingleCapture(CapturedPattern, Instantiated++);738}739}740return false;741}742743bool Sema::SetupConstraintScope(744FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,745const MultiLevelTemplateArgumentList &MLTAL,746LocalInstantiationScope &Scope) {747if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {748FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();749InstantiatingTemplate Inst(750*this, FD->getPointOfInstantiation(),751Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,752TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},753SourceRange());754if (Inst.isInvalid())755return true;756757// addInstantiatedParametersToScope creates a map of 'uninstantiated' to758// 'instantiated' parameters and adds it to the context. For the case where759// this function is a template being instantiated NOW, we also need to add760// the list of current template arguments to the list so that they also can761// be picked out of the map.762if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {763MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),764/*Final=*/false);765if (addInstantiatedParametersToScope(766FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))767return true;768}769770// If this is a member function, make sure we get the parameters that771// reference the original primary template.772// We walk up the instantiated template chain so that nested lambdas get773// handled properly.774// We should only collect instantiated parameters from the primary template.775// Otherwise, we may have mismatched template parameter depth!776if (FunctionTemplateDecl *FromMemTempl =777PrimaryTemplate->getInstantiatedFromMemberTemplate()) {778while (FromMemTempl->getInstantiatedFromMemberTemplate())779FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();780if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),781Scope, MLTAL))782return true;783}784785return false;786}787788if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||789FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {790FunctionDecl *InstantiatedFrom =791FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization792? FD->getInstantiatedFromMemberFunction()793: FD->getInstantiatedFromDecl();794795InstantiatingTemplate Inst(796*this, FD->getPointOfInstantiation(),797Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,798TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},799SourceRange());800if (Inst.isInvalid())801return true;802803// Case where this was not a template, but instantiated as a804// child-function.805if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))806return true;807}808809return false;810}811812// This function collects all of the template arguments for the purposes of813// constraint-instantiation and checking.814std::optional<MultiLevelTemplateArgumentList>815Sema::SetupConstraintCheckingTemplateArgumentsAndScope(816FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,817LocalInstantiationScope &Scope) {818MultiLevelTemplateArgumentList MLTAL;819820// Collect the list of template arguments relative to the 'primary' template.821// We need the entire list, since the constraint is completely uninstantiated822// at this point.823MLTAL =824getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),825/*Final=*/false, /*Innermost=*/std::nullopt,826/*RelativeToPrimary=*/true,827/*Pattern=*/nullptr,828/*ForConstraintInstantiation=*/true);829if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))830return std::nullopt;831832return MLTAL;833}834835bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,836ConstraintSatisfaction &Satisfaction,837SourceLocation UsageLoc,838bool ForOverloadResolution) {839// Don't check constraints if the function is dependent. Also don't check if840// this is a function template specialization, as the call to841// CheckinstantiatedFunctionTemplateConstraints after this will check it842// better.843if (FD->isDependentContext() ||844FD->getTemplatedKind() ==845FunctionDecl::TK_FunctionTemplateSpecialization) {846Satisfaction.IsSatisfied = true;847return false;848}849850// A lambda conversion operator has the same constraints as the call operator851// and constraints checking relies on whether we are in a lambda call operator852// (and may refer to its parameters), so check the call operator instead.853// Note that the declarations outside of the lambda should also be854// considered. Turning on the 'ForOverloadResolution' flag results in the855// LocalInstantiationScope not looking into its parents, but we can still856// access Decls from the parents while building a lambda RAII scope later.857if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);858MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))859return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),860Satisfaction, UsageLoc,861/*ShouldAddDeclsFromParentScope=*/true);862863DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);864865while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {866if (isLambdaCallOperator(CtxToSave))867CtxToSave = CtxToSave->getParent()->getParent();868else869CtxToSave = CtxToSave->getNonTransparentContext();870}871872ContextRAII SavedContext{*this, CtxToSave};873LocalInstantiationScope Scope(*this, !ForOverloadResolution);874std::optional<MultiLevelTemplateArgumentList> MLTAL =875SetupConstraintCheckingTemplateArgumentsAndScope(876const_cast<FunctionDecl *>(FD), {}, Scope);877878if (!MLTAL)879return true;880881Qualifiers ThisQuals;882CXXRecordDecl *Record = nullptr;883if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {884ThisQuals = Method->getMethodQualifiers();885Record = const_cast<CXXRecordDecl *>(Method->getParent());886}887CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);888889LambdaScopeForCallOperatorInstantiationRAII LambdaScope(890*this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,891ForOverloadResolution);892893return CheckConstraintSatisfaction(894FD, {FD->getTrailingRequiresClause()}, *MLTAL,895SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),896Satisfaction);897}898899900// Figure out the to-translation-unit depth for this function declaration for901// the purpose of seeing if they differ by constraints. This isn't the same as902// getTemplateDepth, because it includes already instantiated parents.903static unsigned904CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,905bool SkipForSpecialization = false) {906MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(907ND, ND->getLexicalDeclContext(), /*Final=*/false,908/*Innermost=*/std::nullopt,909/*RelativeToPrimary=*/true,910/*Pattern=*/nullptr,911/*ForConstraintInstantiation=*/true, SkipForSpecialization);912return MLTAL.getNumLevels();913}914915namespace {916class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {917unsigned TemplateDepth = 0;918public:919using inherited = TreeTransform<AdjustConstraintDepth>;920AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)921: inherited(SemaRef), TemplateDepth(TemplateDepth) {}922923using inherited::TransformTemplateTypeParmType;924QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,925TemplateTypeParmTypeLoc TL, bool) {926const TemplateTypeParmType *T = TL.getTypePtr();927928TemplateTypeParmDecl *NewTTPDecl = nullptr;929if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())930NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(931TransformDecl(TL.getNameLoc(), OldTTPDecl));932933QualType Result = getSema().Context.getTemplateTypeParmType(934T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),935NewTTPDecl);936TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);937NewTL.setNameLoc(TL.getNameLoc());938return Result;939}940};941} // namespace942943static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(944Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,945const Expr *ConstrExpr) {946MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(947DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,948/*Innermost=*/std::nullopt,949/*RelativeToPrimary=*/true,950/*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,951/*SkipForSpecialization*/ false);952953if (MLTAL.getNumSubstitutedLevels() == 0)954return ConstrExpr;955956Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false);957958Sema::InstantiatingTemplate Inst(959S, DeclInfo.getLocation(),960Sema::InstantiatingTemplate::ConstraintNormalization{},961const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});962if (Inst.isInvalid())963return nullptr;964965// Set up a dummy 'instantiation' scope in the case of reference to function966// parameters that the surrounding function hasn't been instantiated yet. Note967// this may happen while we're comparing two templates' constraint968// equivalence.969LocalInstantiationScope ScopeForParameters(S, /*CombineWithOuterScope=*/true);970if (auto *FD = DeclInfo.getDecl()->getAsFunction())971for (auto *PVD : FD->parameters()) {972if (!PVD->isParameterPack()) {973ScopeForParameters.InstantiatedLocal(PVD, PVD);974continue;975}976// This is hacky: we're mapping the parameter pack to a size-of-1 argument977// to avoid building SubstTemplateTypeParmPackTypes for978// PackExpansionTypes. The SubstTemplateTypeParmPackType node would979// otherwise reference the AssociatedDecl of the template arguments, which980// is, in this case, the template declaration.981//982// However, as we are in the process of comparing potential983// re-declarations, the canonical declaration is the declaration itself at984// this point. So if we didn't expand these packs, we would end up with an985// incorrect profile difference because we will be profiling the986// canonical types!987//988// FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so989// that we can eliminate the Scope in the cases where the declarations are990// not necessarily instantiated. It would also benefit the noexcept991// specifier comparison.992ScopeForParameters.MakeInstantiatedLocalArgPack(PVD);993ScopeForParameters.InstantiatedLocalPackArg(PVD, PVD);994}995996std::optional<Sema::CXXThisScopeRAII> ThisScope;997998// See TreeTransform::RebuildTemplateSpecializationType. A context scope is999// essential for having an injected class as the canonical type for a template1000// specialization type at the rebuilding stage. This guarantees that, for1001// out-of-line definitions, injected class name types and their equivalent1002// template specializations can be profiled to the same value, which makes it1003// possible that e.g. constraints involving C<Class<T>> and C<Class> are1004// perceived identical.1005std::optional<Sema::ContextRAII> ContextScope;1006if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext())) {1007ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());1008ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),1009/*NewThisContext=*/false);1010}1011ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(1012const_cast<clang::Expr *>(ConstrExpr), MLTAL);1013if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())1014return nullptr;1015return SubstConstr.get();1016}10171018bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,1019const Expr *OldConstr,1020const TemplateCompareNewDeclInfo &New,1021const Expr *NewConstr) {1022if (OldConstr == NewConstr)1023return true;1024// C++ [temp.constr.decl]p41025if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&1026Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {1027if (const Expr *SubstConstr =1028SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,1029OldConstr))1030OldConstr = SubstConstr;1031else1032return false;1033if (const Expr *SubstConstr =1034SubstituteConstraintExpressionWithoutSatisfaction(*this, New,1035NewConstr))1036NewConstr = SubstConstr;1037else1038return false;1039}10401041llvm::FoldingSetNodeID ID1, ID2;1042OldConstr->Profile(ID1, Context, /*Canonical=*/true);1043NewConstr->Profile(ID2, Context, /*Canonical=*/true);1044return ID1 == ID2;1045}10461047bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {1048assert(FD->getFriendObjectKind() && "Must be a friend!");10491050// The logic for non-templates is handled in ASTContext::isSameEntity, so we1051// don't have to bother checking 'DependsOnEnclosingTemplate' for a1052// non-function-template.1053assert(FD->getDescribedFunctionTemplate() &&1054"Non-function templates don't need to be checked");10551056SmallVector<const Expr *, 3> ACs;1057FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);10581059unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);1060for (const Expr *Constraint : ACs)1061if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,1062Constraint))1063return true;10641065return false;1066}10671068bool Sema::EnsureTemplateArgumentListConstraints(1069TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,1070SourceRange TemplateIDRange) {1071ConstraintSatisfaction Satisfaction;1072llvm::SmallVector<const Expr *, 3> AssociatedConstraints;1073TD->getAssociatedConstraints(AssociatedConstraints);1074if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,1075TemplateIDRange, Satisfaction))1076return true;10771078if (!Satisfaction.IsSatisfied) {1079SmallString<128> TemplateArgString;1080TemplateArgString = " ";1081TemplateArgString += getTemplateArgumentBindingsText(1082TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),1083TemplateArgsLists.getInnermost().size());10841085Diag(TemplateIDRange.getBegin(),1086diag::err_template_arg_list_constraints_not_satisfied)1087<< (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD1088<< TemplateArgString << TemplateIDRange;1089DiagnoseUnsatisfiedConstraint(Satisfaction);1090return true;1091}1092return false;1093}10941095bool Sema::CheckInstantiatedFunctionTemplateConstraints(1096SourceLocation PointOfInstantiation, FunctionDecl *Decl,1097ArrayRef<TemplateArgument> TemplateArgs,1098ConstraintSatisfaction &Satisfaction) {1099// In most cases we're not going to have constraints, so check for that first.1100FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();1101// Note - code synthesis context for the constraints check is created1102// inside CheckConstraintsSatisfaction.1103SmallVector<const Expr *, 3> TemplateAC;1104Template->getAssociatedConstraints(TemplateAC);1105if (TemplateAC.empty()) {1106Satisfaction.IsSatisfied = true;1107return false;1108}11091110// Enter the scope of this instantiation. We don't use1111// PushDeclContext because we don't have a scope.1112Sema::ContextRAII savedContext(*this, Decl);1113LocalInstantiationScope Scope(*this);11141115std::optional<MultiLevelTemplateArgumentList> MLTAL =1116SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,1117Scope);11181119if (!MLTAL)1120return true;11211122Qualifiers ThisQuals;1123CXXRecordDecl *Record = nullptr;1124if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {1125ThisQuals = Method->getMethodQualifiers();1126Record = Method->getParent();1127}11281129CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);1130LambdaScopeForCallOperatorInstantiationRAII LambdaScope(1131*this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);11321133llvm::SmallVector<Expr *, 1> Converted;1134return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,1135PointOfInstantiation, Satisfaction);1136}11371138static void diagnoseUnsatisfiedRequirement(Sema &S,1139concepts::ExprRequirement *Req,1140bool First) {1141assert(!Req->isSatisfied()1142&& "Diagnose() can only be used on an unsatisfied requirement");1143switch (Req->getSatisfactionStatus()) {1144case concepts::ExprRequirement::SS_Dependent:1145llvm_unreachable("Diagnosing a dependent requirement");1146break;1147case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {1148auto *SubstDiag = Req->getExprSubstitutionDiagnostic();1149if (!SubstDiag->DiagMessage.empty())1150S.Diag(SubstDiag->DiagLoc,1151diag::note_expr_requirement_expr_substitution_error)1152<< (int)First << SubstDiag->SubstitutedEntity1153<< SubstDiag->DiagMessage;1154else1155S.Diag(SubstDiag->DiagLoc,1156diag::note_expr_requirement_expr_unknown_substitution_error)1157<< (int)First << SubstDiag->SubstitutedEntity;1158break;1159}1160case concepts::ExprRequirement::SS_NoexceptNotMet:1161S.Diag(Req->getNoexceptLoc(),1162diag::note_expr_requirement_noexcept_not_met)1163<< (int)First << Req->getExpr();1164break;1165case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {1166auto *SubstDiag =1167Req->getReturnTypeRequirement().getSubstitutionDiagnostic();1168if (!SubstDiag->DiagMessage.empty())1169S.Diag(SubstDiag->DiagLoc,1170diag::note_expr_requirement_type_requirement_substitution_error)1171<< (int)First << SubstDiag->SubstitutedEntity1172<< SubstDiag->DiagMessage;1173else1174S.Diag(SubstDiag->DiagLoc,1175diag::note_expr_requirement_type_requirement_unknown_substitution_error)1176<< (int)First << SubstDiag->SubstitutedEntity;1177break;1178}1179case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {1180ConceptSpecializationExpr *ConstraintExpr =1181Req->getReturnTypeRequirementSubstitutedConstraintExpr();1182if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {1183// A simple case - expr type is the type being constrained and the concept1184// was not provided arguments.1185Expr *e = Req->getExpr();1186S.Diag(e->getBeginLoc(),1187diag::note_expr_requirement_constraints_not_satisfied_simple)1188<< (int)First << S.Context.getReferenceQualifiedType(e)1189<< ConstraintExpr->getNamedConcept();1190} else {1191S.Diag(ConstraintExpr->getBeginLoc(),1192diag::note_expr_requirement_constraints_not_satisfied)1193<< (int)First << ConstraintExpr;1194}1195S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());1196break;1197}1198case concepts::ExprRequirement::SS_Satisfied:1199llvm_unreachable("We checked this above");1200}1201}12021203static void diagnoseUnsatisfiedRequirement(Sema &S,1204concepts::TypeRequirement *Req,1205bool First) {1206assert(!Req->isSatisfied()1207&& "Diagnose() can only be used on an unsatisfied requirement");1208switch (Req->getSatisfactionStatus()) {1209case concepts::TypeRequirement::SS_Dependent:1210llvm_unreachable("Diagnosing a dependent requirement");1211return;1212case concepts::TypeRequirement::SS_SubstitutionFailure: {1213auto *SubstDiag = Req->getSubstitutionDiagnostic();1214if (!SubstDiag->DiagMessage.empty())1215S.Diag(SubstDiag->DiagLoc,1216diag::note_type_requirement_substitution_error) << (int)First1217<< SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;1218else1219S.Diag(SubstDiag->DiagLoc,1220diag::note_type_requirement_unknown_substitution_error)1221<< (int)First << SubstDiag->SubstitutedEntity;1222return;1223}1224default:1225llvm_unreachable("Unknown satisfaction status");1226return;1227}1228}1229static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,1230Expr *SubstExpr,1231bool First = true);12321233static void diagnoseUnsatisfiedRequirement(Sema &S,1234concepts::NestedRequirement *Req,1235bool First) {1236using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;1237for (auto &Record : Req->getConstraintSatisfaction()) {1238if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>())1239S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)1240<< (int)First << Req->getInvalidConstraintEntity()1241<< SubstDiag->second;1242else1243diagnoseWellFormedUnsatisfiedConstraintExpr(S, Record.dyn_cast<Expr *>(),1244First);1245First = false;1246}1247}12481249static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,1250Expr *SubstExpr,1251bool First) {1252SubstExpr = SubstExpr->IgnoreParenImpCasts();1253if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {1254switch (BO->getOpcode()) {1255// These two cases will in practice only be reached when using fold1256// expressions with || and &&, since otherwise the || and && will have been1257// broken down into atomic constraints during satisfaction checking.1258case BO_LOr:1259// Or evaluated to false - meaning both RHS and LHS evaluated to false.1260diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);1261diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),1262/*First=*/false);1263return;1264case BO_LAnd: {1265bool LHSSatisfied =1266BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();1267if (LHSSatisfied) {1268// LHS is true, so RHS must be false.1269diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);1270return;1271}1272// LHS is false1273diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);12741275// RHS might also be false1276bool RHSSatisfied =1277BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();1278if (!RHSSatisfied)1279diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),1280/*First=*/false);1281return;1282}1283case BO_GE:1284case BO_LE:1285case BO_GT:1286case BO_LT:1287case BO_EQ:1288case BO_NE:1289if (BO->getLHS()->getType()->isIntegerType() &&1290BO->getRHS()->getType()->isIntegerType()) {1291Expr::EvalResult SimplifiedLHS;1292Expr::EvalResult SimplifiedRHS;1293BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,1294Expr::SE_NoSideEffects,1295/*InConstantContext=*/true);1296BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,1297Expr::SE_NoSideEffects,1298/*InConstantContext=*/true);1299if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {1300S.Diag(SubstExpr->getBeginLoc(),1301diag::note_atomic_constraint_evaluated_to_false_elaborated)1302<< (int)First << SubstExpr1303<< toString(SimplifiedLHS.Val.getInt(), 10)1304<< BinaryOperator::getOpcodeStr(BO->getOpcode())1305<< toString(SimplifiedRHS.Val.getInt(), 10);1306return;1307}1308}1309break;13101311default:1312break;1313}1314} else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {1315if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {1316S.Diag(1317CSE->getSourceRange().getBegin(),1318diag::1319note_single_arg_concept_specialization_constraint_evaluated_to_false)1320<< (int)First1321<< CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()1322<< CSE->getNamedConcept();1323} else {1324S.Diag(SubstExpr->getSourceRange().getBegin(),1325diag::note_concept_specialization_constraint_evaluated_to_false)1326<< (int)First << CSE;1327}1328S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());1329return;1330} else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {1331// FIXME: RequiresExpr should store dependent diagnostics.1332for (concepts::Requirement *Req : RE->getRequirements())1333if (!Req->isDependent() && !Req->isSatisfied()) {1334if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))1335diagnoseUnsatisfiedRequirement(S, E, First);1336else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))1337diagnoseUnsatisfiedRequirement(S, T, First);1338else1339diagnoseUnsatisfiedRequirement(1340S, cast<concepts::NestedRequirement>(Req), First);1341break;1342}1343return;1344} else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);1345TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {1346assert(TTE->getNumArgs() == 2);1347S.Diag(SubstExpr->getSourceRange().getBegin(),1348diag::note_is_deducible_constraint_evaluated_to_false)1349<< TTE->getArg(0)->getType() << TTE->getArg(1)->getType();1350return;1351}13521353S.Diag(SubstExpr->getSourceRange().getBegin(),1354diag::note_atomic_constraint_evaluated_to_false)1355<< (int)First << SubstExpr;1356}13571358template <typename SubstitutionDiagnostic>1359static void diagnoseUnsatisfiedConstraintExpr(1360Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,1361bool First = true) {1362if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) {1363S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)1364<< Diag->second;1365return;1366}13671368diagnoseWellFormedUnsatisfiedConstraintExpr(S,1369Record.template get<Expr *>(), First);1370}13711372void1373Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,1374bool First) {1375assert(!Satisfaction.IsSatisfied &&1376"Attempted to diagnose a satisfied constraint");1377for (auto &Record : Satisfaction.Details) {1378diagnoseUnsatisfiedConstraintExpr(*this, Record, First);1379First = false;1380}1381}13821383void Sema::DiagnoseUnsatisfiedConstraint(1384const ASTConstraintSatisfaction &Satisfaction,1385bool First) {1386assert(!Satisfaction.IsSatisfied &&1387"Attempted to diagnose a satisfied constraint");1388for (auto &Record : Satisfaction) {1389diagnoseUnsatisfiedConstraintExpr(*this, Record, First);1390First = false;1391}1392}13931394const NormalizedConstraint *1395Sema::getNormalizedAssociatedConstraints(1396NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {1397// In case the ConstrainedDecl comes from modules, it is necessary to use1398// the canonical decl to avoid different atomic constraints with the 'same'1399// declarations.1400ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl());14011402auto CacheEntry = NormalizationCache.find(ConstrainedDecl);1403if (CacheEntry == NormalizationCache.end()) {1404auto Normalized =1405NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,1406AssociatedConstraints);1407CacheEntry =1408NormalizationCache1409.try_emplace(ConstrainedDecl,1410Normalized1411? new (Context) NormalizedConstraint(1412std::move(*Normalized))1413: nullptr)1414.first;1415}1416return CacheEntry->second;1417}14181419const NormalizedConstraint *clang::getNormalizedAssociatedConstraints(1420Sema &S, NamedDecl *ConstrainedDecl,1421ArrayRef<const Expr *> AssociatedConstraints) {1422return S.getNormalizedAssociatedConstraints(ConstrainedDecl,1423AssociatedConstraints);1424}14251426static bool1427substituteParameterMappings(Sema &S, NormalizedConstraint &N,1428ConceptDecl *Concept,1429const MultiLevelTemplateArgumentList &MLTAL,1430const ASTTemplateArgumentListInfo *ArgsAsWritten) {14311432if (N.isCompound()) {1433if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,1434ArgsAsWritten))1435return true;1436return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,1437ArgsAsWritten);1438}14391440if (N.isFoldExpanded()) {1441Sema::ArgumentPackSubstitutionIndexRAII _(S, -1);1442return substituteParameterMappings(1443S, N.getFoldExpandedConstraint()->Constraint, Concept, MLTAL,1444ArgsAsWritten);1445}14461447TemplateParameterList *TemplateParams = Concept->getTemplateParameters();14481449AtomicConstraint &Atomic = *N.getAtomicConstraint();1450TemplateArgumentListInfo SubstArgs;1451if (!Atomic.ParameterMapping) {1452llvm::SmallBitVector OccurringIndices(TemplateParams->size());1453S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,1454/*Depth=*/0, OccurringIndices);1455TemplateArgumentLoc *TempArgs =1456new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];1457for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)1458if (OccurringIndices[I])1459new (&(TempArgs)[J++])1460TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(1461TemplateParams->begin()[I],1462// Here we assume we do not support things like1463// template<typename A, typename B>1464// concept C = ...;1465//1466// template<typename... Ts> requires C<Ts...>1467// struct S { };1468// The above currently yields a diagnostic.1469// We still might have default arguments for concept parameters.1470ArgsAsWritten->NumTemplateArgs > I1471? ArgsAsWritten->arguments()[I].getLocation()1472: SourceLocation()));1473Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());1474}1475SourceLocation InstLocBegin =1476ArgsAsWritten->arguments().empty()1477? ArgsAsWritten->getLAngleLoc()1478: ArgsAsWritten->arguments().front().getSourceRange().getBegin();1479SourceLocation InstLocEnd =1480ArgsAsWritten->arguments().empty()1481? ArgsAsWritten->getRAngleLoc()1482: ArgsAsWritten->arguments().front().getSourceRange().getEnd();1483Sema::InstantiatingTemplate Inst(1484S, InstLocBegin,1485Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,1486{InstLocBegin, InstLocEnd});1487if (Inst.isInvalid())1488return true;1489if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))1490return true;14911492TemplateArgumentLoc *TempArgs =1493new (S.Context) TemplateArgumentLoc[SubstArgs.size()];1494std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),1495TempArgs);1496Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());1497return false;1498}14991500static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,1501const ConceptSpecializationExpr *CSE) {1502MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(1503CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),1504/*Final=*/false, CSE->getTemplateArguments(),1505/*RelativeToPrimary=*/true,1506/*Pattern=*/nullptr,1507/*ForConstraintInstantiation=*/true);15081509return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,1510CSE->getTemplateArgsAsWritten());1511}15121513NormalizedConstraint::NormalizedConstraint(ASTContext &C,1514NormalizedConstraint LHS,1515NormalizedConstraint RHS,1516CompoundConstraintKind Kind)1517: Constraint{CompoundConstraint{1518new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},1519Kind}} {}15201521NormalizedConstraint::NormalizedConstraint(ASTContext &C,1522const NormalizedConstraint &Other) {1523if (Other.isAtomic()) {1524Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());1525} else if (Other.isFoldExpanded()) {1526Constraint = new (C) FoldExpandedConstraint(1527Other.getFoldExpandedConstraint()->Kind,1528NormalizedConstraint(C, Other.getFoldExpandedConstraint()->Constraint),1529Other.getFoldExpandedConstraint()->Pattern);1530} else {1531Constraint = CompoundConstraint(1532new (C)1533NormalizedConstraintPair{NormalizedConstraint(C, Other.getLHS()),1534NormalizedConstraint(C, Other.getRHS())},1535Other.getCompoundKind());1536}1537}15381539NormalizedConstraint &NormalizedConstraint::getLHS() const {1540assert(isCompound() && "getLHS called on a non-compound constraint.");1541return Constraint.get<CompoundConstraint>().getPointer()->LHS;1542}15431544NormalizedConstraint &NormalizedConstraint::getRHS() const {1545assert(isCompound() && "getRHS called on a non-compound constraint.");1546return Constraint.get<CompoundConstraint>().getPointer()->RHS;1547}15481549std::optional<NormalizedConstraint>1550NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,1551ArrayRef<const Expr *> E) {1552assert(E.size() != 0);1553auto Conjunction = fromConstraintExpr(S, D, E[0]);1554if (!Conjunction)1555return std::nullopt;1556for (unsigned I = 1; I < E.size(); ++I) {1557auto Next = fromConstraintExpr(S, D, E[I]);1558if (!Next)1559return std::nullopt;1560*Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),1561std::move(*Next), CCK_Conjunction);1562}1563return Conjunction;1564}15651566std::optional<NormalizedConstraint>1567NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {1568assert(E != nullptr);15691570// C++ [temp.constr.normal]p1.11571// [...]1572// - The normal form of an expression (E) is the normal form of E.1573// [...]1574E = E->IgnoreParenImpCasts();15751576// C++2a [temp.param]p4:1577// [...] If T is not a pack, then E is E', otherwise E is (E' && ...).1578// Fold expression is considered atomic constraints per current wording.1579// See http://cplusplus.github.io/concepts-ts/ts-active.html#2815801581if (LogicalBinOp BO = E) {1582auto LHS = fromConstraintExpr(S, D, BO.getLHS());1583if (!LHS)1584return std::nullopt;1585auto RHS = fromConstraintExpr(S, D, BO.getRHS());1586if (!RHS)1587return std::nullopt;15881589return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),1590BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);1591} else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {1592const NormalizedConstraint *SubNF;1593{1594Sema::InstantiatingTemplate Inst(1595S, CSE->getExprLoc(),1596Sema::InstantiatingTemplate::ConstraintNormalization{}, D,1597CSE->getSourceRange());1598if (Inst.isInvalid())1599return std::nullopt;1600// C++ [temp.constr.normal]p1.11601// [...]1602// The normal form of an id-expression of the form C<A1, A2, ..., AN>,1603// where C names a concept, is the normal form of the1604// constraint-expression of C, after substituting A1, A2, ..., AN for C’s1605// respective template parameters in the parameter mappings in each atomic1606// constraint. If any such substitution results in an invalid type or1607// expression, the program is ill-formed; no diagnostic is required.1608// [...]1609ConceptDecl *CD = CSE->getNamedConcept();1610SubNF = S.getNormalizedAssociatedConstraints(CD,1611{CD->getConstraintExpr()});1612if (!SubNF)1613return std::nullopt;1614}16151616std::optional<NormalizedConstraint> New;1617New.emplace(S.Context, *SubNF);16181619if (substituteParameterMappings(S, *New, CSE))1620return std::nullopt;16211622return New;1623} else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);1624FE && S.getLangOpts().CPlusPlus26 &&1625(FE->getOperator() == BinaryOperatorKind::BO_LAnd ||1626FE->getOperator() == BinaryOperatorKind::BO_LOr)) {16271628// Normalize fold expressions in C++26.16291630FoldExpandedConstraint::FoldOperatorKind Kind =1631FE->getOperator() == BinaryOperatorKind::BO_LAnd1632? FoldExpandedConstraint::FoldOperatorKind::And1633: FoldExpandedConstraint::FoldOperatorKind::Or;16341635if (FE->getInit()) {1636auto LHS = fromConstraintExpr(S, D, FE->getLHS());1637auto RHS = fromConstraintExpr(S, D, FE->getRHS());1638if (!LHS || !RHS)1639return std::nullopt;16401641if (FE->isRightFold())1642RHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{1643Kind, std::move(*RHS), FE->getPattern()}};1644else1645LHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{1646Kind, std::move(*LHS), FE->getPattern()}};16471648return NormalizedConstraint(1649S.Context, std::move(*LHS), std::move(*RHS),1650FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction1651: CCK_Disjunction);1652}1653auto Sub = fromConstraintExpr(S, D, FE->getPattern());1654if (!Sub)1655return std::nullopt;1656return NormalizedConstraint{new (S.Context) FoldExpandedConstraint{1657Kind, std::move(*Sub), FE->getPattern()}};1658}16591660return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};1661}16621663bool FoldExpandedConstraint::AreCompatibleForSubsumption(1664const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) {16651666// [C++26] [temp.constr.fold]1667// Two fold expanded constraints are compatible for subsumption1668// if their respective constraints both contain an equivalent unexpanded pack.16691670llvm::SmallVector<UnexpandedParameterPack> APacks, BPacks;1671Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.Pattern), APacks);1672Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks);16731674for (const UnexpandedParameterPack &APack : APacks) {1675std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack);1676auto it = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {1677return getDepthAndIndex(BPack) == DepthAndIndex;1678});1679if (it != BPacks.end())1680return true;1681}1682return false;1683}16841685NormalForm clang::makeCNF(const NormalizedConstraint &Normalized) {1686if (Normalized.isAtomic())1687return {{Normalized.getAtomicConstraint()}};16881689else if (Normalized.isFoldExpanded())1690return {{Normalized.getFoldExpandedConstraint()}};16911692NormalForm LCNF = makeCNF(Normalized.getLHS());1693NormalForm RCNF = makeCNF(Normalized.getRHS());1694if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {1695LCNF.reserve(LCNF.size() + RCNF.size());1696while (!RCNF.empty())1697LCNF.push_back(RCNF.pop_back_val());1698return LCNF;1699}17001701// Disjunction1702NormalForm Res;1703Res.reserve(LCNF.size() * RCNF.size());1704for (auto &LDisjunction : LCNF)1705for (auto &RDisjunction : RCNF) {1706NormalForm::value_type Combined;1707Combined.reserve(LDisjunction.size() + RDisjunction.size());1708std::copy(LDisjunction.begin(), LDisjunction.end(),1709std::back_inserter(Combined));1710std::copy(RDisjunction.begin(), RDisjunction.end(),1711std::back_inserter(Combined));1712Res.emplace_back(Combined);1713}1714return Res;1715}17161717NormalForm clang::makeDNF(const NormalizedConstraint &Normalized) {1718if (Normalized.isAtomic())1719return {{Normalized.getAtomicConstraint()}};17201721else if (Normalized.isFoldExpanded())1722return {{Normalized.getFoldExpandedConstraint()}};17231724NormalForm LDNF = makeDNF(Normalized.getLHS());1725NormalForm RDNF = makeDNF(Normalized.getRHS());1726if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {1727LDNF.reserve(LDNF.size() + RDNF.size());1728while (!RDNF.empty())1729LDNF.push_back(RDNF.pop_back_val());1730return LDNF;1731}17321733// Conjunction1734NormalForm Res;1735Res.reserve(LDNF.size() * RDNF.size());1736for (auto &LConjunction : LDNF) {1737for (auto &RConjunction : RDNF) {1738NormalForm::value_type Combined;1739Combined.reserve(LConjunction.size() + RConjunction.size());1740std::copy(LConjunction.begin(), LConjunction.end(),1741std::back_inserter(Combined));1742std::copy(RConjunction.begin(), RConjunction.end(),1743std::back_inserter(Combined));1744Res.emplace_back(Combined);1745}1746}1747return Res;1748}17491750bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,1751MutableArrayRef<const Expr *> AC1,1752NamedDecl *D2,1753MutableArrayRef<const Expr *> AC2,1754bool &Result) {1755if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {1756auto IsExpectedEntity = [](const FunctionDecl *FD) {1757FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();1758return Kind == FunctionDecl::TK_NonTemplate ||1759Kind == FunctionDecl::TK_FunctionTemplate;1760};1761const auto *FD2 = dyn_cast<FunctionDecl>(D2);1762(void)IsExpectedEntity;1763(void)FD1;1764(void)FD2;1765assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&1766"use non-instantiated function declaration for constraints partial "1767"ordering");1768}17691770if (AC1.empty()) {1771Result = AC2.empty();1772return false;1773}1774if (AC2.empty()) {1775// TD1 has associated constraints and TD2 does not.1776Result = true;1777return false;1778}17791780std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};1781auto CacheEntry = SubsumptionCache.find(Key);1782if (CacheEntry != SubsumptionCache.end()) {1783Result = CacheEntry->second;1784return false;1785}17861787unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);1788unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);17891790for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {1791if (Depth2 > Depth1) {1792AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)1793.TransformExpr(const_cast<Expr *>(AC1[I]))1794.get();1795} else if (Depth1 > Depth2) {1796AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)1797.TransformExpr(const_cast<Expr *>(AC2[I]))1798.get();1799}1800}18011802if (clang::subsumes(1803*this, D1, AC1, D2, AC2, Result,1804[this](const AtomicConstraint &A, const AtomicConstraint &B) {1805return A.subsumes(Context, B);1806}))1807return true;1808SubsumptionCache.try_emplace(Key, Result);1809return false;1810}18111812bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,1813ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {1814if (isSFINAEContext())1815// No need to work here because our notes would be discarded.1816return false;18171818if (AC1.empty() || AC2.empty())1819return false;18201821auto NormalExprEvaluator =1822[this] (const AtomicConstraint &A, const AtomicConstraint &B) {1823return A.subsumes(Context, B);1824};18251826const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;1827auto IdenticalExprEvaluator =1828[&] (const AtomicConstraint &A, const AtomicConstraint &B) {1829if (!A.hasMatchingParameterMapping(Context, B))1830return false;1831const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;1832if (EA == EB)1833return true;18341835// Not the same source level expression - are the expressions1836// identical?1837llvm::FoldingSetNodeID IDA, IDB;1838EA->Profile(IDA, Context, /*Canonical=*/true);1839EB->Profile(IDB, Context, /*Canonical=*/true);1840if (IDA != IDB)1841return false;18421843AmbiguousAtomic1 = EA;1844AmbiguousAtomic2 = EB;1845return true;1846};18471848{1849// The subsumption checks might cause diagnostics1850SFINAETrap Trap(*this);1851auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);1852if (!Normalized1)1853return false;1854const NormalForm DNF1 = makeDNF(*Normalized1);1855const NormalForm CNF1 = makeCNF(*Normalized1);18561857auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);1858if (!Normalized2)1859return false;1860const NormalForm DNF2 = makeDNF(*Normalized2);1861const NormalForm CNF2 = makeCNF(*Normalized2);18621863bool Is1AtLeastAs2Normally =1864clang::subsumes(DNF1, CNF2, NormalExprEvaluator);1865bool Is2AtLeastAs1Normally =1866clang::subsumes(DNF2, CNF1, NormalExprEvaluator);1867bool Is1AtLeastAs2 = clang::subsumes(DNF1, CNF2, IdenticalExprEvaluator);1868bool Is2AtLeastAs1 = clang::subsumes(DNF2, CNF1, IdenticalExprEvaluator);1869if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&1870Is2AtLeastAs1 == Is2AtLeastAs1Normally)1871// Same result - no ambiguity was caused by identical atomic expressions.1872return false;1873}18741875// A different result! Some ambiguous atomic constraint(s) caused a difference1876assert(AmbiguousAtomic1 && AmbiguousAtomic2);18771878Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)1879<< AmbiguousAtomic1->getSourceRange();1880Diag(AmbiguousAtomic2->getBeginLoc(),1881diag::note_ambiguous_atomic_constraints_similar_expression)1882<< AmbiguousAtomic2->getSourceRange();1883return true;1884}18851886concepts::ExprRequirement::ExprRequirement(1887Expr *E, bool IsSimple, SourceLocation NoexceptLoc,1888ReturnTypeRequirement Req, SatisfactionStatus Status,1889ConceptSpecializationExpr *SubstitutedConstraintExpr) :1890Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,1891Status == SS_Dependent &&1892(E->containsUnexpandedParameterPack() ||1893Req.containsUnexpandedParameterPack()),1894Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),1895TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),1896Status(Status) {1897assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&1898"Simple requirement must not have a return type requirement or a "1899"noexcept specification");1900assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==1901(SubstitutedConstraintExpr != nullptr));1902}19031904concepts::ExprRequirement::ExprRequirement(1905SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,1906SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :1907Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),1908Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),1909Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),1910Status(SS_ExprSubstitutionFailure) {1911assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&1912"Simple requirement must not have a return type requirement or a "1913"noexcept specification");1914}19151916concepts::ExprRequirement::ReturnTypeRequirement::1917ReturnTypeRequirement(TemplateParameterList *TPL) :1918TypeConstraintInfo(TPL, false) {1919assert(TPL->size() == 1);1920const TypeConstraint *TC =1921cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();1922assert(TC &&1923"TPL must have a template type parameter with a type constraint");1924auto *Constraint =1925cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());1926bool Dependent =1927Constraint->getTemplateArgsAsWritten() &&1928TemplateSpecializationType::anyInstantiationDependentTemplateArguments(1929Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));1930TypeConstraintInfo.setInt(Dependent ? true : false);1931}19321933concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :1934Requirement(RK_Type, T->getType()->isInstantiationDependentType(),1935T->getType()->containsUnexpandedParameterPack(),1936// We reach this ctor with either dependent types (in which1937// IsSatisfied doesn't matter) or with non-dependent type in1938// which the existence of the type indicates satisfaction.1939/*IsSatisfied=*/true),1940Value(T),1941Status(T->getType()->isInstantiationDependentType() ? SS_Dependent1942: SS_Satisfied) {}194319441945