Skip to content

Commit 3972ed5

Browse files
authored
Revert "[Clang] Implement CWG2369 "Ordering between constraints and substitution"" (llvm#122130)
Unfortunately that breaks some code on Windows when lambdas come into play, as reported in llvm#102857 (comment) This reverts commit 96eced6.
1 parent 570f030 commit 3972ed5

22 files changed

+62
-289
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13062,7 +13062,6 @@ class Sema final : public SemaBase {
1306213062
///
1306313063
/// \param SkipForSpecialization when specified, any template specializations
1306413064
/// in a traversal would be ignored.
13065-
///
1306613065
/// \param ForDefaultArgumentSubstitution indicates we should continue looking
1306713066
/// when encountering a specialized member function template, rather than
1306813067
/// returning immediately.
@@ -13074,17 +13073,6 @@ class Sema final : public SemaBase {
1307413073
bool SkipForSpecialization = false,
1307513074
bool ForDefaultArgumentSubstitution = false);
1307613075

13077-
/// Apart from storing the result to \p Result, this behaves the same as
13078-
/// another overload.
13079-
void getTemplateInstantiationArgs(
13080-
MultiLevelTemplateArgumentList &Result, const NamedDecl *D,
13081-
const DeclContext *DC = nullptr, bool Final = false,
13082-
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
13083-
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
13084-
bool ForConstraintInstantiation = false,
13085-
bool SkipForSpecialization = false,
13086-
bool ForDefaultArgumentSubstitution = false);
13087-
1308813076
/// RAII object to handle the state changes required to synthesize
1308913077
/// a function body.
1309013078
class SynthesizedFunctionScope {
@@ -13354,7 +13342,7 @@ class Sema final : public SemaBase {
1335413342
ExprResult
1335513343
SubstConstraintExpr(Expr *E,
1335613344
const MultiLevelTemplateArgumentList &TemplateArgs);
13357-
// Unlike the above, this does not evaluate constraints.
13345+
// Unlike the above, this does not evaluates constraints.
1335813346
ExprResult SubstConstraintExprWithoutSatisfaction(
1335913347
Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs);
1336013348

@@ -14475,10 +14463,10 @@ class Sema final : public SemaBase {
1447514463
const MultiLevelTemplateArgumentList &TemplateArgs,
1447614464
SourceRange TemplateIDRange);
1447714465

14478-
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation,
14479-
FunctionDecl *Decl,
14480-
ArrayRef<TemplateArgument> TemplateArgs,
14481-
ConstraintSatisfaction &Satisfaction);
14466+
bool CheckInstantiatedFunctionTemplateConstraints(
14467+
SourceLocation PointOfInstantiation, FunctionDecl *Decl,
14468+
ArrayRef<TemplateArgument> TemplateArgs,
14469+
ConstraintSatisfaction &Satisfaction);
1448214470

1448314471
/// \brief Emit diagnostics explaining why a constraint expression was deemed
1448414472
/// unsatisfied.

clang/include/clang/Sema/Template.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -522,12 +522,6 @@ enum class TemplateSubstitutionKind : char {
522522
llvm::PointerUnion<Decl *, DeclArgumentPack *> *
523523
findInstantiationOf(const Decl *D);
524524

525-
/// Similar to \p findInstantiationOf(), but it wouldn't assert if the
526-
/// instantiation was not found within the current instantiation scope. This
527-
/// is helpful for on-demand declaration instantiation.
528-
llvm::PointerUnion<Decl *, DeclArgumentPack *> *
529-
findInstantiationUnsafe(const Decl *D);
530-
531525
void InstantiatedLocal(const Decl *D, Decl *Inst);
532526
void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
533527
void MakeInstantiatedLocalArgPack(const Decl *D);

clang/lib/Sema/SemaConcept.cpp

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -846,7 +846,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
846846
bool ForOverloadResolution) {
847847
// Don't check constraints if the function is dependent. Also don't check if
848848
// this is a function template specialization, as the call to
849-
// CheckFunctionTemplateConstraints after this will check it
849+
// CheckinstantiatedFunctionTemplateConstraints after this will check it
850850
// better.
851851
if (FD->isDependentContext() ||
852852
FD->getTemplatedKind() ==
@@ -1111,55 +1111,12 @@ bool Sema::EnsureTemplateArgumentListConstraints(
11111111
return false;
11121112
}
11131113

1114-
static bool CheckFunctionConstraintsWithoutInstantiation(
1115-
Sema &SemaRef, SourceLocation PointOfInstantiation,
1116-
FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
1117-
ConstraintSatisfaction &Satisfaction) {
1118-
SmallVector<const Expr *, 3> TemplateAC;
1119-
Template->getAssociatedConstraints(TemplateAC);
1120-
if (TemplateAC.empty()) {
1121-
Satisfaction.IsSatisfied = true;
1122-
return false;
1123-
}
1124-
1125-
LocalInstantiationScope Scope(SemaRef);
1126-
1127-
FunctionDecl *FD = Template->getTemplatedDecl();
1128-
// Collect the list of template arguments relative to the 'primary'
1129-
// template. We need the entire list, since the constraint is completely
1130-
// uninstantiated at this point.
1131-
1132-
// FIXME: Add TemplateArgs through the 'Innermost' parameter once
1133-
// the refactoring of getTemplateInstantiationArgs() relands.
1134-
MultiLevelTemplateArgumentList MLTAL;
1135-
MLTAL.addOuterTemplateArguments(Template, std::nullopt, /*Final=*/false);
1136-
SemaRef.getTemplateInstantiationArgs(
1137-
MLTAL, /*D=*/FD, FD,
1138-
/*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true,
1139-
/*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1140-
MLTAL.replaceInnermostTemplateArguments(Template, TemplateArgs);
1141-
1142-
Sema::ContextRAII SavedContext(SemaRef, FD);
1143-
std::optional<Sema::CXXThisScopeRAII> ThisScope;
1144-
if (auto *Method = dyn_cast<CXXMethodDecl>(FD))
1145-
ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(),
1146-
/*ThisQuals=*/Method->getMethodQualifiers());
1147-
return SemaRef.CheckConstraintSatisfaction(
1148-
Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1149-
}
1150-
1151-
bool Sema::CheckFunctionTemplateConstraints(
1114+
bool Sema::CheckInstantiatedFunctionTemplateConstraints(
11521115
SourceLocation PointOfInstantiation, FunctionDecl *Decl,
11531116
ArrayRef<TemplateArgument> TemplateArgs,
11541117
ConstraintSatisfaction &Satisfaction) {
11551118
// In most cases we're not going to have constraints, so check for that first.
11561119
FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1157-
1158-
if (!Template)
1159-
return ::CheckFunctionConstraintsWithoutInstantiation(
1160-
*this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1161-
TemplateArgs, Satisfaction);
1162-
11631120
// Note - code synthesis context for the constraints check is created
11641121
// inside CheckConstraintsSatisfaction.
11651122
SmallVector<const Expr *, 3> TemplateAC;

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3936,6 +3936,18 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
39363936
Result != TemplateDeductionResult::Success)
39373937
return Result;
39383938

3939+
// C++ [temp.deduct.call]p10: [DR1391]
3940+
// If deduction succeeds for all parameters that contain
3941+
// template-parameters that participate in template argument deduction,
3942+
// and all template arguments are explicitly specified, deduced, or
3943+
// obtained from default template arguments, remaining parameters are then
3944+
// compared with the corresponding arguments. For each remaining parameter
3945+
// P with a type that was non-dependent before substitution of any
3946+
// explicitly-specified template arguments, if the corresponding argument
3947+
// A cannot be implicitly converted to P, deduction fails.
3948+
if (CheckNonDependent())
3949+
return TemplateDeductionResult::NonDependentConversionFailure;
3950+
39393951
// Form the template argument list from the deduced template arguments.
39403952
TemplateArgumentList *SugaredDeducedArgumentList =
39413953
TemplateArgumentList::CreateCopy(Context, SugaredBuilder);
@@ -3965,39 +3977,6 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
39653977
FD = const_cast<FunctionDecl *>(FDFriend);
39663978
Owner = FD->getLexicalDeclContext();
39673979
}
3968-
// C++20 [temp.deduct.general]p5: [CWG2369]
3969-
// If the function template has associated constraints, those constraints
3970-
// are checked for satisfaction. If the constraints are not satisfied, type
3971-
// deduction fails.
3972-
//
3973-
// FIXME: We haven't implemented CWG2369 for lambdas yet, because we need
3974-
// to figure out how to instantiate lambda captures to the scope without
3975-
// first instantiating the lambda.
3976-
bool IsLambda = isLambdaCallOperator(FD) || isLambdaConversionOperator(FD);
3977-
if (!IsLambda && !IsIncomplete) {
3978-
if (CheckFunctionTemplateConstraints(
3979-
Info.getLocation(),
3980-
FunctionTemplate->getCanonicalDecl()->getTemplatedDecl(),
3981-
CanonicalBuilder, Info.AssociatedConstraintsSatisfaction))
3982-
return TemplateDeductionResult::MiscellaneousDeductionFailure;
3983-
if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
3984-
Info.reset(Info.takeSugared(),
3985-
TemplateArgumentList::CreateCopy(Context, CanonicalBuilder));
3986-
return TemplateDeductionResult::ConstraintsNotSatisfied;
3987-
}
3988-
}
3989-
// C++ [temp.deduct.call]p10: [CWG1391]
3990-
// If deduction succeeds for all parameters that contain
3991-
// template-parameters that participate in template argument deduction,
3992-
// and all template arguments are explicitly specified, deduced, or
3993-
// obtained from default template arguments, remaining parameters are then
3994-
// compared with the corresponding arguments. For each remaining parameter
3995-
// P with a type that was non-dependent before substitution of any
3996-
// explicitly-specified template arguments, if the corresponding argument
3997-
// A cannot be implicitly converted to P, deduction fails.
3998-
if (CheckNonDependent())
3999-
return TemplateDeductionResult::NonDependentConversionFailure;
4000-
40013980
MultiLevelTemplateArgumentList SubstArgs(
40023981
FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
40033982
/*Final=*/false);
@@ -4032,8 +4011,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
40324011
// ([temp.constr.decl]), those constraints are checked for satisfaction
40334012
// ([temp.constr.constr]). If the constraints are not satisfied, type
40344013
// deduction fails.
4035-
if (IsLambda && !IsIncomplete) {
4036-
if (CheckFunctionTemplateConstraints(
4014+
if (!IsIncomplete) {
4015+
if (CheckInstantiatedFunctionTemplateConstraints(
40374016
Info.getLocation(), Specialization, CanonicalBuilder,
40384017
Info.AssociatedConstraintsSatisfaction))
40394018
return TemplateDeductionResult::MiscellaneousDeductionFailure;

clang/lib/Sema/SemaTemplateDeductionGuide.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -902,12 +902,10 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
902902
Context.getTrivialTypeSourceInfo(
903903
Context.getDeducedTemplateSpecializationType(
904904
TemplateName(AliasTemplate), /*DeducedType=*/QualType(),
905-
/*IsDependent=*/true),
906-
AliasTemplate->getLocation()), // template specialization type whose
907-
// arguments will be deduced.
905+
/*IsDependent=*/true)), // template specialization type whose
906+
// arguments will be deduced.
908907
Context.getTrivialTypeSourceInfo(
909-
ReturnType, AliasTemplate->getLocation()), // type from which template
910-
// arguments are deduced.
908+
ReturnType), // type from which template arguments are deduced.
911909
};
912910
return TypeTraitExpr::Create(
913911
Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(),

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 11 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -475,21 +475,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
475475
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
476476
// Accumulate the set of template argument lists in this structure.
477477
MultiLevelTemplateArgumentList Result;
478-
getTemplateInstantiationArgs(
479-
Result, ND, DC, Final, Innermost, RelativeToPrimary, Pattern,
480-
ForConstraintInstantiation, SkipForSpecialization,
481-
ForDefaultArgumentSubstitution);
482-
return Result;
483-
}
484-
485-
void Sema::getTemplateInstantiationArgs(
486-
MultiLevelTemplateArgumentList &Result, const NamedDecl *ND,
487-
const DeclContext *DC, bool Final,
488-
std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
489-
const FunctionDecl *Pattern, bool ForConstraintInstantiation,
490-
bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
491-
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
492-
// Accumulate the set of template argument lists in this structure.
493478

494479
using namespace TemplateInstArgsHelpers;
495480
const Decl *CurDecl = ND;
@@ -550,12 +535,14 @@ void Sema::getTemplateInstantiationArgs(
550535
}
551536

552537
if (R.IsDone)
553-
return;
538+
return Result;
554539
if (R.ClearRelativeToPrimary)
555540
RelativeToPrimary = false;
556541
assert(R.NextDecl);
557542
CurDecl = R.NextDecl;
558543
}
544+
545+
return Result;
559546
}
560547

561548
bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
@@ -1362,19 +1349,6 @@ namespace {
13621349
// Whether an incomplete substituion should be treated as an error.
13631350
bool BailOutOnIncomplete;
13641351

1365-
private:
1366-
bool isSubstitutingConstraints() const {
1367-
return llvm::any_of(SemaRef.CodeSynthesisContexts, [](auto &Context) {
1368-
return Context.Kind ==
1369-
Sema::CodeSynthesisContext::ConstraintSubstitution;
1370-
});
1371-
}
1372-
1373-
// CWG2770: Function parameters should be instantiated when they are
1374-
// needed by a satisfaction check of an atomic constraint or
1375-
// (recursively) by another function parameter.
1376-
bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm);
1377-
13781352
public:
13791353
typedef TreeTransform<TemplateInstantiator> inherited;
13801354

@@ -1431,19 +1405,12 @@ namespace {
14311405
ArrayRef<UnexpandedParameterPack> Unexpanded,
14321406
bool &ShouldExpand, bool &RetainExpansion,
14331407
std::optional<unsigned> &NumExpansions) {
1434-
if (SemaRef.CurrentInstantiationScope && isSubstitutingConstraints()) {
1435-
for (UnexpandedParameterPack ParmPack : Unexpanded) {
1436-
NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>();
1437-
if (!isa_and_present<ParmVarDecl>(VD))
1438-
continue;
1439-
if (maybeInstantiateFunctionParameterToScope(cast<ParmVarDecl>(VD)))
1440-
return true;
1441-
}
1442-
}
1443-
1444-
return getSema().CheckParameterPacksForExpansion(
1445-
EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, ShouldExpand,
1446-
RetainExpansion, NumExpansions);
1408+
return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
1409+
PatternRange, Unexpanded,
1410+
TemplateArgs,
1411+
ShouldExpand,
1412+
RetainExpansion,
1413+
NumExpansions);
14471414
}
14481415

14491416
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
@@ -1944,62 +1911,9 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
19441911
// template parameter.
19451912
}
19461913

1947-
if (SemaRef.CurrentInstantiationScope) {
1948-
if (isSubstitutingConstraints() && isa<ParmVarDecl>(D) &&
1949-
maybeInstantiateFunctionParameterToScope(cast<ParmVarDecl>(D)))
1950-
return nullptr;
1951-
}
1952-
19531914
return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
19541915
}
19551916

1956-
bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope(
1957-
ParmVarDecl *OldParm) {
1958-
if (SemaRef.CurrentInstantiationScope->findInstantiationUnsafe(OldParm))
1959-
return false;
1960-
// We're instantiating a function parameter whose associated function template
1961-
// has not been instantiated at this point for constraint evaluation, so make
1962-
// sure the instantiated parameters are owned by a function declaration such
1963-
// that they can be correctly 'captured' in tryCaptureVariable().
1964-
Sema::ContextRAII Context(SemaRef, OldParm->getDeclContext());
1965-
1966-
if (!OldParm->isParameterPack())
1967-
return !TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0,
1968-
/*NumExpansions=*/std::nullopt,
1969-
/*ExpectParameterPack=*/false);
1970-
1971-
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
1972-
1973-
// Find the parameter packs that could be expanded.
1974-
TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc();
1975-
PackExpansionTypeLoc ExpansionTL = TL.castAs<PackExpansionTypeLoc>();
1976-
TypeLoc Pattern = ExpansionTL.getPatternLoc();
1977-
SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
1978-
assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
1979-
1980-
bool ShouldExpand = false;
1981-
bool RetainExpansion = false;
1982-
std::optional<unsigned> OrigNumExpansions =
1983-
ExpansionTL.getTypePtr()->getNumExpansions();
1984-
std::optional<unsigned> NumExpansions = OrigNumExpansions;
1985-
if (TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
1986-
Pattern.getSourceRange(), Unexpanded,
1987-
ShouldExpand, RetainExpansion, NumExpansions))
1988-
return true;
1989-
1990-
assert(ShouldExpand && !RetainExpansion &&
1991-
"Shouldn't preserve pack expansion when evaluating constraints");
1992-
ExpandingFunctionParameterPack(OldParm);
1993-
for (unsigned I = 0; I != *NumExpansions; ++I) {
1994-
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
1995-
if (!TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0,
1996-
/*NumExpansions=*/OrigNumExpansions,
1997-
/*ExpectParameterPack=*/false))
1998-
return true;
1999-
}
2000-
return false;
2001-
}
2002-
20031917
Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
20041918
Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
20051919
if (!Inst)
@@ -4677,8 +4591,9 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) {
46774591
return D;
46784592
}
46794593

4594+
46804595
llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
4681-
LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) {
4596+
LocalInstantiationScope::findInstantiationOf(const Decl *D) {
46824597
D = getCanonicalParmVarDecl(D);
46834598
for (LocalInstantiationScope *Current = this; Current;
46844599
Current = Current->Outer) {
@@ -4703,14 +4618,6 @@ LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) {
47034618
break;
47044619
}
47054620

4706-
return nullptr;
4707-
}
4708-
4709-
llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
4710-
LocalInstantiationScope::findInstantiationOf(const Decl *D) {
4711-
auto *Result = findInstantiationUnsafe(D);
4712-
if (Result)
4713-
return Result;
47144621
// If we're performing a partial substitution during template argument
47154622
// deduction, we may not have values for template parameters yet.
47164623
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||

clang/lib/Sema/TreeTransform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ class TreeTransform {
713713
/// variables vector are acceptable.
714714
///
715715
/// LastParamTransformed, if non-null, will be set to the index of the last
716-
/// parameter on which transformation was started. In the event of an error,
716+
/// parameter on which transfromation was started. In the event of an error,
717717
/// this will contain the parameter which failed to instantiate.
718718
///
719719
/// Return true on error.

0 commit comments

Comments
 (0)