Skip to content

Commit befa8cf

Browse files
author
Erich Keane
committed
Re-apply "Deferred Concept Instantiation Implementation""
This reverts commit d4d47e5. This fixes the lldb crash that was observed by ensuring that our friend-'template contains reference to' TreeTransform properly handles a TemplateDecl.
1 parent 696bca9 commit befa8cf

26 files changed

+1574
-217
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,10 +451,11 @@ C++20 Feature Support
451451
- No longer attempt to evaluate a consteval UDL function call at runtime when
452452
it is called through a template instantiation. This fixes
453453
`Issue 54578 <https://github.com/llvm/llvm-project/issues/54578>`_.
454-
455-
- Implemented ``__builtin_source_location()``, which enables library support
456-
for ``std::source_location``.
457-
454+
- Implemented `__builtin_source_location()` which enables library support for std::source_location.
455+
- Clang now correctly delays the instantiation of function constraints until
456+
the time of checking, which should now allow the libstdc++ ranges implementation
457+
to work for at least trivial examples. This fixes
458+
`Issue 44178 <https://github.com/llvm/llvm-project/issues/44178>`_.
458459
- The mangling scheme for C++20 modules has incompatibly changed. The
459460
initial mangling was discovered not to be reversible, and the weak
460461
ownership design decision did not give the backwards compatibility

clang/include/clang/AST/Decl.h

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,7 +1890,9 @@ class FunctionDecl : public DeclaratorDecl,
18901890
TK_FunctionTemplateSpecialization,
18911891
// A function template specialization that hasn't yet been resolved to a
18921892
// particular specialized function template.
1893-
TK_DependentFunctionTemplateSpecialization
1893+
TK_DependentFunctionTemplateSpecialization,
1894+
// A non templated function which is in a dependent scope.
1895+
TK_DependentNonTemplate
18941896
};
18951897

18961898
/// Stashed information about a defaulted function definition whose body has
@@ -1939,20 +1941,21 @@ class FunctionDecl : public DeclaratorDecl,
19391941
/// The template or declaration that this declaration
19401942
/// describes or was instantiated from, respectively.
19411943
///
1942-
/// For non-templates, this value will be NULL. For function
1943-
/// declarations that describe a function template, this will be a
1944-
/// pointer to a FunctionTemplateDecl. For member functions
1945-
/// of class template specializations, this will be a MemberSpecializationInfo
1946-
/// pointer containing information about the specialization.
1947-
/// For function template specializations, this will be a
1948-
/// FunctionTemplateSpecializationInfo, which contains information about
1949-
/// the template being specialized and the template arguments involved in
1950-
/// that specialization.
1951-
llvm::PointerUnion<FunctionTemplateDecl *,
1952-
MemberSpecializationInfo *,
1944+
/// For non-templates this value will be NULL, unless this non-template
1945+
/// function declaration was declared directly inside of a function template,
1946+
/// in which case this will have a pointer to a FunctionDecl, stored in the
1947+
/// NamedDecl. For function declarations that describe a function template,
1948+
/// this will be a pointer to a FunctionTemplateDecl, stored in the NamedDecl.
1949+
/// For member functions of class template specializations, this will be a
1950+
/// MemberSpecializationInfo pointer containing information about the
1951+
/// specialization. For function template specializations, this will be a
1952+
/// FunctionTemplateSpecializationInfo, which contains information about the
1953+
/// template being specialized and the template arguments involved in that
1954+
/// specialization.
1955+
llvm::PointerUnion<NamedDecl *, MemberSpecializationInfo *,
19531956
FunctionTemplateSpecializationInfo *,
19541957
DependentFunctionTemplateSpecializationInfo *>
1955-
TemplateOrSpecialization;
1958+
TemplateOrSpecialization;
19561959

19571960
/// Provides source/type location info for the declaration name embedded in
19581961
/// the DeclaratorDecl base class.
@@ -2695,6 +2698,11 @@ class FunctionDecl : public DeclaratorDecl,
26952698
setInstantiationOfMemberFunction(getASTContext(), FD, TSK);
26962699
}
26972700

2701+
/// Specify that this function declaration was instantiated from FunctionDecl
2702+
/// FD. This is only used if this is a function declaration declared locally
2703+
/// inside of a function template.
2704+
void setInstantiatedFromDecl(FunctionDecl *FD);
2705+
26982706
/// Retrieves the function template that is described by this
26992707
/// function declaration.
27002708
///
@@ -2709,6 +2717,8 @@ class FunctionDecl : public DeclaratorDecl,
27092717
/// FunctionTemplateDecl from a FunctionDecl.
27102718
FunctionTemplateDecl *getDescribedFunctionTemplate() const;
27112719

2720+
FunctionDecl *getInstantiatedFromDecl() const;
2721+
27122722
void setDescribedFunctionTemplate(FunctionTemplateDecl *Template);
27132723

27142724
/// Determine whether this function is a function template

clang/include/clang/AST/DeclBase.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -920,10 +920,10 @@ class alignas(8) Decl {
920920

921921
/// If this decl is defined inside a function/method/block it returns
922922
/// the corresponding DeclContext, otherwise it returns null.
923-
const DeclContext *getParentFunctionOrMethod() const;
924-
DeclContext *getParentFunctionOrMethod() {
925-
return const_cast<DeclContext*>(
926-
const_cast<const Decl*>(this)->getParentFunctionOrMethod());
923+
const DeclContext *getParentFunctionOrMethod(bool Lexical = false) const;
924+
DeclContext *getParentFunctionOrMethod(bool Lexical = false) {
925+
return const_cast<DeclContext *>(
926+
const_cast<const Decl *>(this)->getParentFunctionOrMethod(Lexical));
927927
}
928928

929929
/// Retrieves the "canonical" declaration of the given declaration.

clang/include/clang/Sema/Sema.h

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3622,6 +3622,11 @@ class Sema final {
36223622
bool ConsiderCudaAttrs = true,
36233623
bool ConsiderRequiresClauses = true);
36243624

3625+
// Calculates whether the expression Constraint depends on an enclosing
3626+
// template, for the purposes of [temp.friend] p9.
3627+
bool ConstraintExpressionDependsOnEnclosingTemplate(unsigned TemplateDepth,
3628+
const Expr *Constraint);
3629+
36253630
enum class AllowedExplicit {
36263631
/// Allow no explicit functions to be used.
36273632
None,
@@ -7091,6 +7096,21 @@ class Sema final {
70917096
LocalInstantiationScope &Scope,
70927097
const MultiLevelTemplateArgumentList &TemplateArgs);
70937098

7099+
/// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
7100+
/// the case of lambdas) set up the LocalInstantiationScope of the current
7101+
/// function.
7102+
bool SetupConstraintScope(
7103+
FunctionDecl *FD, llvm::Optional<ArrayRef<TemplateArgument>> TemplateArgs,
7104+
MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope);
7105+
7106+
/// Used during constraint checking, sets up the constraint template arguemnt
7107+
/// lists, and calls SetupConstraintScope to set up the
7108+
/// LocalInstantiationScope to have the proper set of ParVarDecls configured.
7109+
llvm::Optional<MultiLevelTemplateArgumentList>
7110+
SetupConstraintCheckingTemplateArgumentsAndScope(
7111+
FunctionDecl *FD, llvm::Optional<ArrayRef<TemplateArgument>> TemplateArgs,
7112+
LocalInstantiationScope &Scope);
7113+
70947114
public:
70957115
const NormalizedConstraint *
70967116
getNormalizedAssociatedConstraints(
@@ -7121,8 +7141,10 @@ class Sema final {
71217141
/// check (either a concept or a constrained entity).
71227142
/// \param ConstraintExprs a list of constraint expressions, treated as if
71237143
/// they were 'AND'ed together.
7124-
/// \param TemplateArgs the list of template arguments to substitute into the
7125-
/// constraint expression.
7144+
/// \param TemplateArgList the multi-level list of template arguments to
7145+
/// substitute into the constraint expression. This should be relative to the
7146+
/// top-level (hence multi-level), since we need to instantiate fully at the
7147+
/// time of checking.
71267148
/// \param TemplateIDRange The source range of the template id that
71277149
/// caused the constraints check.
71287150
/// \param Satisfaction if true is returned, will contain details of the
@@ -7132,7 +7154,40 @@ class Sema final {
71327154
/// false otherwise.
71337155
bool CheckConstraintSatisfaction(
71347156
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
7135-
ArrayRef<TemplateArgument> TemplateArgs,
7157+
const MultiLevelTemplateArgumentList &TemplateArgList,
7158+
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
7159+
llvm::SmallVector<Expr *, 4> Converted;
7160+
return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted,
7161+
TemplateArgList, TemplateIDRange,
7162+
Satisfaction);
7163+
}
7164+
7165+
/// \brief Check whether the given list of constraint expressions are
7166+
/// satisfied (as if in a 'conjunction') given template arguments.
7167+
/// Additionally, takes an empty list of Expressions which is populated with
7168+
/// the instantiated versions of the ConstraintExprs.
7169+
/// \param Template the template-like entity that triggered the constraints
7170+
/// check (either a concept or a constrained entity).
7171+
/// \param ConstraintExprs a list of constraint expressions, treated as if
7172+
/// they were 'AND'ed together.
7173+
/// \param ConvertedConstraints a out parameter that will get populated with
7174+
/// the instantiated version of the ConstraintExprs if we successfully checked
7175+
/// satisfaction.
7176+
/// \param TemplateArgList the multi-level list of template arguments to
7177+
/// substitute into the constraint expression. This should be relative to the
7178+
/// top-level (hence multi-level), since we need to instantiate fully at the
7179+
/// time of checking.
7180+
/// \param TemplateIDRange The source range of the template id that
7181+
/// caused the constraints check.
7182+
/// \param Satisfaction if true is returned, will contain details of the
7183+
/// satisfaction, with enough information to diagnose an unsatisfied
7184+
/// expression.
7185+
/// \returns true if an error occurred and satisfaction could not be checked,
7186+
/// false otherwise.
7187+
bool CheckConstraintSatisfaction(
7188+
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
7189+
llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
7190+
const MultiLevelTemplateArgumentList &TemplateArgList,
71367191
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
71377192

71387193
/// \brief Check whether the given non-dependent constraint expression is
@@ -7168,9 +7223,9 @@ class Sema final {
71687223
///
71697224
/// \returns true if the constrains are not satisfied or could not be checked
71707225
/// for satisfaction, false if the constraints are satisfied.
7171-
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template,
7172-
ArrayRef<TemplateArgument> TemplateArgs,
7173-
SourceRange TemplateIDRange);
7226+
bool EnsureTemplateArgumentListConstraints(
7227+
TemplateDecl *Template, MultiLevelTemplateArgumentList TemplateArgs,
7228+
SourceRange TemplateIDRange);
71747229

71757230
/// \brief Emit diagnostics explaining why a constraint expression was deemed
71767231
/// unsatisfied.
@@ -8904,7 +8959,8 @@ class Sema final {
89048959

89058960
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
89068961
const NamedDecl *D, const TemplateArgumentList *Innermost = nullptr,
8907-
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr);
8962+
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
8963+
bool LookBeyondLambda = false, bool IncludeContainingStruct = false);
89088964

89098965
/// A context in which code is being synthesized (where a source location
89108966
/// alone is not sufficient to identify the context). This covers template
@@ -9637,6 +9693,11 @@ class Sema final {
96379693
ExtParameterInfoBuilder &ParamInfos);
96389694
ExprResult SubstExpr(Expr *E,
96399695
const MultiLevelTemplateArgumentList &TemplateArgs);
9696+
// Unlike the above, this evaluates constraints, which should only happen at
9697+
// 'constraint checking' time.
9698+
ExprResult
9699+
SubstConstraintExpr(Expr *E,
9700+
const MultiLevelTemplateArgumentList &TemplateArgs);
96409701

96419702
/// Substitute the given template arguments into a list of
96429703
/// expressions, expanding pack expansions if required.
@@ -9660,13 +9721,14 @@ class Sema final {
96609721

96619722
TemplateParameterList *
96629723
SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
9663-
const MultiLevelTemplateArgumentList &TemplateArgs);
9724+
const MultiLevelTemplateArgumentList &TemplateArgs,
9725+
bool InstantiateConstraints = false);
96649726

96659727
bool
96669728
SubstTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
96679729
const MultiLevelTemplateArgumentList &TemplateArgs,
9668-
TemplateArgumentListInfo &Outputs);
9669-
9730+
TemplateArgumentListInfo &Outputs,
9731+
bool InstantiateConstraints = false);
96709732

96719733
Decl *SubstDecl(Decl *D, DeclContext *Owner,
96729734
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -9758,7 +9820,8 @@ class Sema final {
97589820
const MultiLevelTemplateArgumentList &TemplateArgs);
97599821

97609822
bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
9761-
const MultiLevelTemplateArgumentList &TemplateArgs);
9823+
const MultiLevelTemplateArgumentList &TemplateArgs,
9824+
bool isEvaluatingAConstraint);
97629825

97639826
bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
97649827
ParmVarDecl *Param);

clang/include/clang/Sema/Template.h

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ enum class TemplateSubstitutionKind : char {
7575
class MultiLevelTemplateArgumentList {
7676
/// The template argument list at a certain template depth
7777
using ArgList = ArrayRef<TemplateArgument>;
78+
using ArgListsIterator = SmallVector<ArgList, 4>::iterator;
79+
using ConstArgListsIterator = SmallVector<ArgList, 4>::const_iterator;
7880

7981
/// The template argument lists, stored from the innermost template
8082
/// argument list (first) to the outermost template argument list (last).
@@ -121,6 +123,12 @@ enum class TemplateSubstitutionKind : char {
121123
return TemplateArgumentLists.size();
122124
}
123125

126+
/// Determine the number of substituted args at 'Depth'.
127+
unsigned getNumSubstitutedArgs(unsigned Depth) const {
128+
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
129+
return TemplateArgumentLists[getNumLevels() - Depth - 1].size();
130+
}
131+
124132
unsigned getNumRetainedOuterLevels() const {
125133
return NumRetainedOuterLevels;
126134
}
@@ -158,6 +166,14 @@ enum class TemplateSubstitutionKind : char {
158166
return !(*this)(Depth, Index).isNull();
159167
}
160168

169+
bool isAnyArgInstantiationDependent() const {
170+
for (ArgList List : TemplateArgumentLists)
171+
for (const TemplateArgument &TA : List)
172+
if (TA.isInstantiationDependent())
173+
return true;
174+
return false;
175+
}
176+
161177
/// Clear out a specific template argument.
162178
void setArgument(unsigned Depth, unsigned Index,
163179
TemplateArgument Arg) {
@@ -183,6 +199,14 @@ enum class TemplateSubstitutionKind : char {
183199
TemplateArgumentLists.push_back(Args);
184200
}
185201

202+
/// Replaces the current 'innermost' level with the provided argument list.
203+
/// This is useful for type deduction cases where we need to get the entire
204+
/// list from the AST, but then add the deduced innermost list.
205+
void replaceInnermostTemplateArguments(ArgList Args) {
206+
assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?");
207+
TemplateArgumentLists[0] = Args;
208+
}
209+
186210
/// Add an outermost level that we are not substituting. We have no
187211
/// arguments at this level, and do not remove it from the depth of inner
188212
/// template parameters that we instantiate.
@@ -197,6 +221,16 @@ enum class TemplateSubstitutionKind : char {
197221
const ArgList &getInnermost() const {
198222
return TemplateArgumentLists.front();
199223
}
224+
225+
/// Retrieve the outermost template argument list.
226+
const ArgList &getOutermost() const { return TemplateArgumentLists.back(); }
227+
228+
ArgListsIterator begin() { return TemplateArgumentLists.begin(); }
229+
ConstArgListsIterator begin() const {
230+
return TemplateArgumentLists.begin();
231+
}
232+
ArgListsIterator end() { return TemplateArgumentLists.end(); }
233+
ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
200234
};
201235

202236
/// The context in which partial ordering of function templates occurs.
@@ -469,6 +503,7 @@ enum class TemplateSubstitutionKind : char {
469503
const MultiLevelTemplateArgumentList &TemplateArgs;
470504
Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
471505
LocalInstantiationScope *StartingScope = nullptr;
506+
bool EvaluatingAConstraint = false;
472507

473508
/// A list of out-of-line class template partial
474509
/// specializations that will need to be instantiated after the
@@ -487,10 +522,12 @@ enum class TemplateSubstitutionKind : char {
487522

488523
public:
489524
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
490-
const MultiLevelTemplateArgumentList &TemplateArgs)
525+
const MultiLevelTemplateArgumentList &TemplateArgs,
526+
bool EvaluatingConstraint = false)
491527
: SemaRef(SemaRef),
492528
SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
493-
Owner(Owner), TemplateArgs(TemplateArgs) {}
529+
Owner(Owner), TemplateArgs(TemplateArgs),
530+
EvaluatingAConstraint(EvaluatingConstraint) {}
494531

495532
// Define all the decl visitors using DeclNodes.inc
496533
#define DECL(DERIVED, BASE) \

clang/lib/AST/ASTImporter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3109,6 +3109,11 @@ Error ASTNodeImporter::ImportTemplateInformation(
31093109
case FunctionDecl::TK_FunctionTemplate:
31103110
return Error::success();
31113111

3112+
case FunctionDecl::TK_DependentNonTemplate:
3113+
if (Expected<FunctionDecl *> InstFDOrErr =
3114+
import(FromFD->getInstantiatedFromDecl()))
3115+
ToFD->setInstantiatedFromDecl(*InstFDOrErr);
3116+
return Error::success();
31123117
case FunctionDecl::TK_MemberSpecialization: {
31133118
TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind();
31143119

clang/lib/AST/Decl.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3732,8 +3732,12 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
37323732
FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
37333733
if (TemplateOrSpecialization.isNull())
37343734
return TK_NonTemplate;
3735-
if (TemplateOrSpecialization.is<FunctionTemplateDecl *>())
3735+
if (auto *ND = TemplateOrSpecialization.dyn_cast<NamedDecl *>()) {
3736+
if (isa<FunctionDecl>(ND))
3737+
return TK_DependentNonTemplate;
3738+
assert(isa<FunctionTemplateDecl>(ND) && "No other types it could be?");
37363739
return TK_FunctionTemplate;
3740+
}
37373741
if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
37383742
return TK_MemberSpecialization;
37393743
if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
@@ -3774,15 +3778,28 @@ FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
37743778
}
37753779

37763780
FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
3777-
return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>();
3781+
return dyn_cast_or_null<FunctionTemplateDecl>(
3782+
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
37783783
}
37793784

3780-
void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
3785+
void FunctionDecl::setDescribedFunctionTemplate(
3786+
FunctionTemplateDecl *Template) {
37813787
assert(TemplateOrSpecialization.isNull() &&
37823788
"Member function is already a specialization");
37833789
TemplateOrSpecialization = Template;
37843790
}
37853791

3792+
void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
3793+
assert(TemplateOrSpecialization.isNull() &&
3794+
"function is already a specialization");
3795+
TemplateOrSpecialization = FD;
3796+
}
3797+
3798+
FunctionDecl *FunctionDecl::getInstantiatedFromDecl() const {
3799+
return dyn_cast_or_null<FunctionDecl>(
3800+
TemplateOrSpecialization.dyn_cast<NamedDecl *>());
3801+
}
3802+
37863803
bool FunctionDecl::isImplicitlyInstantiable() const {
37873804
// If the function is invalid, it can't be implicitly instantiated.
37883805
if (isInvalidDecl())

0 commit comments

Comments
 (0)