Richard Smith 2519554134 When diagnosing the lack of a viable conversion function, also list
explicit functions that are not candidates.

It's not always obvious that the reason a conversion was not possible is
because the function you wanted to call is 'explicit', so explicitly say
if that's the case.

It would be nice to rank the explicit candidates higher in the
diagnostic if an implicit conversion sequence exists for their
arguments, but unfortunately we can't determine that without potentially
triggering non-immediate-context errors that we're not permitted to
produce.
2020-01-09 15:15:02 -08:00

87 lines
2.4 KiB
C++

// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
namespace Ints {
int zero = 0; // expected-note {{candidate found by name lookup is 'Ints::zero'}}
void f(int); // expected-note 3 {{candidate function}}
void g(int);
}
namespace Floats {
float zero = 0.0f; // expected-note {{candidate found by name lookup is 'Floats::zero'}}
void f(float); // expected-note 3 {{candidate function}}
void g(float);
}
namespace Numbers {
using namespace Ints;
using namespace Floats;
}
void test() {
int i = Ints::zero;
Ints::f(i);
float f = Floats::zero;
Floats::f(f);
double n = Numbers::zero; // expected-error {{reference to 'zero' is ambiguous}}
Numbers::f(n); // expected-error{{call to 'f' is ambiguous}}
Numbers::f(i);
Numbers::f(f);
}
namespace Numbers {
struct Number { // expected-note 2 {{candidate constructor (the implicit copy constructor) not viable}}
#if __cplusplus >= 201103L // C++11 or later
// expected-note@-2 2 {{candidate constructor (the implicit move constructor) not viable}}
#endif
explicit Number(double d) : d(d) {} // expected-note 2{{explicit constructor is not a candidate}}
double d;
};
Number zero(0.0f);
void g(Number); // expected-note 2{{passing argument to parameter here}}
}
void test2() {
Numbers::Number n = Numbers::zero;
Numbers::f(n); // expected-error {{no matching function for call to 'f'}}
Numbers::g(n);
}
namespace Numbers2 {
using Numbers::f;
using Numbers::g;
}
void test3() {
Numbers::Number n = Numbers::zero;
Numbers2::f(n); // expected-error {{no matching function for call to 'f'}}
Numbers2::g(n);
int i = Ints::zero;
Numbers2::f(i);
Numbers2::g(i); // expected-error {{no viable conversion from 'int' to 'Numbers::Number'}}
float f = Floats::zero;
Numbers2::f(f);
Numbers2::g(f); // expected-error {{no viable conversion from 'float' to 'Numbers::Number'}}
}
namespace inline_ns {
int x; // expected-note 2{{found}}
inline namespace A {
#if __cplusplus <= 199711L // C++03 or earlier
// expected-warning@-2 {{inline namespaces are a C++11 feature}}
#endif
int x; // expected-note 2{{found}}
int y; // expected-note 2{{found}}
}
int y; // expected-note 2{{found}}
int k1 = x + y; // expected-error 2{{ambiguous}}
int k2 = inline_ns::x + inline_ns::y; // expected-error 2{{ambiguous}}
}