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());
209 const_cast<NamedDecl *>(Template), Info,
211 if (Inst.isInvalid())
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);
277 if (Inst.isInvalid())
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();
360 Record = const_cast<CXXRecordDecl *>(Method->getParent());
379 TemplateIDRange, Satisfaction))
384 TemplateArgString =
" ";
385 TemplateArgString += getTemplateArgumentBindingsText(
389 diag::err_template_arg_list_constraints_not_satisfied)
390 << (
int)getTemplateNameKindForDiagnostics(
TemplateName(TD)) << TD
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;
446 diag::note_expr_requirement_constraints_not_satisfied_simple)
452 diag::note_expr_requirement_constraints_not_satisfied)
453 << (
int)
First << ConstraintExpr;
458 llvm_unreachable(
"We checked this above");
466 &&
"Diagnose() can only be used on an unsatisfied requirement");
469 llvm_unreachable(
"Diagnosing a dependent requirement");
473 if (!SubstDiag->DiagMessage.empty())
474 S.
Diag(SubstDiag->DiagLoc,
475 diag::note_type_requirement_substitution_error) << (
int)
First 476 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
478 S.
Diag(SubstDiag->DiagLoc,
479 diag::note_type_requirement_unknown_substitution_error)
480 << (
int)
First << SubstDiag->SubstitutedEntity;
484 llvm_unreachable(
"Unknown satisfaction status");
497 diag::note_nested_requirement_substitution_error)
502 diag::note_nested_requirement_unknown_substitution_error)
515 switch (BO->getOpcode()) {
527 BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.
Context);
538 BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.
Context);
549 if (BO->getLHS()->getType()->isIntegerType() &&
550 BO->getRHS()->getType()->isIntegerType()) {
553 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context);
554 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context);
555 if (!SimplifiedLHS.
Diag && ! SimplifiedRHS.
Diag) {
557 diag::note_atomic_constraint_evaluated_to_false_elaborated)
558 << (
int)
First << SubstExpr
559 << SimplifiedLHS.
Val.
getInt().toString(10)
561 << SimplifiedRHS.
Val.
getInt().toString(10);
570 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
571 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
573 CSE->getSourceRange().getBegin(),
575 note_single_arg_concept_specialization_constraint_evaluated_to_false)
577 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
578 << CSE->getNamedConcept();
581 diag::note_concept_specialization_constraint_evaluated_to_false)
582 << (
int)
First << CSE;
586 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
588 if (!Req->isDependent() && !Req->isSatisfied()) {
589 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
591 else if (
auto *T = dyn_cast<concepts::TypeRequirement>(Req))
595 S, cast<concepts::NestedRequirement>(Req),
First);
602 diag::note_atomic_constraint_evaluated_to_false)
603 << (
int)
First << SubstExpr;
606 template<
typename SubstitutionDiagnostic>
609 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
611 if (
auto *
Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
612 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
618 Record.template get<Expr *>(),
First);
625 "Attempted to diagnose a satisfied constraint");
626 for (
auto &Pair : Satisfaction.
Details) {
636 "Attempted to diagnose a satisfied constraint");
637 for (
auto &Pair : Satisfaction) {
646 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
647 if (CacheEntry == NormalizationCache.end()) {
649 NormalizedConstraint::fromConstraintExprs(*
this, ConstrainedDecl,
650 AssociatedConstraints);
653 .try_emplace(ConstrainedDecl,
656 std::move(*Normalized))
660 return CacheEntry->second;
680 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
682 0, OccurringIndices);
686 OccurringIndices.count()));
687 for (
unsigned I = 0, J = 0, C = TemplateParams->
size(); I != C; ++I)
688 if (OccurringIndices[I])
700 ArgsAsWritten->
arguments()[I].getLocation() :
704 S, ArgsAsWritten->
arguments().front().getSourceRange().getBegin(),
707 ArgsAsWritten->
arguments().back().getSourceRange().getEnd()));
720 NormalizedConstraint::fromConstraintExprs(
Sema &S,
NamedDecl *D,
722 assert(E.size() != 0);
723 auto First = fromConstraintExpr(S, D, E[0]);
726 auto Second = fromConstraintExpr(S, D, E[1]);
730 Conjunction.emplace(S.
Context, std::move(*First), std::move(*Second),
732 for (
unsigned I = 2; I < E.size(); ++I) {
733 auto Next = fromConstraintExpr(S, D, E[I]);
737 std::move(*Next), CCK_Conjunction);
738 *Conjunction = std::move(NewConjunction);
745 assert(E !=
nullptr);
752 if (LogicalBinOp BO = E) {
753 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
756 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
761 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
762 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
766 S, CSE->getExprLoc(),
780 {CD->getConstraintExpr()});
786 New.emplace(S.
Context, *SubNF);
789 S, *New, CSE->getNamedConcept(),
790 CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
808 LCNF.reserve(LCNF.size() + RCNF.size());
809 while (!RCNF.empty())
810 LCNF.push_back(RCNF.pop_back_val());
816 Res.reserve(LCNF.size() * RCNF.size());
817 for (
auto &LDisjunction : LCNF)
818 for (
auto &RDisjunction : RCNF) {
819 NormalForm::value_type Combined;
820 Combined.reserve(LDisjunction.size() + RDisjunction.size());
821 std::copy(LDisjunction.begin(), LDisjunction.end(),
822 std::back_inserter(Combined));
823 std::copy(RDisjunction.begin(), RDisjunction.end(),
824 std::back_inserter(Combined));
825 Res.emplace_back(Combined);
837 LDNF.reserve(LDNF.size() + RDNF.size());
838 while (!RDNF.empty())
839 LDNF.push_back(RDNF.pop_back_val());
845 Res.reserve(LDNF.size() * RDNF.size());
846 for (
auto &LConjunction : LDNF) {
847 for (
auto &RConjunction : RDNF) {
848 NormalForm::value_type Combined;
849 Combined.reserve(LConjunction.size() + RConjunction.size());
850 std::copy(LConjunction.begin(), LConjunction.end(),
851 std::back_inserter(Combined));
852 std::copy(RConjunction.begin(), RConjunction.end(),
853 std::back_inserter(Combined));
854 Res.emplace_back(Combined);
860 template<
typename AtomicSubsumptionEvaluator>
862 AtomicSubsumptionEvaluator E) {
867 for (
const auto &Pi : PDNF) {
868 for (
const auto &Qj : QCNF) {
892 template<
typename AtomicSubsumptionEvaluator>
895 AtomicSubsumptionEvaluator E) {
918 Result = AC2.empty();
927 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
928 auto CacheEntry = SubsumptionCache.find(Key);
929 if (CacheEntry != SubsumptionCache.end()) {
930 Result = CacheEntry->second;
934 if (
subsumes(*
this, D1, AC1, D2, AC2, Result,
939 SubsumptionCache.try_emplace(Key, Result);
945 if (isSFINAEContext())
949 if (AC1.empty() || AC2.empty())
952 auto NormalExprEvaluator =
957 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
958 auto IdenticalExprEvaluator =
968 llvm::FoldingSetNodeID IDA, IDB;
969 EA->
Profile(IDA, Context,
true);
970 EB->Profile(IDB, Context,
true);
974 AmbiguousAtomic1 = EA;
975 AmbiguousAtomic2 = EB;
982 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
988 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
994 bool Is1AtLeastAs2Normally =
subsumes(DNF1, CNF2, NormalExprEvaluator);
995 bool Is2AtLeastAs1Normally =
subsumes(DNF2, CNF1, NormalExprEvaluator);
996 bool Is1AtLeastAs2 =
subsumes(DNF1, CNF2, IdenticalExprEvaluator);
997 bool Is2AtLeastAs1 =
subsumes(DNF2, CNF1, IdenticalExprEvaluator);
998 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
999 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1005 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1007 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1009 Diag(AmbiguousAtomic2->getBeginLoc(),
1010 diag::note_ambiguous_atomic_constraints_similar_expression)
1011 << AmbiguousAtomic2->getSourceRange();
1019 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1020 Status == SS_Dependent &&
1021 (E->containsUnexpandedParameterPack() ||
1022 Req.containsUnexpandedParameterPack()),
1023 Status == SS_Satisfied),
Value(E), NoexceptLoc(NoexceptLoc),
1024 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1027 "Simple requirement must not have a return type requirement or a " 1028 "noexcept specification");
1030 (SubstitutedConstraintExpr !=
nullptr));
1034 SubstitutionDiagnostic *ExprSubstDiag,
bool IsSimple,
1036 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1037 Req.containsUnexpandedParameterPack(),
false),
1038 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1039 Status(SS_ExprSubstitutionFailure) {
1040 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.
isInvalid())) &&
1041 "Simple requirement must not have a return type requirement or a " 1042 "noexcept specification");
1047 TypeConstraintInfo(TPL, 0) {
1048 assert(TPL->
size() == 1);
1052 "TPL must have a template type parameter with a type constraint");
1054 cast_or_null<ConceptSpecializationExpr>(
1055 TC->getImmediatelyDeclaredConstraint());
1057 Constraint->getTemplateArgsAsWritten() &&
1059 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1060 TypeConstraintInfo.setInt(Dependent ? 1 : 0);
1071 Status(T->getType()->isInstantiationDependentType() ?
SS_Dependent
Represents a function declaration or definition.
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.
A (possibly-)qualified type.
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
A requires-expression requirement which queries the validity and properties of an expression ('simple...
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs)
Add a new outermost level to the multi-level template argument list.
Provides information about an attempted template argument deduction, whose success or failure was des...
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)) {....
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
The base class of the type hierarchy.
const Expr * ConstraintExpr
NamedDecl * getParam(unsigned Idx)
A container of type source information.
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
RAII object that enters a new expression evaluation context.
ExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc, ReturnTypeRequirement Req, SatisfactionStatus Status, ConceptSpecializationExpr *SubstitutedConstraintExpr=nullptr)
Construct a compound requirement.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const
Produce a unique representation of the given statement.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Stores a list of template parameters for a TemplateDecl and its derived classes.
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
tok::TokenKind getKind() const
The collection of all-type qualifiers we support.
SourceLocation getBeginLoc() const LLVM_READONLY
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Token - This structure provides full information about a lexed token.
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
StringRef getOpcodeStr() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
APValue Val
Val - This is the value the expression can be folded to.
A convenient class for passing around template argument information.
SatisfactionStatus getSatisfactionStatus() const
static bool calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, AtomicEvaluator &&Evaluator)
A builtin binary operation expression such as "x + y" or "x <= y".
ConceptDecl * getNamedConcept() const
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
bool CheckConstraintSatisfaction(const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, ArrayRef< TemplateArgument > TemplateArgs, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
bool isTypeDependent() const
Determines whether the type of this expression depends on.
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
DiagnosticsEngine & getDiagnostics() const
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Sema - This implements semantic analysis and AST building for C.
A requires-expression requirement which queries the existence of a type name or type template special...
static NormalForm makeCNF(const NormalizedConstraint &Normalized)
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
This represents one expression.
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, ArrayRef< TemplateArgument > TemplateArgs, const ASTTemplateArgumentListInfo *ArgsAsWritten)
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
static bool subsumes(NormalForm PDNF, NormalForm QCNF, AtomicSubsumptionEvaluator E)
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
bool isSubstitutionFailure() const
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
SatisfactionStatus getSatisfactionStatus() const
Represents a C++ template name within the type system.
const NormalizedConstraint * getNormalizedAssociatedConstraints(NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)
bool isTypeConstraint() const
NormalizedConstraint & getRHS() const
bool IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef< const Expr * > AC1, NamedDecl *D2, ArrayRef< const Expr * > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
Defines and computes precedence levels for binary/ternary operators.
Data structure that captures multiple levels of template argument lists for use in template instantia...
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
StringRef SubstitutedEntity
CompoundConstraintKind getCompoundKind() const
static bool anyInstantiationDependentTemplateArguments(ArrayRef< TemplateArgumentLoc > Args)
Expr * getTrailingRequiresClause()
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
A stack object to be created when performing template instantiation.
Encodes a location in the source.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
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...
SourceLocation getNoexceptLoc() const
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
constexpr XRayInstrMask None
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
SourceLocation getBeginLoc() const LLVM_READONLY
A static requirement that can be used in a requires-expression to check properties of types and expre...
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
void getAssociatedConstraints(llvm::SmallVectorImpl< const Expr * > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
Declaration of a C++2a concept.
SourceLocation getBeginLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
The base class of all kinds of template declarations (e.g., class, function, etc.).
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
ReturnTypeRequirement()
No return type requirement was specified.
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
NormalizedConstraint & getLHS() const
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
llvm::SmallVector< std::pair< const Expr *, Detail >, 4 > Details
Pairs of unsatisfied atomic constraint expressions along with the substituted constraint expr,...
Not an overloaded operator.
Location wrapper for a TemplateArgument.
bool containsUnexpandedParameterPack() const
bool isFunctionType() const
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
QualType BuildDecltypeType(Expr *E, SourceLocation Loc, bool AsUnevaluated=true)
If AsUnevaluated is false, E is treated as though it were an evaluated context, such as when building...
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation())
Check whether the given function decl's trailing requires clause is satisfied, if any.
ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
ActionResult< Expr * > ExprResult
Defines Expressions and AST nodes for C++2a concepts.
Represents a C++ struct/union/class.
TypeRequirement(TypeSourceInfo *T)
Construct a type requirement from a type.
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
Represents the specialization of a concept - evaluates to a prvalue of type bool.
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
AtomicConstraint * getAtomicConstraint() const
static NormalForm makeDNF(const NormalizedConstraint &Normalized)
A trivial tuple used to represent a source range.
This represents a decl that may have a name.
const TypeConstraint * getTypeConstraint() const
Optional< MutableArrayRef< TemplateArgumentLoc > > ParameterMapping
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, ArrayRef< TemplateArgument > TemplateArgs, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
SourceLocation getBegin() const
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const Expr *E, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic * > &Record, bool First=true)
SourceLocation getLocation() const
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
const ReturnTypeRequirement & getReturnTypeRequirement() const