Skip to content

[Clang] Fix IsOverload for function templates #77323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 37 additions & 37 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions clang/test/CXX/over/over.load/p2-0x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down