clang 17.0.0git
SemaConcept.cpp
Go to the documentation of this file.
1//===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis for C++ constraints and concepts.
10//
11//===----------------------------------------------------------------------===//
12
13#include "TreeTransform.h"
15#include "clang/Sema/Sema.h"
19#include "clang/Sema/Template.h"
20#include "clang/Sema/Overload.h"
22#include "clang/AST/ASTLambda.h"
26#include "llvm/ADT/DenseMap.h"
27#include "llvm/ADT/PointerUnion.h"
28#include "llvm/ADT/StringExtras.h"
29#include <optional>
30
31using namespace clang;
32using namespace sema;
33
34namespace {
35class LogicalBinOp {
38 const Expr *LHS = nullptr;
39 const Expr *RHS = nullptr;
40
41public:
42 LogicalBinOp(const Expr *E) {
43 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
44 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
45 LHS = BO->getLHS();
46 RHS = BO->getRHS();
47 Loc = BO->getExprLoc();
48 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
49 // If OO is not || or && it might not have exactly 2 arguments.
50 if (OO->getNumArgs() == 2) {
51 Op = OO->getOperator();
52 LHS = OO->getArg(0);
53 RHS = OO->getArg(1);
54 Loc = OO->getOperatorLoc();
55 }
56 }
57 }
58
59 bool isAnd() const { return Op == OO_AmpAmp; }
60 bool isOr() const { return Op == OO_PipePipe; }
61 explicit operator bool() const { return isAnd() || isOr(); }
62
63 const Expr *getLHS() const { return LHS; }
64 const Expr *getRHS() const { return RHS; }
65
66 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
67 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
68 }
69
70 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
71 ExprResult RHS) const {
72 assert((isAnd() || isOr()) && "Not the right kind of op?");
73 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
74
75 if (!LHS.isUsable() || !RHS.isUsable())
76 return ExprEmpty();
77
78 // We should just be able to 'normalize' these to the builtin Binary
79 // Operator, since that is how they are evaluated in constriant checks.
80 return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
82 SemaRef.Context.BoolTy, VK_PRValue,
84 }
85};
86}
87
88bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
89 Token NextToken, bool *PossibleNonPrimary,
90 bool IsTrailingRequiresClause) {
91 // C++2a [temp.constr.atomic]p1
92 // ..E shall be a constant expression of type bool.
93
94 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
95
96 if (LogicalBinOp BO = ConstraintExpression) {
97 return CheckConstraintExpression(BO.getLHS(), NextToken,
98 PossibleNonPrimary) &&
99 CheckConstraintExpression(BO.getRHS(), NextToken,
100 PossibleNonPrimary);
101 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
102 return CheckConstraintExpression(C->getSubExpr(), NextToken,
103 PossibleNonPrimary);
104
105 QualType Type = ConstraintExpression->getType();
106
107 auto CheckForNonPrimary = [&] {
108 if (!PossibleNonPrimary)
109 return;
110
111 *PossibleNonPrimary =
112 // We have the following case:
113 // template<typename> requires func(0) struct S { };
114 // The user probably isn't aware of the parentheses required around
115 // the function call, and we're only going to parse 'func' as the
116 // primary-expression, and complain that it is of non-bool type.
117 //
118 // However, if we're in a lambda, this might also be:
119 // []<typename> requires var () {};
120 // Which also looks like a function call due to the lambda parentheses,
121 // but unlike the first case, isn't an error, so this check is skipped.
122 (NextToken.is(tok::l_paren) &&
123 (IsTrailingRequiresClause ||
124 (Type->isDependentType() &&
125 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
126 !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
127 Type->isFunctionType() ||
128 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
129 // We have the following case:
130 // template<typename T> requires size_<T> == 0 struct S { };
131 // The user probably isn't aware of the parentheses required around
132 // the binary operator, and we're only going to parse 'func' as the
133 // first operand, and complain that it is of non-bool type.
134 getBinOpPrecedence(NextToken.getKind(),
135 /*GreaterThanIsOperator=*/true,
137 };
138
139 // An atomic constraint!
140 if (ConstraintExpression->isTypeDependent()) {
141 CheckForNonPrimary();
142 return true;
143 }
144
146 Diag(ConstraintExpression->getExprLoc(),
147 diag::err_non_bool_atomic_constraint) << Type
148 << ConstraintExpression->getSourceRange();
149 CheckForNonPrimary();
150 return false;
151 }
152
153 if (PossibleNonPrimary)
154 *PossibleNonPrimary = false;
155 return true;
156}
157
158namespace {
159struct SatisfactionStackRAII {
160 Sema &SemaRef;
161 bool Inserted = false;
162 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
163 llvm::FoldingSetNodeID FSNID)
164 : SemaRef(SemaRef) {
165 if (ND) {
166 SemaRef.PushSatisfactionStackEntry(ND, FSNID);
167 Inserted = true;
168 }
169 }
170 ~SatisfactionStackRAII() {
171 if (Inserted)
173 }
174};
175} // namespace
176
177template <typename AtomicEvaluator>
178static ExprResult
179calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
180 ConstraintSatisfaction &Satisfaction,
181 AtomicEvaluator &&Evaluator) {
182 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
183
184 if (LogicalBinOp BO = ConstraintExpr) {
186 S, BO.getLHS(), Satisfaction, Evaluator);
187
188 if (LHSRes.isInvalid())
189 return ExprError();
190
191 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
192
193 if (BO.isOr() && IsLHSSatisfied)
194 // [temp.constr.op] p3
195 // A disjunction is a constraint taking two operands. To determine if
196 // a disjunction is satisfied, the satisfaction of the first operand
197 // is checked. If that is satisfied, the disjunction is satisfied.
198 // Otherwise, the disjunction is satisfied if and only if the second
199 // operand is satisfied.
200 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
201 return LHSRes;
202
203 if (BO.isAnd() && !IsLHSSatisfied)
204 // [temp.constr.op] p2
205 // A conjunction is a constraint taking two operands. To determine if
206 // a conjunction is satisfied, the satisfaction of the first operand
207 // is checked. If that is not satisfied, the conjunction is not
208 // satisfied. Otherwise, the conjunction is satisfied if and only if
209 // the second operand is satisfied.
210 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
211 return LHSRes;
212
214 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
215 if (RHSRes.isInvalid())
216 return ExprError();
217
218 return BO.recreateBinOp(S, LHSRes, RHSRes);
219 }
220
221 if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
222 // These aren't evaluated, so we don't care about cleanups, so we can just
223 // evaluate these as if the cleanups didn't exist.
225 S, C->getSubExpr(), Satisfaction,
226 std::forward<AtomicEvaluator>(Evaluator));
227 }
228
229 // An atomic constraint expression
230 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
231
232 if (SubstitutedAtomicExpr.isInvalid())
233 return ExprError();
234
235 if (!SubstitutedAtomicExpr.isUsable())
236 // Evaluator has decided satisfaction without yielding an expression.
237 return ExprEmpty();
238
239 // We don't have the ability to evaluate this, since it contains a
240 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
241 // we'd potentially pick up a different overload, and cause confusing
242 // diagnostics. SO, add a failure detail that will cause us to make this
243 // overload set not viable.
244 if (SubstitutedAtomicExpr.get()->containsErrors()) {
245 Satisfaction.IsSatisfied = false;
246 Satisfaction.ContainsErrors = true;
247
248 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
249 SmallString<128> DiagString;
250 DiagString = ": ";
251 Msg.EmitToString(S.getDiagnostics(), DiagString);
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(
256 ConstraintExpr,
258 SubstitutedAtomicExpr.get()->getBeginLoc(),
259 StringRef(Mem, MessageSize)});
260 return SubstitutedAtomicExpr;
261 }
262
263 EnterExpressionEvaluationContext ConstantEvaluated(
266 Expr::EvalResult EvalResult;
267 EvalResult.Diag = &EvaluationDiags;
268 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
269 S.Context) ||
270 !EvaluationDiags.empty()) {
271 // C++2a [temp.constr.atomic]p1
272 // ...E shall be a constant expression of type bool.
273 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
274 diag::err_non_constant_constraint_expression)
275 << SubstitutedAtomicExpr.get()->getSourceRange();
276 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
277 S.Diag(PDiag.first, PDiag.second);
278 return ExprError();
279 }
280
281 assert(EvalResult.Val.isInt() &&
282 "evaluating bool expression didn't produce int");
283 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
284 if (!Satisfaction.IsSatisfied)
285 Satisfaction.Details.emplace_back(ConstraintExpr,
286 SubstitutedAtomicExpr.get());
287
288 return SubstitutedAtomicExpr;
289}
290
291static bool
292DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
293 const NamedDecl *Templ, const Expr *E,
294 const MultiLevelTemplateArgumentList &MLTAL) {
295 E->Profile(ID, S.Context, /*Canonical=*/true);
296 for (const auto &List : MLTAL)
297 for (const auto &TemplateArg : List.Args)
298 TemplateArg.Profile(ID, S.Context);
299
300 // Note that we have to do this with our own collection, because there are
301 // times where a constraint-expression check can cause us to need to evaluate
302 // other constriants that are unrelated, such as when evaluating a recovery
303 // expression, or when trying to determine the constexpr-ness of special
304 // members. Otherwise we could just use the
305 // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
306 if (S.SatisfactionStackContains(Templ, ID)) {
307 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
308 << const_cast<Expr *>(E) << E->getSourceRange();
309 return true;
310 }
311
312 return false;
313}
314
316 Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
317 const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
318 ConstraintSatisfaction &Satisfaction) {
320 S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
321 EnterExpressionEvaluationContext ConstantEvaluated(
324
325 // Atomic constraint - substitute arguments and check satisfaction.
326 ExprResult SubstitutedExpression;
327 {
328 TemplateDeductionInfo Info(TemplateNameLoc);
331 const_cast<NamedDecl *>(Template), Info,
333 if (Inst.isInvalid())
334 return ExprError();
335
336 llvm::FoldingSetNodeID ID;
337 if (Template &&
338 DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
339 Satisfaction.IsSatisfied = false;
340 Satisfaction.ContainsErrors = true;
341 return ExprEmpty();
342 }
343
344 SatisfactionStackRAII StackRAII(S, Template, ID);
345
346 // We do not want error diagnostics escaping here.
347 Sema::SFINAETrap Trap(S);
348 SubstitutedExpression =
349 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
350
351 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
352 // C++2a [temp.constr.atomic]p1
353 // ...If substitution results in an invalid type or expression, the
354 // constraint is not satisfied.
355 if (!Trap.hasErrorOccurred())
356 // A non-SFINAE error has occurred as a result of this
357 // substitution.
358 return ExprError();
359
362 Info.takeSFINAEDiagnostic(SubstDiag);
363 // FIXME: Concepts: This is an unfortunate consequence of there
364 // being no serialization code for PartialDiagnostics and the fact
365 // that serializing them would likely take a lot more storage than
366 // just storing them as strings. We would still like, in the
367 // future, to serialize the proper PartialDiagnostic as serializing
368 // it as a string defeats the purpose of the diagnostic mechanism.
369 SmallString<128> DiagString;
370 DiagString = ": ";
371 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
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)});
379 Satisfaction.IsSatisfied = false;
380 return ExprEmpty();
381 }
382 }
383
384 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
385 return ExprError();
386
387 // [temp.constr.atomic]p3: To determine if an atomic constraint is
388 // satisfied, the parameter mapping and template arguments are first
389 // substituted into its expression. If substitution results in an
390 // invalid type or expression, the constraint is not satisfied.
391 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
392 // and E shall be a constant expression of type bool.
393 //
394 // Perform the L to R Value conversion if necessary. We do so for all
395 // non-PRValue categories, else we fail to extend the lifetime of
396 // temporaries, and that fails the constant expression check.
397 if (!SubstitutedExpression.get()->isPRValue())
398 SubstitutedExpression = ImplicitCastExpr::Create(
399 S.Context, SubstitutedExpression.get()->getType(),
400 CK_LValueToRValue, SubstitutedExpression.get(),
401 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
402
403 return SubstitutedExpression;
404 });
405}
406
408 Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
410 const MultiLevelTemplateArgumentList &TemplateArgsLists,
411 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
412 if (ConstraintExprs.empty()) {
413 Satisfaction.IsSatisfied = true;
414 return false;
415 }
416
417 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
418 // No need to check satisfaction for dependent constraint expressions.
419 Satisfaction.IsSatisfied = true;
420 return false;
421 }
422
423 ArrayRef<TemplateArgument> TemplateArgs =
424 TemplateArgsLists.getNumSubstitutedLevels() > 0
425 ? TemplateArgsLists.getOutermost()
427 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
429 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
430 if (Inst.isInvalid())
431 return true;
432
433 for (const Expr *ConstraintExpr : ConstraintExprs) {
435 S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
436 ConstraintExpr, Satisfaction);
437 if (Res.isInvalid())
438 return true;
439
440 Converted.push_back(Res.get());
441 if (!Satisfaction.IsSatisfied) {
442 // Backfill the 'converted' list with nulls so we can keep the Converted
443 // and unconverted lists in sync.
444 Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
445 // [temp.constr.op] p2
446 // [...] To determine if a conjunction is satisfied, the satisfaction
447 // of the first operand is checked. If that is not satisfied, the
448 // conjunction is not satisfied. [...]
449 return false;
450 }
451 }
452 return false;
453}
454
456 const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
457 llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
458 const MultiLevelTemplateArgumentList &TemplateArgsLists,
459 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
460 if (ConstraintExprs.empty()) {
461 OutSatisfaction.IsSatisfied = true;
462 return false;
463 }
464 if (!Template) {
465 return ::CheckConstraintSatisfaction(
466 *this, nullptr, ConstraintExprs, ConvertedConstraints,
467 TemplateArgsLists, TemplateIDRange, OutSatisfaction);
468 }
469
470 // A list of the template argument list flattened in a predictible manner for
471 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
472 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
473 // here.
475 for (auto List : TemplateArgsLists)
476 FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
477 List.Args.end());
478
479 llvm::FoldingSetNodeID ID;
480 ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
481 void *InsertPos;
482 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
483 OutSatisfaction = *Cached;
484 return false;
485 }
486
487 auto Satisfaction =
488 std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
489 if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
490 ConvertedConstraints, TemplateArgsLists,
491 TemplateIDRange, *Satisfaction)) {
492 OutSatisfaction = *Satisfaction;
493 return true;
494 }
495
496 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
497 // The evaluation of this constraint resulted in us trying to re-evaluate it
498 // recursively. This isn't really possible, except we try to form a
499 // RecoveryExpr as a part of the evaluation. If this is the case, just
500 // return the 'cached' version (which will have the same result), and save
501 // ourselves the extra-insert. If it ever becomes possible to legitimately
502 // recursively check a constraint, we should skip checking the 'inner' one
503 // above, and replace the cached version with this one, as it would be more
504 // specific.
505 OutSatisfaction = *Cached;
506 return false;
507 }
508
509 // Else we can simply add this satisfaction to the list.
510 OutSatisfaction = *Satisfaction;
511 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
512 // invalidated it.
513 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
514 SatisfactionCache.InsertNode(Satisfaction.release());
515 return false;
516}
517
518bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
519 ConstraintSatisfaction &Satisfaction) {
521 *this, ConstraintExpr, Satisfaction,
522 [this](const Expr *AtomicExpr) -> ExprResult {
523 // We only do this to immitate lvalue-to-rvalue conversion.
525 const_cast<Expr *>(AtomicExpr));
526 })
527 .isInvalid();
528}
529
530bool Sema::addInstantiatedCapturesToScope(
531 FunctionDecl *Function, const FunctionDecl *PatternDecl,
533 const MultiLevelTemplateArgumentList &TemplateArgs) {
534 const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
535 const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
536
537 unsigned Instantiated = 0;
538
539 auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
540 unsigned Index) {
541 ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
542 if (cast<CXXMethodDecl>(Function)->isConst()) {
543 QualType T = CapturedVar->getType();
544 T.addConst();
545 CapturedVar->setType(T);
546 }
547 if (CapturedVar->isInitCapture())
548 Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
549 };
550
551 for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
552 if (!CapturePattern.capturesVariable()) {
553 Instantiated++;
554 continue;
555 }
556 const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
557 if (!CapturedPattern->isParameterPack()) {
558 AddSingleCapture(CapturedPattern, Instantiated++);
559 } else {
560 Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
561 std::optional<unsigned> NumArgumentsInExpansion =
562 getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
563 if (!NumArgumentsInExpansion)
564 continue;
565 for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
566 AddSingleCapture(CapturedPattern, Instantiated++);
567 }
568 }
569 return false;
570}
571
572bool Sema::SetupConstraintScope(
573 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
575 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
576 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
577 InstantiatingTemplate Inst(
578 *this, FD->getPointOfInstantiation(),
580 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
581 SourceRange());
582 if (Inst.isInvalid())
583 return true;
584
585 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
586 // 'instantiated' parameters and adds it to the context. For the case where
587 // this function is a template being instantiated NOW, we also need to add
588 // the list of current template arguments to the list so that they also can
589 // be picked out of the map.
590 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
591 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
592 /*Final=*/false);
593 if (addInstantiatedParametersToScope(
594 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
595 return true;
596 }
597
598 // If this is a member function, make sure we get the parameters that
599 // reference the original primary template.
600 if (const auto *FromMemTempl =
601 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
602 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
603 Scope, MLTAL))
604 return true;
605 // Make sure the captures are also added to the instantiation scope.
606 if (isLambdaCallOperator(FD) &&
607 addInstantiatedCapturesToScope(FD, FromMemTempl->getTemplatedDecl(),
608 Scope, MLTAL))
609 return true;
610 }
611
612 return false;
613 }
614
617 FunctionDecl *InstantiatedFrom =
621
622 InstantiatingTemplate Inst(
623 *this, FD->getPointOfInstantiation(),
625 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
626 SourceRange());
627 if (Inst.isInvalid())
628 return true;
629
630 // Case where this was not a template, but instantiated as a
631 // child-function.
632 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
633 return true;
634
635 // Make sure the captures are also added to the instantiation scope.
636 if (isLambdaCallOperator(FD) &&
637 addInstantiatedCapturesToScope(FD, InstantiatedFrom, Scope, MLTAL))
638 return true;
639 }
640
641 return false;
642}
643
644// This function collects all of the template arguments for the purposes of
645// constraint-instantiation and checking.
646std::optional<MultiLevelTemplateArgumentList>
647Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
648 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
651
652 // Collect the list of template arguments relative to the 'primary' template.
653 // We need the entire list, since the constraint is completely uninstantiated
654 // at this point.
655 MLTAL =
656 getTemplateInstantiationArgs(FD, /*Final=*/false, /*Innermost=*/nullptr,
657 /*RelativeToPrimary=*/true,
658 /*Pattern=*/nullptr,
659 /*ForConstraintInstantiation=*/true);
660 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
661 return std::nullopt;
662
663 return MLTAL;
664}
665
667 ConstraintSatisfaction &Satisfaction,
668 SourceLocation UsageLoc,
669 bool ForOverloadResolution) {
670 // Don't check constraints if the function is dependent. Also don't check if
671 // this is a function template specialization, as the call to
672 // CheckinstantiatedFunctionTemplateConstraints after this will check it
673 // better.
674 if (FD->isDependentContext() ||
675 FD->getTemplatedKind() ==
677 Satisfaction.IsSatisfied = true;
678 return false;
679 }
680
681 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
682
683 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
684 if (isLambdaCallOperator(CtxToSave))
685 CtxToSave = CtxToSave->getParent()->getParent();
686 else
687 CtxToSave = CtxToSave->getNonTransparentContext();
688 }
689
690 ContextRAII SavedContext{*this, CtxToSave};
691 LocalInstantiationScope Scope(*this, !ForOverloadResolution ||
693 std::optional<MultiLevelTemplateArgumentList> MLTAL =
694 SetupConstraintCheckingTemplateArgumentsAndScope(
695 const_cast<FunctionDecl *>(FD), {}, Scope);
696
697 if (!MLTAL)
698 return true;
699
700 Qualifiers ThisQuals;
701 CXXRecordDecl *Record = nullptr;
702 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
703 ThisQuals = Method->getMethodQualifiers();
704 Record = const_cast<CXXRecordDecl *>(Method->getParent());
705 }
706 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
707 // We substitute with empty arguments in order to rebuild the atomic
708 // constraint in a constant-evaluated context.
709 // FIXME: Should this be a dedicated TreeTransform?
710 const Expr *RC = FD->getTrailingRequiresClause();
712
714 FD, {RC}, Converted, *MLTAL,
715 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
716 Satisfaction))
717 return true;
718
719 // FIXME: we need to do this for the function constraints for
720 // comparison of constraints to work, but do we also need to do it for
721 // CheckInstantiatedFunctionConstraints? That one is more difficult, but we
722 // seem to always just pick up the constraints from the primary template.
723 assert(Converted.size() <= 1 && "Got more expressions converted?");
724 if (!Converted.empty() && Converted[0] != nullptr)
725 const_cast<FunctionDecl *>(FD)->setTrailingRequiresClause(Converted[0]);
726 return false;
727}
728
729
730// Figure out the to-translation-unit depth for this function declaration for
731// the purpose of seeing if they differ by constraints. This isn't the same as
732// getTemplateDepth, because it includes already instantiated parents.
733static unsigned
735 bool SkipForSpecialization = false) {
737 ND, /*Final=*/false, /*Innermost=*/nullptr, /*RelativeToPrimary=*/true,
738 /*Pattern=*/nullptr,
739 /*ForConstraintInstantiation=*/true, SkipForSpecialization);
740 return MLTAL.getNumSubstitutedLevels();
741}
742
743namespace {
744 class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
745 unsigned TemplateDepth = 0;
746 public:
747 using inherited = TreeTransform<AdjustConstraintDepth>;
748 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
749 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
750
751 using inherited::TransformTemplateTypeParmType;
752 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
753 TemplateTypeParmTypeLoc TL, bool) {
754 const TemplateTypeParmType *T = TL.getTypePtr();
755
756 TemplateTypeParmDecl *NewTTPDecl = nullptr;
757 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
758 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
759 TransformDecl(TL.getNameLoc(), OldTTPDecl));
760
761 QualType Result = getSema().Context.getTemplateTypeParmType(
762 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
763 NewTTPDecl);
765 NewTL.setNameLoc(TL.getNameLoc());
766 return Result;
767 }
768 };
769} // namespace
770
772 const Expr *OldConstr,
773 const NamedDecl *New,
774 const Expr *NewConstr) {
775 if (Old && New && Old != New) {
776 unsigned Depth1 = CalculateTemplateDepthForConstraints(
777 *this, Old);
778 unsigned Depth2 = CalculateTemplateDepthForConstraints(
779 *this, New);
780
781 // Adjust the 'shallowest' verison of this to increase the depth to match
782 // the 'other'.
783 if (Depth2 > Depth1) {
784 OldConstr = AdjustConstraintDepth(*this, Depth2 - Depth1)
785 .TransformExpr(const_cast<Expr *>(OldConstr))
786 .get();
787 } else if (Depth1 > Depth2) {
788 NewConstr = AdjustConstraintDepth(*this, Depth1 - Depth2)
789 .TransformExpr(const_cast<Expr *>(NewConstr))
790 .get();
791 }
792 }
793
794 llvm::FoldingSetNodeID ID1, ID2;
795 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
796 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
797 return ID1 == ID2;
798}
799
801 assert(FD->getFriendObjectKind() && "Must be a friend!");
802
803 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
804 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
805 // non-function-template.
806 assert(FD->getDescribedFunctionTemplate() &&
807 "Non-function templates don't need to be checked");
808
811
812 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
813 for (const Expr *Constraint : ACs)
814 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
815 Constraint))
816 return true;
817
818 return false;
819}
820
822 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
823 SourceRange TemplateIDRange) {
824 ConstraintSatisfaction Satisfaction;
825 llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
826 TD->getAssociatedConstraints(AssociatedConstraints);
827 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
828 TemplateIDRange, Satisfaction))
829 return true;
830
831 if (!Satisfaction.IsSatisfied) {
832 SmallString<128> TemplateArgString;
833 TemplateArgString = " ";
834 TemplateArgString += getTemplateArgumentBindingsText(
835 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
836 TemplateArgsLists.getInnermost().size());
837
838 Diag(TemplateIDRange.getBegin(),
839 diag::err_template_arg_list_constraints_not_satisfied)
841 << TemplateArgString << TemplateIDRange;
842 DiagnoseUnsatisfiedConstraint(Satisfaction);
843 return true;
844 }
845 return false;
846}
847
849 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
850 ArrayRef<TemplateArgument> TemplateArgs,
851 ConstraintSatisfaction &Satisfaction) {
852 // In most cases we're not going to have constraints, so check for that first.
853 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
854 // Note - code synthesis context for the constraints check is created
855 // inside CheckConstraintsSatisfaction.
857 Template->getAssociatedConstraints(TemplateAC);
858 if (TemplateAC.empty()) {
859 Satisfaction.IsSatisfied = true;
860 return false;
861 }
862
863 // Enter the scope of this instantiation. We don't use
864 // PushDeclContext because we don't have a scope.
865 Sema::ContextRAII savedContext(*this, Decl);
867
868 std::optional<MultiLevelTemplateArgumentList> MLTAL =
869 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
870 Scope);
871
872 if (!MLTAL)
873 return true;
874
875 Qualifiers ThisQuals;
876 CXXRecordDecl *Record = nullptr;
877 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
878 ThisQuals = Method->getMethodQualifiers();
879 Record = Method->getParent();
880 }
881 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
882 FunctionScopeRAII FuncScope(*this);
885 else
886 FuncScope.disable();
887
889 return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
890 PointOfInstantiation, Satisfaction);
891}
892
895 bool First) {
896 assert(!Req->isSatisfied()
897 && "Diagnose() can only be used on an unsatisfied requirement");
898 switch (Req->getSatisfactionStatus()) {
900 llvm_unreachable("Diagnosing a dependent requirement");
901 break;
903 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
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;
909 else
910 S.Diag(SubstDiag->DiagLoc,
911 diag::note_expr_requirement_expr_unknown_substitution_error)
912 << (int)First << SubstDiag->SubstitutedEntity;
913 break;
914 }
916 S.Diag(Req->getNoexceptLoc(),
917 diag::note_expr_requirement_noexcept_not_met)
918 << (int)First << Req->getExpr();
919 break;
921 auto *SubstDiag =
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;
928 else
929 S.Diag(SubstDiag->DiagLoc,
930 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
931 << (int)First << SubstDiag->SubstitutedEntity;
932 break;
933 }
935 ConceptSpecializationExpr *ConstraintExpr =
937 if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
938 // A simple case - expr type is the type being constrained and the concept
939 // was not provided arguments.
940 Expr *e = Req->getExpr();
941 S.Diag(e->getBeginLoc(),
942 diag::note_expr_requirement_constraints_not_satisfied_simple)
944 << ConstraintExpr->getNamedConcept();
945 } else {
946 S.Diag(ConstraintExpr->getBeginLoc(),
947 diag::note_expr_requirement_constraints_not_satisfied)
948 << (int)First << ConstraintExpr;
949 }
951 break;
952 }
954 llvm_unreachable("We checked this above");
955 }
956}
957
960 bool First) {
961 assert(!Req->isSatisfied()
962 && "Diagnose() can only be used on an unsatisfied requirement");
963 switch (Req->getSatisfactionStatus()) {
965 llvm_unreachable("Diagnosing a dependent requirement");
966 return;
968 auto *SubstDiag = Req->getSubstitutionDiagnostic();
969 if (!SubstDiag->DiagMessage.empty())
970 S.Diag(SubstDiag->DiagLoc,
971 diag::note_type_requirement_substitution_error) << (int)First
972 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
973 else
974 S.Diag(SubstDiag->DiagLoc,
975 diag::note_type_requirement_unknown_substitution_error)
976 << (int)First << SubstDiag->SubstitutedEntity;
977 return;
978 }
979 default:
980 llvm_unreachable("Unknown satisfaction status");
981 return;
982 }
983}
985 Expr *SubstExpr,
986 bool First = true);
987
990 bool First) {
991 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
992 for (auto &Pair : Req->getConstraintSatisfaction()) {
993 if (auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
994 S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
995 << (int)First << Req->getInvalidConstraintEntity() << SubstDiag->second;
996 else
998 S, Pair.second.dyn_cast<Expr *>(), First);
999 First = false;
1000 }
1001}
1002
1004 Expr *SubstExpr,
1005 bool First) {
1006 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1007 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1008 switch (BO->getOpcode()) {
1009 // These two cases will in practice only be reached when using fold
1010 // expressions with || and &&, since otherwise the || and && will have been
1011 // broken down into atomic constraints during satisfaction checking.
1012 case BO_LOr:
1013 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1016 /*First=*/false);
1017 return;
1018 case BO_LAnd: {
1019 bool LHSSatisfied =
1020 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1021 if (LHSSatisfied) {
1022 // LHS is true, so RHS must be false.
1024 return;
1025 }
1026 // LHS is false
1028
1029 // RHS might also be false
1030 bool RHSSatisfied =
1031 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1032 if (!RHSSatisfied)
1034 /*First=*/false);
1035 return;
1036 }
1037 case BO_GE:
1038 case BO_LE:
1039 case BO_GT:
1040 case BO_LT:
1041 case BO_EQ:
1042 case BO_NE:
1043 if (BO->getLHS()->getType()->isIntegerType() &&
1044 BO->getRHS()->getType()->isIntegerType()) {
1045 Expr::EvalResult SimplifiedLHS;
1046 Expr::EvalResult SimplifiedRHS;
1047 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1049 /*InConstantContext=*/true);
1050 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1052 /*InConstantContext=*/true);
1053 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
1054 S.Diag(SubstExpr->getBeginLoc(),
1055 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1056 << (int)First << SubstExpr
1057 << toString(SimplifiedLHS.Val.getInt(), 10)
1058 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1059 << toString(SimplifiedRHS.Val.getInt(), 10);
1060 return;
1061 }
1062 }
1063 break;
1064
1065 default:
1066 break;
1067 }
1068 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1069 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1070 S.Diag(
1071 CSE->getSourceRange().getBegin(),
1072 diag::
1073 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1074 << (int)First
1075 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1076 << CSE->getNamedConcept();
1077 } else {
1078 S.Diag(SubstExpr->getSourceRange().getBegin(),
1079 diag::note_concept_specialization_constraint_evaluated_to_false)
1080 << (int)First << CSE;
1081 }
1082 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1083 return;
1084 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1085 // FIXME: RequiresExpr should store dependent diagnostics.
1086 for (concepts::Requirement *Req : RE->getRequirements())
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))
1092 else
1094 S, cast<concepts::NestedRequirement>(Req), First);
1095 break;
1096 }
1097 return;
1098 }
1099
1100 S.Diag(SubstExpr->getSourceRange().getBegin(),
1101 diag::note_atomic_constraint_evaluated_to_false)
1102 << (int)First << SubstExpr;
1103}
1104
1105template<typename SubstitutionDiagnostic>
1107 Sema &S, const Expr *E,
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)
1112 << Diag->second;
1113 return;
1114 }
1115
1117 Record.template get<Expr *>(), First);
1118}
1119
1120void
1122 bool First) {
1123 assert(!Satisfaction.IsSatisfied &&
1124 "Attempted to diagnose a satisfied constraint");
1125 for (auto &Pair : Satisfaction.Details) {
1126 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1127 First = false;
1128 }
1129}
1130
1132 const ASTConstraintSatisfaction &Satisfaction,
1133 bool First) {
1134 assert(!Satisfaction.IsSatisfied &&
1135 "Attempted to diagnose a satisfied constraint");
1136 for (auto &Pair : Satisfaction) {
1137 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1138 First = false;
1139 }
1140}
1141
1144 NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
1145 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1146 if (CacheEntry == NormalizationCache.end()) {
1147 auto Normalized =
1148 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1149 AssociatedConstraints);
1150 CacheEntry =
1151 NormalizationCache
1152 .try_emplace(ConstrainedDecl,
1153 Normalized
1155 std::move(*Normalized))
1156 : nullptr)
1157 .first;
1158 }
1159 return CacheEntry->second;
1160}
1161
1162static bool
1164 ConceptDecl *Concept,
1165 const MultiLevelTemplateArgumentList &MLTAL,
1166 const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1167 if (!N.isAtomic()) {
1168 if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1169 ArgsAsWritten))
1170 return true;
1171 return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1172 ArgsAsWritten);
1173 }
1174 TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1175
1177 TemplateArgumentListInfo SubstArgs;
1178 if (!Atomic.ParameterMapping) {
1179 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1180 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1181 /*Depth=*/0, OccurringIndices);
1182 TemplateArgumentLoc *TempArgs =
1183 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
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],
1189 // Here we assume we do not support things like
1190 // template<typename A, typename B>
1191 // concept C = ...;
1192 //
1193 // template<typename... Ts> requires C<Ts...>
1194 // struct S { };
1195 // The above currently yields a diagnostic.
1196 // We still might have default arguments for concept parameters.
1197 ArgsAsWritten->NumTemplateArgs > I
1198 ? ArgsAsWritten->arguments()[I].getLocation()
1199 : SourceLocation()));
1200 Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
1201 }
1203 S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
1205 ArgsAsWritten->arguments().front().getSourceRange());
1206 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1207 return true;
1208
1209 TemplateArgumentLoc *TempArgs =
1210 new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1211 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1212 TempArgs);
1213 Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1214 return false;
1215}
1216
1218 const ConceptSpecializationExpr *CSE) {
1220 CSE->getTemplateArguments()};
1222 CSE->getNamedConcept(), /*Final=*/false, &TAL,
1223 /*RelativeToPrimary=*/true,
1224 /*Pattern=*/nullptr,
1225 /*ForConstraintInstantiation=*/true);
1226
1227 return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1229}
1230
1231std::optional<NormalizedConstraint>
1232NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1234 assert(E.size() != 0);
1235 auto Conjunction = fromConstraintExpr(S, D, E[0]);
1236 if (!Conjunction)
1237 return std::nullopt;
1238 for (unsigned I = 1; I < E.size(); ++I) {
1239 auto Next = fromConstraintExpr(S, D, E[I]);
1240 if (!Next)
1241 return std::nullopt;
1242 *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1243 std::move(*Next), CCK_Conjunction);
1244 }
1245 return Conjunction;
1246}
1247
1248std::optional<NormalizedConstraint>
1249NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1250 assert(E != nullptr);
1251
1252 // C++ [temp.constr.normal]p1.1
1253 // [...]
1254 // - The normal form of an expression (E) is the normal form of E.
1255 // [...]
1256 E = E->IgnoreParenImpCasts();
1257
1258 // C++2a [temp.param]p4:
1259 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1260 // Fold expression is considered atomic constraints per current wording.
1261 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1262
1263 if (LogicalBinOp BO = E) {
1264 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1265 if (!LHS)
1266 return std::nullopt;
1267 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1268 if (!RHS)
1269 return std::nullopt;
1270
1271 return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
1272 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1273 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1274 const NormalizedConstraint *SubNF;
1275 {
1277 S, CSE->getExprLoc(),
1279 CSE->getSourceRange());
1280 // C++ [temp.constr.normal]p1.1
1281 // [...]
1282 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1283 // where C names a concept, is the normal form of the
1284 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1285 // respective template parameters in the parameter mappings in each atomic
1286 // constraint. If any such substitution results in an invalid type or
1287 // expression, the program is ill-formed; no diagnostic is required.
1288 // [...]
1289 ConceptDecl *CD = CSE->getNamedConcept();
1291 {CD->getConstraintExpr()});
1292 if (!SubNF)
1293 return std::nullopt;
1294 }
1295
1296 std::optional<NormalizedConstraint> New;
1297 New.emplace(S.Context, *SubNF);
1298
1299 if (substituteParameterMappings(S, *New, CSE))
1300 return std::nullopt;
1301
1302 return New;
1303 }
1304 return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
1305}
1306
1309
1310static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
1311 if (Normalized.isAtomic())
1312 return {{Normalized.getAtomicConstraint()}};
1313
1314 NormalForm LCNF = makeCNF(Normalized.getLHS());
1315 NormalForm RCNF = makeCNF(Normalized.getRHS());
1317 LCNF.reserve(LCNF.size() + RCNF.size());
1318 while (!RCNF.empty())
1319 LCNF.push_back(RCNF.pop_back_val());
1320 return LCNF;
1321 }
1322
1323 // Disjunction
1324 NormalForm Res;
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);
1335 }
1336 return Res;
1337}
1338
1339static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
1340 if (Normalized.isAtomic())
1341 return {{Normalized.getAtomicConstraint()}};
1342
1343 NormalForm LDNF = makeDNF(Normalized.getLHS());
1344 NormalForm RDNF = makeDNF(Normalized.getRHS());
1346 LDNF.reserve(LDNF.size() + RDNF.size());
1347 while (!RDNF.empty())
1348 LDNF.push_back(RDNF.pop_back_val());
1349 return LDNF;
1350 }
1351
1352 // Conjunction
1353 NormalForm Res;
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);
1364 }
1365 }
1366 return Res;
1367}
1368
1369template<typename AtomicSubsumptionEvaluator>
1370static bool subsumes(NormalForm PDNF, NormalForm QCNF,
1371 AtomicSubsumptionEvaluator E) {
1372 // C++ [temp.constr.order] p2
1373 // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
1374 // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
1375 // the conjuctive normal form of Q, where [...]
1376 for (const auto &Pi : PDNF) {
1377 for (const auto &Qj : QCNF) {
1378 // C++ [temp.constr.order] p2
1379 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
1380 // and only if there exists an atomic constraint Pia in Pi for which
1381 // there exists an atomic constraint, Qjb, in Qj such that Pia
1382 // subsumes Qjb.
1383 bool Found = false;
1384 for (const AtomicConstraint *Pia : Pi) {
1385 for (const AtomicConstraint *Qjb : Qj) {
1386 if (E(*Pia, *Qjb)) {
1387 Found = true;
1388 break;
1389 }
1390 }
1391 if (Found)
1392 break;
1393 }
1394 if (!Found)
1395 return false;
1396 }
1397 }
1398 return true;
1399}
1400
1401template<typename AtomicSubsumptionEvaluator>
1403 NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
1404 AtomicSubsumptionEvaluator E) {
1405 // C++ [temp.constr.order] p2
1406 // In order to determine if a constraint P subsumes a constraint Q, P is
1407 // transformed into disjunctive normal form, and Q is transformed into
1408 // conjunctive normal form. [...]
1409 auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
1410 if (!PNormalized)
1411 return true;
1412 const NormalForm PDNF = makeDNF(*PNormalized);
1413
1414 auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
1415 if (!QNormalized)
1416 return true;
1417 const NormalForm QCNF = makeCNF(*QNormalized);
1418
1419 Subsumes = subsumes(PDNF, QCNF, E);
1420 return false;
1421}
1422
1425 NamedDecl *D2,
1427 bool &Result) {
1428 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1429 auto IsExpectedEntity = [](const FunctionDecl *FD) {
1431 return Kind == FunctionDecl::TK_NonTemplate ||
1433 };
1434 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1435 (void)IsExpectedEntity;
1436 (void)FD1;
1437 (void)FD2;
1438 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1439 "use non-instantiated function declaration for constraints partial "
1440 "ordering");
1441 }
1442
1443 if (AC1.empty()) {
1444 Result = AC2.empty();
1445 return false;
1446 }
1447 if (AC2.empty()) {
1448 // TD1 has associated constraints and TD2 does not.
1449 Result = true;
1450 return false;
1451 }
1452
1453 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1454 auto CacheEntry = SubsumptionCache.find(Key);
1455 if (CacheEntry != SubsumptionCache.end()) {
1456 Result = CacheEntry->second;
1457 return false;
1458 }
1459
1460 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1461 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1462
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]))
1467 .get();
1468 } else if (Depth1 > Depth2) {
1469 AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1470 .TransformExpr(const_cast<Expr *>(AC2[I]))
1471 .get();
1472 }
1473 }
1474
1475 if (subsumes(*this, D1, AC1, D2, AC2, Result,
1476 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1477 return A.subsumes(Context, B);
1478 }))
1479 return true;
1480 SubsumptionCache.try_emplace(Key, Result);
1481 return false;
1482}
1483
1486 if (isSFINAEContext())
1487 // No need to work here because our notes would be discarded.
1488 return false;
1489
1490 if (AC1.empty() || AC2.empty())
1491 return false;
1492
1493 auto NormalExprEvaluator =
1494 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1495 return A.subsumes(Context, B);
1496 };
1497
1498 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1499 auto IdenticalExprEvaluator =
1500 [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1502 return false;
1503 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1504 if (EA == EB)
1505 return true;
1506
1507 // Not the same source level expression - are the expressions
1508 // identical?
1509 llvm::FoldingSetNodeID IDA, IDB;
1510 EA->Profile(IDA, Context, /*Canonical=*/true);
1511 EB->Profile(IDB, Context, /*Canonical=*/true);
1512 if (IDA != IDB)
1513 return false;
1514
1515 AmbiguousAtomic1 = EA;
1516 AmbiguousAtomic2 = EB;
1517 return true;
1518 };
1519
1520 {
1521 // The subsumption checks might cause diagnostics
1522 SFINAETrap Trap(*this);
1523 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1524 if (!Normalized1)
1525 return false;
1526 const NormalForm DNF1 = makeDNF(*Normalized1);
1527 const NormalForm CNF1 = makeCNF(*Normalized1);
1528
1529 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1530 if (!Normalized2)
1531 return false;
1532 const NormalForm DNF2 = makeDNF(*Normalized2);
1533 const NormalForm CNF2 = makeCNF(*Normalized2);
1534
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)
1541 // Same result - no ambiguity was caused by identical atomic expressions.
1542 return false;
1543 }
1544
1545 // A different result! Some ambiguous atomic constraint(s) caused a difference
1546 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1547
1548 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1549 << AmbiguousAtomic1->getSourceRange();
1550 Diag(AmbiguousAtomic2->getBeginLoc(),
1551 diag::note_ambiguous_atomic_constraints_similar_expression)
1552 << AmbiguousAtomic2->getSourceRange();
1553 return true;
1554}
1555
1557 Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1559 ConceptSpecializationExpr *SubstitutedConstraintExpr) :
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),
1566 Status(Status) {
1567 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1568 "Simple requirement must not have a return type requirement or a "
1569 "noexcept specification");
1570 assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1571 (SubstitutedConstraintExpr != nullptr));
1572}
1573
1575 SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1576 SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1577 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1578 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1579 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1580 Status(SS_ExprSubstitutionFailure) {
1581 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1582 "Simple requirement must not have a return type requirement or a "
1583 "noexcept specification");
1584}
1585
1588 TypeConstraintInfo(TPL, false) {
1589 assert(TPL->size() == 1);
1590 const TypeConstraint *TC =
1591 cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1592 assert(TC &&
1593 "TPL must have a template type parameter with a type constraint");
1594 auto *Constraint =
1595 cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1596 bool Dependent =
1597 Constraint->getTemplateArgsAsWritten() &&
1599 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1600 TypeConstraintInfo.setInt(Dependent ? true : false);
1601}
1602
1604 Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
1605 T->getType()->containsUnexpandedParameterPack(),
1606 // We reach this ctor with either dependent types (in which
1607 // IsSatisfied doesn't matter) or with non-dependent type in
1608 // which the existence of the type indicates satisfaction.
1609 /*IsSatisfied=*/true),
1610 Value(T),
1611 Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1612 : SS_Satisfied) {}
This file provides some common utility functions for processing Lambda related AST Constructs.
StringRef P
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)
__device__ int
APSInt & getInt()
Definition: APValue.h:415
bool isInt() const
Definition: APValue.h:393
QualType getReferenceQualifiedType(const Expr *e) const
getReferenceQualifiedType - Given an expr, will return the type for that expression,...
CanQualType BoolTy
Definition: ASTContext.h:1079
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2548
bool isInvalid() const
Definition: Ownership.h:165
bool isUsable() const
Definition: Ownership.h:166
PtrTy get() const
Definition: Ownership.h:169
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition: Expr.h:6239
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:6334
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3814
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2170
StringRef getOpcodeStr() const
Definition: Expr.h:3879
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Definition: Expr.cpp:4639
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2132
Represents a C++ struct/union/class.
Definition: DeclCXX.h:254
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
ConceptDecl * getNamedConcept() const
Definition: ASTConcept.h:165
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Definition: ASTConcept.h:169
Represents the specialization of a concept - evaluates to a prvalue of type bool.
Definition: ExprConcepts.h:41
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: ExprConcepts.h:119
ArrayRef< TemplateArgument > getTemplateArguments() const
Definition: ExprConcepts.h:88
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
Definition: ExprConcepts.h:109
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:28
llvm::SmallVector< std::pair< const Expr *, Detail >, 4 > Details
Pairs of unsatisfied atomic constraint expressions along with the substituted constraint expr,...
Definition: ASTConcept.h:53
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
Definition: ASTConcept.h:43
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
Definition: ASTConcept.h:55
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1393
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1933
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
Definition: DeclBase.cpp:1220
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1186
DeclContext * getNonTransparentContext()
Definition: DeclBase.cpp:1267
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
Definition: DeclBase.h:1185
bool isParameterPack() const
Whether this declaration is a parameter pack.
Definition: DeclBase.cpp:220
SourceLocation getLocation() const
Definition: DeclBase.h:432
Expr * getTrailingRequiresClause()
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition: Decl.h:841
RAII object that enters a new expression evaluation context.
Definition: Sema.h:13959
This represents one expression.
Definition: Expr.h:110
@ SE_NoSideEffects
Strictly evaluate the expression.
Definition: Expr.h:649
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:186
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3046
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition: Expr.h:239
bool isPRValue() const
Definition: Expr.h:272
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...
Definition: Expr.cpp:330
QualType getType() const
Definition: Expr.h:142
Represents difference between two FPOptions values.
Definition: LangOptions.h:806
Represents a function declaration or definition.
Definition: Decl.h:1917
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition: Decl.cpp:3825
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition: Decl.cpp:4119
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition: Decl.cpp:3939
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition: Decl.cpp:3955
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition: Decl.cpp:3883
TemplatedKind
The kind of templated function a FunctionDecl can be.
Definition: Decl.h:1922
@ TK_MemberSpecialization
Definition: Decl.h:1929
@ TK_DependentNonTemplate
Definition: Decl.h:1938
@ TK_FunctionTemplateSpecialization
Definition: Decl.h:1933
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition: Decl.cpp:3776
FunctionDecl * getInstantiatedFromDecl() const
Definition: Decl.cpp:3843
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition: Decl.cpp:3797
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)
Definition: Expr.cpp:2063
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:502
Describes the capture of a variable or of this, or of a C++1y init-capture.
Definition: LambdaCapture.h:25
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Definition: Template.h:334
Data structure that captures multiple levels of template argument lists for use in template instantia...
Definition: Template.h:76
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
Definition: Template.h:251
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
Definition: Template.h:129
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
Definition: Template.h:255
This represents a decl that may have a name.
Definition: Decl.h:247
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
A (possibly-)qualified type.
Definition: Type.h:736
void addConst()
Add the const type qualifier to this QualType.
Definition: Type.h:912
The collection of all-type qualifiers we support.
Definition: Type.h:146
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition: Sema.h:6647
A RAII object to temporarily push a declaration context.
Definition: Sema.h:998
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition: Sema.h:9756
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition: Sema.h:9787
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:356
bool CheckInstantiatedFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: Sema.cpp:1884
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...
ASTContext & Context
Definition: Sema.h:407
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
DiagnosticsEngine & getDiagnostics() const
Definition: Sema.h:1649
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
Definition: SemaConcept.cpp:88
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
sema::LambdaScopeInfo * PushLambdaScope()
Definition: Sema.cpp:2141
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
Definition: Sema.h:1645
@ ReuseLambdaContextDecl
Definition: Sema.h:5400
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...
Definition: Sema.h:7393
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:1977
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)
Definition: SemaDecl.cpp:1325
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)
Definition: Sema.h:7316
void PopSatisfactionStackEntry()
Definition: Sema.h:7322
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.
Definition: SemaInternal.h:24
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
Definition: Sema.h:7324
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...
Definition: Stmt.cpp:325
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const
Produce a unique representation of the given statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:337
A convenient class for passing around template argument information.
Definition: TemplateBase.h:590
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:618
A template argument list.
Definition: DeclTemplate.h:238
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:484
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:407
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.
Definition: DeclTemplate.h:426
Represents a C++ template name within the type system.
Definition: TemplateName.h:202
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:73
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:138
static bool anyInstantiationDependentTemplateArguments(ArrayRef< TemplateArgumentLoc > Args)
Definition: Type.cpp:3808
Declaration of a template type parameter.
Wrapper for template type parameters.
Definition: TypeLoc.h:746
TemplateTypeParmDecl * getDecl() const
Definition: Type.h:5068
bool isParameterPack() const
Definition: Type.h:5066
unsigned getIndex() const
Definition: Type.h:5065
unsigned getDepth() const
Definition: Type.h:5064
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
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)) {....
Definition: Token.h:98
tok::TokenKind getKind() const
Definition: Token.h:93
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Expr * getImmediatelyDeclaredConstraint() const
Get the immediately-declared constraint expression introduced by this type-constraint,...
Definition: ASTConcept.h:198
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
A container of type source information.
Definition: Type.h:6620
SourceLocation getNameLoc() const
Definition: TypeLoc.h:523
void setNameLoc(SourceLocation Loc)
Definition: TypeLoc.h:527
The base class of the type hierarchy.
Definition: Type.h:1566
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:7187
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2317
bool isFunctionType() const
Definition: Type.h:6906
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:701
void setType(QualType newType)
Definition: Decl.h:713
QualType getType() const
Definition: Decl.h:712
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Definition: Decl.cpp:5066
ReturnTypeRequirement()
No return type requirement was specified.
Definition: ExprConcepts.h:275
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:315
A requires-expression requirement which queries the validity and properties of an expression ('simple...
Definition: ExprConcepts.h:255
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
Definition: ExprConcepts.h:383
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
Definition: ExprConcepts.h:378
const ReturnTypeRequirement & getReturnTypeRequirement() const
Definition: ExprConcepts.h:373
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:367
SourceLocation getNoexceptLoc() const
Definition: ExprConcepts.h:365
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...
Definition: ExprConcepts.h:404
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
Definition: ExprConcepts.h:459
A static requirement that can be used in a requires-expression to check properties of types and expre...
Definition: ExprConcepts.h:146
bool containsUnexpandedParameterPack() const
Definition: ExprConcepts.h:193
A requires-expression requirement which queries the existence of a type name or type template special...
Definition: ExprConcepts.h:200
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:235
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:226
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.
Definition: OperatorKinds.h:21
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
@ CPlusPlus11
Definition: LangStandard.h:54
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:139
ExprResult ExprEmpty()
Definition: Ownership.h:289
@ C
Languages that the frontend can parse and compile.
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition: ASTLambda.h:27
@ Result
The result type of a method or function.
ExprResult ExprError()
Definition: Ownership.h:278
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.
Definition: Specifiers.h:123
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
#define true
Definition: stdbool.h:21
#define false
Definition: stdbool.h:22
#define bool
Definition: stdbool.h:20
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:86
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Definition: TemplateBase.h:641
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:670
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
Definition: TemplateBase.h:659
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
Definition: SemaConcept.h:57
std::optional< ArrayRef< TemplateArgumentLoc > > ParameterMapping
Definition: SemaConcept.h:31
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
Definition: SemaConcept.h:36
const Expr * ConstraintExpr
Definition: SemaConcept.h:30
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:623
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:625
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:610
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
Definition: SemaConcept.h:81
AtomicConstraint * getAtomicConstraint() const
Definition: SemaConcept.h:140
CompoundConstraintKind getCompoundKind() const
Definition: SemaConcept.h:123
NormalizedConstraint & getRHS() const
Definition: SemaConcept.h:135
NormalizedConstraint & getLHS() const
Definition: SemaConcept.h:130
An RAII helper that pops function a function scope on exit.
Definition: Sema.h:5052
A stack object to be created when performing template instantiation.
Definition: Sema.h:9491
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition: Sema.h:9635