diff options
Diffstat (limited to 'clang/test/SemaCXX/conversion-function.cpp')
-rw-r--r-- | clang/test/SemaCXX/conversion-function.cpp | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp new file mode 100644 index 0000000..a7a1782 --- /dev/null +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -0,0 +1,394 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class X { +public: + operator bool(); + operator int() const; + + bool f() { + return operator bool(); + } + + float g() { + return operator float(); // expected-error{{use of undeclared 'operator float'}} + } +}; + +operator int(); // expected-error{{conversion function must be a non-static member function}} + +operator int; // expected-error{{'operator int' cannot be the name of a variable or data member}} + +typedef int func_type(int); +typedef int array_type[10]; + +class Y { +public: + void operator bool(int, ...) const; // expected-error{{conversion function cannot have a return type}} \ + // expected-error{{conversion function cannot have any parameters}} + + operator float(...) const; // expected-error{{conversion function cannot be variadic}} + + + operator func_type(); // expected-error{{conversion function cannot convert to a function type}} + operator array_type(); // expected-error{{conversion function cannot convert to an array type}} +}; + + +typedef int INT; +typedef INT* INT_PTR; + +class Z { + operator int(); // expected-note {{previous declaration is here}} + operator int**(); // expected-note {{previous declaration is here}} + + operator INT(); // expected-error{{conversion function cannot be redeclared}} + operator INT_PTR*(); // expected-error{{conversion function cannot be redeclared}} +}; + + +class A { }; + +class B : public A { +public: + operator A&() const; // expected-warning{{conversion function converting 'B' to its base class 'A' will never be used}} + operator const void() const; // expected-warning{{conversion function converting 'B' to 'const void' will never be used}} + operator const B(); // expected-warning{{conversion function converting 'B' to itself will never be used}} +}; + +// This used to crash Clang. +struct Flip; +struct Flop { + Flop(); + Flop(const Flip&); // expected-note{{candidate constructor}} +}; +struct Flip { + operator Flop() const; // expected-note{{candidate function}} +}; +Flop flop = Flip(); // expected-error {{conversion from 'Flip' to 'Flop' is ambiguous}} + +// This tests that we don't add the second conversion declaration to the list of user conversions +struct C { + operator const char *() const; +}; + +C::operator const char*() const { return 0; } + +void f(const C& c) { + const char* v = c; +} + +// Test. Conversion in base class is visible in derived class. +class XB { +public: + operator int(); // expected-note {{candidate function}} +}; + +class Yb : public XB { +public: + operator char(); // expected-note {{candidate function}} +}; + +void f(Yb& a) { + if (a) { } // expected-error {{conversion from 'Yb' to 'bool' is ambiguous}} + int i = a; // OK. calls XB::operator int(); + char ch = a; // OK. calls Yb::operator char(); +} + +// Test conversion + copy construction. +class AutoPtrRef { }; + +class AutoPtr { + AutoPtr(AutoPtr &); // expected-note{{declared private here}} + +public: + AutoPtr(); + AutoPtr(AutoPtrRef); + + operator AutoPtrRef(); +}; + +AutoPtr make_auto_ptr(); + +AutoPtr test_auto_ptr(bool Cond) { + AutoPtr p1( make_auto_ptr() ); + + AutoPtr p; + if (Cond) + return p; // expected-error{{calling a private constructor}} + + return AutoPtr(); +} + +struct A1 { + A1(const char *); + ~A1(); + +private: + A1(const A1&); // expected-note 2 {{declared private here}} +}; + +A1 f() { + // FIXME: redundant diagnostics! + return "Hello"; // expected-error {{calling a private constructor}} expected-warning {{an accessible copy constructor}} +} + +namespace source_locations { + template<typename T> + struct sneaky_int { + typedef int type; + }; + + template<typename T, typename U> + struct A { }; + + template<typename T> + struct A<T, T> : A<T, int> { }; + + struct E { + template<typename T> + operator A<T, typename sneaky_int<T>::type>&() const; // expected-note{{candidate function}} + }; + + void f() { + A<float, float> &af = E(); // expected-error{{no viable conversion}} + A<float, int> &af2 = E(); + const A<float, int> &caf2 = E(); + } + + // Check + template<typename T> + struct E2 { + operator T + * // expected-error{{pointer to a reference}} + () const; + }; + + E2<int&> e2i; // expected-note{{in instantiation}} +} + +namespace crazy_declarators { + struct A { + (&operator bool())(); // expected-error {{must use a typedef to declare a conversion to 'bool (&)()'}} + + // FIXME: This diagnostic is misleading (the correct spelling + // would be 'operator int*'), but it's a corner case of a + // rarely-used syntax extension. + *operator int(); // expected-error {{must use a typedef to declare a conversion to 'int *'}} + }; +} + +namespace smart_ptr { + class Y { + class YRef { }; + + Y(Y&); + + public: + Y(); + Y(YRef); + + operator YRef(); // expected-note{{candidate function}} + }; + + struct X { // expected-note{{candidate constructor (the implicit copy constructor) not}} + explicit X(Y); + }; + + Y make_Y(); + + X f() { + X x = make_Y(); // expected-error{{no viable conversion from 'smart_ptr::Y' to 'smart_ptr::X'}} + X x2(make_Y()); + return X(Y()); + } +} + +struct Any { + Any(...); +}; + +struct Other { + Other(const Other &); + Other(); +}; + +void test_any() { + Any any = Other(); // expected-error{{cannot pass object of non-POD type 'Other' through variadic constructor; call will abort at runtime}} +} + +namespace PR7055 { + // Make sure that we don't allow too many conversions in an + // auto_ptr-like template. In particular, we can't create multiple + // temporary objects when binding to a reference. + struct auto_ptr { + struct auto_ptr_ref { }; + + auto_ptr(auto_ptr&); + auto_ptr(auto_ptr_ref); + explicit auto_ptr(int *); + + operator auto_ptr_ref(); + }; + + struct X { + X(auto_ptr); + }; + + X f() { + X x(auto_ptr(new int)); + return X(auto_ptr(new int)); + } + + auto_ptr foo(); + + X e(foo()); + + struct Y { + Y(X); + }; + + Y f2(foo()); +} + +namespace PR7934 { + typedef unsigned char uint8; + + struct MutablePtr { + MutablePtr() : ptr(0) {} + void *ptr; + + operator void*() { return ptr; } + + private: + operator uint8*() { return reinterpret_cast<uint8*>(ptr); } + operator const char*() const { return reinterpret_cast<const char*>(ptr); } + }; + + void fake_memcpy(const void *); + + void use() { + MutablePtr ptr; + fake_memcpy(ptr); + } +} + +namespace rdar8018274 { + struct X { }; + struct Y { + operator const struct X *() const; + }; + + struct Z : Y { + operator struct X * (); + }; + + void test() { + Z x; + (void) (x != __null); + } + + + struct Base { + operator int(); + }; + + struct Derived1 : Base { }; + + struct Derived2 : Base { }; + + struct SuperDerived : Derived1, Derived2 { + using Derived1::operator int; + }; + + struct UeberDerived : SuperDerived { + operator long(); + }; + + void test2(UeberDerived ud) { + int i = ud; // expected-error{{ambiguous conversion from derived class 'rdar8018274::SuperDerived' to base class 'rdar8018274::Base'}} + } + + struct Base2 { + operator int(); + }; + + struct Base3 { + operator int(); + }; + + struct Derived23 : Base2, Base3 { + using Base2::operator int; + }; + + struct ExtraDerived23 : Derived23 { }; + + void test3(ExtraDerived23 ed) { + int i = ed; + } +} + +namespace PR8065 { + template <typename T> struct Iterator; + template <typename T> struct Container; + + template<> + struct Iterator<int> { + typedef Container<int> container_type; + }; + + template <typename T> + struct Container { + typedef typename Iterator<T>::container_type X; + operator X(void) { return X(); } + }; + + Container<int> test; +} + +namespace PR8034 { + struct C { + operator int(); + + private: + template <typename T> operator T(); + }; + int x = C().operator int(); +} + +namespace PR9336 { + template<class T> + struct generic_list + { + template<class Container> + operator Container() + { + Container ar; + T* i; + ar[0]=*i; + return ar; + } + }; + + template<class T> + struct array + { + T& operator[](int); + const T& operator[](int)const; + }; + + generic_list<generic_list<int> > l; + array<array<int> > a = l; +} + +namespace PR8800 { + struct A; + struct C { + operator A&(); + }; + void f() { + C c; + A& a1(c); + A& a2 = c; + A& a3 = static_cast<A&>(c); + A& a4 = (A&)c; + } +} |