// PR c++/106784 // { dg-do compile { target c++11 } } #define SA(X) static_assert((X),#X) template 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(obj.i)) {} operator float() const { return f; } operator I() const { return I(static_cast(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 struct X { template X(const X&); }; SA(__is_convertible(X, X)); SA(__is_convertible(X, X)); 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)); }