Skip to content

Commit

Permalink
[Clang] Fix IsOverload for function templates
Browse files Browse the repository at this point in the history
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 llvm#76358
  • Loading branch information
cor3ntin committed Jan 8, 2024
1 parent b4ee7d6 commit 1b84a4f
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 37 deletions.
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

0 comments on commit 1b84a4f

Please sign in to comment.