26 #include "llvm/ADT/DenseMap.h"
27 #include "llvm/ADT/PointerUnion.h"
28 using namespace clang;
34 const Expr *LHS =
nullptr;
35 const Expr *RHS =
nullptr;
38 LogicalBinOp(
const Expr *E) {
39 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
43 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
44 Op = OO->getOperator();
50 bool isAnd()
const {
return Op == OO_AmpAmp; }
51 bool isOr()
const {
return Op == OO_PipePipe; }
52 explicit operator bool()
const {
return isAnd() || isOr(); }
54 const Expr *getLHS()
const {
return LHS; }
55 const Expr *getRHS()
const {
return RHS; }
60 Token NextToken,
bool *PossibleNonPrimary,
61 bool IsTrailingRequiresClause) {
67 if (LogicalBinOp BO = ConstraintExpression) {
68 return CheckConstraintExpression(BO.getLHS(), NextToken,
69 PossibleNonPrimary) &&
70 CheckConstraintExpression(BO.getRHS(), NextToken,
72 }
else if (
auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
73 return CheckConstraintExpression(C->getSubExpr(), NextToken,
78 auto CheckForNonPrimary = [&] {
79 if (PossibleNonPrimary)
86 (NextToken.
is(tok::l_paren) &&
87 (IsTrailingRequiresClause ||
89 isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
104 CheckForNonPrimary();
110 diag::err_non_bool_atomic_constraint) <<
Type
112 CheckForNonPrimary();
116 if (PossibleNonPrimary)
117 *PossibleNonPrimary =
false;
121 template <
typename AtomicEvaluator>
125 AtomicEvaluator &&Evaluator) {
128 if (LogicalBinOp BO = ConstraintExpr) {
135 if (BO.isOr() && IsLHSSatisfied)
144 if (BO.isAnd() && !IsLHSSatisfied)
154 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
155 }
else if (
auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
157 std::forward<AtomicEvaluator>(Evaluator));
161 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
166 if (!SubstitutedAtomicExpr.
isUsable())
174 EvalResult.
Diag = &EvaluationDiags;
179 diag::err_non_constant_constraint_expression)
182 S.
Diag(PDiag.first, PDiag.second);
188 Satisfaction.
Details.emplace_back(ConstraintExpr,
189 SubstitutedAtomicExpr.
get());
238 unsigned MessageSize = DiagString.size();
239 char *Mem =
new (S.
Context)
char[MessageSize];
240 memcpy(Mem, DiagString.c_str(), MessageSize);
241 Satisfaction.
Details.emplace_back(
244 SubstDiag.first, StringRef(Mem, MessageSize)});
253 return SubstitutedExpression;
262 if (ConstraintExprs.empty()) {
267 for (
auto& Arg : TemplateArgs)
268 if (Arg.isInstantiationDependent()) {
276 const_cast<NamedDecl *
>(Template), TemplateArgs, TemplateIDRange);
283 for (
const Expr *ConstraintExpr : ConstraintExprs) {
286 ConstraintExpr, Satisfaction))
302 if (ConstraintExprs.empty()) {
307 llvm::FoldingSetNodeID
ID;
310 bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
313 Satisfaction = SatisfactionCache.FindNodeOrInsertPos(
ID, InsertPos);
315 OutSatisfaction = *Satisfaction;
320 Satisfaction = &OutSatisfaction;
323 TemplateArgs, TemplateIDRange,
333 SatisfactionCache.InsertNode(Satisfaction);
334 OutSatisfaction = *Satisfaction;
342 *
this, ConstraintExpr, Satisfaction,
358 if (
auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
359 ThisQuals = Method->getMethodQualifiers();
379 TemplateIDRange, Satisfaction))
384 TemplateArgString =
" ";
385 TemplateArgString += getTemplateArgumentBindingsText(
389 diag::err_template_arg_list_constraints_not_satisfied)
391 << TemplateArgString << TemplateIDRange;
392 DiagnoseUnsatisfiedConstraint(Satisfaction);
402 &&
"Diagnose() can only be used on an unsatisfied requirement");
405 llvm_unreachable(
"Diagnosing a dependent requirement");
409 if (!SubstDiag->DiagMessage.empty())
410 S.
Diag(SubstDiag->DiagLoc,
411 diag::note_expr_requirement_expr_substitution_error)
412 << (
int)
First << SubstDiag->SubstitutedEntity
413 << SubstDiag->DiagMessage;
415 S.
Diag(SubstDiag->DiagLoc,
416 diag::note_expr_requirement_expr_unknown_substitution_error)
417 << (
int)
First << SubstDiag->SubstitutedEntity;
422 diag::note_expr_requirement_noexcept_not_met)
428 if (!SubstDiag->DiagMessage.empty())
429 S.
Diag(SubstDiag->DiagLoc,
430 diag::note_expr_requirement_type_requirement_substitution_error)
431 << (
int)
First << SubstDiag->SubstitutedEntity
432 << SubstDiag->DiagMessage;
434 S.
Diag(SubstDiag->DiagLoc,
435 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
436 << (
int)
First << SubstDiag->SubstitutedEntity;
447 diag::note_expr_requirement_constraints_not_satisfied_simple)
452 diag::note_expr_requirement_constraints_not_satisfied)
453 << (
int)
First << ConstraintExpr;
459 llvm_unreachable(
"We checked this above");
467 &&
"Diagnose() can only be used on an unsatisfied requirement");
470 llvm_unreachable(
"Diagnosing a dependent requirement");
474 if (!SubstDiag->DiagMessage.empty())
475 S.
Diag(SubstDiag->DiagLoc,
476 diag::note_type_requirement_substitution_error) << (
int)
First
477 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
479 S.
Diag(SubstDiag->DiagLoc,
480 diag::note_type_requirement_unknown_substitution_error)
481 << (
int)
First << SubstDiag->SubstitutedEntity;
485 llvm_unreachable(
"Unknown satisfaction status");
498 diag::note_nested_requirement_substitution_error)
503 diag::note_nested_requirement_unknown_substitution_error)
516 switch (BO->getOpcode()) {
528 BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.
Context);
539 BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.
Context);
550 if (BO->getLHS()->getType()->isIntegerType() &&
551 BO->getRHS()->getType()->isIntegerType()) {
554 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context);
555 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context);
556 if (!SimplifiedLHS.
Diag && ! SimplifiedRHS.
Diag) {
558 diag::note_atomic_constraint_evaluated_to_false_elaborated)
560 << SimplifiedLHS.
Val.
getInt().toString(10)
562 << SimplifiedRHS.
Val.
getInt().toString(10);
571 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
572 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
574 CSE->getSourceRange().getBegin(),
576 note_single_arg_concept_specialization_constraint_evaluated_to_false)
578 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
579 << CSE->getNamedConcept();
582 diag::note_concept_specialization_constraint_evaluated_to_false)
583 << (
int)
First << CSE;
587 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
589 if (!Req->isDependent() && !Req->isSatisfied()) {
590 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
592 else if (
auto *T = dyn_cast<concepts::TypeRequirement>(Req))
596 S, cast<concepts::NestedRequirement>(Req),
First);
603 diag::note_atomic_constraint_evaluated_to_false)
607 template<
typename SubstitutionDiagnostic>
610 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
612 if (
auto *
Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
613 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
619 Record.template get<Expr *>(),
First);
626 "Attempted to diagnose a satisfied constraint");
627 for (
auto &Pair : Satisfaction.
Details) {
637 "Attempted to diagnose a satisfied constraint");
638 for (
auto &Pair : Satisfaction) {
647 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
648 if (CacheEntry == NormalizationCache.end()) {
650 NormalizedConstraint::fromConstraintExprs(*
this, ConstrainedDecl,
651 AssociatedConstraints);
654 .try_emplace(ConstrainedDecl,
657 std::move(*Normalized))
661 return CacheEntry->second;
681 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
683 0, OccurringIndices);
687 OccurringIndices.count()));
688 for (
unsigned I = 0, J = 0, C = TemplateParams->
size(); I != C; ++I)
689 if (OccurringIndices[I])
701 ArgsAsWritten->
arguments()[I].getLocation() :
705 S, ArgsAsWritten->
arguments().front().getSourceRange().getBegin(),
708 ArgsAsWritten->
arguments().back().getSourceRange().getEnd()));
721 NormalizedConstraint::fromConstraintExprs(
Sema &S,
NamedDecl *D,
723 assert(E.size() != 0);
724 auto First = fromConstraintExpr(S, D, E[0]);
727 auto Second = fromConstraintExpr(S, D, E[1]);
731 Conjunction.emplace(S.
Context, std::move(*First), std::move(*Second),
733 for (
unsigned I = 2; I < E.size(); ++I) {
734 auto Next = fromConstraintExpr(S, D, E[I]);
738 std::move(*Next), CCK_Conjunction);
739 *Conjunction = std::move(NewConjunction);
746 assert(E !=
nullptr);
753 if (LogicalBinOp BO = E) {
754 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
757 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
762 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
763 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
767 S, CSE->getExprLoc(),
769 CSE->getSourceRange());
787 New.emplace(S.
Context, *SubNF);
790 S, *New, CSE->getNamedConcept(),
791 CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
809 LCNF.reserve(LCNF.size() + RCNF.size());
810 while (!RCNF.empty())
811 LCNF.push_back(RCNF.pop_back_val());
817 Res.reserve(LCNF.size() * RCNF.size());
818 for (
auto &LDisjunction : LCNF)
819 for (
auto &RDisjunction : RCNF) {
820 NormalForm::value_type Combined;
821 Combined.reserve(LDisjunction.size() + RDisjunction.size());
822 std::copy(LDisjunction.begin(), LDisjunction.end(),
823 std::back_inserter(Combined));
824 std::copy(RDisjunction.begin(), RDisjunction.end(),
825 std::back_inserter(Combined));
826 Res.emplace_back(Combined);
838 LDNF.reserve(LDNF.size() + RDNF.size());
839 while (!RDNF.empty())
840 LDNF.push_back(RDNF.pop_back_val());
846 Res.reserve(LDNF.size() * RDNF.size());
847 for (
auto &LConjunction : LDNF) {
848 for (
auto &RConjunction : RDNF) {
849 NormalForm::value_type Combined;
850 Combined.reserve(LConjunction.size() + RConjunction.size());
851 std::copy(LConjunction.begin(), LConjunction.end(),
852 std::back_inserter(Combined));
853 std::copy(RConjunction.begin(), RConjunction.end(),
854 std::back_inserter(Combined));
855 Res.emplace_back(Combined);
861 template<
typename AtomicSubsumptionEvaluator>
863 AtomicSubsumptionEvaluator E) {
868 for (
const auto &Pi : PDNF) {
869 for (
const auto &Qj : QCNF) {
893 template<
typename AtomicSubsumptionEvaluator>
896 AtomicSubsumptionEvaluator E) {
919 Result = AC2.empty();
928 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
929 auto CacheEntry = SubsumptionCache.find(Key);
930 if (CacheEntry != SubsumptionCache.end()) {
931 Result = CacheEntry->second;
935 if (
subsumes(*
this, D1, AC1, D2, AC2, Result,
940 SubsumptionCache.try_emplace(Key, Result);
946 if (isSFINAEContext())
950 if (AC1.empty() || AC2.empty())
953 auto NormalExprEvaluator =
958 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
959 auto IdenticalExprEvaluator =
969 llvm::FoldingSetNodeID IDA, IDB;
970 EA->
Profile(IDA, Context,
true);
971 EB->Profile(IDB, Context,
true);
975 AmbiguousAtomic1 = EA;
976 AmbiguousAtomic2 = EB;
983 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
989 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
995 bool Is1AtLeastAs2Normally =
subsumes(DNF1, CNF2, NormalExprEvaluator);
996 bool Is2AtLeastAs1Normally =
subsumes(DNF2, CNF1, NormalExprEvaluator);
997 bool Is1AtLeastAs2 =
subsumes(DNF1, CNF2, IdenticalExprEvaluator);
998 bool Is2AtLeastAs1 =
subsumes(DNF2, CNF1, IdenticalExprEvaluator);
999 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1000 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1006 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1008 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1010 Diag(AmbiguousAtomic2->getBeginLoc(),
1011 diag::note_ambiguous_atomic_constraints_similar_expression)
1012 << AmbiguousAtomic2->getSourceRange();
1020 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1021 Status == SS_Dependent &&
1022 (E->containsUnexpandedParameterPack() ||
1023 Req.containsUnexpandedParameterPack()),
1024 Status == SS_Satisfied),
Value(E), NoexceptLoc(NoexceptLoc),
1025 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1028 "Simple requirement must not have a return type requirement or a "
1029 "noexcept specification");
1031 (SubstitutedConstraintExpr !=
nullptr));
1037 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1038 Req.containsUnexpandedParameterPack(),
false),
1039 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1040 Status(SS_ExprSubstitutionFailure) {
1042 "Simple requirement must not have a return type requirement or a "
1043 "noexcept specification");
1048 TypeConstraintInfo(TPL, 0) {
1049 assert(TPL->
size() == 1);
1051 cast<TemplateTypeParmDecl>(TPL->
getParam(0))->getTypeConstraint();
1053 "TPL must have a template type parameter with a type constraint");
1055 cast_or_null<ConceptSpecializationExpr>(
1058 Constraint->getTemplateArgsAsWritten() &&
1060 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1061 TypeConstraintInfo.setInt(Dependent ? 1 : 0);
1072 Status(T->getType()->isInstantiationDependentType() ?
SS_Dependent