29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/PointerUnion.h"
31#include "llvm/ADT/StringExtras.h"
41 const Expr *LHS =
nullptr;
42 const Expr *RHS =
nullptr;
45 LogicalBinOp(
const Expr *E) {
46 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
50 Loc = BO->getExprLoc();
51 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
53 if (OO->getNumArgs() == 2) {
54 Op = OO->getOperator();
57 Loc = OO->getOperatorLoc();
62 bool isAnd()
const {
return Op == OO_AmpAmp; }
63 bool isOr()
const {
return Op == OO_PipePipe; }
64 explicit operator bool()
const {
return isAnd() || isOr(); }
66 const Expr *getLHS()
const {
return LHS; }
67 const Expr *getRHS()
const {
return RHS; }
70 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
75 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
92 Token NextToken,
bool *PossibleNonPrimary,
93 bool IsTrailingRequiresClause) {
99 if (LogicalBinOp BO = ConstraintExpression) {
101 PossibleNonPrimary) &&
104 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
110 auto CheckForNonPrimary = [&] {
111 if (!PossibleNonPrimary)
114 *PossibleNonPrimary =
125 (NextToken.
is(tok::l_paren) &&
126 (IsTrailingRequiresClause ||
128 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
144 CheckForNonPrimary();
150 diag::err_non_bool_atomic_constraint) <<
Type
152 CheckForNonPrimary();
156 if (PossibleNonPrimary)
157 *PossibleNonPrimary =
false;
162struct SatisfactionStackRAII {
164 bool Inserted =
false;
166 const llvm::FoldingSetNodeID &FSNID)
173 ~SatisfactionStackRAII() {
180template <
typename AtomicEvaluator>
184 AtomicEvaluator &&Evaluator) {
187 if (LogicalBinOp BO = ConstraintExpr) {
188 size_t EffectiveDetailEndIndex = Satisfaction.
Details.size();
190 S, BO.getLHS(), Satisfaction, Evaluator);
197 if (BO.isOr() && IsLHSSatisfied)
207 if (BO.isAnd() && !IsLHSSatisfied)
218 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
231 if (BO.isOr() && IsRHSSatisfied) {
232 auto EffectiveDetailEnd = Satisfaction.
Details.begin();
233 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
234 Satisfaction.
Details.erase(EffectiveDetailEnd,
238 return BO.recreateBinOp(S, LHSRes, RHSRes);
241 if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
245 S,
C->getSubExpr(), Satisfaction,
246 std::forward<AtomicEvaluator>(Evaluator));
250 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
255 if (!SubstitutedAtomicExpr.
isUsable())
272 unsigned MessageSize = DiagString.size();
273 char *Mem =
new (S.
Context)
char[MessageSize];
274 memcpy(Mem, DiagString.c_str(), MessageSize);
275 Satisfaction.
Details.emplace_back(
278 SubstitutedAtomicExpr.get()->getBeginLoc(),
279 StringRef(Mem, MessageSize)});
280 return SubstitutedAtomicExpr;
287 EvalResult.
Diag = &EvaluationDiags;
290 !EvaluationDiags.empty()) {
294 diag::err_non_constant_constraint_expression)
297 S.
Diag(PDiag.first, PDiag.second);
302 "evaluating bool expression didn't produce int");
305 Satisfaction.
Details.emplace_back(ConstraintExpr,
306 SubstitutedAtomicExpr.
get());
308 return SubstitutedAtomicExpr;
316 for (
const auto &List : MLTAL)
356 llvm::FoldingSetNodeID ID;
364 SatisfactionStackRAII StackRAII(S, Template, ID);
368 SubstitutedExpression =
392 unsigned MessageSize = DiagString.size();
393 char *Mem =
new (S.
Context)
char[MessageSize];
394 memcpy(Mem, DiagString.c_str(), MessageSize);
395 Satisfaction.
Details.emplace_back(
398 SubstDiag.first, StringRef(Mem, MessageSize)});
420 CK_LValueToRValue, SubstitutedExpression.
get(),
423 return SubstitutedExpression;
432 if (ConstraintExprs.empty()) {
449 const_cast<NamedDecl *
>(Template), TemplateArgs, TemplateIDRange);
453 for (
const Expr *ConstraintExpr : ConstraintExprs) {
455 S, Template, TemplateIDRange.
getBegin(), TemplateArgsLists,
456 ConstraintExpr, Satisfaction);
460 Converted.push_back(Res.
get());
464 Converted.append(ConstraintExprs.size() - Converted.size(),
nullptr);
480 if (ConstraintExprs.empty()) {
485 return ::CheckConstraintSatisfaction(
486 *
this,
nullptr, ConstraintExprs, ConvertedConstraints,
487 TemplateArgsLists, TemplateIDRange, OutSatisfaction);
495 for (
auto List : TemplateArgsLists)
496 FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
499 llvm::FoldingSetNodeID ID;
502 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
503 OutSatisfaction = *Cached;
508 std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
510 ConvertedConstraints, TemplateArgsLists,
511 TemplateIDRange, *Satisfaction)) {
512 OutSatisfaction = *Satisfaction;
516 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
525 OutSatisfaction = *Cached;
530 OutSatisfaction = *Satisfaction;
534 SatisfactionCache.InsertNode(Satisfaction.release());
541 *
this, ConstraintExpr, Satisfaction,
550bool Sema::addInstantiatedCapturesToScope(
554 const auto *LambdaClass = cast<CXXMethodDecl>(
Function)->getParent();
555 const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
557 unsigned Instantiated = 0;
559 auto AddSingleCapture = [&](
const ValueDecl *CapturedPattern,
561 ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
563 Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
566 for (
const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
567 if (!CapturePattern.capturesVariable()) {
571 const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
573 AddSingleCapture(CapturedPattern, Instantiated++);
575 Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
576 std::optional<unsigned> NumArgumentsInExpansion =
578 if (!NumArgumentsInExpansion)
580 for (
unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
581 AddSingleCapture(CapturedPattern, Instantiated++);
587bool Sema::SetupConstraintScope(
593 InstantiatingTemplate Inst(
598 if (Inst.isInvalid())
609 if (addInstantiatedParametersToScope(
622 while (FromMemTempl->getInstantiatedFromMemberTemplate())
623 FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();
624 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
639 InstantiatingTemplate Inst(
644 if (Inst.isInvalid())
649 if (addInstantiatedParametersToScope(FD, InstantiatedFrom,
Scope, MLTAL))
658std::optional<MultiLevelTemplateArgumentList>
659Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
673 if (SetupConstraintScope(FD, TemplateArgs, MLTAL,
Scope))
682 bool ForOverloadResolution) {
701 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
704 Satisfaction, UsageLoc,
718 std::optional<MultiLevelTemplateArgumentList> MLTAL =
719 SetupConstraintCheckingTemplateArgumentsAndScope(
727 if (
auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
728 ThisQuals = Method->getMethodQualifiers();
735 ForOverloadResolution);
749 bool SkipForSpecialization =
false) {
755 true, SkipForSpecialization);
760 class AdjustConstraintDepth :
public TreeTransform<AdjustConstraintDepth> {
761 unsigned TemplateDepth = 0;
764 AdjustConstraintDepth(
Sema &SemaRef,
unsigned TemplateDepth)
765 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
767 using inherited::TransformTemplateTypeParmType;
774 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
777 QualType Result = getSema().Context.getTemplateTypeParmType(
778 T->getDepth() + TemplateDepth,
T->getIndex(),
T->isParameterPack(),
789 const Expr *ConstrExpr) {
818 std::optional<Sema::CXXThisScopeRAII> ThisScope;
827 std::optional<Sema::ContextRAII> ContextScope;
828 if (
auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.
getDeclContext())) {
830 ContextScope.emplace(S,
const_cast<DeclContext *
>(cast<DeclContext>(RD)),
837 return SubstConstr.
get();
841 const Expr *OldConstr,
843 const Expr *NewConstr) {
844 if (OldConstr == NewConstr)
849 if (
const Expr *SubstConstr =
852 OldConstr = SubstConstr;
855 if (
const Expr *SubstConstr =
858 NewConstr = SubstConstr;
863 llvm::FoldingSetNodeID ID1, ID2;
876 "Non-function templates don't need to be checked");
882 for (
const Expr *Constraint : ACs)
897 TemplateIDRange, Satisfaction))
902 TemplateArgString =
" ";
908 diag::err_template_arg_list_constraints_not_satisfied)
910 << TemplateArgString << TemplateIDRange;
927 if (TemplateAC.empty()) {
937 std::optional<MultiLevelTemplateArgumentList> MLTAL =
938 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
946 if (
auto *Method = dyn_cast<CXXMethodDecl>(
Decl)) {
947 ThisQuals = Method->getMethodQualifiers();
948 Record = Method->getParent();
957 PointOfInstantiation, Satisfaction);
964 &&
"Diagnose() can only be used on an unsatisfied requirement");
967 llvm_unreachable(
"Diagnosing a dependent requirement");
971 if (!SubstDiag->DiagMessage.empty())
972 S.
Diag(SubstDiag->DiagLoc,
973 diag::note_expr_requirement_expr_substitution_error)
974 << (
int)
First << SubstDiag->SubstitutedEntity
975 << SubstDiag->DiagMessage;
977 S.
Diag(SubstDiag->DiagLoc,
978 diag::note_expr_requirement_expr_unknown_substitution_error)
979 << (
int)
First << SubstDiag->SubstitutedEntity;
984 diag::note_expr_requirement_noexcept_not_met)
990 if (!SubstDiag->DiagMessage.empty())
991 S.
Diag(SubstDiag->DiagLoc,
992 diag::note_expr_requirement_type_requirement_substitution_error)
993 << (
int)
First << SubstDiag->SubstitutedEntity
994 << SubstDiag->DiagMessage;
996 S.
Diag(SubstDiag->DiagLoc,
997 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
998 << (
int)
First << SubstDiag->SubstitutedEntity;
1009 diag::note_expr_requirement_constraints_not_satisfied_simple)
1014 diag::note_expr_requirement_constraints_not_satisfied)
1015 << (
int)
First << ConstraintExpr;
1021 llvm_unreachable(
"We checked this above");
1029 &&
"Diagnose() can only be used on an unsatisfied requirement");
1032 llvm_unreachable(
"Diagnosing a dependent requirement");
1036 if (!SubstDiag->DiagMessage.empty())
1037 S.
Diag(SubstDiag->DiagLoc,
1038 diag::note_type_requirement_substitution_error) << (
int)
First
1039 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
1041 S.
Diag(SubstDiag->DiagLoc,
1042 diag::note_type_requirement_unknown_substitution_error)
1043 << (
int)
First << SubstDiag->SubstitutedEntity;
1047 llvm_unreachable(
"Unknown satisfaction status");
1058 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
1060 if (
auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
1061 S.
Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
1065 S, Pair.second.dyn_cast<
Expr *>(),
First);
1075 switch (BO->getOpcode()) {
1087 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1098 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1110 if (BO->getLHS()->getType()->isIntegerType() &&
1111 BO->getRHS()->getType()->isIntegerType()) {
1114 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1117 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1120 if (!SimplifiedLHS.
Diag && ! SimplifiedRHS.
Diag) {
1122 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1135 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1136 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1138 CSE->getSourceRange().getBegin(),
1140 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1142 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1143 << CSE->getNamedConcept();
1146 diag::note_concept_specialization_constraint_evaluated_to_false)
1147 << (
int)
First << CSE;
1151 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1154 if (!Req->isDependent() && !Req->isSatisfied()) {
1155 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1157 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
1161 S, cast<concepts::NestedRequirement>(Req),
First);
1165 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1166 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1167 assert(TTE->getNumArgs() == 2);
1169 diag::note_is_deducible_constraint_evaluated_to_false)
1170 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1175 diag::note_atomic_constraint_evaluated_to_false)
1179template<
typename SubstitutionDiagnostic>
1182 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &
Record,
1183 bool First =
true) {
1184 if (
auto *
Diag =
Record.template dyn_cast<SubstitutionDiagnostic *>()){
1185 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1198 "Attempted to diagnose a satisfied constraint");
1199 for (
auto &Pair : Satisfaction.
Details) {
1209 "Attempted to diagnose a satisfied constraint");
1210 for (
auto &Pair : Satisfaction) {
1224 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1225 if (CacheEntry == NormalizationCache.end()) {
1227 NormalizedConstraint::fromConstraintExprs(*
this, ConstrainedDecl,
1228 AssociatedConstraints);
1231 .try_emplace(ConstrainedDecl,
1234 std::move(*Normalized))
1238 return CacheEntry->second;
1257 if (!
Atomic.ParameterMapping) {
1258 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
1260 0, OccurringIndices);
1263 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I)
1264 if (OccurringIndices[I])
1265 new (&(TempArgs)[J++])
1267 TemplateParams->
begin()[I],
1277 ? ArgsAsWritten->
arguments()[I].getLocation()
1279 Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
1284 : ArgsAsWritten->
arguments().front().getSourceRange().getBegin();
1288 : ArgsAsWritten->
arguments().front().getSourceRange().getEnd();
1292 {InstLocBegin, InstLocEnd});
1293 if (Inst.isInvalid())
1302 Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.
size());
1319std::optional<NormalizedConstraint>
1320NormalizedConstraint::fromConstraintExprs(
Sema &S,
NamedDecl *D,
1322 assert(E.size() != 0);
1323 auto Conjunction = fromConstraintExpr(S, D, E[0]);
1325 return std::nullopt;
1326 for (
unsigned I = 1; I < E.size(); ++I) {
1327 auto Next = fromConstraintExpr(S, D, E[I]);
1329 return std::nullopt;
1336std::optional<NormalizedConstraint>
1338 assert(E !=
nullptr);
1351 if (LogicalBinOp BO = E) {
1352 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1354 return std::nullopt;
1355 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1357 return std::nullopt;
1361 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1365 S, CSE->getExprLoc(),
1367 CSE->getSourceRange());
1368 if (Inst.isInvalid())
1369 return std::nullopt;
1383 return std::nullopt;
1386 std::optional<NormalizedConstraint> New;
1387 New.emplace(S.
Context, *SubNF);
1390 return std::nullopt;
1407 LCNF.reserve(LCNF.size() + RCNF.size());
1408 while (!RCNF.empty())
1409 LCNF.push_back(RCNF.pop_back_val());
1415 Res.reserve(LCNF.size() * RCNF.size());
1416 for (
auto &LDisjunction : LCNF)
1417 for (
auto &RDisjunction : RCNF) {
1418 NormalForm::value_type Combined;
1419 Combined.reserve(LDisjunction.size() + RDisjunction.size());
1420 std::copy(LDisjunction.begin(), LDisjunction.end(),
1421 std::back_inserter(Combined));
1422 std::copy(RDisjunction.begin(), RDisjunction.end(),
1423 std::back_inserter(Combined));
1424 Res.emplace_back(Combined);
1436 LDNF.reserve(LDNF.size() + RDNF.size());
1437 while (!RDNF.empty())
1438 LDNF.push_back(RDNF.pop_back_val());
1444 Res.reserve(LDNF.size() * RDNF.size());
1445 for (
auto &LConjunction : LDNF) {
1446 for (
auto &RConjunction : RDNF) {
1447 NormalForm::value_type Combined;
1448 Combined.reserve(LConjunction.size() + RConjunction.size());
1449 std::copy(LConjunction.begin(), LConjunction.end(),
1450 std::back_inserter(Combined));
1451 std::copy(RConjunction.begin(), RConjunction.end(),
1452 std::back_inserter(Combined));
1453 Res.emplace_back(Combined);
1459template<
typename AtomicSubsumptionEvaluator>
1461 AtomicSubsumptionEvaluator E) {
1466 for (
const auto &Pi : PDNF) {
1467 for (
const auto &Qj : QCNF) {
1476 if (E(*Pia, *Qjb)) {
1491template<
typename AtomicSubsumptionEvaluator>
1494 AtomicSubsumptionEvaluator E) {
1509 Subsumes =
subsumes(PDNF, QCNF, E);
1518 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1524 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1525 (void)IsExpectedEntity;
1528 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1529 "use non-instantiated function declaration for constraints partial "
1543 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1544 auto CacheEntry = SubsumptionCache.find(Key);
1545 if (CacheEntry != SubsumptionCache.end()) {
1546 Result = CacheEntry->second;
1553 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1554 if (Depth2 > Depth1) {
1555 AC1[I] = AdjustConstraintDepth(*
this, Depth2 - Depth1)
1556 .TransformExpr(
const_cast<Expr *
>(AC1[I]))
1558 }
else if (Depth1 > Depth2) {
1559 AC2[I] = AdjustConstraintDepth(*
this, Depth1 - Depth2)
1560 .TransformExpr(
const_cast<Expr *
>(AC2[I]))
1570 SubsumptionCache.try_emplace(Key,
Result);
1580 if (AC1.empty() || AC2.empty())
1583 auto NormalExprEvaluator =
1588 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
1589 auto IdenticalExprEvaluator =
1599 llvm::FoldingSetNodeID IDA, IDB;
1601 EB->Profile(IDB,
Context,
true);
1605 AmbiguousAtomic1 = EA;
1606 AmbiguousAtomic2 = EB;
1625 bool Is1AtLeastAs2Normally =
subsumes(DNF1, CNF2, NormalExprEvaluator);
1626 bool Is2AtLeastAs1Normally =
subsumes(DNF2, CNF1, NormalExprEvaluator);
1627 bool Is1AtLeastAs2 =
subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1628 bool Is2AtLeastAs1 =
subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1629 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1630 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1636 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1638 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1640 Diag(AmbiguousAtomic2->getBeginLoc(),
1641 diag::note_ambiguous_atomic_constraints_similar_expression)
1642 << AmbiguousAtomic2->getSourceRange();
1650 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1651 Status == SS_Dependent &&
1652 (E->containsUnexpandedParameterPack() ||
1653 Req.containsUnexpandedParameterPack()),
1654 Status == SS_Satisfied),
Value(E), NoexceptLoc(NoexceptLoc),
1655 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1658 "Simple requirement must not have a return type requirement or a "
1659 "noexcept specification");
1661 (SubstitutedConstraintExpr !=
nullptr));
1667 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1668 Req.containsUnexpandedParameterPack(),
false),
1669 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1670 Status(SS_ExprSubstitutionFailure) {
1672 "Simple requirement must not have a return type requirement or a "
1673 "noexcept specification");
1678 TypeConstraintInfo(TPL,
false) {
1679 assert(TPL->
size() == 1);
1681 cast<TemplateTypeParmDecl>(TPL->
getParam(0))->getTypeConstraint();
1683 "TPL must have a template type parameter with a type constraint");
1687 Constraint->getTemplateArgsAsWritten() &&
1689 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1690 TypeConstraintInfo.setInt(Dependent ?
true :
false);
1701 Status(
T->getType()->isInstantiationDependentType() ?
SS_Dependent
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
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.
llvm::MachO::Record Record
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 subsumes(const NormalForm &PDNF, const NormalForm &QCNF, AtomicSubsumptionEvaluator E)
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 const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)
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 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++ conversion function within a class.
Represents a C++ struct/union/class.
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConceptDecl * getNamedConcept() const
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.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
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...
ArrayRef< ParmVarDecl * > parameters() const
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...
void InstantiatedLocal(const Decl *D, Decl *Inst)
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 getNumLevels() const
Determine the number of levels in this 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.
The collection of all-type qualifiers we support.
Scope - A scope is a transient data structure that is used while parsing the program.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
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.
SourceLocation getLocation() const
bool ContainsDecl(const NamedDecl *ND) const
const DeclContext * getDeclContext() const
const NamedDecl * getDecl() const
const DeclContext * getLexicalDeclContext() const
Sema - This implements semantic analysis and AST building for C.
bool CheckInstantiatedFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
DiagnosticsEngine & getDiagnostics() const
ExprResult SubstConstraintExprWithoutSatisfaction(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
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)
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...
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
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.
const NormalizedConstraint * getNormalizedAssociatedConstraints(NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, const DeclContext *DC=nullptr, bool Final=false, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, 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...
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, bool ProfileLambdaExpr=false) 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
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.
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
Models the abbreviated syntax to constrain a template type parameter: template <convertible_to<string...
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 ...
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.
The JSON file list parser is used to communicate input to InstallAPI.
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.
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.
bool isLambdaConversionOperator(CXXConversionDecl *C)
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
const FunctionProtoType * T
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>".
SourceLocation getLAngleLoc() const
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
SourceLocation getRAngleLoc() const
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
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
A stack object to be created when performing template instantiation.
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.