@@ -10354,23 +10354,27 @@ bool Sema::CheckFunctionTemplateSpecialization(
10354
10354
return false ;
10355
10355
}
10356
10356
10357
- static bool IsMoreConstrainedFunction (Sema &S, FunctionDecl *FD1,
10358
- FunctionDecl *FD2) {
10357
+ FunctionDecl *Sema::getMoreConstrainedFunction (FunctionDecl *FD1,
10358
+ FunctionDecl *FD2) {
10359
+ assert (!FD1->getDescribedTemplate () && !FD2->getDescribedTemplate () &&
10360
+ " not for function templates" );
10361
+ FunctionDecl *F1 = FD1;
10359
10362
if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction ())
10360
- FD1 = MF;
10363
+ F1 = MF;
10364
+ FunctionDecl *F2 = FD2;
10361
10365
if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction ())
10362
- FD2 = MF;
10366
+ F2 = MF;
10363
10367
llvm::SmallVector<const Expr *, 3 > AC1, AC2;
10364
- FD1 ->getAssociatedConstraints (AC1);
10365
- FD2 ->getAssociatedConstraints (AC2);
10368
+ F1 ->getAssociatedConstraints (AC1);
10369
+ F2 ->getAssociatedConstraints (AC2);
10366
10370
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
10367
- if (S. IsAtLeastAsConstrained (FD1 , AC1, FD2 , AC2, AtLeastAsConstrained1))
10368
- return false ;
10369
- if (S. IsAtLeastAsConstrained (FD2 , AC2, FD1 , AC1, AtLeastAsConstrained2))
10370
- return false ;
10371
+ if (IsAtLeastAsConstrained (F1 , AC1, F2 , AC2, AtLeastAsConstrained1))
10372
+ return nullptr ;
10373
+ if (IsAtLeastAsConstrained (F2 , AC2, F1 , AC1, AtLeastAsConstrained2))
10374
+ return nullptr ;
10371
10375
if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
10372
- return false ;
10373
- return AtLeastAsConstrained1;
10376
+ return nullptr ;
10377
+ return AtLeastAsConstrained1 ? FD1 : FD2 ;
10374
10378
}
10375
10379
10376
10380
// / Perform semantic analysis for the given non-template member
@@ -10400,35 +10404,54 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
10400
10404
if (Previous.empty ()) {
10401
10405
// Nowhere to look anyway.
10402
10406
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
10407
+ SmallVector<FunctionDecl *> Candidates;
10408
+ bool Ambiguous = false ;
10403
10409
for (LookupResult::iterator I = Previous.begin (), E = Previous.end ();
10404
10410
I != E; ++I) {
10405
- NamedDecl *D = (*I)->getUnderlyingDecl ();
10406
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
10407
- QualType Adjusted = Function->getType ();
10408
- if (!hasExplicitCallingConv (Adjusted))
10409
- Adjusted = adjustCCAndNoReturn (Adjusted, Method->getType ());
10410
- if (!Context.hasSameType (Adjusted, Method->getType ()))
10411
- continue ;
10412
- if (Method->getTrailingRequiresClause ()) {
10413
- ConstraintSatisfaction Satisfaction;
10414
- if (CheckFunctionConstraints (Method, Satisfaction,
10415
- /* UsageLoc=*/ Member->getLocation (),
10416
- /* ForOverloadResolution=*/ true ) ||
10417
- !Satisfaction.IsSatisfied )
10418
- continue ;
10419
- if (Instantiation &&
10420
- !IsMoreConstrainedFunction (*this , Method,
10421
- cast<CXXMethodDecl>(Instantiation)))
10422
- continue ;
10423
- }
10424
- // This doesn't handle deduced return types, but both function
10425
- // declarations should be undeduced at this point.
10411
+ CXXMethodDecl *Method =
10412
+ dyn_cast<CXXMethodDecl>((*I)->getUnderlyingDecl ());
10413
+ if (!Method)
10414
+ continue ;
10415
+ QualType Adjusted = Function->getType ();
10416
+ if (!hasExplicitCallingConv (Adjusted))
10417
+ Adjusted = adjustCCAndNoReturn (Adjusted, Method->getType ());
10418
+ // This doesn't handle deduced return types, but both function
10419
+ // declarations should be undeduced at this point.
10420
+ if (!Context.hasSameType (Adjusted, Function->getType ()))
10421
+ continue ;
10422
+ // FIXME: What if neither function is more constrained than the other?
10423
+ if (ConstraintSatisfaction Satisfaction;
10424
+ Method->getTrailingRequiresClause () &&
10425
+ (CheckFunctionConstraints (Method, Satisfaction,
10426
+ /* UsageLoc=*/ Member->getLocation (),
10427
+ /* ForOverloadResolution=*/ true ) ||
10428
+ !Satisfaction.IsSatisfied ))
10429
+ continue ;
10430
+ Candidates.push_back (Method);
10431
+ FunctionDecl *MoreConstrained =
10432
+ Instantiation ? getMoreConstrainedFunction (
10433
+ Method, cast<FunctionDecl>(Instantiation))
10434
+ : Method;
10435
+ if (!MoreConstrained) {
10436
+ Ambiguous = true ;
10437
+ continue ;
10438
+ }
10439
+ if (MoreConstrained == Method) {
10440
+ Ambiguous = false ;
10426
10441
FoundInstantiation = *I;
10427
10442
Instantiation = Method;
10428
10443
InstantiatedFrom = Method->getInstantiatedFromMemberFunction ();
10429
10444
MSInfo = Method->getMemberSpecializationInfo ();
10430
10445
}
10431
10446
}
10447
+ if (Ambiguous) {
10448
+ Diag (Member->getLocation (), diag::err_function_member_spec_ambiguous)
10449
+ << Member;
10450
+ for (FunctionDecl *Candidate : Candidates)
10451
+ Diag (Candidate->getLocation (), diag::note_function_member_spec_matched)
10452
+ << Candidate;
10453
+ return true ;
10454
+ }
10432
10455
} else if (isa<VarDecl>(Member)) {
10433
10456
VarDecl *PrevVar;
10434
10457
if (Previous.isSingleResult () &&
0 commit comments