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