xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/misc/definitions-in-headers.hpp (revision 50320ec967a2c6546e53998225dddb76c4016dc5)
1 // RUN: %check_clang_tidy %s misc-definitions-in-headers %t -- --fix-notes
2 
3 int f() {
4 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f' defined in a header file; function definitions in header files can lead to ODR violations [misc-definitions-in-headers]
5 // CHECK-MESSAGES: :[[@LINE-2]]:5: note: mark the definition as 'inline'
6 // CHECK-FIXES: inline int f() {
7   return 1;
8 }
9 
10 class CA {
11   void f1() {} // OK: inline class member function definition.
12   void f2();
13   template<typename T>
14   T f3() {
15     T a = 1;
16     return a;
17   }
18   template<typename T>
19   struct CAA {
20     struct CAB {
21       void f4();
22     };
23   };
24 };
25 
26 void CA::f2() { }
27 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: function 'f2' defined in a header file;
28 // CHECK-FIXES: inline void CA::f2() {
29 
30 template <>
31 int CA::f3() {
32 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: full function template specialization 'f3<int>' defined in a header file;
33 // CHECK-FIXES: inline int CA::f3() {
34   int a = 1;
35   return a;
36 }
37 
38 template <typename T>
39 void CA::CAA<T>::CAB::f4() {
40 // OK: member function definition of a nested template class in a class.
41 }
42 
43 template <typename T>
44 struct CB {
45   void f1();
46   struct CCA {
47     void f2(T a);
48   };
49   struct CCB;  // OK: forward declaration.
50   static int a; // OK: class static data member declaration.
51 };
52 
53 template <typename T>
54 void CB<T>::f1() { // OK: Member function definition of a class template.
55 }
56 
57 template <typename T>
58 void CB<T>::CCA::f2(T a) {
59 // OK: member function definition of a nested class in a class template.
60 }
61 
62 template <typename T>
63 struct CB<T>::CCB {
64   void f3();
65 };
66 
67 template <typename T>
68 void CB<T>::CCB::f3() {
69 // OK: member function definition of a nested class in a class template.
70 }
71 
72 template <typename T>
73 int CB<T>::a = 2; // OK: static data member definition of a class template.
74 
75 template class CB<int>; // OK: explicitly instantiated static data member of a class template.
76 inline int callCB() {
77   CB<double> cb; // OK: implicitly instantiated static data member of a class template.
78   return cb.a;
79 }
80 
81 template <typename T>
82 T tf() { // OK: template function definition.
83   T a;
84   return a;
85 }
86 
87 
88 namespace NA {
89   int f() { return 1; }
90 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: function 'f' defined in a header file;
91 // CHECK-FIXES: inline int f() { return 1; }
92 }
93 
94 template <typename T>
95 T f3() {
96   T a = 1;
97   return a;
98 }
99 
100 template <>
101 int f3() {
102 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: full function template specialization 'f3<int>' defined in a header file;
103 // CHECK-FIXES: inline int f3() {
104   int a = 1;
105   return a;
106 }
107 
108 int f5(); // OK: function declaration.
109 inline int f6() { return 1; } // OK: inline function definition.
110 namespace {
111   int f7() { return 1; }  // OK: each TU defines the function in a unique namespace.
112 }
113 
114 int f8() = delete; // OK: the function being marked delete is not callable.
115 
116 template <typename T>
117 int f9(T t) { return 1; }
118 
119 inline void callF9() { f9(1); } // OK: implicitly instantiated function.
120 template int f9(double); // OK: explicitly instantiated function.
121 
122 int a = 1;
123 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'a' defined in a header file; variable definitions in header files can lead to ODR violations [misc-definitions-in-headers]
124 CA a1;
125 // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: variable 'a1' defined in a header file;
126 
127 namespace NB {
128   int b = 1;
129 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'b' defined in a header file;
130   const int c = 1; // OK: internal linkage variable definition.
131 }
132 
133 class CC {
134   static int d; // OK: class static data member declaration.
135 };
136 
137 int CC::d = 1;
138 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: variable 'd' defined in a header file;
139 
140 const char* ca = "foo";
141 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'ca' defined in a header file;
142 
143 namespace {
144   int e = 2;  // OK: each TU defines the variable in a unique namespace.
145 }
146 
147 const char* const g = "foo"; // OK: internal linkage variable definition.
148 static int h = 1; // OK: internal linkage variable definition.
149 const int i = 1; // OK: internal linkage variable definition.
150 extern int j; // OK: internal linkage variable definition.
151 
152 template <typename T, typename U>
153 struct CD {
154   int f();
155 };
156 
157 template <typename T>
158 struct CD<T, int> {
159   int f();
160 };
161 
162 template <>
163 struct CD<int, int> {
164   int f();
165 };
166 
167 int CD<int, int>::f() {
168 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: function 'f' defined in a header file;
169 // CHECK-FIXES: inline int CD<int, int>::f() {
170   return 0;
171 }
172 
173 template <typename T>
174 int CD<T, int>::f() { // OK: partial template specialization.
175   return 0;
176 }
177 
178 constexpr int k = 1; // OK: constexpr variable has internal linkage.
179 
180 constexpr int f10() { return 0; } // OK: constexpr function definition.
181 
182 const int f11() { return 0; }
183 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: function 'f11' defined in a header file;
184 // CHECK-FIXES: inline const int f11() { return 0; }
185 
186 template <typename T>
187 const T f12();
188 
189 template <>
190 const int f12() { return 0; }
191 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: full function template specialization 'f12<int>' defined in a header file;
192 // CHECK-FIXES: inline const int f12() { return 0; }
193 
194 template <typename T1, typename T2>
195 constexpr bool f13 = false;
196 
197 template <typename T>
198 constexpr bool f13<T, int> = true; // OK: template partial specialization
199 
200 template <>
201 constexpr bool f13<void, int> = false;
202 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: variable 'f13<void, int>' defined in a header file;
203 
204 int main() {}
205 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'main' defined in a header file;
206 // CHECK-FIXES: {{^}}int main() {
207