[clang] Revert "[Clang] Implement CWG2369 "Ordering between constraints and substitution"" (PR #122130)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 8 07:36:42 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Younan Zhang (zyn0217)
<details>
<summary>Changes</summary>
Unfortunately that breaks some code on Windows when lambdas come into play, as reported in https://github.com/llvm/llvm-project/pull/102857#issuecomment-2577861178
This reverts commit 96eced624e0f120155256033fdcb8342e7e58d6e.
---
Patch is 37.23 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/122130.diff
22 Files Affected:
- (modified) clang/include/clang/Sema/Sema.h (+5-17)
- (modified) clang/include/clang/Sema/Template.h (-6)
- (modified) clang/lib/Sema/SemaConcept.cpp (+2-45)
- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+14-35)
- (modified) clang/lib/Sema/SemaTemplateDeductionGuide.cpp (+3-5)
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+11-104)
- (modified) clang/lib/Sema/TreeTransform.h (+1-1)
- (modified) clang/test/CXX/drs/cwg23xx.cpp (-29)
- (modified) clang/test/CXX/drs/cwg26xx.cpp (+1-1)
- (modified) clang/test/CXX/drs/cwg27xx.cpp (-20)
- (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp (+1-1)
- (modified) clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp (+3-3)
- (modified) clang/test/SemaCXX/concept-crash-on-diagnostic.cpp (+1-1)
- (modified) clang/test/SemaCXX/cxx20-ctad-type-alias.cpp (+1-1)
- (modified) clang/test/SemaCXX/cxx23-assume.cpp (+3-3)
- (modified) clang/test/SemaCXX/cxx2c-fold-exprs.cpp (+1-1)
- (modified) clang/test/SemaCXX/lambda-unevaluated.cpp (+2-2)
- (modified) clang/test/SemaTemplate/concepts-recursive-inst.cpp (+2-2)
- (modified) clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp (+1-1)
- (modified) clang/test/SemaTemplate/deduction-guide.cpp (+5)
- (modified) clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp (+3-5)
- (modified) clang/www/cxx_dr_status.html (+2-6)
``````````diff
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 18fd95f77ec227..a41f16f6dc8c9b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13062,7 +13062,6 @@ class Sema final : public SemaBase {
///
/// \param SkipForSpecialization when specified, any template specializations
/// in a traversal would be ignored.
- ///
/// \param ForDefaultArgumentSubstitution indicates we should continue looking
/// when encountering a specialized member function template, rather than
/// returning immediately.
@@ -13074,17 +13073,6 @@ class Sema final : public SemaBase {
bool SkipForSpecialization = false,
bool ForDefaultArgumentSubstitution = false);
- /// Apart from storing the result to \p Result, this behaves the same as
- /// another overload.
- void getTemplateInstantiationArgs(
- MultiLevelTemplateArgumentList &Result, const NamedDecl *D,
- const DeclContext *DC = nullptr, bool Final = false,
- std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
- bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
- bool ForConstraintInstantiation = false,
- bool SkipForSpecialization = false,
- bool ForDefaultArgumentSubstitution = false);
-
/// RAII object to handle the state changes required to synthesize
/// a function body.
class SynthesizedFunctionScope {
@@ -13354,7 +13342,7 @@ class Sema final : public SemaBase {
ExprResult
SubstConstraintExpr(Expr *E,
const MultiLevelTemplateArgumentList &TemplateArgs);
- // Unlike the above, this does not evaluate constraints.
+ // Unlike the above, this does not evaluates constraints.
ExprResult SubstConstraintExprWithoutSatisfaction(
Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -14475,10 +14463,10 @@ class Sema final : public SemaBase {
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceRange TemplateIDRange);
- bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation,
- FunctionDecl *Decl,
- ArrayRef<TemplateArgument> TemplateArgs,
- ConstraintSatisfaction &Satisfaction);
+ bool CheckInstantiatedFunctionTemplateConstraints(
+ SourceLocation PointOfInstantiation, FunctionDecl *Decl,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ ConstraintSatisfaction &Satisfaction);
/// \brief Emit diagnostics explaining why a constraint expression was deemed
/// unsatisfied.
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 59a0575ca98036..9800f75f676aaf 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -522,12 +522,6 @@ enum class TemplateSubstitutionKind : char {
llvm::PointerUnion<Decl *, DeclArgumentPack *> *
findInstantiationOf(const Decl *D);
- /// Similar to \p findInstantiationOf(), but it wouldn't assert if the
- /// instantiation was not found within the current instantiation scope. This
- /// is helpful for on-demand declaration instantiation.
- llvm::PointerUnion<Decl *, DeclArgumentPack *> *
- findInstantiationUnsafe(const Decl *D);
-
void InstantiatedLocal(const Decl *D, Decl *Inst);
void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
void MakeInstantiatedLocalArgPack(const Decl *D);
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 10f4920a761f3c..539de00bd104f5 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -846,7 +846,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
bool ForOverloadResolution) {
// Don't check constraints if the function is dependent. Also don't check if
// this is a function template specialization, as the call to
- // CheckFunctionTemplateConstraints after this will check it
+ // CheckinstantiatedFunctionTemplateConstraints after this will check it
// better.
if (FD->isDependentContext() ||
FD->getTemplatedKind() ==
@@ -1111,55 +1111,12 @@ bool Sema::EnsureTemplateArgumentListConstraints(
return false;
}
-static bool CheckFunctionConstraintsWithoutInstantiation(
- Sema &SemaRef, SourceLocation PointOfInstantiation,
- FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
- ConstraintSatisfaction &Satisfaction) {
- SmallVector<const Expr *, 3> TemplateAC;
- Template->getAssociatedConstraints(TemplateAC);
- if (TemplateAC.empty()) {
- Satisfaction.IsSatisfied = true;
- return false;
- }
-
- LocalInstantiationScope Scope(SemaRef);
-
- FunctionDecl *FD = Template->getTemplatedDecl();
- // Collect the list of template arguments relative to the 'primary'
- // template. We need the entire list, since the constraint is completely
- // uninstantiated at this point.
-
- // FIXME: Add TemplateArgs through the 'Innermost' parameter once
- // the refactoring of getTemplateInstantiationArgs() relands.
- MultiLevelTemplateArgumentList MLTAL;
- MLTAL.addOuterTemplateArguments(Template, std::nullopt, /*Final=*/false);
- SemaRef.getTemplateInstantiationArgs(
- MLTAL, /*D=*/FD, FD,
- /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true,
- /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
- MLTAL.replaceInnermostTemplateArguments(Template, TemplateArgs);
-
- Sema::ContextRAII SavedContext(SemaRef, FD);
- std::optional<Sema::CXXThisScopeRAII> ThisScope;
- if (auto *Method = dyn_cast<CXXMethodDecl>(FD))
- ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(),
- /*ThisQuals=*/Method->getMethodQualifiers());
- return SemaRef.CheckConstraintSatisfaction(
- Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
-}
-
-bool Sema::CheckFunctionTemplateConstraints(
+bool Sema::CheckInstantiatedFunctionTemplateConstraints(
SourceLocation PointOfInstantiation, FunctionDecl *Decl,
ArrayRef<TemplateArgument> TemplateArgs,
ConstraintSatisfaction &Satisfaction) {
// In most cases we're not going to have constraints, so check for that first.
FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
-
- if (!Template)
- return ::CheckFunctionConstraintsWithoutInstantiation(
- *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
- TemplateArgs, Satisfaction);
-
// Note - code synthesis context for the constraints check is created
// inside CheckConstraintsSatisfaction.
SmallVector<const Expr *, 3> TemplateAC;
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index acd1151184e42f..1c1f6e30ab7b83 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3936,6 +3936,18 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
Result != TemplateDeductionResult::Success)
return Result;
+ // C++ [temp.deduct.call]p10: [DR1391]
+ // If deduction succeeds for all parameters that contain
+ // template-parameters that participate in template argument deduction,
+ // and all template arguments are explicitly specified, deduced, or
+ // obtained from default template arguments, remaining parameters are then
+ // compared with the corresponding arguments. For each remaining parameter
+ // P with a type that was non-dependent before substitution of any
+ // explicitly-specified template arguments, if the corresponding argument
+ // A cannot be implicitly converted to P, deduction fails.
+ if (CheckNonDependent())
+ return TemplateDeductionResult::NonDependentConversionFailure;
+
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *SugaredDeducedArgumentList =
TemplateArgumentList::CreateCopy(Context, SugaredBuilder);
@@ -3965,39 +3977,6 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
FD = const_cast<FunctionDecl *>(FDFriend);
Owner = FD->getLexicalDeclContext();
}
- // C++20 [temp.deduct.general]p5: [CWG2369]
- // If the function template has associated constraints, those constraints
- // are checked for satisfaction. If the constraints are not satisfied, type
- // deduction fails.
- //
- // FIXME: We haven't implemented CWG2369 for lambdas yet, because we need
- // to figure out how to instantiate lambda captures to the scope without
- // first instantiating the lambda.
- bool IsLambda = isLambdaCallOperator(FD) || isLambdaConversionOperator(FD);
- if (!IsLambda && !IsIncomplete) {
- if (CheckFunctionTemplateConstraints(
- Info.getLocation(),
- FunctionTemplate->getCanonicalDecl()->getTemplatedDecl(),
- CanonicalBuilder, Info.AssociatedConstraintsSatisfaction))
- return TemplateDeductionResult::MiscellaneousDeductionFailure;
- if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
- Info.reset(Info.takeSugared(),
- TemplateArgumentList::CreateCopy(Context, CanonicalBuilder));
- return TemplateDeductionResult::ConstraintsNotSatisfied;
- }
- }
- // C++ [temp.deduct.call]p10: [CWG1391]
- // If deduction succeeds for all parameters that contain
- // template-parameters that participate in template argument deduction,
- // and all template arguments are explicitly specified, deduced, or
- // obtained from default template arguments, remaining parameters are then
- // compared with the corresponding arguments. For each remaining parameter
- // P with a type that was non-dependent before substitution of any
- // explicitly-specified template arguments, if the corresponding argument
- // A cannot be implicitly converted to P, deduction fails.
- if (CheckNonDependent())
- return TemplateDeductionResult::NonDependentConversionFailure;
-
MultiLevelTemplateArgumentList SubstArgs(
FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
/*Final=*/false);
@@ -4032,8 +4011,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
// ([temp.constr.decl]), those constraints are checked for satisfaction
// ([temp.constr.constr]). If the constraints are not satisfied, type
// deduction fails.
- if (IsLambda && !IsIncomplete) {
- if (CheckFunctionTemplateConstraints(
+ if (!IsIncomplete) {
+ if (CheckInstantiatedFunctionTemplateConstraints(
Info.getLocation(), Specialization, CanonicalBuilder,
Info.AssociatedConstraintsSatisfaction))
return TemplateDeductionResult::MiscellaneousDeductionFailure;
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 5d6c11a75303df..d42c3765aa534f 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -902,12 +902,10 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
Context.getTrivialTypeSourceInfo(
Context.getDeducedTemplateSpecializationType(
TemplateName(AliasTemplate), /*DeducedType=*/QualType(),
- /*IsDependent=*/true),
- AliasTemplate->getLocation()), // template specialization type whose
- // arguments will be deduced.
+ /*IsDependent=*/true)), // template specialization type whose
+ // arguments will be deduced.
Context.getTrivialTypeSourceInfo(
- ReturnType, AliasTemplate->getLocation()), // type from which template
- // arguments are deduced.
+ ReturnType), // type from which template arguments are deduced.
};
return TypeTraitExpr::Create(
Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(),
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index cab9ae79ce5cb0..fb0f38df62a744 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -475,21 +475,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
// Accumulate the set of template argument lists in this structure.
MultiLevelTemplateArgumentList Result;
- getTemplateInstantiationArgs(
- Result, ND, DC, Final, Innermost, RelativeToPrimary, Pattern,
- ForConstraintInstantiation, SkipForSpecialization,
- ForDefaultArgumentSubstitution);
- return Result;
-}
-
-void Sema::getTemplateInstantiationArgs(
- MultiLevelTemplateArgumentList &Result, const NamedDecl *ND,
- const DeclContext *DC, bool Final,
- std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
- const FunctionDecl *Pattern, bool ForConstraintInstantiation,
- bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
- assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
- // Accumulate the set of template argument lists in this structure.
using namespace TemplateInstArgsHelpers;
const Decl *CurDecl = ND;
@@ -550,12 +535,14 @@ void Sema::getTemplateInstantiationArgs(
}
if (R.IsDone)
- return;
+ return Result;
if (R.ClearRelativeToPrimary)
RelativeToPrimary = false;
assert(R.NextDecl);
CurDecl = R.NextDecl;
}
+
+ return Result;
}
bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
@@ -1362,19 +1349,6 @@ namespace {
// Whether an incomplete substituion should be treated as an error.
bool BailOutOnIncomplete;
- private:
- bool isSubstitutingConstraints() const {
- return llvm::any_of(SemaRef.CodeSynthesisContexts, [](auto &Context) {
- return Context.Kind ==
- Sema::CodeSynthesisContext::ConstraintSubstitution;
- });
- }
-
- // CWG2770: Function parameters should be instantiated when they are
- // needed by a satisfaction check of an atomic constraint or
- // (recursively) by another function parameter.
- bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm);
-
public:
typedef TreeTransform<TemplateInstantiator> inherited;
@@ -1431,19 +1405,12 @@ namespace {
ArrayRef<UnexpandedParameterPack> Unexpanded,
bool &ShouldExpand, bool &RetainExpansion,
std::optional<unsigned> &NumExpansions) {
- if (SemaRef.CurrentInstantiationScope && isSubstitutingConstraints()) {
- for (UnexpandedParameterPack ParmPack : Unexpanded) {
- NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>();
- if (!isa_and_present<ParmVarDecl>(VD))
- continue;
- if (maybeInstantiateFunctionParameterToScope(cast<ParmVarDecl>(VD)))
- return true;
- }
- }
-
- return getSema().CheckParameterPacksForExpansion(
- EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, ShouldExpand,
- RetainExpansion, NumExpansions);
+ return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
+ PatternRange, Unexpanded,
+ TemplateArgs,
+ ShouldExpand,
+ RetainExpansion,
+ NumExpansions);
}
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
@@ -1944,62 +1911,9 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
// template parameter.
}
- if (SemaRef.CurrentInstantiationScope) {
- if (isSubstitutingConstraints() && isa<ParmVarDecl>(D) &&
- maybeInstantiateFunctionParameterToScope(cast<ParmVarDecl>(D)))
- return nullptr;
- }
-
return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
}
-bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope(
- ParmVarDecl *OldParm) {
- if (SemaRef.CurrentInstantiationScope->findInstantiationUnsafe(OldParm))
- return false;
- // We're instantiating a function parameter whose associated function template
- // has not been instantiated at this point for constraint evaluation, so make
- // sure the instantiated parameters are owned by a function declaration such
- // that they can be correctly 'captured' in tryCaptureVariable().
- Sema::ContextRAII Context(SemaRef, OldParm->getDeclContext());
-
- if (!OldParm->isParameterPack())
- return !TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0,
- /*NumExpansions=*/std::nullopt,
- /*ExpectParameterPack=*/false);
-
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
-
- // Find the parameter packs that could be expanded.
- TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc();
- PackExpansionTypeLoc ExpansionTL = TL.castAs<PackExpansionTypeLoc>();
- TypeLoc Pattern = ExpansionTL.getPatternLoc();
- SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
- assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
-
- bool ShouldExpand = false;
- bool RetainExpansion = false;
- std::optional<unsigned> OrigNumExpansions =
- ExpansionTL.getTypePtr()->getNumExpansions();
- std::optional<unsigned> NumExpansions = OrigNumExpansions;
- if (TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
- Pattern.getSourceRange(), Unexpanded,
- ShouldExpand, RetainExpansion, NumExpansions))
- return true;
-
- assert(ShouldExpand && !RetainExpansion &&
- "Shouldn't preserve pack expansion when evaluating constraints");
- ExpandingFunctionParameterPack(OldParm);
- for (unsigned I = 0; I != *NumExpansions; ++I) {
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
- if (!TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0,
- /*NumExpansions=*/OrigNumExpansions,
- /*ExpectParameterPack=*/false))
- return true;
- }
- return false;
-}
-
Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
if (!Inst)
@@ -4677,8 +4591,9 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) {
return D;
}
+
llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
-LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) {
+LocalInstantiationScope::findInstantiationOf(const Decl *D) {
D = getCanonicalParmVarDecl(D);
for (LocalInstantiationScope *Current = this; Current;
Current = Current->Outer) {
@@ -4703,14 +4618,6 @@ LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) {
break;
}
- return nullptr;
-}
-
-llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
-LocalInstantiationScope::findInstantiationOf(const Decl *D) {
- auto *Result = findInstantiationUnsafe(D);
- if (Result)
- return Result;
// If we're performing a partial substitution during template argument
// deduction, we may not have values for template parameters yet.
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index bff1e5bd8f078e..15ea8c7128f38d 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -713,7 +713,7 @@ class TreeTransform {
/// variables vector are acceptable.
///
/// LastParamTransformed, if non-null, will be set to the index of the last
- /// parameter on which transformation was started. In the event of an error,
+ /// parameter on which transfromation was started. In the event of an error,
/// this will contain the parameter which failed to instantiate.
///
/// Return true on error.
diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp
index d0ec48e3f86cd6..d144cf9e4e8681 100644
--- a/clang/test/CXX/drs/cwg23xx.cpp...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/122130
More information about the cfe-commits
mailing list