Skip to content

Commit c624dc9

Browse files
committed
bugfix 3
1 parent e2d16a1 commit c624dc9

File tree

3 files changed

+114
-118
lines changed

3 files changed

+114
-118
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9458,7 +9458,8 @@ class Sema final {
94589458
FunctionTemplateDecl *getMoreSpecializedTemplate(
94599459
FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
94609460
TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1,
9461-
unsigned NumCallArguments2, bool Reversed = false);
9461+
unsigned NumCallArguments2, QualType ObjType1={},
9462+
QualType ObjType2={}, bool Reversed = false);
94629463
UnresolvedSetIterator
94639464
getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
94649465
TemplateSpecCandidateSet &FailedCandidates,

clang/lib/Sema/SemaOverload.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10516,12 +10516,16 @@ bool clang::isBetterOverloadCandidate(
1051610516
// according to the partial ordering rules described in 14.5.5.2, or,
1051710517
// if not that,
1051810518
if (Cand1IsSpecialization && Cand2IsSpecialization) {
10519+
auto* ObjContext1=dyn_cast<CXXRecordDecl>(Cand1.FoundDecl->getDeclContext());
10520+
auto* ObjContext2=dyn_cast<CXXRecordDecl>(Cand2.FoundDecl->getDeclContext());
1051910521
if (FunctionTemplateDecl *BetterTemplate = S.getMoreSpecializedTemplate(
1052010522
Cand1.Function->getPrimaryTemplate(),
1052110523
Cand2.Function->getPrimaryTemplate(), Loc,
1052210524
isa<CXXConversionDecl>(Cand1.Function) ? TPOC_Conversion
1052310525
: TPOC_Call,
1052410526
Cand1.ExplicitCallArguments, Cand2.ExplicitCallArguments,
10527+
ObjContext1?QualType(ObjContext1->getTypeForDecl(),0):QualType{},
10528+
ObjContext2?QualType(ObjContext2->getTypeForDecl(),0):QualType{},
1052510529
Cand1.isReversed() ^ Cand2.isReversed())){
1052610530
if (LLVM_UNLIKELY(!S.OverloadInspectionCallbacks.empty()))
1052710531
atCompareOverloadEnd(S.OverloadInspectionCallbacks,S,Loc,Cand1,Cand2,

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 108 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,12 +1101,8 @@ DeduceTemplateArguments(Sema &S,
11011101
S, TemplateParams, Params[ParamIdx].getUnqualifiedType(),
11021102
Args[ArgIdx].getUnqualifiedType(), Info, Deduced, TDF,
11031103
PartialOrdering,
1104-
/*DeducedFromArrayBound=*/false)){
1105-
llvm::errs()<<Result<<"=x";
1106-
Args[ArgIdx].dump();
1107-
Params[ParamIdx].dump();
1104+
/*DeducedFromArrayBound=*/false))
11081105
return Result;
1109-
}
11101106

11111107
++ArgIdx;
11121108
continue;
@@ -5297,32 +5293,30 @@ bool Sema::CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
52975293
return false;
52985294
}
52995295

5300-
static void
5301-
AddImplicitObjectParameterTypeCXX20(ASTContext &Context,
5296+
static QualType
5297+
GetImplicitObjectParameterTypeCXX20(ASTContext &Context,
53025298
const CXXMethodDecl *Method,
5303-
bool isOtherRvr,
5304-
SmallVectorImpl<QualType> &ArgTypes) {
5299+
QualType rawType,
5300+
bool isOtherRvr) {
53055301
//- The type X(M ) is “rvalue reference to cv A” if the optional ref-qualifier of M is && or if M has no
53065302
// ref-qualifier and the positionally-corresponding parameter of the other transformed template has rvalue
53075303
// reference type; if this determination depends recursively upon whether X(M ) is an rvalue reference
53085304
// type, it is not considered to have rvalue reference type.
53095305
//- Otherwise, X(M ) is “lvalue reference to cv A”.
53105306
assert(Method && !Method->isExplicitObjectMemberFunction()&&" ");
53115307

5312-
QualType ArgTy = Context.getTypeDeclType(Method->getParent());
5313-
ArgTy = Context.getQualifiedType(ArgTy, Method->getMethodQualifiers());
5314-
if (Method->getRefQualifier() == RQ_RValue || (isOtherRvr && Method->getRefQualifier()==RQ_None))
5315-
ArgTy = Context.getRValueReferenceType(ArgTy);
5316-
else
5317-
ArgTy = Context.getLValueReferenceType(ArgTy);
5318-
ArgTypes.push_back(ArgTy);
5319-
5308+
//QualType ArgTy = Context.getTypeDeclType(Method->getParent());
5309+
rawType = Context.getQualifiedType(rawType, Method->getMethodQualifiers());
5310+
if (Method->getRefQualifier() == RQ_RValue ||
5311+
(isOtherRvr && Method->getRefQualifier()==RQ_None))
5312+
return Context.getRValueReferenceType(rawType);
5313+
return Context.getLValueReferenceType(rawType);
53205314
}
53215315
/// If this is a non-static member function,
5322-
static void
5323-
AddImplicitObjectParameterType(ASTContext &Context,
5316+
static QualType
5317+
GetImplicitObjectParameterType(ASTContext &Context,
53245318
const CXXMethodDecl *Method,
5325-
SmallVectorImpl<QualType> &ArgTypes) {
5319+
QualType rawType) {
53265320
// C++11 [temp.func.order]p3:
53275321
// [...] The new parameter is of type "reference to cv A," where cv are
53285322
// the cv-qualifiers of the function template (if any) and A is
@@ -5332,13 +5326,11 @@ AddImplicitObjectParameterType(ASTContext &Context,
53325326
// reference type based on [over.match.funcs]p4.
53335327
assert(Method && Method->isImplicitObjectMemberFunction() &&
53345328
"expected an implicit objet function");
5335-
QualType ArgTy = Context.getTypeDeclType(Method->getParent());
5336-
ArgTy = Context.getQualifiedType(ArgTy, Method->getMethodQualifiers());
5329+
//QualType ArgTy = Context.getTypeDeclType(Method->getParent());
5330+
rawType = Context.getQualifiedType(rawType, Method->getMethodQualifiers());
53375331
if (Method->getRefQualifier() == RQ_RValue)
5338-
ArgTy = Context.getRValueReferenceType(ArgTy);
5339-
else
5340-
ArgTy = Context.getLValueReferenceType(ArgTy);
5341-
ArgTypes.push_back(ArgTy);
5332+
return Context.getRValueReferenceType(rawType);
5333+
return Context.getLValueReferenceType(rawType);
53425334
}
53435335

53445336
/// Determine whether the function template \p FT1 is at least as
@@ -5348,7 +5340,6 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
53485340
const FunctionTemplateDecl *FT1,
53495341
const FunctionTemplateDecl *FT2,
53505342
TemplatePartialOrderingContext TPOC,
5351-
unsigned NumCallArguments1,
53525343
bool Reversed,
53535344
const SmallVector<QualType, 4>& Args1,
53545345
const SmallVector<QualType, 4>& Args2) {
@@ -5476,106 +5467,106 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
54765467
FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
54775468
FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
54785469
TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1,
5479-
unsigned NumCallArguments2, bool Reversed) {
5480-
5470+
unsigned NumCallArguments2, QualType RawObjType1, QualType RawObjType2, bool Reversed) {
54815471
SmallVector<QualType, 4> Args1;
54825472
SmallVector<QualType, 4> Args2;
54835473
const FunctionDecl *FD1 = FT1->getTemplatedDecl();
54845474
const FunctionDecl *FD2 = FT2->getTemplatedDecl();
5485-
const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
5486-
const FunctionProtoType *Proto2 = FD2->getType()->getAs<FunctionProtoType>();
5487-
5488-
// - In the context of a function call, the function parameter types are
5489-
// used.
5490-
const CXXMethodDecl *Method1 = dyn_cast<CXXMethodDecl>(FD1);
5491-
const CXXMethodDecl *Method2 = dyn_cast<CXXMethodDecl>(FD2);
5492-
5493-
bool shouldConvert1;
5494-
bool shouldConvert2;
5475+
bool shouldConvert1=false;
5476+
bool shouldConvert2=false;
54955477
QualType ObjType1;
54965478
QualType ObjType2;
5497-
if (getLangOpts().CPlusPlus20){
5498-
// C++20 [temp.func.order]p3
5499-
// [...] Each function template M that is a member function is considered to have a new first parameter of type
5500-
// X(M), described below, inserted in its function parameter list.
5501-
//
5502-
// Note that we interpret "that is a member function" as
5503-
// "that is a member function with no expicit object argument".
5504-
// Otherwise the ordering rules for methods with expicit objet arguments
5505-
// against anything else make no sense.
5506-
shouldConvert1= Method1 && !Method1->isExplicitObjectMemberFunction();
5507-
shouldConvert2= Method2 && !Method2->isExplicitObjectMemberFunction();
5508-
if (shouldConvert1 && shouldConvert2 && !Reversed){
5509-
shouldConvert1=false;
5510-
shouldConvert2=false;
5511-
}
5512-
if (shouldConvert1){
5513-
bool isR2=Method2 && !Method2->isExplicitObjectMemberFunction() ?
5514-
Method2->getRefQualifier() == RQ_RValue:
5515-
Proto2->param_type_begin()[0]->isRValueReferenceType();
5516-
// Compare 'this' from Method1 against first parameter from Method2.
5517-
AddImplicitObjectParameterTypeCXX20(this->Context, Method1,isR2, Args1);
5518-
ObjType1=Args1[0];
5519-
}
5520-
if (shouldConvert2) {
5521-
bool isR1=Method1 && !Method1->isExplicitObjectMemberFunction() ?
5522-
Method1->getRefQualifier() == RQ_RValue:
5523-
Proto1->param_type_begin()[0]->isRValueReferenceType();
5524-
// Compare 'this' from Method2 against first parameter from Method1.
5525-
AddImplicitObjectParameterTypeCXX20(this->Context, Method2,isR1, Args2);
5526-
ObjType2=Args2[0];
5527-
}
5528-
}else{
5529-
// C++11 [temp.func.order]p3:
5530-
// [...] If only one of the function templates is a non-static
5531-
// member, that function template is considered to have a new
5532-
// first parameter inserted in its function parameter list. The
5533-
// new parameter is of type "reference to cv A," where cv are
5534-
// the cv-qualifiers of the function template (if any) and A is
5535-
// the class of which the function template is a member.
5536-
//
5537-
// Note that we interpret this to mean "if one of the function
5538-
// templates is a non-static member and the other is a non-member";
5539-
// otherwise, the ordering rules for static functions against non-static
5540-
// functions don't make any sense.
5541-
//
5542-
// C++98/03 doesn't have this provision but we've extended DR532 to cover
5543-
// it as wording was broken prior to it.
5544-
shouldConvert1=!Method2 && Method1 && Method1->isImplicitObjectMemberFunction();
5545-
shouldConvert2=!Method1 && Method2 && Method2->isImplicitObjectMemberFunction();
5546-
if (shouldConvert1){
5547-
// Compare 'this' from Method1 against first parameter from Method2.
5548-
AddImplicitObjectParameterType(this->Context, Method1, Args1);
5549-
ObjType1=Args1[0];
5550-
}
5551-
if (shouldConvert2){
5552-
// Compare 'this' from Method2 against first parameter from Method1.
5553-
AddImplicitObjectParameterType(this->Context, Method2, Args2);
5554-
ObjType2=Args2[0];
5479+
if (TPOC==TPOC_Call){
5480+
const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
5481+
const FunctionProtoType *Proto2 = FD2->getType()->getAs<FunctionProtoType>();
5482+
5483+
// - In the context of a function call, the function parameter types are
5484+
// used.
5485+
const CXXMethodDecl *Method1 = dyn_cast<CXXMethodDecl>(FD1);
5486+
const CXXMethodDecl *Method2 = dyn_cast<CXXMethodDecl>(FD2);
5487+
5488+
if (getLangOpts().CPlusPlus20){
5489+
// C++20 [temp.func.order]p3
5490+
// [...] Each function template M that is a member function is considered to have a new first parameter of type
5491+
// X(M), described below, inserted in its function parameter list.
5492+
//
5493+
// Note that we interpret "that is a member function" as
5494+
// "that is a member function with no expicit object argument".
5495+
// Otherwise the ordering rules for methods with expicit objet arguments
5496+
// against anything else make no sense.
5497+
shouldConvert1= Method1 && !Method1->isExplicitObjectMemberFunction();
5498+
shouldConvert2= Method2 && !Method2->isExplicitObjectMemberFunction();
5499+
/*if (shouldConvert1 && shouldConvert2 && !Reversed){
5500+
shouldConvert1=false;
5501+
shouldConvert2=false;
5502+
}*/
5503+
if (shouldConvert1){
5504+
bool isR2=Method2 && !Method2->isExplicitObjectMemberFunction() ?
5505+
Method2->getRefQualifier() == RQ_RValue:
5506+
Proto2->param_type_begin()[0]->isRValueReferenceType();
5507+
// Compare 'this' from Method1 against first parameter from Method2.
5508+
ObjType1=GetImplicitObjectParameterTypeCXX20(this->Context, Method1,RawObjType1 ,isR2);
5509+
Args1.push_back(ObjType1);
5510+
}
5511+
if (shouldConvert2) {
5512+
bool isR1=Method1 && !Method1->isExplicitObjectMemberFunction() ?
5513+
Method1->getRefQualifier() == RQ_RValue:
5514+
Proto1->param_type_begin()[0]->isRValueReferenceType();
5515+
// Compare 'this' from Method2 against first parameter from Method1.
5516+
ObjType2=GetImplicitObjectParameterTypeCXX20(this->Context, Method2,RawObjType2 ,isR1);
5517+
Args2.push_back(ObjType2);
5518+
}
5519+
}else{
5520+
// C++11 [temp.func.order]p3:
5521+
// [...] If only one of the function templates is a non-static
5522+
// member, that function template is considered to have a new
5523+
// first parameter inserted in its function parameter list. The
5524+
// new parameter is of type "reference to cv A," where cv are
5525+
// the cv-qualifiers of the function template (if any) and A is
5526+
// the class of which the function template is a member.
5527+
//
5528+
// Note that we interpret this to mean "if one of the function
5529+
// templates is a non-static member and the other is a non-member";
5530+
// otherwise, the ordering rules for static functions against non-static
5531+
// functions don't make any sense.
5532+
//
5533+
// C++98/03 doesn't have this provision but we've extended DR532 to cover
5534+
// it as wording was broken prior to it.
5535+
shouldConvert1=!Method2 && Method1 && Method1->isImplicitObjectMemberFunction();
5536+
shouldConvert2=!Method1 && Method2 && Method2->isImplicitObjectMemberFunction();
5537+
if (shouldConvert1){
5538+
// Compare 'this' from Method1 against first parameter from Method2.
5539+
ObjType1=GetImplicitObjectParameterType(this->Context, Method1, RawObjType1);
5540+
Args1.push_back(ObjType1);
5541+
}
5542+
if (shouldConvert2){
5543+
// Compare 'this' from Method2 against first parameter from Method1.
5544+
ObjType2=GetImplicitObjectParameterType(this->Context, Method2, RawObjType2);
5545+
Args2.push_back(ObjType2);
5546+
}
55555547
}
5548+
unsigned NumComparedArguments = NumCallArguments1 + shouldConvert1;
5549+
5550+
Args1.insert(Args1.end(), Proto1->param_type_begin(),
5551+
Proto1->param_type_end());
5552+
Args2.insert(Args2.end(), Proto2->param_type_begin(),
5553+
Proto2->param_type_end());
5554+
5555+
// C++ [temp.func.order]p5:
5556+
// The presence of unused ellipsis and default arguments has no effect on
5557+
// the partial ordering of function templates.
5558+
if (Args1.size() > NumComparedArguments)
5559+
Args1.resize(NumComparedArguments);
5560+
if (Args2.size() > NumComparedArguments)
5561+
Args2.resize(NumComparedArguments);
5562+
if (Reversed)
5563+
std::reverse(Args2.begin(), Args2.end());
55565564
}
5557-
unsigned NumComparedArguments = NumCallArguments1 + shouldConvert1;
5558-
5559-
Args1.insert(Args1.end(), Proto1->param_type_begin(),
5560-
Proto1->param_type_end());
5561-
Args2.insert(Args2.end(), Proto2->param_type_begin(),
5562-
Proto2->param_type_end());
5563-
5564-
// C++ [temp.func.order]p5:
5565-
// The presence of unused ellipsis and default arguments has no effect on
5566-
// the partial ordering of function templates.
5567-
if (Args1.size() > NumComparedArguments)
5568-
Args1.resize(NumComparedArguments);
5569-
if (Args2.size() > NumComparedArguments)
5570-
Args2.resize(NumComparedArguments);
5571-
if (Reversed)
5572-
std::reverse(Args2.begin(), Args2.end());
5573-
55745565
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
5575-
NumCallArguments1, Reversed,Args1,Args2);
5566+
Reversed,Args1,Args2);
55765567
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
5577-
NumCallArguments2, Reversed,Args2,Args1);
5578-
5568+
Reversed,Args2,Args1);
5569+
55795570
// C++ [temp.deduct.partial]p10:
55805571
// F is more specialized than G if F is at least as specialized as G and G
55815572
// is not at least as specialized as F.

0 commit comments

Comments
 (0)