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