1 //===--- fwd_decl_nested_class.cc - test input file for iwyu --------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // Various tests of the handling of the forward declaration of nested
11 // classes. For some uses the forward declaration is needed, for
12 // others it isn't.
13 
TplFn()14 template<typename T> void TplFn() { T t; (void)t; }
15 
16 class Foo {
17   class NoUsage;  // Unnecessary -- defined inline later in the class.
18   class NoUsageDefinedOutOfLine;  // Necessary -- part of the public API.
19   class UsedAsPtrInMethod;  // Unnecessary -- all uses see the later dfn.
20   class UsedFullyInMethod;  // Unnecessary -- all uses see the later dfn.
21   class UsedFullyInInitializer;  // Unnecessary -- same as in a method.
22   class UsedImplicitlyInInitializer;  // Unnecessary -- same as explicit use.
23   class UsedInTypedef;  // Necessary -- this use doesn't see the later dfn.
24   class UsedAsPtrArg;  // Necessary -- this use doesn't see the later dfn.
25   class UsedAsPtrReturn;  // Necessary -- this use doesn't see the later dfn.
26   class UsedAsPtrMember;  // Necessary -- this use doesn't see the later dfn.
27   class UsedAsFriend;  // Necessary -- used as part of a friend declaration
28 
29   friend class Foo::UsedAsFriend;
30 
Foo()31   Foo() : init_(UsedFullyInInitializer()) { }
~Foo()32   ~Foo() { }
33 
34   // If a nested class is used in a body of a method, no preceding
35   // declaration/definition is needed.
Bar1()36   void Bar1() {
37     UsedAsPtrInMethod* x;
38   }
Bar2()39   void Bar2() {
40     UsedFullyInMethod x;
41     UsedFullyInMethodNotForwardDeclared y;
42     // Make sure we don't have trouble saying we're inside a method
43     // even when templates get in the way.
44     TplFn<UsedFullyInMethodNotForwardDeclared>();
45   }
46 
47   // If a nested class is used in a typedef, a preceding declaration
48   // is needed.
49   typedef UsedInTypedef UsedInTypedefType;
50 
51   // If a nested class is used in a method declaration, a preceding
52   // declaration is needed.
53   void Bar3(UsedAsPtrArg* p);
54   UsedAsPtrReturn* Bar4();
55 
56   UsedAsPtrMember* x_;
57 
58   class NoUsage { };
59   class UsedAsPtrInMethod { };
60   class UsedFullyInMethod { };
61   class UsedFullyInInitializer { };
62   class UsedImplicitlyInInitializer { };
63   class UsedImplicitlyInInitializerNeverDeclared { };
64   class UsedAsPtrArg { };
65   class UsedAsPtrReturn { };
66   class UsedAsPtrMember { };
67   struct UsedFullyInMethodNotForwardDeclared { };
68   class UsedAsFriend { };
69 
70   UsedFullyInInitializer init_;
71   UsedImplicitlyInInitializer implicit_;
72   UsedImplicitlyInInitializerNeverDeclared implicit_never_declared_;
73   UsedImplicitlyInInitializerNeverDeclared* implicit_never_declared_ptr_;
74 };
75 
76 class Foo::NoUsageDefinedOutOfLine {};
77 
78 // Now do the same thing again, but the nested classes are all templated.
79 
80 class Outer {
81   template<typename T> class NoUsage;  // Unnecessary
82   template<typename T> class NoUsageDefinedOutOfLine;  // Necessary
83   template<typename T> class NoUsageDefinedOutOfLine;  // Unnecessary
84   template<typename T> class UsedAsPtrInMethod;  // Unnecessary
85   template<typename T> class UsedFullyInMethod;  // Unnecessary
86   template<typename T> class UsedFullyInInitializer;  // Unnecessary
87   template<typename T> class UsedImplicitlyInInitializer;  // Unnecessary
88   template<typename T> class UsedInTypedef;  // Necessary
89   template<typename T> class UsedAsPtrArg;  // Necessary
90   template<typename T> class UsedAsPtrReturn;  // Necessary
91   template<typename T> class UsedAsPtrMember;  // Necessary
92   template<typename T> class UsedAsFriend;  // Necessary
93 
94   friend class Outer::UsedAsFriend<int>;
95 
Outer()96   Outer() : init_(UsedFullyInInitializer<int>()) { }
~Outer()97   ~Outer() { }
98 
99   // If a nested class is used in a body of a method, no preceding
100   // declaration/definition is needed.
Bar1()101   void Bar1() {
102     UsedAsPtrInMethod<int>* x;
103   }
Bar2()104   void Bar2() {
105     UsedFullyInMethod<int> x;
106     UsedFullyInMethodNotForwardDeclared<int> y;
107     TplFn<UsedFullyInMethodNotForwardDeclared<int> >();
108   }
109 
110   // If a nested class is used in a typedef, a preceding declaration
111   // is needed.
112   typedef UsedInTypedef<int> UsedInTypedefType;
113 
114   // If a nested class is used in a method declaration, a preceding
115   // declaration is needed.
116   void Bar3(UsedAsPtrArg<int>* p);
117   UsedAsPtrReturn<int>* Bar4();
118 
119   UsedAsPtrMember<int>* x_;
120 
121   template<typename T> class NoUsage { };
122   template<typename T> class UsedAsPtrInMethod { };
123   template<typename T> class UsedFullyInMethod { };
124   template<typename T> class UsedFullyInInitializer { };
125   template<typename T> class UsedImplicitlyInInitializer { };
126   template<typename T> class UsedImplicitlyInInitializerNeverDeclared { };
127   template<typename T> class UsedAsPtrArg { };
128   template<typename T> class UsedAsPtrReturn { };
129   template<typename T> class UsedAsPtrMember { };
130   template<typename T> class UsedFullyInMethodNotForwardDeclared { };
131   template<typename T> class UsedAsFriend { };
132 
133   UsedFullyInInitializer<int> init_;
134   UsedImplicitlyInInitializer<int> implicit_;
135   UsedImplicitlyInInitializerNeverDeclared<int> implicit_never_declared_;
136   UsedImplicitlyInInitializerNeverDeclared<int>* implicit_never_declared_ptr_;
137 };
138 
139 template<typename T> class Outer::NoUsageDefinedOutOfLine {};
140 
141 
142 // Now do the same thing again, but the containing class is templated
143 
144 template<class T>
145 class Container {
146   class NoUsage;  // Unnecessary
147   class UsedAsPtrInMethod;  // Unnecessary
148   class UsedFullyInMethod;  // Unnecessary
149   class UsedFullyInInitializer;  // Unnecessary
150   class UsedImplicitlyInInitializer;  // Unnecessary
151   class UsedInTypedef;  // Necessary
152   class UsedAsPtrArg;  // Necessary
153   class UsedAsPtrReturn;  // Necessary
154   class UsedAsPtrMember;  // Necessary
155   class UsedAsFriend;  // Necessary
156 
157   friend class Container<T>::UsedAsFriend;
158 
Container()159   Container() : init_(UsedFullyInInitializer()) { }
~Container()160   ~Container() { }
161 
162   // If a nested class is used in a body of a method, no preceding
163   // declaration/definition is needed.
Bar1()164   void Bar1() {
165     UsedAsPtrInMethod* x;
166   }
Bar2()167   void Bar2() {
168     UsedFullyInMethod x;
169     UsedFullyInMethodNotForwardDeclared y;
170     TplFn<UsedFullyInMethodNotForwardDeclared>();
171   }
172 
173   // If a nested class is used in a typedef, a preceding declaration
174   // is needed.
175   typedef UsedInTypedef UsedInTypedefType;
176 
177   // If a nested class is used in a method declaration, a preceding
178   // declaration is needed.
179   void Bar3(UsedAsPtrArg* p);
180   UsedAsPtrReturn* Bar4();
181 
182   UsedAsPtrMember* x_;
183 
184   class NoUsage { };
185   class UsedAsPtrInMethod { };
186   class UsedFullyInMethod { };
187   class UsedFullyInInitializer { };
188   class UsedImplicitlyInInitializer { };
189   class UsedImplicitlyInInitializerNeverDeclared { };
190   class UsedAsPtrArg { };
191   class UsedAsPtrReturn { };
192   class UsedAsPtrMember { };
193   class UsedFullyInMethodNotForwardDeclared { };
194   class UsedAsFriend { };
195 
196   UsedFullyInInitializer init_;
197   UsedImplicitlyInInitializer implicit_;
198   UsedImplicitlyInInitializerNeverDeclared implicit_never_declared_;
199   UsedImplicitlyInInitializerNeverDeclared* implicit_never_declared_ptr_;
200 };
201 
202 /**** IWYU_SUMMARY
203 
204 tests/cxx/fwd_decl_nested_class.cc should add these lines:
205 
206 tests/cxx/fwd_decl_nested_class.cc should remove these lines:
207 - class Container::NoUsage;  // lines XX-XX
208 - class Container::UsedAsPtrInMethod;  // lines XX-XX
209 - class Container::UsedFullyInInitializer;  // lines XX-XX
210 - class Container::UsedFullyInMethod;  // lines XX-XX
211 - class Container::UsedImplicitlyInInitializer;  // lines XX-XX
212 - class Foo::NoUsage;  // lines XX-XX
213 - class Foo::UsedAsPtrInMethod;  // lines XX-XX
214 - class Foo::UsedFullyInInitializer;  // lines XX-XX
215 - class Foo::UsedFullyInMethod;  // lines XX-XX
216 - class Foo::UsedImplicitlyInInitializer;  // lines XX-XX
217 - template <typename T> class Outer::NoUsage;  // lines XX-XX
218 - template <typename T> class Outer::NoUsageDefinedOutOfLine;  // lines XX-XX
219 - template <typename T> class Outer::UsedAsPtrInMethod;  // lines XX-XX
220 - template <typename T> class Outer::UsedFullyInInitializer;  // lines XX-XX
221 - template <typename T> class Outer::UsedFullyInMethod;  // lines XX-XX
222 - template <typename T> class Outer::UsedImplicitlyInInitializer;  // lines XX-XX
223 
224 The full include-list for tests/cxx/fwd_decl_nested_class.cc:
225 class Container::UsedAsFriend;  // lines XX-XX
226 class Container::UsedAsPtrArg;  // lines XX-XX
227 class Container::UsedAsPtrMember;  // lines XX-XX
228 class Container::UsedAsPtrReturn;  // lines XX-XX
229 class Container::UsedInTypedef;  // lines XX-XX
230 class Foo::NoUsageDefinedOutOfLine;  // lines XX-XX
231 class Foo::UsedAsFriend;  // lines XX-XX
232 class Foo::UsedAsPtrArg;  // lines XX-XX
233 class Foo::UsedAsPtrMember;  // lines XX-XX
234 class Foo::UsedAsPtrReturn;  // lines XX-XX
235 class Foo::UsedInTypedef;  // lines XX-XX
236 template <typename T> class Outer::NoUsageDefinedOutOfLine;  // lines XX-XX
237 template <typename T> class Outer::UsedAsFriend;  // lines XX-XX
238 template <typename T> class Outer::UsedAsPtrArg;  // lines XX-XX
239 template <typename T> class Outer::UsedAsPtrMember;  // lines XX-XX
240 template <typename T> class Outer::UsedAsPtrReturn;  // lines XX-XX
241 template <typename T> class Outer::UsedInTypedef;  // lines XX-XX
242 
243 ***** IWYU_SUMMARY */
244