Clang Project

clang_source_code/test/SemaTemplate/virtual-member-functions.cpp
1// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify %s
2// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify -std=c++98 %s
3// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify -std=c++11 %s
4// RUN: %clang_cc1 -triple %ms_abi_triple -DMSABI -fsyntax-only -verify %s
5// RUN: %clang_cc1 -triple %ms_abi_triple -DMSABI -fsyntax-only -std=c++98 -verify %s
6// RUN: %clang_cc1 -triple %ms_abi_triple -DMSABI -fsyntax-only -std=c++11 -verify %s
7
8namespace PR5557 {
9template <class T> struct A {
10  A(); // expected-note{{instantiation}}
11  virtual int a(T x);
12};
13template<class T> A<T>::A() {}
14
15template<class T> int A<T>::a(T x) { 
16  return *x; // expected-error{{requires pointer operand}}
17}
18
19void f() {
20  A<int> x; // expected-note{{instantiation}}
21}
22
23template<typename T>
24struct X {
25  virtual void f();
26};
27
28template<>
29void X<int>::f() { }
30}
31
32// Like PR5557, but with a defined destructor instead of a defined constructor.
33namespace PR5557_dtor {
34template <class T> struct A {
35  A(); // Don't have an implicit constructor.
36  ~A(); // expected-note{{instantiation}}
37  virtual int a(T x);
38};
39template<class T> A<T>::~A() {}
40
41template<class T> int A<T>::a(T x) { 
42  return *x; // expected-error{{requires pointer operand}}
43}
44
45void f() {
46  A<int> x; // expected-note{{instantiation}}
47}
48}
49
50template<typename T>
51struct Base {
52  virtual ~Base() { 
53    int *ptr = 0;
54    T t = ptr; // expected-error{{cannot initialize}}
55  }
56};
57
58template<typename T>
59struct Derived : Base<T> {
60  virtual void foo() { }
61};
62
63template struct Derived<int>; // expected-note {{in instantiation of member function 'Base<int>::~Base' requested here}}
64
65template<typename T>
66struct HasOutOfLineKey {
67  HasOutOfLineKey() { } // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::f' requested here}}
68  virtual T *f(float *fp);
69};
70
71template<typename T>
72T *HasOutOfLineKey<T>::f(float *fp) {
73  return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}}
74}
75
76HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::HasOutOfLineKey' requested here}}
77
78namespace std {
79  class type_info;
80}
81
82namespace PR7114 {
83  class A { virtual ~A(); };
84#if __cplusplus <= 199711L
85  // expected-note@-2{{declared private here}}
86#else
87  // expected-note@-4 3 {{overridden virtual function is here}}
88#endif
89
90  template<typename T>
91  class B {
92  public:
93    class Inner : public A { };
94#if __cplusplus <= 199711L
95// expected-error@-2{{base class 'PR7114::A' has private destructor}}
96#else
97// expected-error@-4 2 {{deleted function '~Inner' cannot override a non-deleted function}}
98// expected-note@-5 2 {{destructor of 'Inner' is implicitly deleted because base class 'PR7114::A' has an inaccessible destructor}}
99#ifdef MSABI
100// expected-note@-7 1 {{destructor of 'Inner' is implicitly deleted because base class 'PR7114::A' has an inaccessible destructor}}
101#endif
102#endif
103
104    static Inner i;
105    static const unsigned value = sizeof(i) == 4;
106#if __cplusplus >= 201103L
107// expected-note@-2 {{in instantiation of member class 'PR7114::B<int>::Inner' requested here}}
108// expected-note@-3 {{in instantiation of member class 'PR7114::B<float>::Inner' requested here}}
109#endif
110  };
111
112  int f() { return B<int>::value; }
113#if __cplusplus >= 201103L
114// expected-note@-2 {{in instantiation of template class 'PR7114::B<int>' requested here}}
115#endif
116
117#ifdef MSABI
118  void test_typeid(B<float>::Inner bfi) {
119#if __cplusplus <= 199711L
120// expected-note@-2 {{implicit destructor}}
121#else
122// expected-error@-4 {{attempt to use a deleted function}}
123// expected-note@-5 {{in instantiation of template class 'PR7114::B<float>' requested here}}
124#endif
125
126    (void)typeid(bfi);
127#else
128  void test_typeid(B<float>::Inner bfi) {
129#if __cplusplus >= 201103L
130// expected-note@-2 {{in instantiation of template class 'PR7114::B<float>' requested here}}
131#endif
132    (void)typeid(bfi);
133#if __cplusplus <= 199711L
134// expected-note@-2 {{implicit destructor}}
135#endif
136#endif
137  }
138
139  template<typename T>
140  struct X : A {
141#if __cplusplus >= 201103L
142// expected-error@-2 {{deleted function '~X' cannot override a non-deleted function}}
143// expected-note@-3  {{destructor of 'X<int>' is implicitly deleted because base class 'PR7114::A' has an inaccessible destructor}}
144#endif
145    void f() { }
146  };
147
148  void test_X(X<int> &xi, X<float> &xf) {
149    xi.f();
150#if __cplusplus >= 201103L
151// expected-note@-2 {{in instantiation of template class 'PR7114::X<int>' requested here}}
152#endif
153  }
154}
155
156namespace DynamicCast {
157  struct Y {};
158  template<typename T> struct X : virtual Y {
159    virtual void foo() { T x; }
160  };
161  template<typename T> struct X2 : virtual Y {
162    virtual void foo() { T x; }
163  };
164  Y* f(X<void>* x) { return dynamic_cast<Y*>(x); }
165  Y* f2(X<void>* x) { return dynamic_cast<Y*>(x); }
166}
167
168namespace avoid_using_vtable {
169// We shouldn't emit the vtable for this code, in any ABI.  If we emit the
170// vtable, we emit an implicit virtual dtor, which calls ~RefPtr, which requires
171// a complete type for DeclaredOnly.
172//
173// Previously we would reference the vtable in the MS C++ ABI, even though we
174// don't need to emit either the ctor or the dtor.  In the Itanium C++ ABI, the
175// 'trace' method is the key function, so even though we use the vtable, we
176// don't emit it.
177
178template <typename T>
179struct RefPtr {
180  T *m_ptr;
181  ~RefPtr() { m_ptr->deref(); }
182};
183struct DeclaredOnly;
184struct Base {
185  virtual ~Base();
186};
187
188struct AvoidVTable : Base {
189  RefPtr<DeclaredOnly> m_insertionStyle;
190  virtual void trace();
191  AvoidVTable();
192};
193// Don't call the dtor, because that will emit an implicit dtor, and require a
194// complete type for DeclaredOnly.
195void foo() { new AvoidVTable; }
196}
197
198namespace vtable_uses_incomplete {
199// Opposite of the previous test that avoids a vtable, this one tests that we
200// use the vtable when the ctor is defined inline.
201template <typename T>
202struct RefPtr {
203  T *m_ptr;
204  ~RefPtr() { m_ptr->deref(); }  // expected-error {{member access into incomplete type 'vtable_uses_incomplete::DeclaredOnly'}}
205};
206struct DeclaredOnly; // expected-note {{forward declaration of 'vtable_uses_incomplete::DeclaredOnly'}}
207struct Base {
208  virtual ~Base();
209};
210
211struct UsesVTable : Base {
212  RefPtr<DeclaredOnly> m_insertionStyle;
213  virtual void trace();
214  UsesVTable() {} // expected-note {{in instantiation of member function 'vtable_uses_incomplete::RefPtr<vtable_uses_incomplete::DeclaredOnly>::~RefPtr' requested here}}
215};
216}
217