@@ -1101,12 +1101,8 @@ DeduceTemplateArguments(Sema &S,
1101
1101
S, TemplateParams, Params[ParamIdx].getUnqualifiedType (),
1102
1102
Args[ArgIdx].getUnqualifiedType (), Info, Deduced, TDF,
1103
1103
PartialOrdering,
1104
- /* DeducedFromArrayBound=*/ false )){
1105
- llvm::errs ()<<Result<<" =x" ;
1106
- Args[ArgIdx].dump ();
1107
- Params[ParamIdx].dump ();
1104
+ /* DeducedFromArrayBound=*/ false ))
1108
1105
return Result;
1109
- }
1110
1106
1111
1107
++ArgIdx;
1112
1108
continue ;
@@ -5297,32 +5293,30 @@ bool Sema::CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
5297
5293
return false ;
5298
5294
}
5299
5295
5300
- static void
5301
- AddImplicitObjectParameterTypeCXX20 (ASTContext &Context,
5296
+ static QualType
5297
+ GetImplicitObjectParameterTypeCXX20 (ASTContext &Context,
5302
5298
const CXXMethodDecl *Method,
5303
- bool isOtherRvr ,
5304
- SmallVectorImpl<QualType> &ArgTypes ) {
5299
+ QualType rawType ,
5300
+ bool isOtherRvr ) {
5305
5301
// - The type X(M ) is “rvalue reference to cv A” if the optional ref-qualifier of M is && or if M has no
5306
5302
// ref-qualifier and the positionally-corresponding parameter of the other transformed template has rvalue
5307
5303
// reference type; if this determination depends recursively upon whether X(M ) is an rvalue reference
5308
5304
// type, it is not considered to have rvalue reference type.
5309
5305
// - Otherwise, X(M ) is “lvalue reference to cv A”.
5310
5306
assert (Method && !Method->isExplicitObjectMemberFunction ()&&" " );
5311
5307
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);
5320
5314
}
5321
5315
// / If this is a non-static member function,
5322
- static void
5323
- AddImplicitObjectParameterType (ASTContext &Context,
5316
+ static QualType
5317
+ GetImplicitObjectParameterType (ASTContext &Context,
5324
5318
const CXXMethodDecl *Method,
5325
- SmallVectorImpl< QualType> &ArgTypes ) {
5319
+ QualType rawType ) {
5326
5320
// C++11 [temp.func.order]p3:
5327
5321
// [...] The new parameter is of type "reference to cv A," where cv are
5328
5322
// the cv-qualifiers of the function template (if any) and A is
@@ -5332,13 +5326,11 @@ AddImplicitObjectParameterType(ASTContext &Context,
5332
5326
// reference type based on [over.match.funcs]p4.
5333
5327
assert (Method && Method->isImplicitObjectMemberFunction () &&
5334
5328
" 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 ());
5337
5331
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);
5342
5334
}
5343
5335
5344
5336
// / Determine whether the function template \p FT1 is at least as
@@ -5348,7 +5340,6 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
5348
5340
const FunctionTemplateDecl *FT1,
5349
5341
const FunctionTemplateDecl *FT2,
5350
5342
TemplatePartialOrderingContext TPOC,
5351
- unsigned NumCallArguments1,
5352
5343
bool Reversed,
5353
5344
const SmallVector<QualType, 4 >& Args1,
5354
5345
const SmallVector<QualType, 4 >& Args2) {
@@ -5476,106 +5467,106 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
5476
5467
FunctionTemplateDecl *Sema::getMoreSpecializedTemplate (
5477
5468
FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
5478
5469
TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1,
5479
- unsigned NumCallArguments2, bool Reversed) {
5480
-
5470
+ unsigned NumCallArguments2, QualType RawObjType1, QualType RawObjType2, bool Reversed) {
5481
5471
SmallVector<QualType, 4 > Args1;
5482
5472
SmallVector<QualType, 4 > Args2;
5483
5473
const FunctionDecl *FD1 = FT1->getTemplatedDecl ();
5484
5474
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 ;
5495
5477
QualType ObjType1;
5496
5478
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
+ }
5555
5547
}
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 ());
5556
5564
}
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
-
5574
5565
bool Better1 = isAtLeastAsSpecializedAs (*this , Loc, FT1, FT2, TPOC,
5575
- NumCallArguments1, Reversed,Args1,Args2);
5566
+ Reversed,Args1,Args2);
5576
5567
bool Better2 = isAtLeastAsSpecializedAs (*this , Loc, FT2, FT1, TPOC,
5577
- NumCallArguments2, Reversed,Args2,Args1);
5578
-
5568
+ Reversed,Args2,Args1);
5569
+
5579
5570
// C++ [temp.deduct.partial]p10:
5580
5571
// F is more specialized than G if F is at least as specialized as G and G
5581
5572
// is not at least as specialized as F.
0 commit comments