1 // RUN: %check_clang_tidy %s misc-definitions-in-headers %t
2
f()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: make as 'inline'
6 // CHECK-FIXES: inline int f() {
7 return 1;
8 }
9
10 class CA {
f1()11 void f1() {} // OK: inline class member function definition.
12 void f2();
13 template<typename T>
f3()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
f2()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 <>
f3()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>
f4()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>
f1()54 void CB<T>::f1() { // OK: Member function definition of a class template.
55 }
56
57 template <typename T>
f2(T a)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>
f3()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.
callCB()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>
tf()82 T tf() { // OK: template function definition.
83 T a;
84 return a;
85 }
86
87
88 namespace NA {
f()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>
f3()95 T f3() {
96 T a = 1;
97 return a;
98 }
99
100 template <>
f3()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.
f6()109 inline int f6() { return 1; } // OK: inline function definition.
110 namespace {
f7()111 int f7() { return 1; }
112 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: function 'f7' defined in a header file;
113 }
114
115 int f8() = delete; // OK: the function being marked delete is not callable.
116
117 template <typename T>
f9(T t)118 int f9(T t) { return 1; }
119
callF9()120 inline void callF9() { f9(1); } // OK: implicitly instantiated function.
121 template int f9(double); // OK: explicitly instantiated function.
122
123 int a = 1;
124 // 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]
125 CA a1;
126 // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: variable 'a1' defined in a header file;
127
128 namespace NB {
129 int b = 1;
130 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'b' defined in a header file;
131 const int c = 1; // OK: internal linkage variable definition.
132 }
133
134 class CC {
135 static int d; // OK: class static data member declaration.
136 };
137
138 int CC::d = 1;
139 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: variable 'd' defined in a header file;
140
141 const char* ca = "foo";
142 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'ca' defined in a header file;
143
144 namespace {
145 int e = 2;
146 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'e' defined in a header file;
147 }
148
149 const char* const g = "foo"; // OK: internal linkage variable definition.
150 static int h = 1; // OK: internal linkage variable definition.
151 const int i = 1; // OK: internal linkage variable definition.
152 extern int j; // OK: internal linkage variable definition.
153
154 template <typename T, typename U>
155 struct CD {
156 int f();
157 };
158
159 template <typename T>
160 struct CD<T, int> {
161 int f();
162 };
163
164 template <>
165 struct CD<int, int> {
166 int f();
167 };
168
f()169 int CD<int, int>::f() {
170 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: function 'f' defined in a header file;
171 // CHECK-FIXES: inline int CD<int, int>::f() {
172 return 0;
173 }
174
175 template <typename T>
f()176 int CD<T, int>::f() { // OK: partial template specialization.
177 return 0;
178 }
179
180 constexpr int k = 1; // OK: constexpr variable has internal linkage.
181
f10()182 constexpr int f10() { return 0; } // OK: constexpr function definition.
183
f11()184 const int f11() { return 0; }
185 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: function 'f11' defined in a header file;
186 // CHECK-FIXES: inline const int f11() { return 0; }
187
188 template <typename T>
189 const T f12();
190
191 template <>
f12()192 const int f12() { return 0; }
193 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: full function template specialization 'f12<int>' defined in a header file;
194 // CHECK-FIXES: inline const int f12() { return 0; }
195