When diagnosing an ambiguity, only note the candidates that contribute

to the ambiguity, rather than noting all viable candidates.
This commit is contained in:
Richard Smith 2019-10-23 17:54:10 -07:00
parent 33fca97880
commit 70f59b5bbc
24 changed files with 138 additions and 99 deletions

View File

@ -68,7 +68,10 @@ class Sema;
OCD_AllCandidates,
/// Requests that only viable candidates be shown.
OCD_ViableCandidates
OCD_ViableCandidates,
/// Requests that only tied-for-best candidates be shown.
OCD_AmbiguousCandidates
};
/// The parameter ordering that will be used for the candidate. This is
@ -791,6 +794,15 @@ class Sema;
/// Viable - True to indicate that this overload candidate is viable.
bool Viable : 1;
/// Whether this candidate is the best viable function, or tied for being
/// the best viable function.
///
/// For an ambiguous overload resolution, indicates whether this candidate
/// was part of the ambiguity kernel: the minimal non-empty set of viable
/// candidates such that all elements of the ambiguity kernel are better
/// than all viable candidates not in the ambiguity kernel.
bool Best : 1;
/// IsSurrogate - True to indicate that this candidate is a
/// surrogate for a conversion to a function pointer or reference
/// (C++ [over.call.object]).

View File

@ -423,7 +423,7 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
case OR_Ambiguous:
msg = diag::err_ovl_ambiguous_conversion_in_cast;
howManyCandidates = OCD_ViableCandidates;
howManyCandidates = OCD_AmbiguousCandidates;
break;
case OR_Deleted:

View File

@ -2323,7 +2323,7 @@ static bool resolveAllocationOverload(
PartialDiagnosticAt(R.getNameLoc(),
S.PDiag(diag::err_ovl_ambiguous_call)
<< R.getLookupName() << Range),
S, OCD_ViableCandidates, Args);
S, OCD_AmbiguousCandidates, Args);
}
return true;
@ -3513,7 +3513,7 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall,
PartialDiagnosticAt(R.getNameLoc(),
S.PDiag(diag::err_ovl_ambiguous_call)
<< R.getLookupName() << Range),
S, OCD_ViableCandidates, Args);
S, OCD_AmbiguousCandidates, Args);
return true;
case OR_Deleted: {

View File

@ -6154,7 +6154,7 @@ static ExprResult CopyObject(Sema &S,
<< (int)Entity.getKind()
<< CurInitExpr->getType()
<< CurInitExpr->getSourceRange()),
S, OCD_ViableCandidates, CurInitExpr);
S, OCD_AmbiguousCandidates, CurInitExpr);
return ExprError();
case OR_Deleted:
@ -6295,7 +6295,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
case OR_Ambiguous:
CandidateSet.NoteCandidates(PartialDiagnosticAt(Loc, Diag), S,
OCD_ViableCandidates, CurInitExpr);
OCD_AmbiguousCandidates, CurInitExpr);
break;
case OR_Deleted:
@ -8806,7 +8806,7 @@ bool InitializationSequence::Diagnose(Sema &S,
: (S.PDiag(diag::err_ref_init_ambiguous)
<< DestType << OnlyArg->getType()
<< Args[0]->getSourceRange())),
S, OCD_ViableCandidates, Args);
S, OCD_AmbiguousCandidates, Args);
break;
case OR_No_Viable_Function: {
@ -9000,7 +9000,7 @@ bool InitializationSequence::Diagnose(Sema &S,
PartialDiagnosticAt(Kind.getLocation(),
S.PDiag(diag::err_ovl_ambiguous_init)
<< DestType << ArgsRange),
S, OCD_ViableCandidates, Args);
S, OCD_AmbiguousCandidates, Args);
break;
case OR_No_Viable_Function:
@ -9863,7 +9863,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
Kind.getLocation(),
PDiag(diag::err_deduced_class_template_ctor_ambiguous)
<< TemplateName),
*this, OCD_ViableCandidates, Inits);
*this, OCD_AmbiguousCandidates, Inits);
return QualType();
case OR_No_Viable_Function: {

View File

@ -1357,7 +1357,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
ICS.Ambiguous.setToType(ToType);
for (OverloadCandidateSet::iterator Cand = Conversions.begin();
Cand != Conversions.end(); ++Cand)
if (Cand->Viable)
if (Cand->Best)
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
break;
@ -3578,7 +3578,10 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
(OvResult == OR_No_Viable_Function && !CandidateSet.empty())))
return false;
auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates, From);
auto Cands = CandidateSet.CompleteCandidates(
*this,
OvResult == OR_Ambiguous ? OCD_AmbiguousCandidates : OCD_AllCandidates,
From);
if (OvResult == OR_Ambiguous)
Diag(From->getBeginLoc(), diag::err_typecheck_ambiguous_condition)
<< From->getType() << ToType << From->getSourceRange();
@ -4602,7 +4605,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
ICS.setAmbiguous();
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
Cand != CandidateSet.end(); ++Cand)
if (Cand->Viable)
if (Cand->Best)
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
return true;
@ -9653,11 +9656,13 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// Find the best viable function.
Best = end();
for (auto *Cand : Candidates)
for (auto *Cand : Candidates) {
Cand->Best = false;
if (Cand->Viable)
if (Best == end() ||
isBetterOverloadCandidate(S, *Cand, *Best, Loc, Kind))
Best = Cand;
}
// If we didn't find any viable functions, abort.
if (Best == end())
@ -9665,22 +9670,33 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
llvm::SmallVector<const NamedDecl *, 4> EquivalentCands;
llvm::SmallVector<OverloadCandidate*, 4> PendingBest;
PendingBest.push_back(&*Best);
Best->Best = true;
// Make sure that this function is better than every other viable
// function. If not, we have an ambiguity.
for (auto *Cand : Candidates) {
if (Cand->Viable && Cand != Best &&
!isBetterOverloadCandidate(S, *Best, *Cand, Loc, Kind)) {
if (S.isEquivalentInternalLinkageDeclaration(Best->Function,
Cand->Function)) {
EquivalentCands.push_back(Cand->Function);
continue;
}
while (!PendingBest.empty()) {
auto *Curr = PendingBest.pop_back_val();
for (auto *Cand : Candidates) {
if (Cand->Viable && !Cand->Best &&
!isBetterOverloadCandidate(S, *Curr, *Cand, Loc, Kind)) {
PendingBest.push_back(Cand);
Cand->Best = true;
Best = end();
return OR_Ambiguous;
if (S.isEquivalentInternalLinkageDeclaration(Cand->Function,
Curr->Function))
EquivalentCands.push_back(Cand->Function);
else
Best = end();
}
}
}
// If we found more than one best candidate, this is ambiguous.
if (Best == end())
return OR_Ambiguous;
// Best is the best viable function.
if (Best->Function && Best->Function->isDeleted())
return OR_Deleted;
@ -11080,15 +11096,30 @@ SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates(
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
if (!Filter(*Cand))
continue;
if (Cand->Viable)
Cands.push_back(Cand);
else if (OCD == OCD_AllCandidates) {
CompleteNonViableCandidate(S, Cand, Args, Kind);
if (Cand->Function || Cand->IsSurrogate)
Cands.push_back(Cand);
// Otherwise, this a non-viable builtin candidate. We do not, in general,
// want to list every possible builtin candidate.
switch (OCD) {
case OCD_AllCandidates:
if (!Cand->Viable) {
if (!Cand->Function && !Cand->IsSurrogate) {
// This a non-viable builtin candidate. We do not, in general,
// want to list every possible builtin candidate.
continue;
}
CompleteNonViableCandidate(S, Cand, Args, Kind);
}
break;
case OCD_ViableCandidates:
if (!Cand->Viable)
continue;
break;
case OCD_AmbiguousCandidates:
if (!Cand->Best)
continue;
break;
}
Cands.push_back(Cand);
}
llvm::stable_sort(
@ -12453,7 +12484,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
PartialDiagnosticAt(Fn->getBeginLoc(),
SemaRef.PDiag(diag::err_ovl_ambiguous_call)
<< ULE->getName() << Fn->getSourceRange()),
SemaRef, OCD_ViableCandidates, Args);
SemaRef, OCD_AmbiguousCandidates, Args);
break;
case OR_Deleted: {
@ -12699,7 +12730,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
PDiag(diag::err_ovl_ambiguous_oper_unary)
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getType() << Input->getSourceRange()),
*this, OCD_ViableCandidates, ArgsArray,
*this, OCD_AmbiguousCandidates, ArgsArray,
UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
@ -13108,7 +13139,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
<< Args[1]->getType()
<< Args[0]->getSourceRange()
<< Args[1]->getSourceRange()),
*this, OCD_ViableCandidates, Args, BinaryOperator::getOpcodeStr(Opc),
*this, OCD_AmbiguousCandidates, Args, BinaryOperator::getOpcodeStr(Opc),
OpLoc);
return ExprError();
@ -13293,7 +13324,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
<< Args[1]->getType()
<< Args[0]->getSourceRange()
<< Args[1]->getSourceRange()),
*this, OCD_ViableCandidates, Args, "[]", LLoc);
*this, OCD_AmbiguousCandidates, Args, "[]", LLoc);
return ExprError();
case OR_Deleted:
@ -13485,7 +13516,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
PartialDiagnosticAt(UnresExpr->getMemberLoc(),
PDiag(diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange()),
*this, OCD_AllCandidates, Args);
*this, OCD_AmbiguousCandidates, Args);
// FIXME: Leaking incoming expressions!
return ExprError();
@ -13717,7 +13748,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
PDiag(diag::err_ovl_ambiguous_object_call)
<< Object.get()->getType()
<< Object.get()->getSourceRange()),
*this, OCD_ViableCandidates, Args);
*this, OCD_AmbiguousCandidates, Args);
break;
case OR_Deleted:
@ -13952,7 +13983,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_ambiguous_oper_unary)
<< "->" << Base->getType()
<< Base->getSourceRange()),
*this, OCD_ViableCandidates, Base);
*this, OCD_AmbiguousCandidates, Base);
return ExprError();
case OR_Deleted:
@ -14032,7 +14063,7 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
CandidateSet.NoteCandidates(
PartialDiagnosticAt(R.getNameLoc(), PDiag(diag::err_ovl_ambiguous_call)
<< R.getLookupName()),
*this, OCD_ViableCandidates, Args);
*this, OCD_AmbiguousCandidates, Args);
return ExprError();
}

View File

@ -8,7 +8,7 @@ struct B2 {
B2(int); // expected-note {{candidate}}
};
struct D1 : B1, B2 { // expected-note 2{{candidate}}
struct D1 : B1, B2 {
using B1::B1; // expected-note {{inherited here}}
using B2::B2; // expected-note {{inherited here}}
};
@ -35,11 +35,11 @@ namespace default_ctor {
operator D&&();
};
struct A { // expected-note 2{{candidate}}
struct A {
A(); // expected-note {{candidate}}
A(C &&); // expected-note {{candidate}}
C &operator=(C&&); // expected-note {{candidate}}
A(C &&);
C &operator=(C&&);
A(D &&);
D &operator=(D&&); // expected-note {{candidate}}
@ -47,11 +47,11 @@ namespace default_ctor {
A(convert_to_D2); // expected-note {{candidate}}
};
struct B { // expected-note 2{{candidate}}
struct B {
B(); // expected-note {{candidate}}
B(C &&); // expected-note {{candidate}}
C &operator=(C&&); // expected-note {{candidate}}
B(C &&);
C &operator=(C&&);
B(D &&);
D &operator=(D&&); // expected-note {{candidate}}
@ -66,14 +66,14 @@ namespace default_ctor {
using B::operator=;
};
struct D : A, B {
using A::A; // expected-note 3{{inherited here}}
using A::A; // expected-note 2{{inherited here}}
using A::operator=;
using B::B; // expected-note 3{{inherited here}}
using B::B; // expected-note 2{{inherited here}}
using B::operator=;
D(int);
D(const D&); // expected-note {{candidate}}
D &operator=(const D&); // expected-note {{candidate}}
D(const D&);
D &operator=(const D&);
};
C c;

View File

@ -399,23 +399,20 @@ namespace dr1589 { // dr1589: 3.7 c++11
void g2() { f2({"foo","bar"}); } // chooses #4
namespace with_error {
void f0(long); // #0 expected-note {{candidate function}}
void f0(std::initializer_list<int>); // #00 expected-note {{candidate function}}
void f0(std::initializer_list<int>, int = 0); // Makes selection of #00 ambiguous \
// expected-note {{candidate function}}
void g0() { f0({1L}); } // chooses #00 expected-error{{call to 'f0' is ambiguous}}
void f0(long); // #0
void f0(std::initializer_list<int>); // #00 expected-note {{candidate function}}
void f0(std::initializer_list<int>, int = 0); // expected-note {{candidate function}}
void g0() { f0({1L}); } // expected-error{{call to 'f0' is ambiguous}}
void f1(int); // #1 expected-note {{candidate function}}
void f1(std::initializer_list<long>); // #2 expected-note {{candidate function}}
void f1(std::initializer_list<long>, int = 0); // Makes selection of #00 ambiguous \
// expected-note {{candidate function}}
void g1() { f1({42}); } // chooses #2 expected-error{{call to 'f1' is ambiguous}}
void f1(int); // #1
void f1(std::initializer_list<long>); // #2 expected-note {{candidate function}}
void f1(std::initializer_list<long>, int = 0); // expected-note {{candidate function}}
void g1() { f1({42}); } // expected-error{{call to 'f1' is ambiguous}}
void f2(std::pair<const char*, const char*>); // #3 TODO: expected- note {{candidate function}}
void f2(std::initializer_list<std::string>); // #4 expected-note {{candidate function}}
void f2(std::initializer_list<std::string>, int = 0); // Makes selection of #00 ambiguous \
// expected-note {{candidate function}}
void g2() { f2({"foo","bar"}); } // chooses #4 expected-error{{call to 'f2' is ambiguous}}
void f2(std::pair<const char*, const char*>); // #3
void f2(std::initializer_list<std::string>); // #4 expected-note {{candidate function}}
void f2(std::initializer_list<std::string>, int = 0); // expected-note {{candidate function}}
void g2() { f2({"foo","bar"}); } // expected-error{{call to 'f2' is ambiguous}}
}
} // dr1589

View File

@ -111,13 +111,13 @@ namespace dr1638 { // dr1638: yes
namespace dr1645 { // dr1645: 3.9
#if __cplusplus >= 201103L
struct A {
constexpr A(int, float = 0); // expected-note 2{{candidate}}
constexpr A(int, float = 0); // expected-note {{candidate}}
explicit A(int, int = 0); // expected-note 2{{candidate}}
A(int, int, int = 0) = delete; // expected-note {{candidate}}
};
struct B : A { // expected-note 2{{candidate}}
using A::A; // expected-note 5{{inherited here}}
struct B : A {
using A::A; // expected-note 4{{inherited here}}
};
constexpr B a(0); // expected-error {{ambiguous}}

View File

@ -2,7 +2,7 @@
namespace std_example {
template <class T> struct A {
explicit A(const T &, ...) noexcept; // expected-note {{explicit}} expected-note 2{{candidate}}
explicit A(const T &, ...) noexcept; // expected-note {{explicit}}
A(T &&, ...); // expected-note 2{{candidate}}
};

View File

@ -3,19 +3,19 @@
// Note: [class.inhctor] was removed by P0136R1. This tests the new behavior
// for the wording that used to be there.
struct A { // expected-note 4{{candidate constructor (the implicit}}
A(...); // expected-note 4{{candidate constructor}} expected-note 4{{candidate inherited constructor}}
struct A {
A(...); // expected-note {{candidate constructor}} expected-note {{candidate inherited constructor}}
A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 3{{candidate constructor}} expected-note 3{{candidate inherited constructor}}
A(int = 0, int = 0, ...); // expected-note 3{{candidate constructor}} expected-note 3{{candidate inherited constructor}}
template<typename T> A(T, int = 0, ...); // expected-note 3{{candidate constructor}} expected-note 3{{candidate inherited constructor}}
template<typename T> A(T, int = 0, ...);
template<typename T, int N> A(const T (&)[N]); // expected-note {{candidate constructor}} expected-note {{candidate inherited constructor}}
template<typename T, int N> A(const T (&)[N], int = 0); // expected-note {{candidate constructor}} expected-note {{candidate inherited constructor}}
};
struct B : A { // expected-note 4{{candidate constructor (the implicit}}
using A::A; // expected-note 15{{inherited here}}
struct B : A {
using A::A; // expected-note 9{{inherited here}}
B(void*);
};

View File

@ -60,13 +60,13 @@ H h2("foo"); // expected-error {{call to deleted constructor of 'H'}}
// same signature.
namespace DRnnnn {
struct A {
constexpr A(int, float = 0) {} // expected-note {{candidate}}
constexpr A(int, float = 0) {}
explicit A(int, int = 0) {} // expected-note {{candidate}}
A(int, int, int = 0) = delete; // expected-note {{deleted}}
};
struct B : A {
using A::A; // expected-note 3{{inherited here}}
using A::A; // expected-note 2{{inherited here}}
};
constexpr B b0(0, 0.0f); // ok, constexpr

View File

@ -9,7 +9,7 @@ struct B1 {
struct B2 {
B2(int); // expected-note {{candidate}}
};
struct D1 : B1, B2 { // expected-note 2{{candidate}}
struct D1 : B1, B2 {
using B1::B1; // expected-note {{inherited here}}
using B2::B2; // expected-note {{inherited here}}
};

View File

@ -13,7 +13,7 @@ namespace test0 {
extern B f();
B b1;
void func(const int ci, const char cc); // expected-note {{candidate function}}
void func(const int ci, const char cc);
void func(const char ci, const B b); // expected-note {{candidate function}}
void func(const B b, const int ci); // expected-note {{candidate function}}

View File

@ -17,11 +17,8 @@ struct C : B {
void foo(C c, int A::* pmf) {
// FIXME. Why so many built-in candidates?
int i = c->*pmf; // expected-error {{use of overloaded operator '->*' is ambiguous}} \
// expected-note {{built-in candidate operator->*(const struct A *, const int struct A::*)}} \
// expected-note {{built-in candidate operator->*(const struct A *, int struct A::*)}} \
// expected-note {{built-in candidate operator->*(struct A *, const int struct A::*)}} \
// expected-note {{built-in candidate operator->*(struct A *, int struct A::*)}}
}

View File

@ -42,5 +42,5 @@ void foo1(C1 c1, int A::* pmf) {
void foo1(C1 c1, int E::* pmf) {
int i = c1->*pmf; // expected-error {{use of overloaded operator '->*' is ambiguous}} \
// expected-note {{because of ambiguity in conversion of 'C1' to 'E *'}} \
// expected-note 4 {{built-in candidate operator}}
// expected-note 2 {{built-in candidate operator}}
}

View File

@ -4,7 +4,7 @@
class X {
public:
explicit X(const X&); // expected-note {{candidate constructor}}
explicit X(const X&);
X(int*); // expected-note 3{{candidate constructor}}
explicit X(float*); // expected-note {{candidate constructor}}
};

View File

@ -266,7 +266,7 @@ namespace PR12120 {
struct A { explicit A(int); A(float); }; // expected-note {{declared here}}
A a = { 0 }; // expected-error {{constructor is explicit}}
struct B { explicit B(short); B(long); }; // expected-note 4{{candidate}}
struct B { explicit B(short); B(long); }; // expected-note 2{{candidate}}
B b = { 0 }; // expected-error {{ambiguous}}
struct C { explicit C(short); C(long); }; // expected-note 2{{candidate}}

View File

@ -11,7 +11,7 @@ template <typename T> struct is_same<T, T> { static constexpr bool value = true;
struct S {
// The only numeric types S can be converted to is __int128 and __float128.
// The only numeric types S can be converted to are [unsigned] __int128 and __float128.
template <typename T, typename = typename enable_if<
!((__is_integral(T) && sizeof(T) != 16) ||
is_same<T, float>::value ||
@ -29,6 +29,8 @@ void f() {
double d = S() + 1.0;
#ifndef MS
// expected-error@-2{{use of overloaded operator '+' is ambiguous}}
// expected-note@-3 36{{built-in candidate operator+}}
// expected-note@-3 {{built-in candidate operator+(__float128, double)}}
// expected-note@-4 {{built-in candidate operator+(__int128, double)}}
// expected-note@-5 {{built-in candidate operator+(unsigned __int128, double)}}
#endif
}

View File

@ -12,9 +12,9 @@ void test_f(int iv, float fv) {
}
int* g(int, float, int); // expected-note {{candidate function}}
float* g(int, int, int); // expected-note {{candidate function}}
float* g(int, int, int);
double* g(int, float, float); // expected-note {{candidate function}}
char* g(int, float, ...); // expected-note {{candidate function}}
char* g(int, float, ...);
void g();
void test_g(int iv, float fv) {

View File

@ -14,7 +14,7 @@ struct X {
int& g(int) const; // expected-note 2 {{candidate function}}
float& g(int); // expected-note 2 {{candidate function}}
static double& g(double); // expected-note 2 {{candidate function}}
static double& g(double);
void h(int);

View File

@ -194,10 +194,9 @@ struct A {
};
void test_dr425(A a) {
// FIXME: lots of candidates here!
(void)(1.0f * a); // expected-error{{ambiguous}} \
// expected-note 4{{candidate}} \
// expected-note {{remaining 140 candidates omitted; pass -fshow-overloads=all to show them}}
// expected-note {{remaining 8 candidates omitted; pass -fshow-overloads=all to show them}}
}
// pr5432
@ -237,9 +236,10 @@ namespace PR8477 {
(void)(foo - zero);
(void)(zero + foo);
(void)(zero[foo]);
// FIXME: It would be nice to report fewer candidates here.
(void)(foo - foo); // expected-error{{use of overloaded operator '-' is ambiguous}} \
// expected-note 4{{built-in candidate operator-}} \
// expected-note{{candidates omitted}}
// expected-note{{142 candidates omitted}}
return foo[zero] == zero;
}
}

View File

@ -16,7 +16,7 @@ void test_Unexpanded() {
}
// Test using non-type members from pack of base classes.
template<typename ...T> struct A : T... { // expected-note 2{{candidate}}
template<typename ...T> struct A : T... {
using T::T ...; // expected-note 2{{inherited here}}
using T::operator() ...;
using T::operator T* ...;
@ -41,7 +41,7 @@ namespace test_A {
Y(int, int);
void operator()(int, int);
operator Y *();
void h(int, int); // expected-note {{not viable}}
void h(int, int);
};
struct Z {
Z();
@ -177,14 +177,14 @@ namespace test_lambda1 {
};
struct B {
template<typename> struct X {
void f(int, int); // expected-note {{declared here}} expected-note {{not viable}}
void f(int, int); // expected-note {{declared here}}
using type = int;
};
};
struct C {
template<typename> struct X {
void f(int); // expected-note {{candidate}}
void f(int, int); // expected-note {{not viable}}
void f(int, int);
using type = int;
};
};

View File

@ -23,7 +23,7 @@ namespace N1 {
}
namespace N2 {
long& operator+=(N1::X&, long); // expected-note{{candidate}}
long& operator+=(N1::X&, long);
template<typename T, typename U, typename Result>
struct PlusEquals0 {

View File

@ -445,10 +445,10 @@ namespace nondependent_default_arg_ordering {
template<typename A> void f(X<A>); // expected-note {{candidate}}
template<typename A> void f(X<A, &m>); // expected-note {{candidate}}
template<typename A, A B> void f(X<A, B>); // expected-note 2{{candidate}}
template<template<typename U, U> class T, typename A, int *B> void f(T<A, B>); // expected-note 2{{candidate}}
template<template<typename U, U> class T, typename A, int *B> void f(T<A, B>);
void g() {
// FIXME: The first and second function templates above should be
// considered more specialized than the last two, but during partial
// considered more specialized than the third, but during partial
// ordering we fail to check that we actually deduced template arguments
// that make the deduced A identical to A.
X<int *, &n> x; f(x); // expected-error {{ambiguous}}