| // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s |
| |
| struct A { }; |
| A::A() { } // expected-error {{definition of implicitly declared default constructor}} |
| |
| struct B { }; |
| B::B(const B&) { } // expected-error {{definition of implicitly declared copy constructor}} |
| |
| struct C { }; |
| C& C::operator=(const C&) { return *this; } // expected-error {{definition of implicitly declared copy assignment operator}} |
| |
| struct D { }; |
| D::~D() { } // expected-error {{definition of implicitly declared destructor}} |
| |
| // Make sure that the special member functions are introduced for |
| // name-lookup purposes and overload with user-declared |
| // constructors and assignment operators. |
| namespace PR6570 { |
| class A { }; |
| |
| class B { |
| public: |
| B() {} |
| |
| B(const A& a) { |
| operator = (CONST); |
| operator = (a); |
| } |
| |
| B& operator = (const A& a) { |
| return *this; |
| } |
| |
| void f(const A &a) { |
| B b(a); |
| }; |
| |
| static const B CONST; |
| }; |
| |
| } |
| |
| namespace PR7594 { |
| // If the lazy declaration of special member functions is triggered |
| // in an out-of-line initializer, make sure the functions aren't in |
| // the initializer scope. This used to crash Clang: |
| struct C { |
| C(); |
| static C *c; |
| }; |
| C *C::c = new C(); |
| } |
| |
| namespace Recursion { |
| template<typename T> struct InvokeCopyConstructor { |
| static const T &get(); |
| typedef decltype(T(get())) type; // expected-error {{no matching conver}} |
| }; |
| struct B; |
| struct A { |
| typedef B type; |
| template<typename T, |
| typename = typename InvokeCopyConstructor<typename T::type>::type> |
| // expected-note@-1 {{in instantiation of template class}} |
| A(const T &); |
| // expected-note@-1 {{in instantiation of default argument}} |
| // expected-note@-2 {{while substituting deduced template arguments}} |
| }; |
| struct B { // expected-note {{candidate constructor (the implicit move }} |
| B(); // expected-note {{candidate constructor not viable}} |
| A a; |
| }; |
| // Triggering the declaration of B's copy constructor causes overload |
| // resolution to occur for A's copying constructor, which instantiates |
| // InvokeCopyConstructor<B>, which triggers the declaration of B's copy |
| // constructor. Notionally, this happens when we get to the end of the |
| // definition of 'struct B', so there is no declared copy constructor yet. |
| // |
| // This behavior is g++-compatible, but isn't exactly right; the class is |
| // supposed to be incomplete when we implicitly declare its special members. |
| B b = B(); |
| |
| |
| // Another case, which isn't ill-formed under our rules. This is inspired by |
| // a problem which occurs when combining CGAL with libstdc++-4.7. |
| |
| template<typename T> T &&declval(); |
| template<typename T, typename U> struct pair { |
| pair(); |
| template<typename V, typename W, |
| typename = decltype(T(declval<const V&>())), |
| typename = decltype(U(declval<const W&>()))> |
| pair(const pair<V,W> &); |
| }; |
| |
| template<typename K> struct Line; |
| |
| template<typename K> struct Vector { |
| Vector(const Line<K> &l); |
| }; |
| |
| template<typename K> struct Point { |
| Vector<K> v; |
| }; |
| |
| template<typename K> struct Line { |
| pair<Point<K>, Vector<K>> x; |
| }; |
| |
| // Trigger declaration of Line copy ctor, which causes substitution into |
| // pair's templated constructor, which triggers instantiation of the |
| // definition of Point's copy constructor, which performs overload resolution |
| // on Vector's constructors, which requires declaring all of Line's |
| // constructors. That should not find a copy constructor (because we've not |
| // declared it yet), but by the time we get all the way back here, we should |
| // find the copy constructor. |
| Line<void> L1; |
| Line<void> L2(L1); |
| } |