26#include "llvm/ADT/DenseMap.h"
27#include "llvm/ADT/PointerUnion.h"
28#include "llvm/ADT/StringExtras.h"
38 const Expr *LHS =
nullptr;
39 const Expr *RHS =
nullptr;
42 LogicalBinOp(
const Expr *E) {
43 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
47 Loc = BO->getExprLoc();
48 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
50 if (OO->getNumArgs() == 2) {
51 Op = OO->getOperator();
54 Loc = OO->getOperatorLoc();
59 bool isAnd()
const {
return Op == OO_AmpAmp; }
60 bool isOr()
const {
return Op == OO_PipePipe; }
61 explicit operator bool()
const {
return isAnd() || isOr(); }
63 const Expr *getLHS()
const {
return LHS; }
64 const Expr *getRHS()
const {
return RHS; }
67 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
72 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
89 Token NextToken,
bool *PossibleNonPrimary,
90 bool IsTrailingRequiresClause) {
96 if (LogicalBinOp BO = ConstraintExpression) {
98 PossibleNonPrimary) &&
101 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
107 auto CheckForNonPrimary = [&] {
108 if (!PossibleNonPrimary)
111 *PossibleNonPrimary =
122 (NextToken.
is(tok::l_paren) &&
123 (IsTrailingRequiresClause ||
125 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
141 CheckForNonPrimary();
147 diag::err_non_bool_atomic_constraint) <<
Type
149 CheckForNonPrimary();
153 if (PossibleNonPrimary)
154 *PossibleNonPrimary =
false;
159struct SatisfactionStackRAII {
161 bool Inserted =
false;
163 llvm::FoldingSetNodeID FSNID)
170 ~SatisfactionStackRAII() {
177template <
typename AtomicEvaluator>
181 AtomicEvaluator &&Evaluator) {
184 if (LogicalBinOp BO = ConstraintExpr) {
186 S, BO.getLHS(), Satisfaction, Evaluator);
193 if (BO.isOr() && IsLHSSatisfied)
203 if (BO.isAnd() && !IsLHSSatisfied)
214 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
218 return BO.recreateBinOp(S, LHSRes, RHSRes);
221 if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
225 S,
C->getSubExpr(), Satisfaction,
226 std::forward<AtomicEvaluator>(Evaluator));
230 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
235 if (!SubstitutedAtomicExpr.
isUsable())
252 unsigned MessageSize = DiagString.size();
253 char *Mem =
new (S.
Context)
char[MessageSize];
254 memcpy(Mem, DiagString.c_str(), MessageSize);
255 Satisfaction.
Details.emplace_back(
258 SubstitutedAtomicExpr.get()->getBeginLoc(),
259 StringRef(Mem, MessageSize)});
260 return SubstitutedAtomicExpr;
267 EvalResult.
Diag = &EvaluationDiags;
270 !EvaluationDiags.empty()) {
274 diag::err_non_constant_constraint_expression)
277 S.
Diag(PDiag.first, PDiag.second);
282 "evaluating bool expression didn't produce int");
285 Satisfaction.
Details.emplace_back(ConstraintExpr,
286 SubstitutedAtomicExpr.
get());
288 return SubstitutedAtomicExpr;
296 for (
const auto &List : MLTAL)
336 llvm::FoldingSetNodeID ID;
344 SatisfactionStackRAII StackRAII(S, Template, ID);
348 SubstitutedExpression =
372 unsigned MessageSize = DiagString.size();
373 char *Mem =
new (S.
Context)
char[MessageSize];
374 memcpy(Mem, DiagString.c_str(), MessageSize);
375 Satisfaction.
Details.emplace_back(
378 SubstDiag.first, StringRef(Mem, MessageSize)});
400 CK_LValueToRValue, SubstitutedExpression.
get(),
403 return SubstitutedExpression;
412 if (ConstraintExprs.empty()) {
429 const_cast<NamedDecl *
>(Template), TemplateArgs, TemplateIDRange);
433 for (
const Expr *ConstraintExpr : ConstraintExprs) {
435 S, Template, TemplateIDRange.
getBegin(), TemplateArgsLists,
436 ConstraintExpr, Satisfaction);
440 Converted.push_back(Res.
get());
444 Converted.append(ConstraintExprs.size() - Converted.size(),
nullptr);
460 if (ConstraintExprs.empty()) {
465 return ::CheckConstraintSatisfaction(
466 *
this,
nullptr, ConstraintExprs, ConvertedConstraints,
467 TemplateArgsLists, TemplateIDRange, OutSatisfaction);
475 for (
auto List : TemplateArgsLists)
476 FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
479 llvm::FoldingSetNodeID ID;
482 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
483 OutSatisfaction = *Cached;
488 std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
490 ConvertedConstraints, TemplateArgsLists,
491 TemplateIDRange, *Satisfaction)) {
492 OutSatisfaction = *Satisfaction;
496 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
505 OutSatisfaction = *Cached;
510 OutSatisfaction = *Satisfaction;
514 SatisfactionCache.InsertNode(Satisfaction.release());
521 *
this, ConstraintExpr, Satisfaction,
530bool Sema::addInstantiatedCapturesToScope(
534 const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
535 const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
537 unsigned Instantiated = 0;
539 auto AddSingleCapture = [&](
const ValueDecl *CapturedPattern,
541 ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
542 if (cast<CXXMethodDecl>(Function)->isConst()) {
548 Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
551 for (
const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
552 if (!CapturePattern.capturesVariable()) {
556 const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
558 AddSingleCapture(CapturedPattern, Instantiated++);
560 Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
561 std::optional<unsigned> NumArgumentsInExpansion =
563 if (!NumArgumentsInExpansion)
565 for (
unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
566 AddSingleCapture(CapturedPattern, Instantiated++);
572bool Sema::SetupConstraintScope(
577 InstantiatingTemplate Inst(
582 if (Inst.isInvalid())
593 if (addInstantiatedParametersToScope(
600 if (
const auto *FromMemTempl =
602 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
607 addInstantiatedCapturesToScope(FD, FromMemTempl->getTemplatedDecl(),
622 InstantiatingTemplate Inst(
627 if (Inst.isInvalid())
632 if (addInstantiatedParametersToScope(FD, InstantiatedFrom,
Scope, MLTAL))
637 addInstantiatedCapturesToScope(FD, InstantiatedFrom,
Scope, MLTAL))
646std::optional<MultiLevelTemplateArgumentList>
647Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
660 if (SetupConstraintScope(FD, TemplateArgs, MLTAL,
Scope))
669 bool ForOverloadResolution) {
693 std::optional<MultiLevelTemplateArgumentList> MLTAL =
694 SetupConstraintCheckingTemplateArgumentsAndScope(
702 if (
auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
703 ThisQuals = Method->getMethodQualifiers();
714 FD, {RC}, Converted, *MLTAL,
723 assert(Converted.size() <= 1 &&
"Got more expressions converted?");
724 if (!Converted.empty() && Converted[0] !=
nullptr)
725 const_cast<FunctionDecl *
>(FD)->setTrailingRequiresClause(Converted[0]);
735 bool SkipForSpecialization =
false) {
737 ND,
false,
nullptr,
true,
739 true, SkipForSpecialization);
744 class AdjustConstraintDepth :
public TreeTransform<AdjustConstraintDepth> {
745 unsigned TemplateDepth = 0;
748 AdjustConstraintDepth(
Sema &SemaRef,
unsigned TemplateDepth)
749 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
751 using inherited::TransformTemplateTypeParmType;
758 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
761 QualType Result = getSema().Context.getTemplateTypeParmType(
772 const Expr *OldConstr,
774 const Expr *NewConstr) {
775 if (Old && New && Old != New) {
783 if (Depth2 > Depth1) {
784 OldConstr = AdjustConstraintDepth(*
this, Depth2 - Depth1)
785 .TransformExpr(
const_cast<Expr *
>(OldConstr))
787 }
else if (Depth1 > Depth2) {
788 NewConstr = AdjustConstraintDepth(*
this, Depth1 - Depth2)
789 .TransformExpr(
const_cast<Expr *
>(NewConstr))
794 llvm::FoldingSetNodeID ID1, ID2;
807 "Non-function templates don't need to be checked");
813 for (
const Expr *Constraint : ACs)
828 TemplateIDRange, Satisfaction))
833 TemplateArgString =
" ";
839 diag::err_template_arg_list_constraints_not_satisfied)
841 << TemplateArgString << TemplateIDRange;
858 if (TemplateAC.empty()) {
868 std::optional<MultiLevelTemplateArgumentList> MLTAL =
869 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
877 if (
auto *Method = dyn_cast<CXXMethodDecl>(
Decl)) {
878 ThisQuals = Method->getMethodQualifiers();
879 Record = Method->getParent();
890 PointOfInstantiation, Satisfaction);
897 &&
"Diagnose() can only be used on an unsatisfied requirement");
900 llvm_unreachable(
"Diagnosing a dependent requirement");
904 if (!SubstDiag->DiagMessage.empty())
905 S.
Diag(SubstDiag->DiagLoc,
906 diag::note_expr_requirement_expr_substitution_error)
907 << (
int)
First << SubstDiag->SubstitutedEntity
908 << SubstDiag->DiagMessage;
910 S.
Diag(SubstDiag->DiagLoc,
911 diag::note_expr_requirement_expr_unknown_substitution_error)
912 << (
int)
First << SubstDiag->SubstitutedEntity;
917 diag::note_expr_requirement_noexcept_not_met)
923 if (!SubstDiag->DiagMessage.empty())
924 S.
Diag(SubstDiag->DiagLoc,
925 diag::note_expr_requirement_type_requirement_substitution_error)
926 << (
int)
First << SubstDiag->SubstitutedEntity
927 << SubstDiag->DiagMessage;
929 S.
Diag(SubstDiag->DiagLoc,
930 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
931 << (
int)
First << SubstDiag->SubstitutedEntity;
942 diag::note_expr_requirement_constraints_not_satisfied_simple)
947 diag::note_expr_requirement_constraints_not_satisfied)
948 << (
int)
First << ConstraintExpr;
954 llvm_unreachable(
"We checked this above");
962 &&
"Diagnose() can only be used on an unsatisfied requirement");
965 llvm_unreachable(
"Diagnosing a dependent requirement");
969 if (!SubstDiag->DiagMessage.empty())
970 S.
Diag(SubstDiag->DiagLoc,
971 diag::note_type_requirement_substitution_error) << (
int)
First
972 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
974 S.
Diag(SubstDiag->DiagLoc,
975 diag::note_type_requirement_unknown_substitution_error)
976 << (
int)
First << SubstDiag->SubstitutedEntity;
980 llvm_unreachable(
"Unknown satisfaction status");
991 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
993 if (
auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
994 S.
Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
998 S, Pair.second.dyn_cast<
Expr *>(),
First);
1008 switch (BO->getOpcode()) {
1020 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1031 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1043 if (BO->getLHS()->getType()->isIntegerType() &&
1044 BO->getRHS()->getType()->isIntegerType()) {
1047 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1050 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1053 if (!SimplifiedLHS.
Diag && ! SimplifiedRHS.
Diag) {
1055 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1068 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1069 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1071 CSE->getSourceRange().getBegin(),
1073 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1075 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1076 << CSE->getNamedConcept();
1079 diag::note_concept_specialization_constraint_evaluated_to_false)
1080 << (
int)
First << CSE;
1084 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1087 if (!Req->isDependent() && !Req->isSatisfied()) {
1088 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1090 else if (
auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1094 S, cast<concepts::NestedRequirement>(Req),
First);
1101 diag::note_atomic_constraint_evaluated_to_false)
1105template<
typename SubstitutionDiagnostic>
1108 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1109 bool First =
true) {
1110 if (
auto *
Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
1111 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1117 Record.template get<Expr *>(),
First);
1124 "Attempted to diagnose a satisfied constraint");
1125 for (
auto &Pair : Satisfaction.
Details) {
1135 "Attempted to diagnose a satisfied constraint");
1136 for (
auto &Pair : Satisfaction) {
1145 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1146 if (CacheEntry == NormalizationCache.end()) {
1148 NormalizedConstraint::fromConstraintExprs(*
this, ConstrainedDecl,
1149 AssociatedConstraints);
1152 .try_emplace(ConstrainedDecl,
1155 std::move(*Normalized))
1159 return CacheEntry->second;
1179 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
1181 0, OccurringIndices);
1184 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I)
1185 if (OccurringIndices[I])
1186 new (&(TempArgs)[J++])
1188 TemplateParams->
begin()[I],
1198 ? ArgsAsWritten->
arguments()[I].getLocation()
1203 S, ArgsAsWritten->
arguments().front().getSourceRange().getBegin(),
1205 ArgsAsWritten->
arguments().front().getSourceRange());
1231std::optional<NormalizedConstraint>
1232NormalizedConstraint::fromConstraintExprs(
Sema &S,
NamedDecl *D,
1234 assert(E.size() != 0);
1235 auto Conjunction = fromConstraintExpr(S, D, E[0]);
1237 return std::nullopt;
1238 for (
unsigned I = 1; I < E.size(); ++I) {
1239 auto Next = fromConstraintExpr(S, D, E[I]);
1241 return std::nullopt;
1248std::optional<NormalizedConstraint>
1250 assert(E !=
nullptr);
1263 if (LogicalBinOp BO = E) {
1264 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1266 return std::nullopt;
1267 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1269 return std::nullopt;
1273 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1277 S, CSE->getExprLoc(),
1279 CSE->getSourceRange());
1293 return std::nullopt;
1296 std::optional<NormalizedConstraint> New;
1297 New.emplace(S.
Context, *SubNF);
1300 return std::nullopt;
1317 LCNF.reserve(LCNF.size() + RCNF.size());
1318 while (!RCNF.empty())
1319 LCNF.push_back(RCNF.pop_back_val());
1325 Res.reserve(LCNF.size() * RCNF.size());
1326 for (
auto &LDisjunction : LCNF)
1327 for (
auto &RDisjunction : RCNF) {
1328 NormalForm::value_type Combined;
1329 Combined.reserve(LDisjunction.size() + RDisjunction.size());
1330 std::copy(LDisjunction.begin(), LDisjunction.end(),
1331 std::back_inserter(Combined));
1332 std::copy(RDisjunction.begin(), RDisjunction.end(),
1333 std::back_inserter(Combined));
1334 Res.emplace_back(Combined);
1346 LDNF.reserve(LDNF.size() + RDNF.size());
1347 while (!RDNF.empty())
1348 LDNF.push_back(RDNF.pop_back_val());
1354 Res.reserve(LDNF.size() * RDNF.size());
1355 for (
auto &LConjunction : LDNF) {
1356 for (
auto &RConjunction : RDNF) {
1357 NormalForm::value_type Combined;
1358 Combined.reserve(LConjunction.size() + RConjunction.size());
1359 std::copy(LConjunction.begin(), LConjunction.end(),
1360 std::back_inserter(Combined));
1361 std::copy(RConjunction.begin(), RConjunction.end(),
1362 std::back_inserter(Combined));
1363 Res.emplace_back(Combined);
1369template<
typename AtomicSubsumptionEvaluator>
1371 AtomicSubsumptionEvaluator E) {
1376 for (
const auto &Pi : PDNF) {
1377 for (
const auto &Qj : QCNF) {
1386 if (E(*Pia, *Qjb)) {
1401template<
typename AtomicSubsumptionEvaluator>
1404 AtomicSubsumptionEvaluator E) {
1419 Subsumes =
subsumes(PDNF, QCNF, E);
1428 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1434 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1435 (void)IsExpectedEntity;
1438 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1439 "use non-instantiated function declaration for constraints partial "
1453 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1454 auto CacheEntry = SubsumptionCache.find(Key);
1455 if (CacheEntry != SubsumptionCache.end()) {
1456 Result = CacheEntry->second;
1463 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1464 if (Depth2 > Depth1) {
1465 AC1[I] = AdjustConstraintDepth(*
this, Depth2 - Depth1)
1466 .TransformExpr(
const_cast<Expr *
>(AC1[I]))
1468 }
else if (Depth1 > Depth2) {
1469 AC2[I] = AdjustConstraintDepth(*
this, Depth1 - Depth2)
1470 .TransformExpr(
const_cast<Expr *
>(AC2[I]))
1480 SubsumptionCache.try_emplace(Key,
Result);
1490 if (AC1.empty() || AC2.empty())
1493 auto NormalExprEvaluator =
1498 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
1499 auto IdenticalExprEvaluator =
1509 llvm::FoldingSetNodeID IDA, IDB;
1511 EB->Profile(IDB,
Context,
true);
1515 AmbiguousAtomic1 = EA;
1516 AmbiguousAtomic2 = EB;
1535 bool Is1AtLeastAs2Normally =
subsumes(DNF1, CNF2, NormalExprEvaluator);
1536 bool Is2AtLeastAs1Normally =
subsumes(DNF2, CNF1, NormalExprEvaluator);
1537 bool Is1AtLeastAs2 =
subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1538 bool Is2AtLeastAs1 =
subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1539 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1540 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1546 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1548 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1550 Diag(AmbiguousAtomic2->getBeginLoc(),
1551 diag::note_ambiguous_atomic_constraints_similar_expression)
1552 << AmbiguousAtomic2->getSourceRange();
1560 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1561 Status == SS_Dependent &&
1562 (E->containsUnexpandedParameterPack() ||
1563 Req.containsUnexpandedParameterPack()),
1564 Status == SS_Satisfied),
Value(E), NoexceptLoc(NoexceptLoc),
1565 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1568 "Simple requirement must not have a return type requirement or a "
1569 "noexcept specification");
1571 (SubstitutedConstraintExpr !=
nullptr));
1577 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1578 Req.containsUnexpandedParameterPack(),
false),
1579 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1580 Status(SS_ExprSubstitutionFailure) {
1582 "Simple requirement must not have a return type requirement or a "
1583 "noexcept specification");
1588 TypeConstraintInfo(TPL,
false) {
1589 assert(TPL->
size() == 1);
1591 cast<TemplateTypeParmDecl>(TPL->
getParam(0))->getTypeConstraint();
1593 "TPL must have a template type parameter with a type constraint");
1597 Constraint->getTemplateArgsAsWritten() &&
1599 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1600 TypeConstraintInfo.setInt(Dependent ?
true :
false);
1611 Status(T->getType()->isInstantiationDependentType() ?
SS_Dependent
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines Expressions and AST nodes for C++2a concepts.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Defines and computes precedence levels for binary/ternary operators.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static NormalForm makeCNF(const NormalizedConstraint &Normalized)
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, llvm::SmallVectorImpl< Expr * > &Converted, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
static NormalForm makeDNF(const NormalizedConstraint &Normalized)
static ExprResult calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, AtomicEvaluator &&Evaluator)
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const Expr *E, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic * > &Record, bool First=true)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList &MLTAL)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static bool subsumes(NormalForm PDNF, NormalForm QCNF, AtomicSubsumptionEvaluator E)
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, const MultiLevelTemplateArgumentList &MLTAL, const ASTTemplateArgumentListInfo *ArgsAsWritten)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
static bool isInvalid(LocType Loc, bool *Invalid)
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
QualType getReferenceQualifiedType(const Expr *e) const
getReferenceQualifiedType - Given an expr, will return the type for that expression,...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
SourceLocation getBeginLoc() const LLVM_READONLY
A builtin binary operation expression such as "x + y" or "x <= y".
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
StringRef getOpcodeStr() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Represents a C++ struct/union/class.
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
ConceptDecl * getNamedConcept() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
llvm::SmallVector< std::pair< const Expr *, Detail >, 4 > Details
Pairs of unsatisfied atomic constraint expressions along with the substituted constraint expr,...
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getNonTransparentContext()
Decl - This represents one declaration (or definition), e.g.
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
bool isParameterPack() const
Whether this declaration is a parameter pack.
SourceLocation getLocation() const
Expr * getTrailingRequiresClause()
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
RAII object that enters a new expression evaluation context.
This represents one expression.
@ SE_NoSideEffects
Strictly evaluate the expression.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
bool EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, ConstantExprKind Kind=ConstantExprKind::Normal) const
Evaluate an expression that is required to be a constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a function declaration or definition.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
TemplatedKind
The kind of templated function a FunctionDecl can be.
@ TK_MemberSpecialization
@ TK_DependentNonTemplate
@ TK_FunctionTemplateSpecialization
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
FunctionDecl * getInstantiatedFromDecl() const
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
FunctionTemplateDecl * getInstantiatedFromMemberTemplate() const
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
const TypeClass * getTypePtr() const
Describes the capture of a variable or of this, or of a C++1y init-capture.
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Data structure that captures multiple levels of template argument lists for use in template instantia...
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
bool isAnyArgInstantiationDependent() const
This represents a decl that may have a name.
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
A (possibly-)qualified type.
void addConst()
Add the const type qualifier to this QualType.
The collection of all-type qualifiers we support.
Scope - A scope is a transient data structure that is used while parsing the program.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Sema - This implements semantic analysis and AST building for C.
bool CheckInstantiatedFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, bool Final=false, const TemplateArgumentList *Innermost=nullptr, bool RelativeToPrimary=false, const FunctionDecl *Pattern=nullptr, bool ForConstraintInstantiation=false, bool SkipForSpecialization=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
DiagnosticsEngine & getDiagnostics() const
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
sema::LambdaScopeInfo * PushLambdaScope()
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
const LangOptions & getLangOpts() const
bool CheckConstraintSatisfaction(const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
sema::FunctionScopeInfo * getCurFunction() const
std::optional< unsigned > getNumArgumentsInExpansion(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs)
Determine the number of arguments in the given pack expansion type.
std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const
Determines whether we are currently in a context where template argument substitution failures are no...
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, ArrayRef< const Expr * > AC1, NamedDecl *D2, ArrayRef< const Expr * > AC2)
If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...
ExprResult PerformContextuallyConvertToBool(Expr *From)
PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation(), bool ForOverloadResolution=false)
Check whether the given function decl's trailing requires clause is satisfied, if any.
TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)
bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef< const Expr * > AC1, NamedDecl *D2, MutableArrayRef< const Expr * > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
void PopSatisfactionStackEntry()
ExprResult SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
@ ConstantEvaluated
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)
Produces a formatted string that describes the binding of template parameters to template arguments.
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const NamedDecl *New, const Expr *NewConstr)
const NormalizedConstraint * getNormalizedAssociatedConstraints(NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const
Produce a unique representation of the given statement.
SourceLocation getBeginLoc() const LLVM_READONLY
A convenient class for passing around template argument information.
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
A template argument list.
Location wrapper for a TemplateArgument.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< const Expr * > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Represents a C++ template name within the type system.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
static bool anyInstantiationDependentTemplateArguments(ArrayRef< TemplateArgumentLoc > Args)
Declaration of a template type parameter.
Wrapper for template type parameters.
TemplateTypeParmDecl * getDecl() const
bool isParameterPack() const
unsigned getIndex() const
unsigned getDepth() const
Token - This structure provides full information about a lexed token.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
Expr * getImmediatelyDeclaredConstraint() const
Get the immediately-declared constraint expression introduced by this type-constraint,...
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
A container of type source information.
SourceLocation getNameLoc() const
void setNameLoc(SourceLocation Loc)
The base class of the type hierarchy.
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isFunctionType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
void setType(QualType newType)
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
ReturnTypeRequirement()
No return type requirement was specified.
bool isTypeConstraint() const
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
A requires-expression requirement which queries the validity and properties of an expression ('simple...
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
@ SS_ConstraintsNotSatisfied
@ SS_TypeRequirementSubstitutionFailure
@ SS_ExprSubstitutionFailure
const ReturnTypeRequirement & getReturnTypeRequirement() const
SatisfactionStatus getSatisfactionStatus() const
SourceLocation getNoexceptLoc() const
ExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc, ReturnTypeRequirement Req, SatisfactionStatus Status, ConceptSpecializationExpr *SubstitutedConstraintExpr=nullptr)
Construct a compound requirement.
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
StringRef getInvalidConstraintEntity()
A static requirement that can be used in a requires-expression to check properties of types and expre...
bool containsUnexpandedParameterPack() const
A requires-expression requirement which queries the existence of a type name or type template special...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SatisfactionStatus getSatisfactionStatus() const
TypeRequirement(TypeSourceInfo *T)
Construct a type requirement from a type.
Provides information about an attempted template argument deduction, whose success or failure was des...
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ OK_Ordinary
An ordinary object is located at an address in memory.
@ C
Languages that the frontend can parse and compile.
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Result
The result type of a method or function.
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
std::optional< ArrayRef< TemplateArgumentLoc > > ParameterMapping
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
const Expr * ConstraintExpr
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
AtomicConstraint * getAtomicConstraint() const
CompoundConstraintKind getCompoundKind() const
NormalizedConstraint & getRHS() const
NormalizedConstraint & getLHS() const
An RAII helper that pops function a function scope on exit.
A stack object to be created when performing template instantiation.
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.