[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
This commit is contained in:
cor3ntin
2024-01-08 16:58:48 +01:00
committed by GitHub
parent 34dbaddc6f
commit 69066ab319
2 changed files with 42 additions and 37 deletions

View File

@@ -1259,6 +1259,43 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
if ((OldTemplate == nullptr) != (NewTemplate == nullptr))
return true;
if (NewTemplate) {
// C++ [temp.over.link]p4:
// The signature of a function template consists of its function
// signature, its return type and its template parameter list. The names
// of the template parameters are significant only for establishing the
// relationship between the template parameters and the rest of the
// signature.
//
// We check the return type and template parameter lists for function
// templates first; the remaining checks follow.
bool SameTemplateParameterList = SemaRef.TemplateParameterListsAreEqual(
NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate,
OldTemplate->getTemplateParameters(), false, Sema::TPL_TemplateMatch);
bool SameReturnType = SemaRef.Context.hasSameType(
Old->getDeclaredReturnType(), New->getDeclaredReturnType());
// FIXME(GH58571): Match template parameter list even for non-constrained
// template heads. This currently ensures that the code prior to C++20 is
// not newly broken.
bool ConstraintsInTemplateHead =
NewTemplate->getTemplateParameters()->hasAssociatedConstraints() ||
OldTemplate->getTemplateParameters()->hasAssociatedConstraints();
// C++ [namespace.udecl]p11:
// The set of declarations named by a using-declarator that inhabits a
// class C does not include member functions and member function
// templates of a base class that "correspond" to (and thus would
// conflict with) a declaration of a function or function template in
// C.
// Comparing return types is not required for the "correspond" check to
// decide whether a member introduced by a shadow declaration is hidden.
if (UseMemberUsingDeclRules && ConstraintsInTemplateHead &&
!SameTemplateParameterList)
return true;
if (!UseMemberUsingDeclRules &&
(!SameTemplateParameterList || !SameReturnType))
return true;
}
// Is the function New an overload of the function Old?
QualType OldQType = SemaRef.Context.getCanonicalType(Old->getType());
QualType NewQType = SemaRef.Context.getCanonicalType(New->getType());
@@ -1410,43 +1447,6 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
}
}
if (NewTemplate) {
// C++ [temp.over.link]p4:
// The signature of a function template consists of its function
// signature, its return type and its template parameter list. The names
// of the template parameters are significant only for establishing the
// relationship between the template parameters and the rest of the
// signature.
//
// We check the return type and template parameter lists for function
// templates first; the remaining checks follow.
bool SameTemplateParameterList = SemaRef.TemplateParameterListsAreEqual(
NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate,
OldTemplate->getTemplateParameters(), false, Sema::TPL_TemplateMatch);
bool SameReturnType = SemaRef.Context.hasSameType(
Old->getDeclaredReturnType(), New->getDeclaredReturnType());
// FIXME(GH58571): Match template parameter list even for non-constrained
// template heads. This currently ensures that the code prior to C++20 is
// not newly broken.
bool ConstraintsInTemplateHead =
NewTemplate->getTemplateParameters()->hasAssociatedConstraints() ||
OldTemplate->getTemplateParameters()->hasAssociatedConstraints();
// C++ [namespace.udecl]p11:
// The set of declarations named by a using-declarator that inhabits a
// class C does not include member functions and member function
// templates of a base class that "correspond" to (and thus would
// conflict with) a declaration of a function or function template in
// C.
// Comparing return types is not required for the "correspond" check to
// decide whether a member introduced by a shadow declaration is hidden.
if (UseMemberUsingDeclRules && ConstraintsInTemplateHead &&
!SameTemplateParameterList)
return true;
if (!UseMemberUsingDeclRules &&
(!SameTemplateParameterList || !SameReturnType))
return true;
}
if (!UseOverrideRules) {
Expr *NewRC = New->getTrailingRequiresClause(),
*OldRC = Old->getTrailingRequiresClause();

View File

@@ -24,6 +24,11 @@ class Y {
void k() &&; // expected-error{{cannot overload a member function with ref-qualifier '&&' with a member function without a ref-qualifier}}
};
struct GH76358 {
template<int> void f() && {}
template<typename T> void f() const {}
};
#if __cplusplus >= 202002L
namespace GH58962 {