Skip to content

Commit 70f59b5

Browse files
committed
When diagnosing an ambiguity, only note the candidates that contribute
to the ambiguity, rather than noting all viable candidates.
1 parent 33fca97 commit 70f59b5

24 files changed

+140
-101
lines changed

clang/include/clang/Sema/Overload.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ class Sema;
6868
OCD_AllCandidates,
6969

7070
/// Requests that only viable candidates be shown.
71-
OCD_ViableCandidates
71+
OCD_ViableCandidates,
72+
73+
/// Requests that only tied-for-best candidates be shown.
74+
OCD_AmbiguousCandidates
7275
};
7376

7477
/// The parameter ordering that will be used for the candidate. This is
@@ -791,6 +794,15 @@ class Sema;
791794
/// Viable - True to indicate that this overload candidate is viable.
792795
bool Viable : 1;
793796

797+
/// Whether this candidate is the best viable function, or tied for being
798+
/// the best viable function.
799+
///
800+
/// For an ambiguous overload resolution, indicates whether this candidate
801+
/// was part of the ambiguity kernel: the minimal non-empty set of viable
802+
/// candidates such that all elements of the ambiguity kernel are better
803+
/// than all viable candidates not in the ambiguity kernel.
804+
bool Best : 1;
805+
794806
/// IsSurrogate - True to indicate that this candidate is a
795807
/// surrogate for a conversion to a function pointer or reference
796808
/// (C++ [over.call.object]).

clang/lib/Sema/SemaCast.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
423423

424424
case OR_Ambiguous:
425425
msg = diag::err_ovl_ambiguous_conversion_in_cast;
426-
howManyCandidates = OCD_ViableCandidates;
426+
howManyCandidates = OCD_AmbiguousCandidates;
427427
break;
428428

429429
case OR_Deleted:

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2323,7 +2323,7 @@ static bool resolveAllocationOverload(
23232323
PartialDiagnosticAt(R.getNameLoc(),
23242324
S.PDiag(diag::err_ovl_ambiguous_call)
23252325
<< R.getLookupName() << Range),
2326-
S, OCD_ViableCandidates, Args);
2326+
S, OCD_AmbiguousCandidates, Args);
23272327
}
23282328
return true;
23292329

@@ -3513,7 +3513,7 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall,
35133513
PartialDiagnosticAt(R.getNameLoc(),
35143514
S.PDiag(diag::err_ovl_ambiguous_call)
35153515
<< R.getLookupName() << Range),
3516-
S, OCD_ViableCandidates, Args);
3516+
S, OCD_AmbiguousCandidates, Args);
35173517
return true;
35183518

35193519
case OR_Deleted: {

clang/lib/Sema/SemaInit.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6154,7 +6154,7 @@ static ExprResult CopyObject(Sema &S,
61546154
<< (int)Entity.getKind()
61556155
<< CurInitExpr->getType()
61566156
<< CurInitExpr->getSourceRange()),
6157-
S, OCD_ViableCandidates, CurInitExpr);
6157+
S, OCD_AmbiguousCandidates, CurInitExpr);
61586158
return ExprError();
61596159

61606160
case OR_Deleted:
@@ -6295,7 +6295,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
62956295

62966296
case OR_Ambiguous:
62976297
CandidateSet.NoteCandidates(PartialDiagnosticAt(Loc, Diag), S,
6298-
OCD_ViableCandidates, CurInitExpr);
6298+
OCD_AmbiguousCandidates, CurInitExpr);
62996299
break;
63006300

63016301
case OR_Deleted:
@@ -8806,7 +8806,7 @@ bool InitializationSequence::Diagnose(Sema &S,
88068806
: (S.PDiag(diag::err_ref_init_ambiguous)
88078807
<< DestType << OnlyArg->getType()
88088808
<< Args[0]->getSourceRange())),
8809-
S, OCD_ViableCandidates, Args);
8809+
S, OCD_AmbiguousCandidates, Args);
88108810
break;
88118811

88128812
case OR_No_Viable_Function: {
@@ -9000,7 +9000,7 @@ bool InitializationSequence::Diagnose(Sema &S,
90009000
PartialDiagnosticAt(Kind.getLocation(),
90019001
S.PDiag(diag::err_ovl_ambiguous_init)
90029002
<< DestType << ArgsRange),
9003-
S, OCD_ViableCandidates, Args);
9003+
S, OCD_AmbiguousCandidates, Args);
90049004
break;
90059005

90069006
case OR_No_Viable_Function:
@@ -9863,7 +9863,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
98639863
Kind.getLocation(),
98649864
PDiag(diag::err_deduced_class_template_ctor_ambiguous)
98659865
<< TemplateName),
9866-
*this, OCD_ViableCandidates, Inits);
9866+
*this, OCD_AmbiguousCandidates, Inits);
98679867
return QualType();
98689868

98699869
case OR_No_Viable_Function: {

clang/lib/Sema/SemaOverload.cpp

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,7 +1357,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
13571357
ICS.Ambiguous.setToType(ToType);
13581358
for (OverloadCandidateSet::iterator Cand = Conversions.begin();
13591359
Cand != Conversions.end(); ++Cand)
1360-
if (Cand->Viable)
1360+
if (Cand->Best)
13611361
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
13621362
break;
13631363

@@ -3578,7 +3578,10 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
35783578
(OvResult == OR_No_Viable_Function && !CandidateSet.empty())))
35793579
return false;
35803580

3581-
auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates, From);
3581+
auto Cands = CandidateSet.CompleteCandidates(
3582+
*this,
3583+
OvResult == OR_Ambiguous ? OCD_AmbiguousCandidates : OCD_AllCandidates,
3584+
From);
35823585
if (OvResult == OR_Ambiguous)
35833586
Diag(From->getBeginLoc(), diag::err_typecheck_ambiguous_condition)
35843587
<< From->getType() << ToType << From->getSourceRange();
@@ -4602,7 +4605,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
46024605
ICS.setAmbiguous();
46034606
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
46044607
Cand != CandidateSet.end(); ++Cand)
4605-
if (Cand->Viable)
4608+
if (Cand->Best)
46064609
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
46074610
return true;
46084611

@@ -9653,34 +9656,47 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
96539656

96549657
// Find the best viable function.
96559658
Best = end();
9656-
for (auto *Cand : Candidates)
9659+
for (auto *Cand : Candidates) {
9660+
Cand->Best = false;
96579661
if (Cand->Viable)
96589662
if (Best == end() ||
96599663
isBetterOverloadCandidate(S, *Cand, *Best, Loc, Kind))
96609664
Best = Cand;
9665+
}
96619666

96629667
// If we didn't find any viable functions, abort.
96639668
if (Best == end())
96649669
return OR_No_Viable_Function;
96659670

96669671
llvm::SmallVector<const NamedDecl *, 4> EquivalentCands;
96679672

9673+
llvm::SmallVector<OverloadCandidate*, 4> PendingBest;
9674+
PendingBest.push_back(&*Best);
9675+
Best->Best = true;
9676+
96689677
// Make sure that this function is better than every other viable
96699678
// function. If not, we have an ambiguity.
9670-
for (auto *Cand : Candidates) {
9671-
if (Cand->Viable && Cand != Best &&
9672-
!isBetterOverloadCandidate(S, *Best, *Cand, Loc, Kind)) {
9673-
if (S.isEquivalentInternalLinkageDeclaration(Best->Function,
9674-
Cand->Function)) {
9675-
EquivalentCands.push_back(Cand->Function);
9676-
continue;
9679+
while (!PendingBest.empty()) {
9680+
auto *Curr = PendingBest.pop_back_val();
9681+
for (auto *Cand : Candidates) {
9682+
if (Cand->Viable && !Cand->Best &&
9683+
!isBetterOverloadCandidate(S, *Curr, *Cand, Loc, Kind)) {
9684+
PendingBest.push_back(Cand);
9685+
Cand->Best = true;
9686+
9687+
if (S.isEquivalentInternalLinkageDeclaration(Cand->Function,
9688+
Curr->Function))
9689+
EquivalentCands.push_back(Cand->Function);
9690+
else
9691+
Best = end();
96779692
}
9678-
9679-
Best = end();
9680-
return OR_Ambiguous;
96819693
}
96829694
}
96839695

9696+
// If we found more than one best candidate, this is ambiguous.
9697+
if (Best == end())
9698+
return OR_Ambiguous;
9699+
96849700
// Best is the best viable function.
96859701
if (Best->Function && Best->Function->isDeleted())
96869702
return OR_Deleted;
@@ -11080,15 +11096,30 @@ SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates(
1108011096
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
1108111097
if (!Filter(*Cand))
1108211098
continue;
11083-
if (Cand->Viable)
11084-
Cands.push_back(Cand);
11085-
else if (OCD == OCD_AllCandidates) {
11086-
CompleteNonViableCandidate(S, Cand, Args, Kind);
11087-
if (Cand->Function || Cand->IsSurrogate)
11088-
Cands.push_back(Cand);
11089-
// Otherwise, this a non-viable builtin candidate. We do not, in general,
11090-
// want to list every possible builtin candidate.
11099+
switch (OCD) {
11100+
case OCD_AllCandidates:
11101+
if (!Cand->Viable) {
11102+
if (!Cand->Function && !Cand->IsSurrogate) {
11103+
// This a non-viable builtin candidate. We do not, in general,
11104+
// want to list every possible builtin candidate.
11105+
continue;
11106+
}
11107+
CompleteNonViableCandidate(S, Cand, Args, Kind);
11108+
}
11109+
break;
11110+
11111+
case OCD_ViableCandidates:
11112+
if (!Cand->Viable)
11113+
continue;
11114+
break;
11115+
11116+
case OCD_AmbiguousCandidates:
11117+
if (!Cand->Best)
11118+
continue;
11119+
break;
1109111120
}
11121+
11122+
Cands.push_back(Cand);
1109211123
}
1109311124

1109411125
llvm::stable_sort(
@@ -12453,7 +12484,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
1245312484
PartialDiagnosticAt(Fn->getBeginLoc(),
1245412485
SemaRef.PDiag(diag::err_ovl_ambiguous_call)
1245512486
<< ULE->getName() << Fn->getSourceRange()),
12456-
SemaRef, OCD_ViableCandidates, Args);
12487+
SemaRef, OCD_AmbiguousCandidates, Args);
1245712488
break;
1245812489

1245912490
case OR_Deleted: {
@@ -12699,7 +12730,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
1269912730
PDiag(diag::err_ovl_ambiguous_oper_unary)
1270012731
<< UnaryOperator::getOpcodeStr(Opc)
1270112732
<< Input->getType() << Input->getSourceRange()),
12702-
*this, OCD_ViableCandidates, ArgsArray,
12733+
*this, OCD_AmbiguousCandidates, ArgsArray,
1270312734
UnaryOperator::getOpcodeStr(Opc), OpLoc);
1270412735
return ExprError();
1270512736

@@ -13108,7 +13139,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
1310813139
<< Args[1]->getType()
1310913140
<< Args[0]->getSourceRange()
1311013141
<< Args[1]->getSourceRange()),
13111-
*this, OCD_ViableCandidates, Args, BinaryOperator::getOpcodeStr(Opc),
13142+
*this, OCD_AmbiguousCandidates, Args, BinaryOperator::getOpcodeStr(Opc),
1311213143
OpLoc);
1311313144
return ExprError();
1311413145

@@ -13293,7 +13324,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
1329313324
<< Args[1]->getType()
1329413325
<< Args[0]->getSourceRange()
1329513326
<< Args[1]->getSourceRange()),
13296-
*this, OCD_ViableCandidates, Args, "[]", LLoc);
13327+
*this, OCD_AmbiguousCandidates, Args, "[]", LLoc);
1329713328
return ExprError();
1329813329

1329913330
case OR_Deleted:
@@ -13485,7 +13516,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
1348513516
PartialDiagnosticAt(UnresExpr->getMemberLoc(),
1348613517
PDiag(diag::err_ovl_ambiguous_member_call)
1348713518
<< DeclName << MemExprE->getSourceRange()),
13488-
*this, OCD_AllCandidates, Args);
13519+
*this, OCD_AmbiguousCandidates, Args);
1348913520
// FIXME: Leaking incoming expressions!
1349013521
return ExprError();
1349113522

@@ -13717,7 +13748,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
1371713748
PDiag(diag::err_ovl_ambiguous_object_call)
1371813749
<< Object.get()->getType()
1371913750
<< Object.get()->getSourceRange()),
13720-
*this, OCD_ViableCandidates, Args);
13751+
*this, OCD_AmbiguousCandidates, Args);
1372113752
break;
1372213753

1372313754
case OR_Deleted:
@@ -13952,7 +13983,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
1395213983
PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_ambiguous_oper_unary)
1395313984
<< "->" << Base->getType()
1395413985
<< Base->getSourceRange()),
13955-
*this, OCD_ViableCandidates, Base);
13986+
*this, OCD_AmbiguousCandidates, Base);
1395613987
return ExprError();
1395713988

1395813989
case OR_Deleted:
@@ -14032,7 +14063,7 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
1403214063
CandidateSet.NoteCandidates(
1403314064
PartialDiagnosticAt(R.getNameLoc(), PDiag(diag::err_ovl_ambiguous_call)
1403414065
<< R.getLookupName()),
14035-
*this, OCD_ViableCandidates, Args);
14066+
*this, OCD_AmbiguousCandidates, Args);
1403614067
return ExprError();
1403714068
}
1403814069

clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ struct B2 {
88
B2(int); // expected-note {{candidate}}
99
};
1010

11-
struct D1 : B1, B2 { // expected-note 2{{candidate}}
11+
struct D1 : B1, B2 {
1212
using B1::B1; // expected-note {{inherited here}}
1313
using B2::B2; // expected-note {{inherited here}}
1414
};
@@ -35,23 +35,23 @@ namespace default_ctor {
3535
operator D&&();
3636
};
3737

38-
struct A { // expected-note 2{{candidate}}
38+
struct A {
3939
A(); // expected-note {{candidate}}
4040

41-
A(C &&); // expected-note {{candidate}}
42-
C &operator=(C&&); // expected-note {{candidate}}
41+
A(C &&);
42+
C &operator=(C&&);
4343

4444
A(D &&);
4545
D &operator=(D&&); // expected-note {{candidate}}
4646

4747
A(convert_to_D2); // expected-note {{candidate}}
4848
};
4949

50-
struct B { // expected-note 2{{candidate}}
50+
struct B {
5151
B(); // expected-note {{candidate}}
5252

53-
B(C &&); // expected-note {{candidate}}
54-
C &operator=(C&&); // expected-note {{candidate}}
53+
B(C &&);
54+
C &operator=(C&&);
5555

5656
B(D &&);
5757
D &operator=(D&&); // expected-note {{candidate}}
@@ -66,14 +66,14 @@ namespace default_ctor {
6666
using B::operator=;
6767
};
6868
struct D : A, B {
69-
using A::A; // expected-note 3{{inherited here}}
69+
using A::A; // expected-note 2{{inherited here}}
7070
using A::operator=;
71-
using B::B; // expected-note 3{{inherited here}}
71+
using B::B; // expected-note 2{{inherited here}}
7272
using B::operator=;
7373

7474
D(int);
75-
D(const D&); // expected-note {{candidate}}
76-
D &operator=(const D&); // expected-note {{candidate}}
75+
D(const D&);
76+
D &operator=(const D&);
7777
};
7878

7979
C c;

clang/test/CXX/drs/dr15xx.cpp

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -399,23 +399,20 @@ namespace dr1589 { // dr1589: 3.7 c++11
399399
void g2() { f2({"foo","bar"}); } // chooses #4
400400

401401
namespace with_error {
402-
void f0(long); // #0 expected-note {{candidate function}}
403-
void f0(std::initializer_list<int>); // #00 expected-note {{candidate function}}
404-
void f0(std::initializer_list<int>, int = 0); // Makes selection of #00 ambiguous \
405-
// expected-note {{candidate function}}
406-
void g0() { f0({1L}); } // chooses #00 expected-error{{call to 'f0' is ambiguous}}
407-
408-
void f1(int); // #1 expected-note {{candidate function}}
409-
void f1(std::initializer_list<long>); // #2 expected-note {{candidate function}}
410-
void f1(std::initializer_list<long>, int = 0); // Makes selection of #00 ambiguous \
411-
// expected-note {{candidate function}}
412-
void g1() { f1({42}); } // chooses #2 expected-error{{call to 'f1' is ambiguous}}
413-
414-
void f2(std::pair<const char*, const char*>); // #3 TODO: expected- note {{candidate function}}
415-
void f2(std::initializer_list<std::string>); // #4 expected-note {{candidate function}}
416-
void f2(std::initializer_list<std::string>, int = 0); // Makes selection of #00 ambiguous \
417-
// expected-note {{candidate function}}
418-
void g2() { f2({"foo","bar"}); } // chooses #4 expected-error{{call to 'f2' is ambiguous}}
402+
void f0(long); // #0
403+
void f0(std::initializer_list<int>); // #00 expected-note {{candidate function}}
404+
void f0(std::initializer_list<int>, int = 0); // expected-note {{candidate function}}
405+
void g0() { f0({1L}); } // expected-error{{call to 'f0' is ambiguous}}
406+
407+
void f1(int); // #1
408+
void f1(std::initializer_list<long>); // #2 expected-note {{candidate function}}
409+
void f1(std::initializer_list<long>, int = 0); // expected-note {{candidate function}}
410+
void g1() { f1({42}); } // expected-error{{call to 'f1' is ambiguous}}
411+
412+
void f2(std::pair<const char*, const char*>); // #3
413+
void f2(std::initializer_list<std::string>); // #4 expected-note {{candidate function}}
414+
void f2(std::initializer_list<std::string>, int = 0); // expected-note {{candidate function}}
415+
void g2() { f2({"foo","bar"}); } // expected-error{{call to 'f2' is ambiguous}}
419416
}
420417

421418
} // dr1589

0 commit comments

Comments
 (0)