Skip to content

Commit 69066ab

Browse files
authored
[Clang] Fix IsOverload for function templates (#77323)
Functions which correspond but have different template parameter lists are not redeclarations. Fixes a regression introduced by af4751 (The patch just moves the template parameters check above if the signature check) Fixes #76358
1 parent 34dbadd commit 69066ab

File tree

2 files changed

+42
-37
lines changed

2 files changed

+42
-37
lines changed

clang/lib/Sema/SemaOverload.cpp

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,43 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
12591259
if ((OldTemplate == nullptr) != (NewTemplate == nullptr))
12601260
return true;
12611261

1262+
if (NewTemplate) {
1263+
// C++ [temp.over.link]p4:
1264+
// The signature of a function template consists of its function
1265+
// signature, its return type and its template parameter list. The names
1266+
// of the template parameters are significant only for establishing the
1267+
// relationship between the template parameters and the rest of the
1268+
// signature.
1269+
//
1270+
// We check the return type and template parameter lists for function
1271+
// templates first; the remaining checks follow.
1272+
bool SameTemplateParameterList = SemaRef.TemplateParameterListsAreEqual(
1273+
NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate,
1274+
OldTemplate->getTemplateParameters(), false, Sema::TPL_TemplateMatch);
1275+
bool SameReturnType = SemaRef.Context.hasSameType(
1276+
Old->getDeclaredReturnType(), New->getDeclaredReturnType());
1277+
// FIXME(GH58571): Match template parameter list even for non-constrained
1278+
// template heads. This currently ensures that the code prior to C++20 is
1279+
// not newly broken.
1280+
bool ConstraintsInTemplateHead =
1281+
NewTemplate->getTemplateParameters()->hasAssociatedConstraints() ||
1282+
OldTemplate->getTemplateParameters()->hasAssociatedConstraints();
1283+
// C++ [namespace.udecl]p11:
1284+
// The set of declarations named by a using-declarator that inhabits a
1285+
// class C does not include member functions and member function
1286+
// templates of a base class that "correspond" to (and thus would
1287+
// conflict with) a declaration of a function or function template in
1288+
// C.
1289+
// Comparing return types is not required for the "correspond" check to
1290+
// decide whether a member introduced by a shadow declaration is hidden.
1291+
if (UseMemberUsingDeclRules && ConstraintsInTemplateHead &&
1292+
!SameTemplateParameterList)
1293+
return true;
1294+
if (!UseMemberUsingDeclRules &&
1295+
(!SameTemplateParameterList || !SameReturnType))
1296+
return true;
1297+
}
1298+
12621299
// Is the function New an overload of the function Old?
12631300
QualType OldQType = SemaRef.Context.getCanonicalType(Old->getType());
12641301
QualType NewQType = SemaRef.Context.getCanonicalType(New->getType());
@@ -1410,43 +1447,6 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
14101447
}
14111448
}
14121449

1413-
if (NewTemplate) {
1414-
// C++ [temp.over.link]p4:
1415-
// The signature of a function template consists of its function
1416-
// signature, its return type and its template parameter list. The names
1417-
// of the template parameters are significant only for establishing the
1418-
// relationship between the template parameters and the rest of the
1419-
// signature.
1420-
//
1421-
// We check the return type and template parameter lists for function
1422-
// templates first; the remaining checks follow.
1423-
bool SameTemplateParameterList = SemaRef.TemplateParameterListsAreEqual(
1424-
NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate,
1425-
OldTemplate->getTemplateParameters(), false, Sema::TPL_TemplateMatch);
1426-
bool SameReturnType = SemaRef.Context.hasSameType(
1427-
Old->getDeclaredReturnType(), New->getDeclaredReturnType());
1428-
// FIXME(GH58571): Match template parameter list even for non-constrained
1429-
// template heads. This currently ensures that the code prior to C++20 is
1430-
// not newly broken.
1431-
bool ConstraintsInTemplateHead =
1432-
NewTemplate->getTemplateParameters()->hasAssociatedConstraints() ||
1433-
OldTemplate->getTemplateParameters()->hasAssociatedConstraints();
1434-
// C++ [namespace.udecl]p11:
1435-
// The set of declarations named by a using-declarator that inhabits a
1436-
// class C does not include member functions and member function
1437-
// templates of a base class that "correspond" to (and thus would
1438-
// conflict with) a declaration of a function or function template in
1439-
// C.
1440-
// Comparing return types is not required for the "correspond" check to
1441-
// decide whether a member introduced by a shadow declaration is hidden.
1442-
if (UseMemberUsingDeclRules && ConstraintsInTemplateHead &&
1443-
!SameTemplateParameterList)
1444-
return true;
1445-
if (!UseMemberUsingDeclRules &&
1446-
(!SameTemplateParameterList || !SameReturnType))
1447-
return true;
1448-
}
1449-
14501450
if (!UseOverrideRules) {
14511451
Expr *NewRC = New->getTrailingRequiresClause(),
14521452
*OldRC = Old->getTrailingRequiresClause();

clang/test/CXX/over/over.load/p2-0x.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ class Y {
2424
void k() &&; // expected-error{{cannot overload a member function with ref-qualifier '&&' with a member function without a ref-qualifier}}
2525
};
2626

27+
struct GH76358 {
28+
template<int> void f() && {}
29+
template<typename T> void f() const {}
30+
};
31+
2732

2833
#if __cplusplus >= 202002L
2934
namespace GH58962 {

0 commit comments

Comments
 (0)