Skip to content

Commit d483730

Browse files
author
Erich Keane
committed
Re-apply "Deferred Concept Instantiation Implementation""
This reverts commit 258c3ae. This should fix the libc++ issue that caused the revert, by re-designing slightly how we determined when we should evaluate the constraints. Additionally, many of the other components to the original patch (the NFC parts) were committed separately to shrink the size of this patch for review. Differential Revision: https://reviews.llvm.org/D126907
1 parent 5ad7cc7 commit d483730

19 files changed

+1522
-195
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ C++ Language Changes in Clang
144144

145145
C++20 Feature Support
146146
^^^^^^^^^^^^^^^^^^^^^
147+
- Clang now correctly delays the instantiation of function constraints until
148+
the time of checking, which should now allow the libstdc++ ranges implementation
149+
to work for at least trivial examples. This fixes
150+
`Issue 44178 <https://github.com/llvm/llvm-project/issues/44178>`_.
147151

148152
- Support capturing structured bindings in lambdas
149153
(`P1091R3 <https://wg21.link/p1091r3>`_ and `P1381R1 <https://wg21.link/P1381R1>`).

clang/include/clang/Sema/Sema.h

Lines changed: 92 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3637,6 +3637,16 @@ class Sema final {
36373637
bool ConsiderCudaAttrs = true,
36383638
bool ConsiderRequiresClauses = true);
36393639

3640+
// Calculates whether the expression Constraint depends on an enclosing
3641+
// template, for the purposes of [temp.friend] p9.
3642+
// TemplateDepth is the 'depth' of the friend function, which is used to
3643+
// compare whether a declaration reference is referring to a containing
3644+
// template, or just the current friend function. A 'lower' TemplateDepth in
3645+
// the AST refers to a 'containing' template. As the constraint is
3646+
// uninstantiated, this is relative to the 'top' of the TU.
3647+
bool ConstraintExpressionDependsOnEnclosingTemplate(unsigned TemplateDepth,
3648+
const Expr *Constraint);
3649+
36403650
enum class AllowedExplicit {
36413651
/// Allow no explicit functions to be used.
36423652
None,
@@ -7109,6 +7119,21 @@ class Sema final {
71097119
LocalInstantiationScope &Scope,
71107120
const MultiLevelTemplateArgumentList &TemplateArgs);
71117121

7122+
/// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
7123+
/// the case of lambdas) set up the LocalInstantiationScope of the current
7124+
/// function.
7125+
bool SetupConstraintScope(
7126+
FunctionDecl *FD, llvm::Optional<ArrayRef<TemplateArgument>> TemplateArgs,
7127+
MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope);
7128+
7129+
/// Used during constraint checking, sets up the constraint template arguemnt
7130+
/// lists, and calls SetupConstraintScope to set up the
7131+
/// LocalInstantiationScope to have the proper set of ParVarDecls configured.
7132+
llvm::Optional<MultiLevelTemplateArgumentList>
7133+
SetupConstraintCheckingTemplateArgumentsAndScope(
7134+
FunctionDecl *FD, llvm::Optional<ArrayRef<TemplateArgument>> TemplateArgs,
7135+
LocalInstantiationScope &Scope);
7136+
71127137
public:
71137138
const NormalizedConstraint *
71147139
getNormalizedAssociatedConstraints(
@@ -7151,6 +7176,39 @@ class Sema final {
71517176
bool CheckConstraintSatisfaction(
71527177
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
71537178
const MultiLevelTemplateArgumentList &TemplateArgLists,
7179+
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
7180+
llvm::SmallVector<Expr *, 4> Converted;
7181+
return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted,
7182+
TemplateArgLists, TemplateIDRange,
7183+
Satisfaction);
7184+
}
7185+
7186+
/// \brief Check whether the given list of constraint expressions are
7187+
/// satisfied (as if in a 'conjunction') given template arguments.
7188+
/// Additionally, takes an empty list of Expressions which is populated with
7189+
/// the instantiated versions of the ConstraintExprs.
7190+
/// \param Template the template-like entity that triggered the constraints
7191+
/// check (either a concept or a constrained entity).
7192+
/// \param ConstraintExprs a list of constraint expressions, treated as if
7193+
/// they were 'AND'ed together.
7194+
/// \param ConvertedConstraints a out parameter that will get populated with
7195+
/// the instantiated version of the ConstraintExprs if we successfully checked
7196+
/// satisfaction.
7197+
/// \param TemplateArgList the multi-level list of template arguments to
7198+
/// substitute into the constraint expression. This should be relative to the
7199+
/// top-level (hence multi-level), since we need to instantiate fully at the
7200+
/// time of checking.
7201+
/// \param TemplateIDRange The source range of the template id that
7202+
/// caused the constraints check.
7203+
/// \param Satisfaction if true is returned, will contain details of the
7204+
/// satisfaction, with enough information to diagnose an unsatisfied
7205+
/// expression.
7206+
/// \returns true if an error occurred and satisfaction could not be checked,
7207+
/// false otherwise.
7208+
bool CheckConstraintSatisfaction(
7209+
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
7210+
llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
7211+
const MultiLevelTemplateArgumentList &TemplateArgList,
71547212
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
71557213

71567214
/// \brief Check whether the given non-dependent constraint expression is
@@ -7170,8 +7228,8 @@ class Sema final {
71707228
/// \returns true if an error occurred, false otherwise.
71717229
bool CheckFunctionConstraints(const FunctionDecl *FD,
71727230
ConstraintSatisfaction &Satisfaction,
7173-
SourceLocation UsageLoc = SourceLocation());
7174-
7231+
SourceLocation UsageLoc = SourceLocation(),
7232+
bool ForOverloadResolution = false);
71757233

71767234
/// \brief Ensure that the given template arguments satisfy the constraints
71777235
/// associated with the given template, emitting a diagnostic if they do not.
@@ -8927,7 +8985,8 @@ class Sema final {
89278985

89288986
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
89298987
const NamedDecl *D, const TemplateArgumentList *Innermost = nullptr,
8930-
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr);
8988+
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
8989+
bool LookBeyondLambda = false, bool IncludeContainingStruct = false);
89318990

89328991
/// A context in which code is being synthesized (where a source location
89338992
/// alone is not sufficient to identify the context). This covers template
@@ -9635,23 +9694,21 @@ class Sema final {
96359694
const MultiLevelTemplateArgumentList &TemplateArgs,
96369695
SourceLocation Loc, DeclarationName Entity);
96379696

9638-
TypeSourceInfo *SubstFunctionDeclType(TypeSourceInfo *T,
9639-
const MultiLevelTemplateArgumentList &TemplateArgs,
9640-
SourceLocation Loc,
9641-
DeclarationName Entity,
9642-
CXXRecordDecl *ThisContext,
9643-
Qualifiers ThisTypeQuals);
9697+
TypeSourceInfo *SubstFunctionDeclType(
9698+
TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs,
9699+
SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext,
9700+
Qualifiers ThisTypeQuals, bool EvaluateConstraints = true);
96449701
void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
96459702
const MultiLevelTemplateArgumentList &Args);
96469703
bool SubstExceptionSpec(SourceLocation Loc,
96479704
FunctionProtoType::ExceptionSpecInfo &ESI,
96489705
SmallVectorImpl<QualType> &ExceptionStorage,
96499706
const MultiLevelTemplateArgumentList &Args);
9650-
ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
9651-
const MultiLevelTemplateArgumentList &TemplateArgs,
9652-
int indexAdjustment,
9653-
Optional<unsigned> NumExpansions,
9654-
bool ExpectParameterPack);
9707+
ParmVarDecl *
9708+
SubstParmVarDecl(ParmVarDecl *D,
9709+
const MultiLevelTemplateArgumentList &TemplateArgs,
9710+
int indexAdjustment, Optional<unsigned> NumExpansions,
9711+
bool ExpectParameterPack, bool EvaluateConstraints = true);
96559712
bool SubstParmTypes(SourceLocation Loc, ArrayRef<ParmVarDecl *> Params,
96569713
const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
96579714
const MultiLevelTemplateArgumentList &TemplateArgs,
@@ -9661,6 +9718,25 @@ class Sema final {
96619718
ExprResult SubstExpr(Expr *E,
96629719
const MultiLevelTemplateArgumentList &TemplateArgs);
96639720

9721+
// A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator
9722+
// to disable constraint evaluation, then restore the state.
9723+
template <typename InstTy> struct ConstraintEvalRAII {
9724+
InstTy &TI;
9725+
bool OldValue;
9726+
9727+
ConstraintEvalRAII(InstTy &TI)
9728+
: TI(TI), OldValue(TI.getEvaluateConstraints()) {
9729+
TI.setEvaluateConstraints(false);
9730+
}
9731+
~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); }
9732+
};
9733+
9734+
// Unlike the above, this evaluates constraints, which should only happen at
9735+
// 'constraint checking' time.
9736+
ExprResult
9737+
SubstConstraintExpr(Expr *E,
9738+
const MultiLevelTemplateArgumentList &TemplateArgs);
9739+
96649740
/// Substitute the given template arguments into a list of
96659741
/// expressions, expanding pack expansions if required.
96669742
///
@@ -9690,7 +9766,6 @@ class Sema final {
96909766
const MultiLevelTemplateArgumentList &TemplateArgs,
96919767
TemplateArgumentListInfo &Outputs);
96929768

9693-
96949769
Decl *SubstDecl(Decl *D, DeclContext *Owner,
96959770
const MultiLevelTemplateArgumentList &TemplateArgs);
96969771

@@ -9781,7 +9856,8 @@ class Sema final {
97819856
const MultiLevelTemplateArgumentList &TemplateArgs);
97829857

97839858
bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
9784-
const MultiLevelTemplateArgumentList &TemplateArgs);
9859+
const MultiLevelTemplateArgumentList &TemplateArgs,
9860+
bool EvaluateConstraint);
97859861

97869862
bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
97879863
ParmVarDecl *Param);

clang/include/clang/Sema/Template.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ enum class TemplateSubstitutionKind : char {
503503
const MultiLevelTemplateArgumentList &TemplateArgs;
504504
Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
505505
LocalInstantiationScope *StartingScope = nullptr;
506+
bool EvaluateConstraints = true;
506507

507508
/// A list of out-of-line class template partial
508509
/// specializations that will need to be instantiated after the
@@ -526,6 +527,13 @@ enum class TemplateSubstitutionKind : char {
526527
SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
527528
Owner(Owner), TemplateArgs(TemplateArgs) {}
528529

530+
void setEvaluateConstraints(bool B) {
531+
EvaluateConstraints = B;
532+
}
533+
bool getEvaluateConstraints() {
534+
return EvaluateConstraints;
535+
}
536+
529537
// Define all the decl visitors using DeclNodes.inc
530538
#define DECL(DERIVED, BASE) \
531539
Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);

0 commit comments

Comments
 (0)