1 // RUN: %check_clang_tidy %s bugprone-forward-declaration-namespace %t
2 
3 namespace {
4 // This is a declaration in a wrong namespace.
5 class T_A;
6 // CHECK-NOTES: :[[@LINE-1]]:7: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace 'na' [bugprone-forward-declaration-namespace]
7 // CHECK-NOTES: note: a declaration of 'T_A' is found here
8 // CHECK-NOTES: :[[@LINE-3]]:7: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)' [bugprone-forward-declaration-namespace]
9 // CHECK-NOTES: note: a definition of 'T_A' is found here
10 }
11 
12 namespace na {
13 // This is a declaration in a wrong namespace.
14 class T_A;
15 // CHECK-NOTES: :[[@LINE-1]]:7: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace '(anonymous)'
16 // CHECK-NOTES: note: a declaration of 'T_A' is found here
17 // CHECK-NOTES: :[[@LINE-3]]:7: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)'
18 // CHECK-NOTES: note: a definition of 'T_A' is found here
19 }
20 
21 class T_A;
22 
23 class T_A {
24   int x;
25 };
26 
27 class NESTED;
28 // CHECK-NOTES: :[[@LINE-1]]:7: warning: no definition found for 'NESTED', but a definition with the same name 'NESTED' found in another namespace '(anonymous namespace)::nq::(anonymous)'
29 // CHECK-NOTES: note: a definition of 'NESTED' is found here
30 
31 namespace {
32 namespace nq {
33 namespace {
34 class NESTED {};
35 }
36 }
37 }
38 
39 namespace na {
40 class T_B;
41 // CHECK-NOTES: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'
42 // CHECK-NOTES: note: a declaration of 'T_B' is found here
43 // CHECK-NOTES: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'
44 // CHECK-NOTES: note: a definition of 'T_B' is found here
45 }
46 
47 namespace nb {
48 class T_B;
49 }
50 
51 namespace nb {
52 class T_B {
53   int x;
54 };
55 }
56 
57 namespace na {
58 class T_B;
59 // CHECK-NOTES: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'
60 // CHECK-NOTES: note: a declaration of 'T_B' is found here
61 // CHECK-NOTES: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'
62 // CHECK-NOTES: note: a definition of 'T_B' is found here
63 }
64 
65 // A simple forward declaration. Although it is never used, but no declaration
66 // with the same name is found in other namespace.
67 class OUTSIDER;
68 
69 namespace na {
70 // This class is referenced declaration, we don't generate warning.
71 class OUTSIDER_1;
72 }
73 
74 void f(na::OUTSIDER_1);
75 
76 namespace nc {
77 // This class is referenced as friend in OOP.
78 class OUTSIDER_1;
79 
80 class OOP {
81   friend struct OUTSIDER_1;
82 };
83 }
84 
85 namespace nd {
86 class OUTSIDER_1;
87 void f(OUTSIDER_1 *);
88 }
89 
90 namespace nb {
91 class OUTSIDER_1;
92 // CHECK-NOTES: :[[@LINE-1]]:7: warning: declaration 'OUTSIDER_1' is never referenced, but a declaration with the same name found in another namespace 'na'
93 // CHECK-NOTES: note: a declaration of 'OUTSIDER_1' is found here
94 }
95 
96 
97 namespace na {
98 template<typename T>
99 class T_C;
100 }
101 
102 namespace nb {
103 // FIXME: this is an error, but we don't consider template class declaration
104 // now.
105 template<typename T>
106 class T_C;
107 }
108 
109 namespace na {
110 template<typename T>
111 class T_C {
112   int x;
113 };
114 }
115 
116 namespace na {
117 
118 template <typename T>
119 class T_TEMP {
120   template <typename _Tp1>
121   struct rebind { typedef T_TEMP<_Tp1> other; };
122 };
123 
124 // We ignore class template specialization.
125 template class T_TEMP<char>;
126 }
127 
128 namespace nb {
129 
130 template <typename T>
131 class T_TEMP_1 {
132   template <typename _Tp1>
133   struct rebind { typedef T_TEMP_1<_Tp1> other; };
134 };
135 
136 // We ignore class template specialization.
137 extern template class T_TEMP_1<char>;
138 }
139 
140 namespace nd {
141 class D;
142 // CHECK-NOTES: :[[@LINE-1]]:7: warning: declaration 'D' is never referenced, but a declaration with the same name found in another namespace 'nd::ne'
143 // CHECK-NOTES: note: a declaration of 'D' is found here
144 }
145 
146 namespace nd {
147 namespace ne {
148 class D;
149 }
150 }
151 
152 int f(nd::ne::D &d);
153 
154 
155 // This should be ignored by the check.
156 template <typename... Args>
157 class Observer {
158   class Impl;
159 };
160 
161 template <typename... Args>
162 class Observer<Args...>::Impl {
163 };
164