Skip to content

Commit 45538b5

Browse files
committed
[Concepts] Fix bug when referencing function parameters in instantiated function template requires clause
Fixes bug llvm#44613 - instantiated parameters were not being added when instantiating the requires clauses.
1 parent 7984b47 commit 45538b5

File tree

2 files changed

+79
-64
lines changed

2 files changed

+79
-64
lines changed

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

+69-64
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,70 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
17661766
return Record;
17671767
}
17681768

1769+
/// Introduce the instantiated function parameters into the local
1770+
/// instantiation scope, and set the parameter names to those used
1771+
/// in the template.
1772+
static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
1773+
const FunctionDecl *PatternDecl,
1774+
LocalInstantiationScope &Scope,
1775+
const MultiLevelTemplateArgumentList &TemplateArgs) {
1776+
unsigned FParamIdx = 0;
1777+
for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
1778+
const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
1779+
if (!PatternParam->isParameterPack()) {
1780+
// Simple case: not a parameter pack.
1781+
assert(FParamIdx < Function->getNumParams());
1782+
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
1783+
FunctionParam->setDeclName(PatternParam->getDeclName());
1784+
// If the parameter's type is not dependent, update it to match the type
1785+
// in the pattern. They can differ in top-level cv-qualifiers, and we want
1786+
// the pattern's type here. If the type is dependent, they can't differ,
1787+
// per core issue 1668. Substitute into the type from the pattern, in case
1788+
// it's instantiation-dependent.
1789+
// FIXME: Updating the type to work around this is at best fragile.
1790+
if (!PatternDecl->getType()->isDependentType()) {
1791+
QualType T = S.SubstType(PatternParam->getType(), TemplateArgs,
1792+
FunctionParam->getLocation(),
1793+
FunctionParam->getDeclName());
1794+
if (T.isNull())
1795+
return true;
1796+
FunctionParam->setType(T);
1797+
}
1798+
1799+
Scope.InstantiatedLocal(PatternParam, FunctionParam);
1800+
++FParamIdx;
1801+
continue;
1802+
}
1803+
1804+
// Expand the parameter pack.
1805+
Scope.MakeInstantiatedLocalArgPack(PatternParam);
1806+
Optional<unsigned> NumArgumentsInExpansion
1807+
= S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
1808+
if (NumArgumentsInExpansion) {
1809+
QualType PatternType =
1810+
PatternParam->getType()->castAs<PackExpansionType>()->getPattern();
1811+
for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
1812+
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
1813+
FunctionParam->setDeclName(PatternParam->getDeclName());
1814+
if (!PatternDecl->getType()->isDependentType()) {
1815+
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg);
1816+
QualType T = S.SubstType(PatternType, TemplateArgs,
1817+
FunctionParam->getLocation(),
1818+
FunctionParam->getDeclName());
1819+
if (T.isNull())
1820+
return true;
1821+
FunctionParam->setType(T);
1822+
}
1823+
1824+
Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
1825+
++FParamIdx;
1826+
}
1827+
}
1828+
}
1829+
1830+
return false;
1831+
}
1832+
17691833
/// Adjust the given function type for an instantiation of the
17701834
/// given declaration, to cope with modifications to the function's type that
17711835
/// aren't reflected in the type-source information.
@@ -1848,6 +1912,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
18481912
// FIXME: Concepts: Do not substitute into constraint expressions
18491913
Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
18501914
if (TrailingRequiresClause) {
1915+
if (D->isTemplateInstantiation() &&
1916+
addInstantiatedParametersToScope(
1917+
SemaRef, D, D->getTemplateInstantiationPattern(), Scope,
1918+
TemplateArgs))
1919+
return nullptr;
18511920
ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause,
18521921
TemplateArgs);
18531922
if (SubstRC.isInvalid())
@@ -4105,70 +4174,6 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
41054174
return NewTInfo;
41064175
}
41074176

4108-
/// Introduce the instantiated function parameters into the local
4109-
/// instantiation scope, and set the parameter names to those used
4110-
/// in the template.
4111-
static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
4112-
const FunctionDecl *PatternDecl,
4113-
LocalInstantiationScope &Scope,
4114-
const MultiLevelTemplateArgumentList &TemplateArgs) {
4115-
unsigned FParamIdx = 0;
4116-
for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
4117-
const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
4118-
if (!PatternParam->isParameterPack()) {
4119-
// Simple case: not a parameter pack.
4120-
assert(FParamIdx < Function->getNumParams());
4121-
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
4122-
FunctionParam->setDeclName(PatternParam->getDeclName());
4123-
// If the parameter's type is not dependent, update it to match the type
4124-
// in the pattern. They can differ in top-level cv-qualifiers, and we want
4125-
// the pattern's type here. If the type is dependent, they can't differ,
4126-
// per core issue 1668. Substitute into the type from the pattern, in case
4127-
// it's instantiation-dependent.
4128-
// FIXME: Updating the type to work around this is at best fragile.
4129-
if (!PatternDecl->getType()->isDependentType()) {
4130-
QualType T = S.SubstType(PatternParam->getType(), TemplateArgs,
4131-
FunctionParam->getLocation(),
4132-
FunctionParam->getDeclName());
4133-
if (T.isNull())
4134-
return true;
4135-
FunctionParam->setType(T);
4136-
}
4137-
4138-
Scope.InstantiatedLocal(PatternParam, FunctionParam);
4139-
++FParamIdx;
4140-
continue;
4141-
}
4142-
4143-
// Expand the parameter pack.
4144-
Scope.MakeInstantiatedLocalArgPack(PatternParam);
4145-
Optional<unsigned> NumArgumentsInExpansion
4146-
= S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
4147-
if (NumArgumentsInExpansion) {
4148-
QualType PatternType =
4149-
PatternParam->getType()->castAs<PackExpansionType>()->getPattern();
4150-
for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
4151-
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
4152-
FunctionParam->setDeclName(PatternParam->getDeclName());
4153-
if (!PatternDecl->getType()->isDependentType()) {
4154-
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg);
4155-
QualType T = S.SubstType(PatternType, TemplateArgs,
4156-
FunctionParam->getLocation(),
4157-
FunctionParam->getDeclName());
4158-
if (T.isNull())
4159-
return true;
4160-
FunctionParam->setType(T);
4161-
}
4162-
4163-
Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
4164-
++FParamIdx;
4165-
}
4166-
}
4167-
}
4168-
4169-
return false;
4170-
}
4171-
41724177
void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
41734178
FunctionDecl *Decl) {
41744179
const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>();

clang/test/SemaTemplate/instantiate-requires-clause.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,13 @@ using f31 = decltype(f3('a'));
2929
using f32 = decltype(f3(1, 'b'));
3030
using f33 = decltype(f3(1, 'b', 2));
3131
// expected-error@-1 {{no matching function for call to 'f3'}}
32+
33+
template<typename T>
34+
struct S {
35+
template<typename U>
36+
static constexpr auto f(U const index) requires(index, true) {
37+
return true;
38+
}
39+
};
40+
41+
static_assert(S<void>::f(1));

0 commit comments

Comments
 (0)