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