clang 18.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
14#include "TreeTransform.h"
15#include "clang/AST/ASTLambda.h"
16#include "clang/AST/DeclCXX.h"
22#include "clang/Sema/Overload.h"
24#include "clang/Sema/Sema.h"
27#include "clang/Sema/Template.h"
29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/PointerUnion.h"
31#include "llvm/ADT/StringExtras.h"
32#include <optional>
33
34using namespace clang;
35using namespace sema;
36
37namespace {
38class LogicalBinOp {
41 const Expr *LHS = nullptr;
42 const Expr *RHS = nullptr;
43
44public:
45 LogicalBinOp(const Expr *E) {
46 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
47 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
48 LHS = BO->getLHS();
49 RHS = BO->getRHS();
50 Loc = BO->getExprLoc();
51 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
52 // If OO is not || or && it might not have exactly 2 arguments.
53 if (OO->getNumArgs() == 2) {
54 Op = OO->getOperator();
55 LHS = OO->getArg(0);
56 RHS = OO->getArg(1);
57 Loc = OO->getOperatorLoc();
58 }
59 }
60 }
61
62 bool isAnd() const { return Op == OO_AmpAmp; }
63 bool isOr() const { return Op == OO_PipePipe; }
64 explicit operator bool() const { return isAnd() || isOr(); }
65
66 const Expr *getLHS() const { return LHS; }
67 const Expr *getRHS() const { return RHS; }
68
69 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
70 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
71 }
72
73 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
74 ExprResult RHS) const {
75 assert((isAnd() || isOr()) && "Not the right kind of op?");
76 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
77
78 if (!LHS.isUsable() || !RHS.isUsable())
79 return ExprEmpty();
80
81 // We should just be able to 'normalize' these to the builtin Binary
82 // Operator, since that is how they are evaluated in constriant checks.
83 return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
85 SemaRef.Context.BoolTy, VK_PRValue,
87 }
88};
89}
90
91bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
92 Token NextToken, bool *PossibleNonPrimary,
93 bool IsTrailingRequiresClause) {
94 // C++2a [temp.constr.atomic]p1
95 // ..E shall be a constant expression of type bool.
96
97 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
98
99 if (LogicalBinOp BO = ConstraintExpression) {
100 return CheckConstraintExpression(BO.getLHS(), NextToken,
101 PossibleNonPrimary) &&
102 CheckConstraintExpression(BO.getRHS(), NextToken,
103 PossibleNonPrimary);
104 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
105 return CheckConstraintExpression(C->getSubExpr(), NextToken,
106 PossibleNonPrimary);
107
108 QualType Type = ConstraintExpression->getType();
109
110 auto CheckForNonPrimary = [&] {
111 if (!PossibleNonPrimary)
112 return;
113
114 *PossibleNonPrimary =
115 // We have the following case:
116 // template<typename> requires func(0) struct S { };
117 // The user probably isn't aware of the parentheses required around
118 // the function call, and we're only going to parse 'func' as the
119 // primary-expression, and complain that it is of non-bool type.
120 //
121 // However, if we're in a lambda, this might also be:
122 // []<typename> requires var () {};
123 // Which also looks like a function call due to the lambda parentheses,
124 // but unlike the first case, isn't an error, so this check is skipped.
125 (NextToken.is(tok::l_paren) &&
126 (IsTrailingRequiresClause ||
127 (Type->isDependentType() &&
128 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
129 !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
130 Type->isFunctionType() ||
131 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
132 // We have the following case:
133 // template<typename T> requires size_<T> == 0 struct S { };
134 // The user probably isn't aware of the parentheses required around
135 // the binary operator, and we're only going to parse 'func' as the
136 // first operand, and complain that it is of non-bool type.
137 getBinOpPrecedence(NextToken.getKind(),
138 /*GreaterThanIsOperator=*/true,
140 };
141
142 // An atomic constraint!
143 if (ConstraintExpression->isTypeDependent()) {
144 CheckForNonPrimary();
145 return true;
146 }
147
149 Diag(ConstraintExpression->getExprLoc(),
150 diag::err_non_bool_atomic_constraint) << Type
151 << ConstraintExpression->getSourceRange();
152 CheckForNonPrimary();
153 return false;
154 }
155
156 if (PossibleNonPrimary)
157 *PossibleNonPrimary = false;
158 return true;
159}
160
161namespace {
162struct SatisfactionStackRAII {
163 Sema &SemaRef;
164 bool Inserted = false;
165 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
166 const llvm::FoldingSetNodeID &FSNID)
167 : SemaRef(SemaRef) {
168 if (ND) {
169 SemaRef.PushSatisfactionStackEntry(ND, FSNID);
170 Inserted = true;
171 }
172 }
173 ~SatisfactionStackRAII() {
174 if (Inserted)
176 }
177};
178} // namespace
179
180template <typename AtomicEvaluator>
181static ExprResult
182calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
183 ConstraintSatisfaction &Satisfaction,
184 AtomicEvaluator &&Evaluator) {
185 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
186
187 if (LogicalBinOp BO = ConstraintExpr) {
188 size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
190 S, BO.getLHS(), Satisfaction, Evaluator);
191
192 if (LHSRes.isInvalid())
193 return ExprError();
194
195 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
196
197 if (BO.isOr() && IsLHSSatisfied)
198 // [temp.constr.op] p3
199 // A disjunction is a constraint taking two operands. To determine if
200 // a disjunction is satisfied, the satisfaction of the first operand
201 // is checked. If that is satisfied, the disjunction is satisfied.
202 // Otherwise, the disjunction is satisfied if and only if the second
203 // operand is satisfied.
204 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
205 return LHSRes;
206
207 if (BO.isAnd() && !IsLHSSatisfied)
208 // [temp.constr.op] p2
209 // A conjunction is a constraint taking two operands. To determine if
210 // a conjunction is satisfied, the satisfaction of the first operand
211 // is checked. If that is not satisfied, the conjunction is not
212 // satisfied. Otherwise, the conjunction is satisfied if and only if
213 // the second operand is satisfied.
214 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
215 return LHSRes;
216
218 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
219 if (RHSRes.isInvalid())
220 return ExprError();
221
222 bool IsRHSSatisfied = Satisfaction.IsSatisfied;
223 // Current implementation adds diagnostic information about the falsity
224 // of each false atomic constraint expression when it evaluates them.
225 // When the evaluation results to `false || true`, the information
226 // generated during the evaluation of left-hand side is meaningless
227 // because the whole expression evaluates to true.
228 // The following code removes the irrelevant diagnostic information.
229 // FIXME: We should probably delay the addition of diagnostic information
230 // until we know the entire expression is false.
231 if (BO.isOr() && IsRHSSatisfied) {
232 auto EffectiveDetailEnd = Satisfaction.Details.begin();
233 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
234 Satisfaction.Details.erase(EffectiveDetailEnd,
235 Satisfaction.Details.end());
236 }
237
238 return BO.recreateBinOp(S, LHSRes, RHSRes);
239 }
240
241 if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
242 // These aren't evaluated, so we don't care about cleanups, so we can just
243 // evaluate these as if the cleanups didn't exist.
245 S, C->getSubExpr(), Satisfaction,
246 std::forward<AtomicEvaluator>(Evaluator));
247 }
248
249 // An atomic constraint expression
250 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
251
252 if (SubstitutedAtomicExpr.isInvalid())
253 return ExprError();
254
255 if (!SubstitutedAtomicExpr.isUsable())
256 // Evaluator has decided satisfaction without yielding an expression.
257 return ExprEmpty();
258
259 // We don't have the ability to evaluate this, since it contains a
260 // RecoveryExpr, so we want to fail overload resolution. Otherwise,
261 // we'd potentially pick up a different overload, and cause confusing
262 // diagnostics. SO, add a failure detail that will cause us to make this
263 // overload set not viable.
264 if (SubstitutedAtomicExpr.get()->containsErrors()) {
265 Satisfaction.IsSatisfied = false;
266 Satisfaction.ContainsErrors = true;
267
268 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
269 SmallString<128> DiagString;
270 DiagString = ": ";
271 Msg.EmitToString(S.getDiagnostics(), DiagString);
272 unsigned MessageSize = DiagString.size();
273 char *Mem = new (S.Context) char[MessageSize];
274 memcpy(Mem, DiagString.c_str(), MessageSize);
275 Satisfaction.Details.emplace_back(
276 ConstraintExpr,
278 SubstitutedAtomicExpr.get()->getBeginLoc(),
279 StringRef(Mem, MessageSize)});
280 return SubstitutedAtomicExpr;
281 }
282
283 EnterExpressionEvaluationContext ConstantEvaluated(
286 Expr::EvalResult EvalResult;
287 EvalResult.Diag = &EvaluationDiags;
288 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
289 S.Context) ||
290 !EvaluationDiags.empty()) {
291 // C++2a [temp.constr.atomic]p1
292 // ...E shall be a constant expression of type bool.
293 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
294 diag::err_non_constant_constraint_expression)
295 << SubstitutedAtomicExpr.get()->getSourceRange();
296 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
297 S.Diag(PDiag.first, PDiag.second);
298 return ExprError();
299 }
300
301 assert(EvalResult.Val.isInt() &&
302 "evaluating bool expression didn't produce int");
303 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
304 if (!Satisfaction.IsSatisfied)
305 Satisfaction.Details.emplace_back(ConstraintExpr,
306 SubstitutedAtomicExpr.get());
307
308 return SubstitutedAtomicExpr;
309}
310
311static bool
312DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
313 const NamedDecl *Templ, const Expr *E,
314 const MultiLevelTemplateArgumentList &MLTAL) {
315 E->Profile(ID, S.Context, /*Canonical=*/true);
316 for (const auto &List : MLTAL)
317 for (const auto &TemplateArg : List.Args)
318 TemplateArg.Profile(ID, S.Context);
319
320 // Note that we have to do this with our own collection, because there are
321 // times where a constraint-expression check can cause us to need to evaluate
322 // other constriants that are unrelated, such as when evaluating a recovery
323 // expression, or when trying to determine the constexpr-ness of special
324 // members. Otherwise we could just use the
325 // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
326 if (S.SatisfactionStackContains(Templ, ID)) {
327 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
328 << const_cast<Expr *>(E) << E->getSourceRange();
329 return true;
330 }
331
332 return false;
333}
334
336 Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
337 const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
338 ConstraintSatisfaction &Satisfaction) {
340 S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
341 EnterExpressionEvaluationContext ConstantEvaluated(
344
345 // Atomic constraint - substitute arguments and check satisfaction.
346 ExprResult SubstitutedExpression;
347 {
348 TemplateDeductionInfo Info(TemplateNameLoc);
351 const_cast<NamedDecl *>(Template), Info,
353 if (Inst.isInvalid())
354 return ExprError();
355
356 llvm::FoldingSetNodeID ID;
357 if (Template &&
358 DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
359 Satisfaction.IsSatisfied = false;
360 Satisfaction.ContainsErrors = true;
361 return ExprEmpty();
362 }
363
364 SatisfactionStackRAII StackRAII(S, Template, ID);
365
366 // We do not want error diagnostics escaping here.
367 Sema::SFINAETrap Trap(S);
368 SubstitutedExpression =
369 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
370
371 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
372 // C++2a [temp.constr.atomic]p1
373 // ...If substitution results in an invalid type or expression, the
374 // constraint is not satisfied.
375 if (!Trap.hasErrorOccurred())
376 // A non-SFINAE error has occurred as a result of this
377 // substitution.
378 return ExprError();
379
382 Info.takeSFINAEDiagnostic(SubstDiag);
383 // FIXME: Concepts: This is an unfortunate consequence of there
384 // being no serialization code for PartialDiagnostics and the fact
385 // that serializing them would likely take a lot more storage than
386 // just storing them as strings. We would still like, in the
387 // future, to serialize the proper PartialDiagnostic as serializing
388 // it as a string defeats the purpose of the diagnostic mechanism.
389 SmallString<128> DiagString;
390 DiagString = ": ";
391 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
392 unsigned MessageSize = DiagString.size();
393 char *Mem = new (S.Context) char[MessageSize];
394 memcpy(Mem, DiagString.c_str(), MessageSize);
395 Satisfaction.Details.emplace_back(
398 SubstDiag.first, StringRef(Mem, MessageSize)});
399 Satisfaction.IsSatisfied = false;
400 return ExprEmpty();
401 }
402 }
403
404 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
405 return ExprError();
406
407 // [temp.constr.atomic]p3: To determine if an atomic constraint is
408 // satisfied, the parameter mapping and template arguments are first
409 // substituted into its expression. If substitution results in an
410 // invalid type or expression, the constraint is not satisfied.
411 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
412 // and E shall be a constant expression of type bool.
413 //
414 // Perform the L to R Value conversion if necessary. We do so for all
415 // non-PRValue categories, else we fail to extend the lifetime of
416 // temporaries, and that fails the constant expression check.
417 if (!SubstitutedExpression.get()->isPRValue())
418 SubstitutedExpression = ImplicitCastExpr::Create(
419 S.Context, SubstitutedExpression.get()->getType(),
420 CK_LValueToRValue, SubstitutedExpression.get(),
421 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
422
423 return SubstitutedExpression;
424 });
425}
426
428 Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
430 const MultiLevelTemplateArgumentList &TemplateArgsLists,
431 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
432 if (ConstraintExprs.empty()) {
433 Satisfaction.IsSatisfied = true;
434 return false;
435 }
436
437 if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
438 // No need to check satisfaction for dependent constraint expressions.
439 Satisfaction.IsSatisfied = true;
440 return false;
441 }
442
443 ArrayRef<TemplateArgument> TemplateArgs =
444 TemplateArgsLists.getNumSubstitutedLevels() > 0
445 ? TemplateArgsLists.getOutermost()
447 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
449 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
450 if (Inst.isInvalid())
451 return true;
452
453 for (const Expr *ConstraintExpr : ConstraintExprs) {
455 S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
456 ConstraintExpr, Satisfaction);
457 if (Res.isInvalid())
458 return true;
459
460 Converted.push_back(Res.get());
461 if (!Satisfaction.IsSatisfied) {
462 // Backfill the 'converted' list with nulls so we can keep the Converted
463 // and unconverted lists in sync.
464 Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
465 // [temp.constr.op] p2
466 // [...] To determine if a conjunction is satisfied, the satisfaction
467 // of the first operand is checked. If that is not satisfied, the
468 // conjunction is not satisfied. [...]
469 return false;
470 }
471 }
472 return false;
473}
474
476 const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
477 llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
478 const MultiLevelTemplateArgumentList &TemplateArgsLists,
479 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
480 if (ConstraintExprs.empty()) {
481 OutSatisfaction.IsSatisfied = true;
482 return false;
483 }
484 if (!Template) {
485 return ::CheckConstraintSatisfaction(
486 *this, nullptr, ConstraintExprs, ConvertedConstraints,
487 TemplateArgsLists, TemplateIDRange, OutSatisfaction);
488 }
489
490 // A list of the template argument list flattened in a predictible manner for
491 // the purposes of caching. The ConstraintSatisfaction type is in AST so it
492 // has no access to the MultiLevelTemplateArgumentList, so this has to happen
493 // here.
495 for (auto List : TemplateArgsLists)
496 FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
497 List.Args.end());
498
499 llvm::FoldingSetNodeID ID;
500 ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
501 void *InsertPos;
502 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
503 OutSatisfaction = *Cached;
504 return false;
505 }
506
507 auto Satisfaction =
508 std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
509 if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
510 ConvertedConstraints, TemplateArgsLists,
511 TemplateIDRange, *Satisfaction)) {
512 OutSatisfaction = *Satisfaction;
513 return true;
514 }
515
516 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
517 // The evaluation of this constraint resulted in us trying to re-evaluate it
518 // recursively. This isn't really possible, except we try to form a
519 // RecoveryExpr as a part of the evaluation. If this is the case, just
520 // return the 'cached' version (which will have the same result), and save
521 // ourselves the extra-insert. If it ever becomes possible to legitimately
522 // recursively check a constraint, we should skip checking the 'inner' one
523 // above, and replace the cached version with this one, as it would be more
524 // specific.
525 OutSatisfaction = *Cached;
526 return false;
527 }
528
529 // Else we can simply add this satisfaction to the list.
530 OutSatisfaction = *Satisfaction;
531 // We cannot use InsertPos here because CheckConstraintSatisfaction might have
532 // invalidated it.
533 // Note that entries of SatisfactionCache are deleted in Sema's destructor.
534 SatisfactionCache.InsertNode(Satisfaction.release());
535 return false;
536}
537
538bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
539 ConstraintSatisfaction &Satisfaction) {
541 *this, ConstraintExpr, Satisfaction,
542 [this](const Expr *AtomicExpr) -> ExprResult {
543 // We only do this to immitate lvalue-to-rvalue conversion.
545 const_cast<Expr *>(AtomicExpr));
546 })
547 .isInvalid();
548}
549
550bool Sema::addInstantiatedCapturesToScope(
551 FunctionDecl *Function, const FunctionDecl *PatternDecl,
553 const MultiLevelTemplateArgumentList &TemplateArgs) {
554 const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
555 const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
556
557 unsigned Instantiated = 0;
558
559 auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
560 unsigned Index) {
561 ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
562 if (CapturedVar->isInitCapture())
563 Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
564 };
565
566 for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
567 if (!CapturePattern.capturesVariable()) {
568 Instantiated++;
569 continue;
570 }
571 const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
572 if (!CapturedPattern->isParameterPack()) {
573 AddSingleCapture(CapturedPattern, Instantiated++);
574 } else {
575 Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
576 std::optional<unsigned> NumArgumentsInExpansion =
577 getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
578 if (!NumArgumentsInExpansion)
579 continue;
580 for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
581 AddSingleCapture(CapturedPattern, Instantiated++);
582 }
583 }
584 return false;
585}
586
587bool Sema::SetupConstraintScope(
588 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
590 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
591 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
592 InstantiatingTemplate Inst(
593 *this, FD->getPointOfInstantiation(),
595 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
596 SourceRange());
597 if (Inst.isInvalid())
598 return true;
599
600 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
601 // 'instantiated' parameters and adds it to the context. For the case where
602 // this function is a template being instantiated NOW, we also need to add
603 // the list of current template arguments to the list so that they also can
604 // be picked out of the map.
605 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
606 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
607 /*Final=*/false);
608 if (addInstantiatedParametersToScope(
609 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
610 return true;
611 }
612
613 // If this is a member function, make sure we get the parameters that
614 // reference the original primary template.
615 if (const auto *FromMemTempl =
616 PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
617 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
618 Scope, MLTAL))
619 return true;
620 }
621
622 return false;
623 }
624
627 FunctionDecl *InstantiatedFrom =
631
632 InstantiatingTemplate Inst(
633 *this, FD->getPointOfInstantiation(),
635 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
636 SourceRange());
637 if (Inst.isInvalid())
638 return true;
639
640 // Case where this was not a template, but instantiated as a
641 // child-function.
642 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
643 return true;
644 }
645
646 return false;
647}
648
649// This function collects all of the template arguments for the purposes of
650// constraint-instantiation and checking.
651std::optional<MultiLevelTemplateArgumentList>
652Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
653 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
656
657 // Collect the list of template arguments relative to the 'primary' template.
658 // We need the entire list, since the constraint is completely uninstantiated
659 // at this point.
660 MLTAL =
661 getTemplateInstantiationArgs(FD, /*Final=*/false, /*Innermost=*/nullptr,
662 /*RelativeToPrimary=*/true,
663 /*Pattern=*/nullptr,
664 /*ForConstraintInstantiation=*/true);
665 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
666 return std::nullopt;
667
668 return MLTAL;
669}
670
672 ConstraintSatisfaction &Satisfaction,
673 SourceLocation UsageLoc,
674 bool ForOverloadResolution) {
675 // Don't check constraints if the function is dependent. Also don't check if
676 // this is a function template specialization, as the call to
677 // CheckinstantiatedFunctionTemplateConstraints after this will check it
678 // better.
679 if (FD->isDependentContext() ||
680 FD->getTemplatedKind() ==
682 Satisfaction.IsSatisfied = true;
683 return false;
684 }
685
686 // A lambda conversion operator has the same constraints as the call operator
687 // and constraints checking relies on whether we are in a lambda call operator
688 // (and may refer to its parameters), so check the call operator instead.
689 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
690 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
691 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
692 Satisfaction, UsageLoc,
693 ForOverloadResolution);
694
695 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
696
697 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
698 if (isLambdaCallOperator(CtxToSave))
699 CtxToSave = CtxToSave->getParent()->getParent();
700 else
701 CtxToSave = CtxToSave->getNonTransparentContext();
702 }
703
704 ContextRAII SavedContext{*this, CtxToSave};
705 LocalInstantiationScope Scope(*this, !ForOverloadResolution ||
707 std::optional<MultiLevelTemplateArgumentList> MLTAL =
708 SetupConstraintCheckingTemplateArgumentsAndScope(
709 const_cast<FunctionDecl *>(FD), {}, Scope);
710
711 if (!MLTAL)
712 return true;
713
714 Qualifiers ThisQuals;
715 CXXRecordDecl *Record = nullptr;
716 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
717 ThisQuals = Method->getMethodQualifiers();
718 Record = const_cast<CXXRecordDecl *>(Method->getParent());
719 }
720 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
721
723 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope);
724
726 FD, {FD->getTrailingRequiresClause()}, *MLTAL,
727 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
728 Satisfaction);
729}
730
731
732// Figure out the to-translation-unit depth for this function declaration for
733// the purpose of seeing if they differ by constraints. This isn't the same as
734// getTemplateDepth, because it includes already instantiated parents.
735static unsigned
737 bool SkipForSpecialization = false) {
739 ND, /*Final=*/false, /*Innermost=*/nullptr, /*RelativeToPrimary=*/true,
740 /*Pattern=*/nullptr,
741 /*ForConstraintInstantiation=*/true, SkipForSpecialization);
742 return MLTAL.getNumLevels();
743}
744
745namespace {
746 class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
747 unsigned TemplateDepth = 0;
748 public:
749 using inherited = TreeTransform<AdjustConstraintDepth>;
750 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
751 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
752
753 using inherited::TransformTemplateTypeParmType;
754 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
755 TemplateTypeParmTypeLoc TL, bool) {
756 const TemplateTypeParmType *T = TL.getTypePtr();
757
758 TemplateTypeParmDecl *NewTTPDecl = nullptr;
759 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
760 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
761 TransformDecl(TL.getNameLoc(), OldTTPDecl));
762
763 QualType Result = getSema().Context.getTemplateTypeParmType(
764 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
765 NewTTPDecl);
767 NewTL.setNameLoc(TL.getNameLoc());
768 return Result;
769 }
770 };
771} // namespace
772
774 const Expr *ConstrExpr) {
776 ND, /*Final=*/false, /*Innermost=*/nullptr,
777 /*RelativeToPrimary=*/true,
778 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
779 /*SkipForSpecialization*/ false);
780 if (MLTAL.getNumSubstitutedLevels() == 0)
781 return ConstrExpr;
782
783 Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false);
784
786 S, ND->getLocation(),
788 const_cast<NamedDecl *>(ND), SourceRange{});
789
790 if (Inst.isInvalid())
791 return nullptr;
792
793 std::optional<Sema::CXXThisScopeRAII> ThisScope;
794 if (auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext()))
795 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
796 ExprResult SubstConstr =
797 S.SubstConstraintExpr(const_cast<clang::Expr *>(ConstrExpr), MLTAL);
798 if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
799 return nullptr;
800 return SubstConstr.get();
801}
802
804 const Expr *OldConstr,
805 const NamedDecl *New,
806 const Expr *NewConstr) {
807 if (OldConstr == NewConstr)
808 return true;
809 // C++ [temp.constr.decl]p4
810 if (Old && New && Old != New &&
812 if (const Expr *SubstConstr =
813 SubstituteConstraintExpression(*this, Old, OldConstr))
814 OldConstr = SubstConstr;
815 else
816 return false;
817 if (const Expr *SubstConstr =
818 SubstituteConstraintExpression(*this, New, NewConstr))
819 NewConstr = SubstConstr;
820 else
821 return false;
822 }
823
824 llvm::FoldingSetNodeID ID1, ID2;
825 OldConstr->Profile(ID1, Context, /*Canonical=*/true);
826 NewConstr->Profile(ID2, Context, /*Canonical=*/true);
827 return ID1 == ID2;
828}
829
831 assert(FD->getFriendObjectKind() && "Must be a friend!");
832
833 // The logic for non-templates is handled in ASTContext::isSameEntity, so we
834 // don't have to bother checking 'DependsOnEnclosingTemplate' for a
835 // non-function-template.
836 assert(FD->getDescribedFunctionTemplate() &&
837 "Non-function templates don't need to be checked");
838
841
842 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
843 for (const Expr *Constraint : ACs)
844 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
845 Constraint))
846 return true;
847
848 return false;
849}
850
852 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
853 SourceRange TemplateIDRange) {
854 ConstraintSatisfaction Satisfaction;
855 llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
856 TD->getAssociatedConstraints(AssociatedConstraints);
857 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
858 TemplateIDRange, Satisfaction))
859 return true;
860
861 if (!Satisfaction.IsSatisfied) {
862 SmallString<128> TemplateArgString;
863 TemplateArgString = " ";
864 TemplateArgString += getTemplateArgumentBindingsText(
865 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
866 TemplateArgsLists.getInnermost().size());
867
868 Diag(TemplateIDRange.getBegin(),
869 diag::err_template_arg_list_constraints_not_satisfied)
871 << TemplateArgString << TemplateIDRange;
872 DiagnoseUnsatisfiedConstraint(Satisfaction);
873 return true;
874 }
875 return false;
876}
877
879 SourceLocation PointOfInstantiation, FunctionDecl *Decl,
880 ArrayRef<TemplateArgument> TemplateArgs,
881 ConstraintSatisfaction &Satisfaction) {
882 // In most cases we're not going to have constraints, so check for that first.
883 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
884 // Note - code synthesis context for the constraints check is created
885 // inside CheckConstraintsSatisfaction.
887 Template->getAssociatedConstraints(TemplateAC);
888 if (TemplateAC.empty()) {
889 Satisfaction.IsSatisfied = true;
890 return false;
891 }
892
893 // Enter the scope of this instantiation. We don't use
894 // PushDeclContext because we don't have a scope.
895 Sema::ContextRAII savedContext(*this, Decl);
897
898 std::optional<MultiLevelTemplateArgumentList> MLTAL =
899 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
900 Scope);
901
902 if (!MLTAL)
903 return true;
904
905 Qualifiers ThisQuals;
906 CXXRecordDecl *Record = nullptr;
907 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
908 ThisQuals = Method->getMethodQualifiers();
909 Record = Method->getParent();
910 }
911
912 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
914 *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
915
917 return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
918 PointOfInstantiation, Satisfaction);
919}
920
923 bool First) {
924 assert(!Req->isSatisfied()
925 && "Diagnose() can only be used on an unsatisfied requirement");
926 switch (Req->getSatisfactionStatus()) {
928 llvm_unreachable("Diagnosing a dependent requirement");
929 break;
931 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
932 if (!SubstDiag->DiagMessage.empty())
933 S.Diag(SubstDiag->DiagLoc,
934 diag::note_expr_requirement_expr_substitution_error)
935 << (int)First << SubstDiag->SubstitutedEntity
936 << SubstDiag->DiagMessage;
937 else
938 S.Diag(SubstDiag->DiagLoc,
939 diag::note_expr_requirement_expr_unknown_substitution_error)
940 << (int)First << SubstDiag->SubstitutedEntity;
941 break;
942 }
944 S.Diag(Req->getNoexceptLoc(),
945 diag::note_expr_requirement_noexcept_not_met)
946 << (int)First << Req->getExpr();
947 break;
949 auto *SubstDiag =
951 if (!SubstDiag->DiagMessage.empty())
952 S.Diag(SubstDiag->DiagLoc,
953 diag::note_expr_requirement_type_requirement_substitution_error)
954 << (int)First << SubstDiag->SubstitutedEntity
955 << SubstDiag->DiagMessage;
956 else
957 S.Diag(SubstDiag->DiagLoc,
958 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
959 << (int)First << SubstDiag->SubstitutedEntity;
960 break;
961 }
963 ConceptSpecializationExpr *ConstraintExpr =
965 if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
966 // A simple case - expr type is the type being constrained and the concept
967 // was not provided arguments.
968 Expr *e = Req->getExpr();
969 S.Diag(e->getBeginLoc(),
970 diag::note_expr_requirement_constraints_not_satisfied_simple)
972 << ConstraintExpr->getNamedConcept();
973 } else {
974 S.Diag(ConstraintExpr->getBeginLoc(),
975 diag::note_expr_requirement_constraints_not_satisfied)
976 << (int)First << ConstraintExpr;
977 }
979 break;
980 }
982 llvm_unreachable("We checked this above");
983 }
984}
985
988 bool First) {
989 assert(!Req->isSatisfied()
990 && "Diagnose() can only be used on an unsatisfied requirement");
991 switch (Req->getSatisfactionStatus()) {
993 llvm_unreachable("Diagnosing a dependent requirement");
994 return;
996 auto *SubstDiag = Req->getSubstitutionDiagnostic();
997 if (!SubstDiag->DiagMessage.empty())
998 S.Diag(SubstDiag->DiagLoc,
999 diag::note_type_requirement_substitution_error) << (int)First
1000 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
1001 else
1002 S.Diag(SubstDiag->DiagLoc,
1003 diag::note_type_requirement_unknown_substitution_error)
1004 << (int)First << SubstDiag->SubstitutedEntity;
1005 return;
1006 }
1007 default:
1008 llvm_unreachable("Unknown satisfaction status");
1009 return;
1010 }
1011}
1013 Expr *SubstExpr,
1014 bool First = true);
1015
1018 bool First) {
1019 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
1020 for (auto &Pair : Req->getConstraintSatisfaction()) {
1021 if (auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
1022 S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
1023 << (int)First << Req->getInvalidConstraintEntity() << SubstDiag->second;
1024 else
1026 S, Pair.second.dyn_cast<Expr *>(), First);
1027 First = false;
1028 }
1029}
1030
1032 Expr *SubstExpr,
1033 bool First) {
1034 SubstExpr = SubstExpr->IgnoreParenImpCasts();
1035 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1036 switch (BO->getOpcode()) {
1037 // These two cases will in practice only be reached when using fold
1038 // expressions with || and &&, since otherwise the || and && will have been
1039 // broken down into atomic constraints during satisfaction checking.
1040 case BO_LOr:
1041 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1044 /*First=*/false);
1045 return;
1046 case BO_LAnd: {
1047 bool LHSSatisfied =
1048 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1049 if (LHSSatisfied) {
1050 // LHS is true, so RHS must be false.
1052 return;
1053 }
1054 // LHS is false
1056
1057 // RHS might also be false
1058 bool RHSSatisfied =
1059 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1060 if (!RHSSatisfied)
1062 /*First=*/false);
1063 return;
1064 }
1065 case BO_GE:
1066 case BO_LE:
1067 case BO_GT:
1068 case BO_LT:
1069 case BO_EQ:
1070 case BO_NE:
1071 if (BO->getLHS()->getType()->isIntegerType() &&
1072 BO->getRHS()->getType()->isIntegerType()) {
1073 Expr::EvalResult SimplifiedLHS;
1074 Expr::EvalResult SimplifiedRHS;
1075 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1077 /*InConstantContext=*/true);
1078 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1080 /*InConstantContext=*/true);
1081 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
1082 S.Diag(SubstExpr->getBeginLoc(),
1083 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1084 << (int)First << SubstExpr
1085 << toString(SimplifiedLHS.Val.getInt(), 10)
1086 << BinaryOperator::getOpcodeStr(BO->getOpcode())
1087 << toString(SimplifiedRHS.Val.getInt(), 10);
1088 return;
1089 }
1090 }
1091 break;
1092
1093 default:
1094 break;
1095 }
1096 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1097 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1098 S.Diag(
1099 CSE->getSourceRange().getBegin(),
1100 diag::
1101 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1102 << (int)First
1103 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1104 << CSE->getNamedConcept();
1105 } else {
1106 S.Diag(SubstExpr->getSourceRange().getBegin(),
1107 diag::note_concept_specialization_constraint_evaluated_to_false)
1108 << (int)First << CSE;
1109 }
1110 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1111 return;
1112 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1113 // FIXME: RequiresExpr should store dependent diagnostics.
1114 for (concepts::Requirement *Req : RE->getRequirements())
1115 if (!Req->isDependent() && !Req->isSatisfied()) {
1116 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1118 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1120 else
1122 S, cast<concepts::NestedRequirement>(Req), First);
1123 break;
1124 }
1125 return;
1126 }
1127
1128 S.Diag(SubstExpr->getSourceRange().getBegin(),
1129 diag::note_atomic_constraint_evaluated_to_false)
1130 << (int)First << SubstExpr;
1131}
1132
1133template<typename SubstitutionDiagnostic>
1135 Sema &S, const Expr *E,
1136 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1137 bool First = true) {
1138 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
1139 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1140 << Diag->second;
1141 return;
1142 }
1143
1145 Record.template get<Expr *>(), First);
1146}
1147
1148void
1150 bool First) {
1151 assert(!Satisfaction.IsSatisfied &&
1152 "Attempted to diagnose a satisfied constraint");
1153 for (auto &Pair : Satisfaction.Details) {
1154 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1155 First = false;
1156 }
1157}
1158
1160 const ASTConstraintSatisfaction &Satisfaction,
1161 bool First) {
1162 assert(!Satisfaction.IsSatisfied &&
1163 "Attempted to diagnose a satisfied constraint");
1164 for (auto &Pair : Satisfaction) {
1165 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1166 First = false;
1167 }
1168}
1169
1172 NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
1173 // In case the ConstrainedDecl comes from modules, it is necessary to use
1174 // the canonical decl to avoid different atomic constraints with the 'same'
1175 // declarations.
1176 ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl());
1177
1178 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1179 if (CacheEntry == NormalizationCache.end()) {
1180 auto Normalized =
1181 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1182 AssociatedConstraints);
1183 CacheEntry =
1184 NormalizationCache
1185 .try_emplace(ConstrainedDecl,
1186 Normalized
1188 std::move(*Normalized))
1189 : nullptr)
1190 .first;
1191 }
1192 return CacheEntry->second;
1193}
1194
1195static bool
1197 ConceptDecl *Concept,
1198 const MultiLevelTemplateArgumentList &MLTAL,
1199 const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1200 if (!N.isAtomic()) {
1201 if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1202 ArgsAsWritten))
1203 return true;
1204 return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1205 ArgsAsWritten);
1206 }
1207 TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1208
1210 TemplateArgumentListInfo SubstArgs;
1211 if (!Atomic.ParameterMapping) {
1212 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1213 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1214 /*Depth=*/0, OccurringIndices);
1215 TemplateArgumentLoc *TempArgs =
1216 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1217 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1218 if (OccurringIndices[I])
1219 new (&(TempArgs)[J++])
1221 TemplateParams->begin()[I],
1222 // Here we assume we do not support things like
1223 // template<typename A, typename B>
1224 // concept C = ...;
1225 //
1226 // template<typename... Ts> requires C<Ts...>
1227 // struct S { };
1228 // The above currently yields a diagnostic.
1229 // We still might have default arguments for concept parameters.
1230 ArgsAsWritten->NumTemplateArgs > I
1231 ? ArgsAsWritten->arguments()[I].getLocation()
1232 : SourceLocation()));
1233 Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
1234 }
1236 S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
1238 ArgsAsWritten->arguments().front().getSourceRange());
1239 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1240 return true;
1241
1242 TemplateArgumentLoc *TempArgs =
1243 new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1244 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1245 TempArgs);
1246 Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1247 return false;
1248}
1249
1251 const ConceptSpecializationExpr *CSE) {
1253 CSE->getTemplateArguments()};
1255 CSE->getNamedConcept(), /*Final=*/false, &TAL,
1256 /*RelativeToPrimary=*/true,
1257 /*Pattern=*/nullptr,
1258 /*ForConstraintInstantiation=*/true);
1259
1260 return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1262}
1263
1264std::optional<NormalizedConstraint>
1265NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1267 assert(E.size() != 0);
1268 auto Conjunction = fromConstraintExpr(S, D, E[0]);
1269 if (!Conjunction)
1270 return std::nullopt;
1271 for (unsigned I = 1; I < E.size(); ++I) {
1272 auto Next = fromConstraintExpr(S, D, E[I]);
1273 if (!Next)
1274 return std::nullopt;
1275 *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1276 std::move(*Next), CCK_Conjunction);
1277 }
1278 return Conjunction;
1279}
1280
1281std::optional<NormalizedConstraint>
1282NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1283 assert(E != nullptr);
1284
1285 // C++ [temp.constr.normal]p1.1
1286 // [...]
1287 // - The normal form of an expression (E) is the normal form of E.
1288 // [...]
1289 E = E->IgnoreParenImpCasts();
1290
1291 // C++2a [temp.param]p4:
1292 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1293 // Fold expression is considered atomic constraints per current wording.
1294 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1295
1296 if (LogicalBinOp BO = E) {
1297 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1298 if (!LHS)
1299 return std::nullopt;
1300 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1301 if (!RHS)
1302 return std::nullopt;
1303
1304 return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
1305 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1306 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1307 const NormalizedConstraint *SubNF;
1308 {
1310 S, CSE->getExprLoc(),
1312 CSE->getSourceRange());
1313 // C++ [temp.constr.normal]p1.1
1314 // [...]
1315 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1316 // where C names a concept, is the normal form of the
1317 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1318 // respective template parameters in the parameter mappings in each atomic
1319 // constraint. If any such substitution results in an invalid type or
1320 // expression, the program is ill-formed; no diagnostic is required.
1321 // [...]
1322 ConceptDecl *CD = CSE->getNamedConcept();
1324 {CD->getConstraintExpr()});
1325 if (!SubNF)
1326 return std::nullopt;
1327 }
1328
1329 std::optional<NormalizedConstraint> New;
1330 New.emplace(S.Context, *SubNF);
1331
1332 if (substituteParameterMappings(S, *New, CSE))
1333 return std::nullopt;
1334
1335 return New;
1336 }
1337 return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
1338}
1339
1342
1343static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
1344 if (Normalized.isAtomic())
1345 return {{Normalized.getAtomicConstraint()}};
1346
1347 NormalForm LCNF = makeCNF(Normalized.getLHS());
1348 NormalForm RCNF = makeCNF(Normalized.getRHS());
1350 LCNF.reserve(LCNF.size() + RCNF.size());
1351 while (!RCNF.empty())
1352 LCNF.push_back(RCNF.pop_back_val());
1353 return LCNF;
1354 }
1355
1356 // Disjunction
1357 NormalForm Res;
1358 Res.reserve(LCNF.size() * RCNF.size());
1359 for (auto &LDisjunction : LCNF)
1360 for (auto &RDisjunction : RCNF) {
1361 NormalForm::value_type Combined;
1362 Combined.reserve(LDisjunction.size() + RDisjunction.size());
1363 std::copy(LDisjunction.begin(), LDisjunction.end(),
1364 std::back_inserter(Combined));
1365 std::copy(RDisjunction.begin(), RDisjunction.end(),
1366 std::back_inserter(Combined));
1367 Res.emplace_back(Combined);
1368 }
1369 return Res;
1370}
1371
1372static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
1373 if (Normalized.isAtomic())
1374 return {{Normalized.getAtomicConstraint()}};
1375
1376 NormalForm LDNF = makeDNF(Normalized.getLHS());
1377 NormalForm RDNF = makeDNF(Normalized.getRHS());
1379 LDNF.reserve(LDNF.size() + RDNF.size());
1380 while (!RDNF.empty())
1381 LDNF.push_back(RDNF.pop_back_val());
1382 return LDNF;
1383 }
1384
1385 // Conjunction
1386 NormalForm Res;
1387 Res.reserve(LDNF.size() * RDNF.size());
1388 for (auto &LConjunction : LDNF) {
1389 for (auto &RConjunction : RDNF) {
1390 NormalForm::value_type Combined;
1391 Combined.reserve(LConjunction.size() + RConjunction.size());
1392 std::copy(LConjunction.begin(), LConjunction.end(),
1393 std::back_inserter(Combined));
1394 std::copy(RConjunction.begin(), RConjunction.end(),
1395 std::back_inserter(Combined));
1396 Res.emplace_back(Combined);
1397 }
1398 }
1399 return Res;
1400}
1401
1402template<typename AtomicSubsumptionEvaluator>
1403static bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF,
1404 AtomicSubsumptionEvaluator E) {
1405 // C++ [temp.constr.order] p2
1406 // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
1407 // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
1408 // the conjuctive normal form of Q, where [...]
1409 for (const auto &Pi : PDNF) {
1410 for (const auto &Qj : QCNF) {
1411 // C++ [temp.constr.order] p2
1412 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
1413 // and only if there exists an atomic constraint Pia in Pi for which
1414 // there exists an atomic constraint, Qjb, in Qj such that Pia
1415 // subsumes Qjb.
1416 bool Found = false;
1417 for (const AtomicConstraint *Pia : Pi) {
1418 for (const AtomicConstraint *Qjb : Qj) {
1419 if (E(*Pia, *Qjb)) {
1420 Found = true;
1421 break;
1422 }
1423 }
1424 if (Found)
1425 break;
1426 }
1427 if (!Found)
1428 return false;
1429 }
1430 }
1431 return true;
1432}
1433
1434template<typename AtomicSubsumptionEvaluator>
1436 NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
1437 AtomicSubsumptionEvaluator E) {
1438 // C++ [temp.constr.order] p2
1439 // In order to determine if a constraint P subsumes a constraint Q, P is
1440 // transformed into disjunctive normal form, and Q is transformed into
1441 // conjunctive normal form. [...]
1442 auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
1443 if (!PNormalized)
1444 return true;
1445 const NormalForm PDNF = makeDNF(*PNormalized);
1446
1447 auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
1448 if (!QNormalized)
1449 return true;
1450 const NormalForm QCNF = makeCNF(*QNormalized);
1451
1452 Subsumes = subsumes(PDNF, QCNF, E);
1453 return false;
1454}
1455
1458 NamedDecl *D2,
1460 bool &Result) {
1461 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1462 auto IsExpectedEntity = [](const FunctionDecl *FD) {
1464 return Kind == FunctionDecl::TK_NonTemplate ||
1466 };
1467 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1468 (void)IsExpectedEntity;
1469 (void)FD1;
1470 (void)FD2;
1471 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1472 "use non-instantiated function declaration for constraints partial "
1473 "ordering");
1474 }
1475
1476 if (AC1.empty()) {
1477 Result = AC2.empty();
1478 return false;
1479 }
1480 if (AC2.empty()) {
1481 // TD1 has associated constraints and TD2 does not.
1482 Result = true;
1483 return false;
1484 }
1485
1486 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1487 auto CacheEntry = SubsumptionCache.find(Key);
1488 if (CacheEntry != SubsumptionCache.end()) {
1489 Result = CacheEntry->second;
1490 return false;
1491 }
1492
1493 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1494 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1495
1496 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1497 if (Depth2 > Depth1) {
1498 AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
1499 .TransformExpr(const_cast<Expr *>(AC1[I]))
1500 .get();
1501 } else if (Depth1 > Depth2) {
1502 AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1503 .TransformExpr(const_cast<Expr *>(AC2[I]))
1504 .get();
1505 }
1506 }
1507
1508 if (subsumes(*this, D1, AC1, D2, AC2, Result,
1509 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1510 return A.subsumes(Context, B);
1511 }))
1512 return true;
1513 SubsumptionCache.try_emplace(Key, Result);
1514 return false;
1515}
1516
1519 if (isSFINAEContext())
1520 // No need to work here because our notes would be discarded.
1521 return false;
1522
1523 if (AC1.empty() || AC2.empty())
1524 return false;
1525
1526 auto NormalExprEvaluator =
1527 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1528 return A.subsumes(Context, B);
1529 };
1530
1531 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1532 auto IdenticalExprEvaluator =
1533 [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1535 return false;
1536 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1537 if (EA == EB)
1538 return true;
1539
1540 // Not the same source level expression - are the expressions
1541 // identical?
1542 llvm::FoldingSetNodeID IDA, IDB;
1543 EA->Profile(IDA, Context, /*Canonical=*/true);
1544 EB->Profile(IDB, Context, /*Canonical=*/true);
1545 if (IDA != IDB)
1546 return false;
1547
1548 AmbiguousAtomic1 = EA;
1549 AmbiguousAtomic2 = EB;
1550 return true;
1551 };
1552
1553 {
1554 // The subsumption checks might cause diagnostics
1555 SFINAETrap Trap(*this);
1556 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1557 if (!Normalized1)
1558 return false;
1559 const NormalForm DNF1 = makeDNF(*Normalized1);
1560 const NormalForm CNF1 = makeCNF(*Normalized1);
1561
1562 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1563 if (!Normalized2)
1564 return false;
1565 const NormalForm DNF2 = makeDNF(*Normalized2);
1566 const NormalForm CNF2 = makeCNF(*Normalized2);
1567
1568 bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1569 bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1570 bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1571 bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1572 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1573 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1574 // Same result - no ambiguity was caused by identical atomic expressions.
1575 return false;
1576 }
1577
1578 // A different result! Some ambiguous atomic constraint(s) caused a difference
1579 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1580
1581 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1582 << AmbiguousAtomic1->getSourceRange();
1583 Diag(AmbiguousAtomic2->getBeginLoc(),
1584 diag::note_ambiguous_atomic_constraints_similar_expression)
1585 << AmbiguousAtomic2->getSourceRange();
1586 return true;
1587}
1588
1590 Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1592 ConceptSpecializationExpr *SubstitutedConstraintExpr) :
1593 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1594 Status == SS_Dependent &&
1595 (E->containsUnexpandedParameterPack() ||
1596 Req.containsUnexpandedParameterPack()),
1597 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1598 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1599 Status(Status) {
1600 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1601 "Simple requirement must not have a return type requirement or a "
1602 "noexcept specification");
1603 assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1604 (SubstitutedConstraintExpr != nullptr));
1605}
1606
1608 SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1609 SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1610 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1611 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1612 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1613 Status(SS_ExprSubstitutionFailure) {
1614 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1615 "Simple requirement must not have a return type requirement or a "
1616 "noexcept specification");
1617}
1618
1621 TypeConstraintInfo(TPL, false) {
1622 assert(TPL->size() == 1);
1623 const TypeConstraint *TC =
1624 cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1625 assert(TC &&
1626 "TPL must have a template type parameter with a type constraint");
1627 auto *Constraint =
1628 cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1629 bool Dependent =
1630 Constraint->getTemplateArgsAsWritten() &&
1632 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1633 TypeConstraintInfo.setInt(Dependent ? true : false);
1634}
1635
1637 Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
1638 T->getType()->containsUnexpandedParameterPack(),
1639 // We reach this ctor with either dependent types (in which
1640 // IsSatisfied doesn't matter) or with non-dependent type in
1641 // which the existence of the type indicates satisfaction.
1642 /*IsSatisfied=*/true),
1643 Value(T),
1644 Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1645 : SS_Satisfied) {}
This file provides some common utility functions for processing Lambda related AST Constructs.
StringRef P
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines Expressions and AST nodes for C++2a concepts.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Defines and computes precedence levels for binary/ternary operators.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static NormalForm makeCNF(const NormalizedConstraint &Normalized)
static bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF, AtomicSubsumptionEvaluator E)
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, llvm::SmallVectorImpl< Expr * > &Converted, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
static NormalForm makeDNF(const NormalizedConstraint &Normalized)
static ExprResult calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, AtomicEvaluator &&Evaluator)
static const Expr * SubstituteConstraintExpression(Sema &S, const NamedDecl *ND, const Expr *ConstrExpr)
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const Expr *E, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic * > &Record, bool First=true)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList &MLTAL)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, const MultiLevelTemplateArgumentList &MLTAL, const ASTTemplateArgumentListInfo *ArgsAsWritten)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
static bool isInvalid(LocType Loc, bool *Invalid)
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
__device__ int
APSInt & getInt()
Definition: APValue.h:423
bool isInt() const
Definition: APValue.h:401
QualType getReferenceQualifiedType(const Expr *e) const
getReferenceQualifiedType - Given an expr, will return the type for that expression,...
CanQualType BoolTy
Definition: ASTContext.h:1078
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2570
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition: Expr.h:6431
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:6536
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3847
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2206
StringRef getOpcodeStr() const
Definition: Expr.h:3912
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:4760
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2168
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2818
Represents a C++ struct/union/class.
Definition: DeclCXX.h:254
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents the specialization of a concept - evaluates to a prvalue of type bool.
Definition: ExprConcepts.h:42
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: ExprConcepts.h:143
ArrayRef< TemplateArgument > getTemplateArguments() const
Definition: ExprConcepts.h:81
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Definition: ExprConcepts.h:98
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
Definition: ExprConcepts.h:133
ConceptDecl * getNamedConcept() const
Definition: ExprConcepts.h:87
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:35
llvm::SmallVector< std::pair< const Expr *, Detail >, 4 > Details
Pairs of unsatisfied atomic constraint expressions along with the substituted constraint expr,...
Definition: ASTConcept.h:60
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
Definition: ASTConcept.h:50
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
Definition: ASTConcept.h:62
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1409
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1951
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
Definition: DeclBase.cpp:1243
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1209
DeclContext * getNonTransparentContext()
Definition: DeclBase.cpp:1290
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:1194
bool isParameterPack() const
Whether this declaration is a parameter pack.
Definition: DeclBase.cpp:221
SourceLocation getLocation() const
Definition: DeclBase.h:432
DeclContext * getDeclContext()
Definition: DeclBase.h:441
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition: DeclBase.h:886
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:946
Expr * getTrailingRequiresClause()
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition: Decl.h:843
RAII object that enters a new expression evaluation context.
This represents one expression.
Definition: Expr.h:110
@ SE_NoSideEffects
Strictly evaluate the expression.
Definition: Expr.h:648
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:3081
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:820
Represents a function declaration or definition.
Definition: Decl.h:1919
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
Definition: Decl.cpp:3952
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
Definition: Decl.cpp:4246
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
Definition: Decl.cpp:4066
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
Definition: Decl.cpp:4082
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
Definition: Decl.cpp:4010
TemplatedKind
The kind of templated function a FunctionDecl can be.
Definition: Decl.h:1924
@ TK_MemberSpecialization
Definition: Decl.h:1931
@ TK_DependentNonTemplate
Definition: Decl.h:1940
@ TK_FunctionTemplateSpecialization
Definition: Decl.h:1935
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
Definition: Decl.cpp:3903
FunctionDecl * getInstantiatedFromDecl() const
Definition: Decl.cpp:3970
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Definition: Decl.cpp:3924
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:2099
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:508
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:363
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:263
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
Definition: Template.h:123
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:267
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
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:6755
A RAII object to temporarily push a declaration context.
Definition: Sema.h:1024
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition: Sema.h:9912
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition: Sema.h:9943
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:1897
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:1689
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:91
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
const LangOptions & getLangOpts() const
Definition: Sema.h:1685
@ ReuseLambdaContextDecl
Definition: Sema.h:5476
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:7513
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:2023
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:1326
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:7436
void PopSatisfactionStackEntry()
Definition: Sema.h:7442
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:7444
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, bool ProfileLambdaExpr=false) 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:240
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:410
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:429
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:140
static bool anyInstantiationDependentTemplateArguments(ArrayRef< TemplateArgumentLoc > Args)
Definition: Type.cpp:3961
Declaration of a template type parameter.
Wrapper for template type parameters.
Definition: TypeLoc.h:752
TemplateTypeParmDecl * getDecl() const
Definition: Type.h:5166
bool isParameterPack() const
Definition: Type.h:5164
unsigned getIndex() const
Definition: Type.h:5163
unsigned getDepth() const
Definition: Type.h:5162
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.
Models the abbreviated syntax to constrain a template type parameter: template <convertible_to<string...
Definition: ASTConcept.h:231
Expr * getImmediatelyDeclaredConstraint() const
Get the immediately-declared constraint expression introduced by this type-constraint,...
Definition: ASTConcept.h:246
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
A container of type source information.
Definition: Type.h:6718
SourceLocation getNameLoc() const
Definition: TypeLoc.h:529
void setNameLoc(SourceLocation Loc)
Definition: TypeLoc.h:533
The base class of the type hierarchy.
Definition: Type.h:1597
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:7286
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2365
bool isFunctionType() const
Definition: Type.h:6995
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:703
QualType getType() const
Definition: Decl.h:714
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Definition: Decl.cpp:5238
ReturnTypeRequirement()
No return type requirement was specified.
Definition: ExprConcepts.h:297
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:337
A requires-expression requirement which queries the validity and properties of an expression ('simple...
Definition: ExprConcepts.h:277
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
Definition: ExprConcepts.h:405
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
Definition: ExprConcepts.h:400
const ReturnTypeRequirement & getReturnTypeRequirement() const
Definition: ExprConcepts.h:395
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:389
SourceLocation getNoexceptLoc() const
Definition: ExprConcepts.h:387
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:426
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
Definition: ExprConcepts.h:481
A static requirement that can be used in a requires-expression to check properties of types and expre...
Definition: ExprConcepts.h:168
bool containsUnexpandedParameterPack() const
Definition: ExprConcepts.h:215
A requires-expression requirement which queries the existence of a type name or type template special...
Definition: ExprConcepts.h:222
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:257
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:248
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:142
ExprResult ExprEmpty()
Definition: Ownership.h:271
@ 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:264
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
bool isLambdaConversionOperator(CXXConversionDecl *C)
Definition: ASTLambda.h:47
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:126
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:93
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:622
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:624
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
A stack object to be created when performing template instantiation.
Definition: Sema.h:9640
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition: Sema.h:9791