Skip to content

[clang] correct argument offset for function template partial ordering #107972

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
Sep 10, 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
28 changes: 14 additions & 14 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5502,10 +5502,6 @@ static TemplateDeductionResult CheckDeductionConsistency(
ArrayRef<TemplateArgument> DeducedArgs, bool CheckConsistency) {
MultiLevelTemplateArgumentList MLTAL(FTD, DeducedArgs,
/*Final=*/true);
if (ArgIdx != -1)
if (auto *MD = dyn_cast<CXXMethodDecl>(FTD->getTemplatedDecl());
MD && MD->isImplicitObjectMemberFunction())
ArgIdx -= 1;
Sema::ArgumentPackSubstitutionIndexRAII PackIndex(
S, ArgIdx != -1 ? ::getPackIndexForParam(S, FTD, MLTAL, ArgIdx) : -1);
bool IsIncompleteSubstitution = false;
Expand Down Expand Up @@ -5576,12 +5572,10 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(

/// Determine whether the function template \p FT1 is at least as
/// specialized as \p FT2.
static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc,
FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC,
ArrayRef<QualType> Args1,
ArrayRef<QualType> Args2) {
static bool isAtLeastAsSpecializedAs(
Sema &S, SourceLocation Loc, FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2, TemplatePartialOrderingContext TPOC,
ArrayRef<QualType> Args1, ArrayRef<QualType> Args2, bool Args1Offset) {
FunctionDecl *FD1 = FT1->getTemplatedDecl();
FunctionDecl *FD2 = FT2->getTemplatedDecl();
const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
Expand Down Expand Up @@ -5676,6 +5670,8 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
PartialOrderingKind) {
if (ArgIdx != -1)
ArgIdx -= Args1Offset;
return ::CheckDeductionConsistency(
S, FTD, ArgIdx, P, A, DeducedArgs,
/*CheckConsistency=*/HasDeducedParam[ParamIdx]);
Expand Down Expand Up @@ -5763,6 +5759,8 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
const FunctionDecl *FD2 = FT2->getTemplatedDecl();
bool ShouldConvert1 = false;
bool ShouldConvert2 = false;
bool Args1Offset = false;
bool Args2Offset = false;
QualType Obj1Ty;
QualType Obj2Ty;
if (TPOC == TPOC_Call) {
Expand Down Expand Up @@ -5811,6 +5809,7 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
Obj1Ty = GetImplicitObjectParameterType(this->Context, Method1,
RawObj1Ty, IsRValRef2);
Args1.push_back(Obj1Ty);
Args1Offset = true;
}
if (ShouldConvert2) {
bool IsRValRef1 =
Expand All @@ -5821,6 +5820,7 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
Obj2Ty = GetImplicitObjectParameterType(this->Context, Method2,
RawObj2Ty, IsRValRef1);
Args2.push_back(Obj2Ty);
Args2Offset = true;
}
} else {
if (NonStaticMethod1 && Method1->hasCXXExplicitFunctionObjectParameter())
Expand All @@ -5842,10 +5842,10 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
} else {
assert(!Reversed && "Only call context could have reversed arguments");
}
bool Better1 =
isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, Args1, Args2);
bool Better2 =
isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, Args2, Args1);
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, Args1,
Args2, Args2Offset);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, Args2,
Args1, Args1Offset);
// C++ [temp.deduct.partial]p10:
// F is more specialized than G if F is at least as specialized as G and G
// is not at least as specialized as F.
Expand Down
27 changes: 26 additions & 1 deletion clang/test/SemaTemplate/GH18291.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,29 @@ namespace func_pointer {
template <class _Tp> void pow(_Tp, complex<typename __promote<_Tp>::type>) = delete;
void (*ptr)(const complex<float> &, complex<float>){pow};
} // namespace param
} // namespace t3
} // namespace func_pointer

namespace static_vs_nonstatic {
namespace implicit_obj_param {
struct A {
template <class... Args>
static void f(int a, Args... args) {}
template <class... Args>
void f(Args... args) = delete;
};
void g(){
A::f(0);
}
} // namespace implicit_obj_param
namespace explicit_obj_param {
struct A {
template <class... Args>
static void f(int, Args... args) {}
template <class... Args>
void f(this A *, Args... args) = delete;
};
void g(){
A::f(0);
}
} // namespace explicit_obj_param
} // namespace static_vs_nonstatic
Loading