@@ -1076,6 +1076,7 @@ DeduceTemplateArguments(Sema &S,
1076
1076
// Pi of the respective parameter-type- list of P is compared with the
1077
1077
// corresponding parameter type Ai of the corresponding parameter-type-list
1078
1078
// of A. [...]
1079
+ Sema::TemplateDeductionResult::TDK_NonDeducedMismatch;
1079
1080
unsigned ArgIdx = 0 , ParamIdx = 0 ;
1080
1081
for (; ParamIdx != NumParams; ++ParamIdx) {
1081
1082
// Check argument types.
@@ -5293,10 +5294,31 @@ bool Sema::CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
5293
5294
return false ;
5294
5295
}
5295
5296
5297
+ static void
5298
+ AddImplicitObjectParameterTypeCXX20 (ASTContext &Context,
5299
+ const CXXMethodDecl *Method,
5300
+ bool isOtherRvr,
5301
+ SmallVectorImpl<QualType> &ArgTypes) {
5302
+ // - The type X(M ) is “rvalue reference to cv A” if the optional ref-qualifier of M is && or if M has no
5303
+ // ref-qualifier and the positionally-corresponding parameter of the other transformed template has rvalue
5304
+ // reference type; if this determination depends recursively upon whether X(M ) is an rvalue reference
5305
+ // type, it is not considered to have rvalue reference type.
5306
+ // - Otherwise, X(M ) is “lvalue reference to cv A”.
5307
+ assert (Method && !Method->isExplicitObjectMemberFunction ()&&" " );
5308
+
5309
+ QualType ArgTy = Context.getTypeDeclType (Method->getParent ());
5310
+ ArgTy = Context.getQualifiedType (ArgTy, Method->getMethodQualifiers ());
5311
+ if (Method->getRefQualifier () == RQ_RValue || (isOtherRvr && Method->getRefQualifier ()==RQ_None))
5312
+ ArgTy = Context.getRValueReferenceType (ArgTy);
5313
+ else
5314
+ ArgTy = Context.getLValueReferenceType (ArgTy);
5315
+ ArgTypes.push_back (ArgTy);
5316
+
5317
+ }
5296
5318
// / If this is a non-static member function,
5297
5319
static void
5298
5320
AddImplicitObjectParameterType (ASTContext &Context,
5299
- CXXMethodDecl *Method,
5321
+ const CXXMethodDecl *Method,
5300
5322
SmallVectorImpl<QualType> &ArgTypes) {
5301
5323
// C++11 [temp.func.order]p3:
5302
5324
// [...] The new parameter is of type "reference to cv A," where cv are
@@ -5320,11 +5342,13 @@ AddImplicitObjectParameterType(ASTContext &Context,
5320
5342
// / specialized as \p FT2.
5321
5343
static bool isAtLeastAsSpecializedAs (Sema &S,
5322
5344
SourceLocation Loc,
5323
- FunctionTemplateDecl *FT1,
5324
- FunctionTemplateDecl *FT2,
5345
+ const FunctionTemplateDecl *FT1,
5346
+ const FunctionTemplateDecl *FT2,
5325
5347
TemplatePartialOrderingContext TPOC,
5326
5348
unsigned NumCallArguments1,
5327
- bool Reversed) {
5349
+ bool Reversed,
5350
+ const SmallVector<QualType, 4 >& Args1,
5351
+ const SmallVector<QualType, 4 >& Args2) {
5328
5352
assert (!Reversed || TPOC == TPOC_Call);
5329
5353
5330
5354
FunctionDecl *FD1 = FT1->getTemplatedDecl ();
@@ -5341,66 +5365,8 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
5341
5365
// The types used to determine the ordering depend on the context in which
5342
5366
// the partial ordering is done:
5343
5367
TemplateDeductionInfo Info (Loc);
5344
- SmallVector<QualType, 4 > Args2;
5345
5368
switch (TPOC) {
5346
5369
case TPOC_Call: {
5347
- // - In the context of a function call, the function parameter types are
5348
- // used.
5349
- CXXMethodDecl *Method1 = dyn_cast<CXXMethodDecl>(FD1);
5350
- CXXMethodDecl *Method2 = dyn_cast<CXXMethodDecl>(FD2);
5351
-
5352
- // C++11 [temp.func.order]p3:
5353
- // [...] If only one of the function templates is a non-static
5354
- // member, that function template is considered to have a new
5355
- // first parameter inserted in its function parameter list. The
5356
- // new parameter is of type "reference to cv A," where cv are
5357
- // the cv-qualifiers of the function template (if any) and A is
5358
- // the class of which the function template is a member.
5359
- //
5360
- // Note that we interpret this to mean "if one of the function
5361
- // templates is a non-static member and the other is a non-member";
5362
- // otherwise, the ordering rules for static functions against non-static
5363
- // functions don't make any sense.
5364
- //
5365
- // C++98/03 doesn't have this provision but we've extended DR532 to cover
5366
- // it as wording was broken prior to it.
5367
- SmallVector<QualType, 4 > Args1;
5368
-
5369
- unsigned NumComparedArguments = NumCallArguments1;
5370
-
5371
- if (!Method2 && Method1 && Method1->isImplicitObjectMemberFunction ()) {
5372
- // Compare 'this' from Method1 against first parameter from Method2.
5373
- AddImplicitObjectParameterType (S.Context , Method1, Args1);
5374
- ++NumComparedArguments;
5375
- } else if (!Method1 && Method2 &&
5376
- Method2->isImplicitObjectMemberFunction ()) {
5377
- // Compare 'this' from Method2 against first parameter from Method1.
5378
- AddImplicitObjectParameterType (S.Context , Method2, Args2);
5379
- } else if (Method1 && Method2 && Reversed &&
5380
- Method1->isImplicitObjectMemberFunction () &&
5381
- Method2->isImplicitObjectMemberFunction ()) {
5382
- // Compare 'this' from Method1 against second parameter from Method2
5383
- // and 'this' from Method2 against second parameter from Method1.
5384
- AddImplicitObjectParameterType (S.Context , Method1, Args1);
5385
- AddImplicitObjectParameterType (S.Context , Method2, Args2);
5386
- ++NumComparedArguments;
5387
- }
5388
-
5389
- Args1.insert (Args1.end (), Proto1->param_type_begin (),
5390
- Proto1->param_type_end ());
5391
- Args2.insert (Args2.end (), Proto2->param_type_begin (),
5392
- Proto2->param_type_end ());
5393
-
5394
- // C++ [temp.func.order]p5:
5395
- // The presence of unused ellipsis and default arguments has no effect on
5396
- // the partial ordering of function templates.
5397
- if (Args1.size () > NumComparedArguments)
5398
- Args1.resize (NumComparedArguments);
5399
- if (Args2.size () > NumComparedArguments)
5400
- Args2.resize (NumComparedArguments);
5401
- if (Reversed)
5402
- std::reverse (Args2.begin (), Args2.end ());
5403
-
5404
5370
if (DeduceTemplateArguments (S, TemplateParams, Args2.data (), Args2.size (),
5405
5371
Args1.data (), Args1.size (), Info, Deduced,
5406
5372
TDF_None, /* PartialOrdering=*/ true ))
@@ -5508,11 +5474,97 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
5508
5474
FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
5509
5475
TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1,
5510
5476
unsigned NumCallArguments2, bool Reversed) {
5477
+
5478
+ SmallVector<QualType, 4 > Args1;
5479
+ SmallVector<QualType, 4 > Args2;
5480
+ const FunctionDecl *FD1 = FT1->getTemplatedDecl ();
5481
+ const FunctionDecl *FD2 = FT2->getTemplatedDecl ();
5482
+ const FunctionProtoType *Proto1 = FD1->getType ()->getAs <FunctionProtoType>();
5483
+ const FunctionProtoType *Proto2 = FD2->getType ()->getAs <FunctionProtoType>();
5484
+
5485
+ // - In the context of a function call, the function parameter types are
5486
+ // used.
5487
+ const CXXMethodDecl *Method1 = dyn_cast<CXXMethodDecl>(FD1);
5488
+ const CXXMethodDecl *Method2 = dyn_cast<CXXMethodDecl>(FD2);
5489
+
5490
+ bool shouldConvert1;
5491
+ bool shouldConvert2;
5492
+ if (getLangOpts ().CPlusPlus20 ){
5493
+ // C++20 [temp.func.order]p3
5494
+ // [...] Each function template M that is a member function is considered to have a new first parameter of type
5495
+ // X(M), described below, inserted in its function parameter list.
5496
+ //
5497
+ // Note that we interpret "that is a member function" as
5498
+ // "that is a member function with no expicit object argument".
5499
+ // Otherwise the ordering rules for methods with expicit objet arguments
5500
+ // against anything else make no sense.
5501
+ shouldConvert1= Method1 && !Method1->isExplicitObjectMemberFunction ();
5502
+ shouldConvert2= Method2 && !Method2->isExplicitObjectMemberFunction ();
5503
+ bool isR1=Method1 && !Method1->isExplicitObjectMemberFunction () ?
5504
+ Method1->getRefQualifier () == RQ_RValue:
5505
+ // Proto1->getRefQualifier() ==RQ_RValue;
5506
+ Proto1->param_type_begin ()[0 ]->isRValueReferenceType ();
5507
+ bool isR2=Method2 && !Method2->isExplicitObjectMemberFunction () ?
5508
+ Method2->getRefQualifier () == RQ_RValue:
5509
+ Proto2->param_type_begin ()[0 ]->isRValueReferenceType ();
5510
+ // FD2->getParamDecl(0)->getRefQualifier() ==RQ_RValue;
5511
+ if (shouldConvert1)
5512
+ // Compare 'this' from Method1 against first parameter from Method2.
5513
+ AddImplicitObjectParameterTypeCXX20 (this ->Context , Method1,isR2, Args1);
5514
+ if (shouldConvert2)
5515
+ // Compare 'this' from Method2 against first parameter from Method1.
5516
+ AddImplicitObjectParameterTypeCXX20 (this ->Context , Method2,isR1, Args2);
5517
+ }else {
5518
+ // C++11 [temp.func.order]p3:
5519
+ // [...] If only one of the function templates is a non-static
5520
+ // member, that function template is considered to have a new
5521
+ // first parameter inserted in its function parameter list. The
5522
+ // new parameter is of type "reference to cv A," where cv are
5523
+ // the cv-qualifiers of the function template (if any) and A is
5524
+ // the class of which the function template is a member.
5525
+ //
5526
+ // Note that we interpret this to mean "if one of the function
5527
+ // templates is a non-static member and the other is a non-member";
5528
+ // otherwise, the ordering rules for static functions against non-static
5529
+ // functions don't make any sense.
5530
+ //
5531
+ // C++98/03 doesn't have this provision but we've extended DR532 to cover
5532
+ // it as wording was broken prior to it.
5533
+ shouldConvert1=!Method2 && Method1 && Method1->isImplicitObjectMemberFunction ();
5534
+ shouldConvert2=!Method1 && Method2 && Method2->isImplicitObjectMemberFunction ();
5535
+ if (shouldConvert1)
5536
+ // Compare 'this' from Method1 against first parameter from Method2.
5537
+ AddImplicitObjectParameterType (this ->Context , Method1, Args1);
5538
+ if (shouldConvert2)
5539
+ // Compare 'this' from Method2 against first parameter from Method1.
5540
+ AddImplicitObjectParameterType (this ->Context , Method2, Args2);
5541
+ }
5542
+ unsigned NumComparedArguments = NumCallArguments1 + shouldConvert1;
5543
+
5544
+ Args1.insert (Args1.end (), Proto1->param_type_begin (),
5545
+ Proto1->param_type_end ());
5546
+ Args2.insert (Args2.end (), Proto2->param_type_begin (),
5547
+ Proto2->param_type_end ());
5548
+
5549
+ // C++ [temp.func.order]p5:
5550
+ // The presence of unused ellipsis and default arguments has no effect on
5551
+ // the partial ordering of function templates.
5552
+ if (Args1.size () > NumComparedArguments)
5553
+ Args1.resize (NumComparedArguments);
5554
+ if (Args2.size () > NumComparedArguments)
5555
+ Args2.resize (NumComparedArguments);
5556
+ if (Reversed)
5557
+ std::reverse (Args2.begin (), Args2.end ());
5511
5558
5512
5559
bool Better1 = isAtLeastAsSpecializedAs (*this , Loc, FT1, FT2, TPOC,
5513
- NumCallArguments1, Reversed);
5560
+ NumCallArguments1, Reversed,Args1,Args2 );
5514
5561
bool Better2 = isAtLeastAsSpecializedAs (*this , Loc, FT2, FT1, TPOC,
5515
- NumCallArguments2, Reversed);
5562
+ NumCallArguments2, Reversed,Args2,Args1);
5563
+ FT1->dump ();
5564
+ llvm::errs ()<<" ---\n " ;
5565
+ FT2->dump ();
5566
+ llvm::errs ()<<" ---" <<NumCallArguments1<<" " <<NumCallArguments2<<" \n " ;
5567
+ llvm::errs ()<<" ---" <<Better1<<" " <<Better2<<" \n " ;
5516
5568
5517
5569
// C++ [temp.deduct.partial]p10:
5518
5570
// F is more specialized than G if F is at least as specialized as G and G
@@ -5527,24 +5579,55 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
5527
5579
// ... and if G has a trailing function parameter pack for which F does not
5528
5580
// have a corresponding parameter, and if F does not have a trailing
5529
5581
// function parameter pack, then F is more specialized than G.
5530
- FunctionDecl *FD1 = FT1->getTemplatedDecl ();
5531
- FunctionDecl *FD2 = FT2->getTemplatedDecl ();
5532
- unsigned NumParams1 = FD1->getNumParams ();
5582
+
5583
+ SmallVector<ParmVarDecl*> param1;
5584
+ if (shouldConvert1){
5585
+ param1.push_back ({});// TODO
5586
+ }
5587
+ param1.insert (param1.end (), FD1->parameters ().begin (),
5588
+ FD1->parameters ().end ());
5589
+
5590
+ SmallVector<ParmVarDecl*> param2;
5591
+ if (shouldConvert2){
5592
+ param2.push_back ({});// TODO
5593
+ }
5594
+ param2.insert (param2.end (), FD2->parameters ().begin (),
5595
+ FD2->parameters ().end ());
5596
+
5597
+ unsigned NumParams1 = param1.size ();
5598
+ unsigned NumParams2 = param2.size ();
5599
+ /* unsigned NumParams1 = FD1->getNumParams();
5533
5600
unsigned NumParams2 = FD2->getNumParams();
5601
+
5602
+ if (Method1) {
5603
+ llvm::errs()<<"METHOD1:";
5604
+ Method1->dump();
5605
+ for (const auto& x:Method1->parameters()){
5606
+ x->dump();
5607
+ }
5608
+ llvm::errs()<<"#";
5609
+ Method1->getNonObjectParameter(0)->dump();
5610
+ llvm::errs()<<"=#";
5611
+ Method1->getThisType().dump();
5612
+ llvm::errs()<<"#=";
5613
+ Method1->getType().dump();
5614
+ }*/
5534
5615
bool Variadic1 = NumParams1 && FD1->parameters ().back ()->isParameterPack ();
5535
5616
bool Variadic2 = NumParams2 && FD2->parameters ().back ()->isParameterPack ();
5536
5617
if (Variadic1 != Variadic2) {
5537
- if (Variadic1 && NumParams1 > NumParams2)
5618
+ if (Variadic1 && NumParams1 + shouldConvert1 > NumParams2 + shouldConvert2 )
5538
5619
return FT2;
5539
- if (Variadic2 && NumParams2 > NumParams1)
5620
+ if (Variadic2 && NumParams2 + shouldConvert2 > NumParams1 + shouldConvert1 )
5540
5621
return FT1;
5541
5622
}
5542
5623
5543
5624
// This a speculative fix for CWG1432 (Similar to the fix for CWG1395) that
5544
5625
// there is no wording or even resolution for this issue.
5545
5626
for (int i = 0 , e = std::min (NumParams1, NumParams2); i < e; ++i) {
5546
- QualType T1 = FD1->getParamDecl (i)->getType ().getCanonicalType ();
5547
- QualType T2 = FD2->getParamDecl (i)->getType ().getCanonicalType ();
5627
+ if (!param1[i] || !param2[i])
5628
+ continue ;
5629
+ QualType T1 = param1[i]->getType ().getCanonicalType ();
5630
+ QualType T2 = param2[i]->getType ().getCanonicalType ();
5548
5631
auto *TST1 = dyn_cast<TemplateSpecializationType>(T1);
5549
5632
auto *TST2 = dyn_cast<TemplateSpecializationType>(T2);
5550
5633
if (!TST1 || !TST2)
@@ -5600,9 +5683,10 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
5600
5683
return nullptr ;
5601
5684
5602
5685
for (unsigned i = 0 ; i < NumParams1; ++i)
5603
- if (!Context.hasSameType (FD1->getParamDecl (i)->getType (),
5604
- FD2->getParamDecl (i)->getType ()))
5605
- return nullptr ;
5686
+ if (param1[i] && param2[i])// TODO: write in from args
5687
+ if (!Context.hasSameType (param1[i]->getType (),
5688
+ param2[i]->getType ()))
5689
+ return nullptr ;
5606
5690
5607
5691
// C++20 [temp.func.order]p6.3:
5608
5692
// Otherwise, if the context in which the partial ordering is done is
0 commit comments