Skip to content

Commit c996b9e

Browse files
zyn0217cor3ntin
authored andcommitted
nested-requirements.cpp (#52)
* Remove unused headers * checkpoint
1 parent 21cb63b commit c996b9e

File tree

5 files changed

+93
-68
lines changed

5 files changed

+93
-68
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14717,7 +14717,8 @@ class Sema final : public SemaBase {
1471714717
ArrayRef<AssociatedConstraint> AssociatedConstraints,
1471814718
const MultiLevelTemplateArgumentList &TemplateArgLists,
1471914719
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
14720-
const ConceptReference *TopLevelConceptId = nullptr);
14720+
const ConceptReference *TopLevelConceptId = nullptr,
14721+
Expr **ConvertedExpr = nullptr);
1472114722

1472214723
/// \brief Check whether the given non-dependent constraint expression is
1472314724
/// satisfied. Returns false and updates Satisfaction with the satisfaction

clang/lib/Sema/SemaConcept.cpp

Lines changed: 70 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
#include "llvm/ADT/PointerUnion.h"
3737
#include "llvm/ADT/SmallVector.h"
3838
#include "llvm/ADT/StringExtras.h"
39-
#include "llvm/Support/Timer.h"
40-
#include "llvm/Support/WithColor.h"
4139
#include <cstddef>
4240
#include <optional>
4341

@@ -345,7 +343,7 @@ static ExprResult EvaluateAtomicConstraint(
345343
return SubstitutedExpression;
346344
}
347345

348-
static bool calculateConstraintSatisfaction(
346+
static ExprResult calculateConstraintSatisfaction(
349347
Sema &S, const NormalizedConstraint &Constraint, const NamedDecl *Template,
350348
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
351349
ConstraintSatisfaction &Satisfaction, UnsignedOrNone PackSubstitutionIndex);
@@ -417,7 +415,7 @@ SubstitutionInTemplateArguments(
417415
return std::move(MLTAL);
418416
}
419417

420-
static bool calculateConstraintSatisfaction(
418+
static ExprResult calculateConstraintSatisfaction(
421419
Sema &S, const AtomicConstraint &Constraint, const NamedDecl *Template,
422420
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
423421
ConstraintSatisfaction &Satisfaction,
@@ -497,7 +495,7 @@ static bool calculateConstraintSatisfaction(
497495
if (!Satisfaction.IsSatisfied)
498496
Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
499497

500-
return SubstitutedAtomicExpr.isUsable();
498+
return SubstitutedAtomicExpr;
501499
}
502500

503501
static UnsignedOrNone EvaluateFoldExpandedConstraintSize(
@@ -533,7 +531,7 @@ static UnsignedOrNone EvaluateFoldExpandedConstraintSize(
533531
return NumExpansions;
534532
}
535533

536-
static bool calculateConstraintSatisfaction(
534+
static ExprResult calculateConstraintSatisfaction(
537535
Sema &S, const FoldExpandedConstraint &FE, const NamedDecl *Template,
538536
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
539537
ConstraintSatisfaction &Satisfaction) {
@@ -568,12 +566,13 @@ static bool calculateConstraintSatisfaction(
568566
Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
569567
Satisfaction.IsSatisfied = false;
570568
Satisfaction.ContainsErrors = false;
571-
bool Success = calculateConstraintSatisfaction(
569+
// FIXME
570+
ExprResult Expr = calculateConstraintSatisfaction(
572571
S, FE.getNormalizedPattern(), Template, TemplateNameLoc,
573572
*SubstitutedArgs, Satisfaction, UnsignedOrNone(I));
574573
// SFINAE errors shouldn't prevent disjunction from evaluating
575574
// FIXME: Does !Success == SFINAE errors occurred?
576-
if (!Success && Conjunction)
575+
if (!Expr.isUsable() && Conjunction)
577576
return false;
578577
if (!Conjunction && Satisfaction.IsSatisfied) {
579578
Satisfaction.Details.erase(Satisfaction.Details.begin() +
@@ -589,25 +588,12 @@ static bool calculateConstraintSatisfaction(
589588
return true;
590589
}
591590

592-
static bool calculateConstraintSatisfaction(
591+
static ExprResult calculateConstraintSatisfaction(
593592
Sema &S, const ConceptIdConstraint &Constraint, const NamedDecl *Template,
594593
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
595594
ConstraintSatisfaction &Satisfaction,
596595
UnsignedOrNone PackSubstitutionIndex) {
597596

598-
// If the expression has been calculated, e.g. when we are in a nested
599-
// requirement, do not compute it repeatedly.
600-
if (auto *Expr = Constraint.getConceptSpecializationExpr();
601-
Expr && Expr->getDependence() == ExprDependence::None) {
602-
auto &Calculated = Expr->getSatisfaction();
603-
Satisfaction.ContainsErrors = Calculated.ContainsErrors;
604-
Satisfaction.IsSatisfied = Calculated.IsSatisfied;
605-
Satisfaction.Details.insert(Satisfaction.Details.end(),
606-
Calculated.records().begin(),
607-
Calculated.records().end());
608-
return !Satisfaction.ContainsErrors;
609-
}
610-
611597
Sema::ContextRAII CurContext(
612598
S, Constraint.getConceptId()->getNamedConcept()->getDeclContext(),
613599
/*NewThisContext=*/false);
@@ -620,11 +606,12 @@ static bool calculateConstraintSatisfaction(
620606

621607
auto Size = Satisfaction.Details.size();
622608

623-
bool Ok = calculateConstraintSatisfaction(
609+
ExprResult E = calculateConstraintSatisfaction(
624610
S, Constraint.getNormalizedConstraint(), Template, TemplateNameLoc, MLTAL,
625611
Satisfaction, PackSubstitutionIndex);
626612

627-
if (Size != Satisfaction.Details.size()) {
613+
if (!E.isUsable())
614+
return E;
628615

629616
llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
630617
std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
@@ -633,7 +620,7 @@ static bool calculateConstraintSatisfaction(
633620
PackSubstitutionIndex);
634621

635622
if (!SubstitutedArgs)
636-
return Ok;
623+
return E.isUsable();
637624

638625
Sema::SFINAETrap Trap(S);
639626
Sema::ArgPackSubstIndexRAII SubstIndex(
@@ -652,12 +639,15 @@ static bool calculateConstraintSatisfaction(
652639
AdjustConstraintDepth Adjust(S, Depth);
653640
if (Adjust.TransformTemplateArguments(Ori->getTemplateArgs(),
654641
Ori->NumTemplateArgs, TransArgs))
655-
return Ok;
642+
return false;
656643

657644
if (S.SubstTemplateArguments(TransArgs.arguments(), *SubstitutedArgs,
658645
OutArgs) ||
659-
Trap.hasErrorOccurred())
660-
return Ok;
646+
Trap.hasErrorOccurred()) {
647+
Satisfaction.ContainsErrors = true;
648+
Satisfaction.IsSatisfied = false;
649+
return false;
650+
}
661651

662652
CXXScopeSpec SS;
663653
SS.Adopt(Constraint.getConceptId()->getNestedNameSpecifierLoc());
@@ -669,18 +659,20 @@ static bool calculateConstraintSatisfaction(
669659
/*CheckConstraintSatisfaction=*/false);
670660

671661
if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())
672-
return Ok;
662+
return false;
663+
664+
if (Size != Satisfaction.Details.size()) {
673665

674666
Satisfaction.Details.insert(
675667
Satisfaction.Details.begin() + Size,
676668
UnsatisfiedConstraintRecord(
677669
SubstitutedConceptId.getAs<ConceptSpecializationExpr>()
678670
->getConceptReference()));
679671
}
680-
return Ok;
672+
return SubstitutedConceptId;
681673
}
682674

683-
static bool calculateConstraintSatisfaction(
675+
static ExprResult calculateConstraintSatisfaction(
684676
Sema &S, const CompoundConstraint &Constraint, const NamedDecl *Template,
685677
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
686678
ConstraintSatisfaction &Satisfaction,
@@ -691,35 +683,49 @@ static bool calculateConstraintSatisfaction(
691683
bool Conjunction =
692684
Constraint.getCompoundKind() == NormalizedConstraint::CCK_Conjunction;
693685

694-
bool Ok = calculateConstraintSatisfaction(
686+
ExprResult LHS = calculateConstraintSatisfaction(
695687
S, Constraint.getLHS(), Template, TemplateNameLoc, MLTAL, Satisfaction,
696688
PackSubstitutionIndex);
697689

698-
if (Conjunction && !Ok)
690+
if (Conjunction && !LHS.isUsable())
699691
return false;
700692

701-
if (!Conjunction && Ok && Satisfaction.IsSatisfied &&
693+
if (!Conjunction && LHS.isUsable() && Satisfaction.IsSatisfied &&
702694
!Satisfaction.ContainsErrors)
703-
return true;
695+
return LHS;
704696

705-
if (Conjunction && Ok &&
697+
if (Conjunction && LHS.isUsable() &&
706698
(!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
707-
return true;
699+
return LHS;
708700

709701
Satisfaction.ContainsErrors = false;
710702
Satisfaction.IsSatisfied = false;
711703

712-
Ok = calculateConstraintSatisfaction(S, Constraint.getRHS(), Template,
713-
TemplateNameLoc, MLTAL, Satisfaction,
704+
ExprResult RHS = calculateConstraintSatisfaction(
705+
S, Constraint.getRHS(), Template, TemplateNameLoc, MLTAL, Satisfaction,
714706
PackSubstitutionIndex);
715-
if (Ok && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors)
707+
if (RHS.isUsable() && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors)
716708
Satisfaction.Details.erase(Satisfaction.Details.begin() +
717709
EffectiveDetailEndIndex,
718710
Satisfaction.Details.end());
719-
return Ok;
711+
712+
if (!LHS.isUsable())
713+
return RHS;
714+
715+
if (!RHS.isUsable())
716+
return LHS;
717+
718+
return BinaryOperator::Create(
719+
S.Context, LHS.get(), RHS.get(),
720+
BinaryOperator::getOverloadedOpcode(
721+
Constraint.getCompoundKind() == NormalizedConstraint::CCK_Conjunction
722+
? OO_AmpAmp
723+
: OO_PipePipe),
724+
S.Context.BoolTy, VK_PRValue, OK_Ordinary, Constraint.getBeginLoc(),
725+
FPOptionsOverride{});
720726
}
721727

722-
static bool calculateConstraintSatisfaction(
728+
static ExprResult calculateConstraintSatisfaction(
723729
Sema &S, const NormalizedConstraint &Constraint, const NamedDecl *Template,
724730
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
725731
ConstraintSatisfaction &Satisfaction,
@@ -753,7 +759,10 @@ static bool CheckConstraintSatisfaction(
753759
ArrayRef<AssociatedConstraint> AssociatedConstraints,
754760
const MultiLevelTemplateArgumentList &TemplateArgsLists,
755761
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
756-
const ConceptReference *TopLevelConceptId = nullptr) {
762+
Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {
763+
764+
if (ConvertedExpr)
765+
*ConvertedExpr = nullptr;
757766

758767
if (AssociatedConstraints.empty()) {
759768
Satisfaction.IsSatisfied = true;
@@ -790,7 +799,6 @@ static bool CheckConstraintSatisfaction(
790799
const_cast<NormalizedConstraint *>(C),
791800
Template, /*CSE=*/nullptr,
792801
S.ArgPackSubstIndex);
793-
}
794802

795803
ExprResult Res = calculateConstraintSatisfaction(
796804
S, *C, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
@@ -810,16 +818,16 @@ bool Sema::CheckConstraintSatisfaction(
810818
ArrayRef<AssociatedConstraint> AssociatedConstraints,
811819
const MultiLevelTemplateArgumentList &TemplateArgsLists,
812820
SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
813-
const ConceptReference *TopLevelConceptId) {
821+
const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {
814822
if (AssociatedConstraints.empty()) {
815823
OutSatisfaction.IsSatisfied = true;
816824
return false;
817825
}
818826
const auto *Template = Entity.dyn_cast<const NamedDecl *>();
819827
if (!Template) {
820-
return ::CheckConstraintSatisfaction(*this, nullptr, AssociatedConstraints,
821-
TemplateArgsLists, TemplateIDRange,
822-
OutSatisfaction, TopLevelConceptId);
828+
return ::CheckConstraintSatisfaction(
829+
*this, nullptr, AssociatedConstraints, TemplateArgsLists,
830+
TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
823831
}
824832
// Invalid templates could make their way here. Substituting them could result
825833
// in dependent expressions.
@@ -850,13 +858,15 @@ bool Sema::CheckConstraintSatisfaction(
850858

851859
auto Satisfaction =
852860
std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
853-
if (::CheckConstraintSatisfaction(*this, Template, AssociatedConstraints,
854-
TemplateArgsLists, TemplateIDRange,
855-
*Satisfaction, TopLevelConceptId)) {
861+
if (::CheckConstraintSatisfaction(
862+
*this, Template, AssociatedConstraints, TemplateArgsLists,
863+
TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
856864
OutSatisfaction = *Satisfaction;
857865
return true;
858866
}
859867

868+
// FIXME: cache ConvertedExpr for nested requirements?
869+
860870
if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
861871
// The evaluation of this constraint resulted in us trying to re-evaluate it
862872
// recursively. This isn't really possible, except we try to form a
@@ -1612,7 +1622,8 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
16121622
SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
16131623
? ArgsAsWritten->arguments()[I].getLocation()
16141624
: SourceLocation();
1615-
// FIXME: Investigate when we couldn't preserve the SourceLoc. What shall we do??
1625+
// FIXME: Investigate when we couldn't preserve the SourceLoc. What shall
1626+
// we do??
16161627
// assert(Loc.isValid());
16171628
if (OccurringIndices[I]) {
16181629
NamedDecl *Param = TemplateParams->begin()[I];
@@ -1945,9 +1956,14 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
19451956
const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(
19461957
ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
19471958
ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1948-
if (!ConstrainedDeclOrNestedReq)
1949-
return NormalizedConstraint::fromAssociatedConstraints(
1959+
if (!ConstrainedDeclOrNestedReq) {
1960+
auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
19501961
*this, nullptr, AssociatedConstraints);
1962+
if (!Normalized || substituteParameterMappings(*this, *Normalized))
1963+
return nullptr;
1964+
1965+
return Normalized;
1966+
}
19511967

19521968
// FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
19531969
const NamedDecl *ND =

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2939,6 +2939,7 @@ TemplateInstantiator::TransformNestedRequirement(
29392939
return Req;
29402940
}
29412941

2942+
#if 0
29422943
if (Req->isDependent() || AlwaysRebuild()) {
29432944
Sema::InstantiatingTemplate ReqInst(
29442945
SemaRef, Constraint->getBeginLoc(), Req,
@@ -2956,24 +2957,29 @@ TemplateInstantiator::TransformNestedRequirement(
29562957

29572958
if (Constraint->isInstantiationDependent())
29582959
return new (C) concepts::NestedRequirement(Constraint);
2960+
#endif
29592961

29602962
bool Success;
2963+
Expr *NewConstraint;
29612964
TemplateDeductionInfo Info(Constraint->getBeginLoc());
29622965
{
29632966
EnterExpressionEvaluationContext ContextRAII(
29642967
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
29652968

2966-
Sema::InstantiatingTemplate ConstrInst(SemaRef, Constraint->getBeginLoc(),
2967-
Req, Info,
2969+
Sema::InstantiatingTemplate ConstrInst(
2970+
SemaRef, Constraint->getBeginLoc(), Req,
2971+
Sema::InstantiatingTemplate::ConstraintsCheck(),
29682972
Constraint->getSourceRange());
2973+
29692974
if (ConstrInst.isInvalid())
29702975
return nullptr;
29712976

29722977
Sema::SFINAETrap Trap(SemaRef);
29732978

29742979
Success = !SemaRef.CheckConstraintSatisfaction(
29752980
Req, AssociatedConstraint(Constraint, SemaRef.ArgPackSubstIndex),
2976-
TemplateArgs, Constraint->getSourceRange(), Satisfaction);
2981+
TemplateArgs, Constraint->getSourceRange(), Satisfaction,
2982+
/*TopLevelConceptId=*/nullptr, &NewConstraint);
29772983

29782984
assert(!Success || !Trap.hasErrorOccurred() &&
29792985
"Substitution failures must be handled "
@@ -2984,7 +2990,10 @@ TemplateInstantiator::TransformNestedRequirement(
29842990
return NestedReqWithDiag(Constraint, Satisfaction);
29852991

29862992
// FIXME: const correctness
2987-
return new (C) concepts::NestedRequirement(C, Constraint, Satisfaction);
2993+
// MLTAL might be dependent.
2994+
if (!NewConstraint)
2995+
NewConstraint = Constraint;
2996+
return new (C) concepts::NestedRequirement(C, NewConstraint, Satisfaction);
29882997
}
29892998

29902999
TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T,

clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@ namespace std_example {
4343
requires sizeof(a) == 4; // OK
4444
requires a == 0; // expected-error{{substitution into constraint expression resulted in a non-constant expression}}
4545
// expected-note@-1{{while checking the satisfaction of nested requirement requested here}}
46-
// expected-note@-2{{in instantiation of requirement here}}
47-
// expected-note@-3{{while checking the satisfaction of nested requirement requested here}}
48-
// expected-note@-6{{while substituting template arguments into constraint expression here}}
49-
// expected-note@-5{{function parameter 'a' with unknown value cannot be used in a constant expression}}
50-
// expected-note@-8{{declared here}}
46+
// expected-note@-2{{while checking the satisfaction of nested requirement requested here}}
47+
// expected-note@-5{{while substituting template arguments into constraint expression here}}
48+
// expected-note@-4{{function parameter 'a' with unknown value cannot be used in a constant expression}}
49+
// expected-note@-7{{declared here}}
5150
};
5251
static_assert(C2<int>); // expected-error{{static assertion failed}}
5352
// expected-note@-1{{while checking the satisfaction of concept 'C2<int>' requested here}}
@@ -161,12 +160,13 @@ void func() {
161160
// expected-note@#bar {{because 'X<SubstitutionFailureNestedRequires::ErrorExpressions_NotSF::False>::value' evaluated to false}}
162161

163162
bar<int>();
163+
// expected-error@-1 {{no matching function for call to 'bar'}} \
164164
// expected-note@-1 {{while checking constraint satisfaction for template 'bar<int>' required here}} \
165-
// expected-note@-1 {{while substituting deduced template arguments into function template 'bar' [with T = int]}}
165+
// expected-note@-1 {{while substituting deduced template arguments into function template 'bar' [with T = int]}} \
166166
// expected-note@#bar {{in instantiation of static data member}}
167-
// expected-note@#bar {{in instantiation of requirement here}}
168167
// expected-note@#bar {{while checking the satisfaction of nested requirement requested here}}
169168
// expected-note@#bar {{while substituting template arguments into constraint expression here}}
169+
// expected-note@#bar {{candidate template ignored}}
170170
// expected-error@#X_Value {{type 'int' cannot be used prior to '::' because it has no members}}
171171
}
172172
}

0 commit comments

Comments
 (0)