blob: 2e72945bceb1d51eea0d9b080fafb6174a738396 [file] [log] [blame]
// PR c++/106784
// { dg-do compile { target c++11 } }
#define SA(X) static_assert((X),#X)
template<typename From, typename To>
struct is_convertible {
static const bool value = __is_convertible(From, To);
};
struct from_int {
from_int(int);
};
struct from_charp {
from_charp(const char *);
};
struct to_int {
operator int();
};
typedef int Fn(int);
typedef char Arr[10];
enum E { XYZZY };
SA(!__is_convertible(int, void));
SA(__is_convertible(int, int));
SA(__is_convertible(int, from_int));
SA(__is_convertible(long, from_int));
SA(__is_convertible(double, from_int));
SA(__is_convertible(const int, from_int));
SA(__is_convertible(const int&, from_int));
SA(__is_convertible(to_int, int));
SA(__is_convertible(to_int, const int&));
SA(__is_convertible(to_int, long));
SA(!__is_convertible(to_int, int&));
SA(!__is_convertible(to_int, from_int));
SA(!__is_convertible(int, Fn));
SA(!__is_convertible(int, Fn*));
SA(!__is_convertible(int, Fn&));
SA(!__is_convertible(int, Arr));
SA(!__is_convertible(int, Arr&));
SA(!__is_convertible(int, int&));
SA(__is_convertible(int, const int&));
SA(!__is_convertible(const int, int&));
SA(__is_convertible(const int, const int&));
SA(!__is_convertible(int, int*));
SA(!__is_convertible(int, E));
SA(__is_convertible(E, int));
SA(__is_convertible(int&, int));
SA(__is_convertible(int&, int&));
SA(__is_convertible(int&, const int&));
SA(!__is_convertible(const int&, int&));
SA(__is_convertible(const int&, const int&));
SA(!__is_convertible(int&, int*));
SA(!__is_convertible(int&, void));
SA(!__is_convertible(int&, Fn));
SA(!__is_convertible(int&, Fn*));
SA(!__is_convertible(int&, Fn&));
SA(!__is_convertible(int&, Arr));
SA(!__is_convertible(int&, Arr&));
SA(!__is_convertible(int*, int));
SA(!__is_convertible(int*, int&));
SA(!__is_convertible(int*, void));
SA(__is_convertible(int*, int*));
SA(__is_convertible(int*, const int*));
SA(!__is_convertible(const int*, int*));
SA(__is_convertible(const int*, const int*));
SA(!__is_convertible(int*, Fn));
SA(!__is_convertible(int*, Fn*));
SA(!__is_convertible(int*, Fn&));
SA(!__is_convertible(int*, Arr));
SA(!__is_convertible(int*, Arr&));
SA(!__is_convertible(int*, float*));
SA(__is_convertible(void, void));
SA(!__is_convertible(void, char));
SA(!__is_convertible(void, char&));
SA(!__is_convertible(void, char*));
SA(!__is_convertible(char, void));
SA(__is_convertible(const void, void));
SA(__is_convertible(void, const void));
SA(__is_convertible(const void, const void));
SA(!__is_convertible(void, Fn));
SA(!__is_convertible(void, Fn&));
SA(!__is_convertible(void, Fn*));
SA(!__is_convertible(void, Arr));
SA(!__is_convertible(void, Arr&));
SA(!__is_convertible(Fn, void));
SA(!__is_convertible(Fn, Fn));
SA(__is_convertible(Fn, Fn*));
SA(__is_convertible(Fn, Fn&));
SA(!__is_convertible(int(int), int(int)));
SA(__is_convertible(int(int), int(&)(int)));
SA(__is_convertible(int(int), int(&&)(int)));
SA(__is_convertible(int(int), int(*)(int)));
SA(__is_convertible(int(int), int(*const)(int)));
SA(!__is_convertible(int(int), char));
SA(!__is_convertible(int(int), char*));
SA(!__is_convertible(int(int), char&));
SA(!__is_convertible(Fn&, void));
SA(!__is_convertible(Fn&, Fn));
SA(__is_convertible(Fn&, Fn&));
SA(__is_convertible(Fn&, Fn*));
SA(!__is_convertible(Fn&, Arr));
SA(!__is_convertible(Fn&, Arr&));
SA(!__is_convertible(Fn&, char));
SA(!__is_convertible(Fn&, char&));
SA(!__is_convertible(Fn&, char*));
SA(!__is_convertible(Fn*, void));
SA(!__is_convertible(Fn*, Fn));
SA(!__is_convertible(Fn*, Fn&));
SA(__is_convertible(Fn*, Fn*));
SA(!__is_convertible(Fn*, Arr));
SA(!__is_convertible(Fn*, Arr&));
SA(!__is_convertible(Fn*, char));
SA(!__is_convertible(Fn*, char&));
SA(!__is_convertible(Fn*, char*));
SA(!__is_convertible(Arr, void));
SA(!__is_convertible(Arr, Fn));
SA(!__is_convertible(Arr, Fn*));
SA(!__is_convertible(Arr, Fn&));
SA(!__is_convertible(Arr, Arr));
SA(!__is_convertible(Arr, Arr&));
SA(__is_convertible(Arr, const Arr&));
SA(!__is_convertible(Arr, volatile Arr&));
SA(!__is_convertible(Arr, const volatile Arr&));
SA(!__is_convertible(const Arr, Arr&));
SA(__is_convertible(const Arr, const Arr&));
SA(__is_convertible(Arr, Arr&&));
SA(__is_convertible(Arr, const Arr&&));
SA(__is_convertible(Arr, volatile Arr&&));
SA(__is_convertible(Arr, const volatile Arr&&));
SA(__is_convertible(const Arr, const Arr&&));
SA(!__is_convertible(Arr&, Arr&&));
SA(!__is_convertible(Arr&&, Arr&));
SA(!__is_convertible(Arr, char));
SA(__is_convertible(Arr, char*));
SA(__is_convertible(Arr, const char*));
SA(!__is_convertible(Arr, char&));
SA(!__is_convertible(const Arr, char*));
SA(__is_convertible(const Arr, const char*));
SA(!__is_convertible(int, int[1]));
SA(!__is_convertible(int[1], int[1]));
SA(!__is_convertible(int[1], int(&)[1]));
SA(__is_convertible(int(&)[1], int(&)[1]));
SA(__is_convertible(int(&)[1], const int(&)[1]));
SA(!__is_convertible(const int(&)[1], int(&)[1]));
SA(!__is_convertible(int[1][1], int*));
SA(!__is_convertible(int[][1], int*));
SA(!__is_convertible(Arr&, void));
SA(!__is_convertible(Arr&, Fn));
SA(!__is_convertible(Arr&, Fn*));
SA(!__is_convertible(Arr&, Fn&));
SA(!__is_convertible(Arr&, Arr));
SA(__is_convertible(Arr&, Arr&));
SA(__is_convertible(Arr&, const Arr&));
SA(!__is_convertible(const Arr&, Arr&));
SA(__is_convertible(const Arr&, const Arr&));
SA(!__is_convertible(Arr&, char));
SA(__is_convertible(Arr&, char*));
SA(__is_convertible(Arr&, const char*));
SA(!__is_convertible(Arr&, char&));
SA(!__is_convertible(const Arr&, char*));
SA(__is_convertible(const Arr&, const char*));
SA(__is_convertible(Arr, from_charp));
SA(__is_convertible(Arr&, from_charp));
struct B { };
struct D : B { };
SA(__is_convertible(D, B));
SA(__is_convertible(D*, B*));
SA(__is_convertible(D&, B&));
SA(!__is_convertible(B, D));
SA(!__is_convertible(B*, D*));
SA(!__is_convertible(B&, D&));
/* These are taken from LLVM's test/SemaCXX/type-traits.cpp. */
struct I {
int i;
I(int _i) : i(_i) { }
operator int() const {
return i;
}
};
struct F
{
float f;
F(float _f) : f(_f) {}
F(const I& obj)
: f(static_cast<float>(obj.i)) {}
operator float() const {
return f;
}
operator I() const {
return I(static_cast<int>(f));
}
};
SA(__is_convertible(I, I));
SA(__is_convertible(I, const I));
SA(__is_convertible(I, int));
SA(__is_convertible(int, I));
SA(__is_convertible(I, F));
SA(__is_convertible(F, I));
SA(__is_convertible(F, float));
SA(__is_convertible(float, F));
template<typename>
struct X {
template<typename U> X(const X<U>&);
};
SA(__is_convertible(X<int>, X<float>));
SA(__is_convertible(X<float>, X<int>));
struct Abstract {
virtual void f() = 0;
};
SA(!__is_convertible(Abstract, Abstract));
class hidden {
hidden(const hidden&);
friend void test ();
};
SA(__is_convertible(hidden&, hidden&));
SA(__is_convertible(hidden&, const hidden&));
SA(__is_convertible(hidden&, volatile hidden&));
SA(__is_convertible(hidden&, const volatile hidden&));
SA(__is_convertible(const hidden&, const hidden&));
SA(__is_convertible(const hidden&, const volatile hidden&));
SA(__is_convertible(volatile hidden&, const volatile hidden&));
SA(__is_convertible(const volatile hidden&, const volatile hidden&));
SA(!__is_convertible(const hidden&, hidden&));
void
test ()
{
/* __is_convertible(hidden, hidden) should be false despite the
friend declaration above, because "Access checks are performed
as if from a context unrelated to either type", but we don't
implement that for the built-in (std::is_convertible works as
expected). This is the case for __is_assignable as well. */
//SA(!__is_convertible(hidden, hidden));
}
void
test2 ()
{
struct X { };
struct Y {
explicit Y(X); // not viable for implicit conversions
};
SA(!__is_convertible(X, Y));
}