xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/misc/definitions-in-headers.hpp (revision 50320ec967a2c6546e53998225dddb76c4016dc5)
189a1d03eSRichard // RUN: %check_clang_tidy %s misc-definitions-in-headers %t -- --fix-notes
289a1d03eSRichard 
389a1d03eSRichard int f() {
489a1d03eSRichard // 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*50320ec9SJulian Schmidt // CHECK-MESSAGES: :[[@LINE-2]]:5: note: mark the definition as 'inline'
689a1d03eSRichard // CHECK-FIXES: inline int f() {
789a1d03eSRichard   return 1;
889a1d03eSRichard }
989a1d03eSRichard 
1089a1d03eSRichard class CA {
1189a1d03eSRichard   void f1() {} // OK: inline class member function definition.
1289a1d03eSRichard   void f2();
1389a1d03eSRichard   template<typename T>
1489a1d03eSRichard   T f3() {
1589a1d03eSRichard     T a = 1;
1689a1d03eSRichard     return a;
1789a1d03eSRichard   }
1889a1d03eSRichard   template<typename T>
1989a1d03eSRichard   struct CAA {
2089a1d03eSRichard     struct CAB {
2189a1d03eSRichard       void f4();
2289a1d03eSRichard     };
2389a1d03eSRichard   };
2489a1d03eSRichard };
2589a1d03eSRichard 
2689a1d03eSRichard void CA::f2() { }
2789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: function 'f2' defined in a header file;
2889a1d03eSRichard // CHECK-FIXES: inline void CA::f2() {
2989a1d03eSRichard 
3089a1d03eSRichard template <>
3189a1d03eSRichard int CA::f3() {
3289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: full function template specialization 'f3<int>' defined in a header file;
3389a1d03eSRichard // CHECK-FIXES: inline int CA::f3() {
3489a1d03eSRichard   int a = 1;
3589a1d03eSRichard   return a;
3689a1d03eSRichard }
3789a1d03eSRichard 
3889a1d03eSRichard template <typename T>
3989a1d03eSRichard void CA::CAA<T>::CAB::f4() {
4089a1d03eSRichard // OK: member function definition of a nested template class in a class.
4189a1d03eSRichard }
4289a1d03eSRichard 
4389a1d03eSRichard template <typename T>
4489a1d03eSRichard struct CB {
4589a1d03eSRichard   void f1();
4689a1d03eSRichard   struct CCA {
4789a1d03eSRichard     void f2(T a);
4889a1d03eSRichard   };
4989a1d03eSRichard   struct CCB;  // OK: forward declaration.
5089a1d03eSRichard   static int a; // OK: class static data member declaration.
5189a1d03eSRichard };
5289a1d03eSRichard 
5389a1d03eSRichard template <typename T>
5489a1d03eSRichard void CB<T>::f1() { // OK: Member function definition of a class template.
5589a1d03eSRichard }
5689a1d03eSRichard 
5789a1d03eSRichard template <typename T>
5889a1d03eSRichard void CB<T>::CCA::f2(T a) {
5989a1d03eSRichard // OK: member function definition of a nested class in a class template.
6089a1d03eSRichard }
6189a1d03eSRichard 
6289a1d03eSRichard template <typename T>
6389a1d03eSRichard struct CB<T>::CCB {
6489a1d03eSRichard   void f3();
6589a1d03eSRichard };
6689a1d03eSRichard 
6789a1d03eSRichard template <typename T>
6889a1d03eSRichard void CB<T>::CCB::f3() {
6989a1d03eSRichard // OK: member function definition of a nested class in a class template.
7089a1d03eSRichard }
7189a1d03eSRichard 
7289a1d03eSRichard template <typename T>
7389a1d03eSRichard int CB<T>::a = 2; // OK: static data member definition of a class template.
7489a1d03eSRichard 
7589a1d03eSRichard template class CB<int>; // OK: explicitly instantiated static data member of a class template.
7689a1d03eSRichard inline int callCB() {
7789a1d03eSRichard   CB<double> cb; // OK: implicitly instantiated static data member of a class template.
7889a1d03eSRichard   return cb.a;
7989a1d03eSRichard }
8089a1d03eSRichard 
8189a1d03eSRichard template <typename T>
8289a1d03eSRichard T tf() { // OK: template function definition.
8389a1d03eSRichard   T a;
8489a1d03eSRichard   return a;
8589a1d03eSRichard }
8689a1d03eSRichard 
8789a1d03eSRichard 
8889a1d03eSRichard namespace NA {
8989a1d03eSRichard   int f() { return 1; }
9089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: function 'f' defined in a header file;
9189a1d03eSRichard // CHECK-FIXES: inline int f() { return 1; }
9289a1d03eSRichard }
9389a1d03eSRichard 
9489a1d03eSRichard template <typename T>
9589a1d03eSRichard T f3() {
9689a1d03eSRichard   T a = 1;
9789a1d03eSRichard   return a;
9889a1d03eSRichard }
9989a1d03eSRichard 
10089a1d03eSRichard template <>
10189a1d03eSRichard int f3() {
10289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: full function template specialization 'f3<int>' defined in a header file;
10389a1d03eSRichard // CHECK-FIXES: inline int f3() {
10489a1d03eSRichard   int a = 1;
10589a1d03eSRichard   return a;
10689a1d03eSRichard }
10789a1d03eSRichard 
10889a1d03eSRichard int f5(); // OK: function declaration.
10989a1d03eSRichard inline int f6() { return 1; } // OK: inline function definition.
11089a1d03eSRichard namespace {
1112469bd98SCarlos Galvez   int f7() { return 1; }  // OK: each TU defines the function in a unique namespace.
11289a1d03eSRichard }
11389a1d03eSRichard 
11489a1d03eSRichard int f8() = delete; // OK: the function being marked delete is not callable.
11589a1d03eSRichard 
11689a1d03eSRichard template <typename T>
11789a1d03eSRichard int f9(T t) { return 1; }
11889a1d03eSRichard 
11989a1d03eSRichard inline void callF9() { f9(1); } // OK: implicitly instantiated function.
12089a1d03eSRichard template int f9(double); // OK: explicitly instantiated function.
12189a1d03eSRichard 
12289a1d03eSRichard int a = 1;
12389a1d03eSRichard // 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]
12489a1d03eSRichard CA a1;
12589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: variable 'a1' defined in a header file;
12689a1d03eSRichard 
12789a1d03eSRichard namespace NB {
12889a1d03eSRichard   int b = 1;
12989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'b' defined in a header file;
13089a1d03eSRichard   const int c = 1; // OK: internal linkage variable definition.
13189a1d03eSRichard }
13289a1d03eSRichard 
13389a1d03eSRichard class CC {
13489a1d03eSRichard   static int d; // OK: class static data member declaration.
13589a1d03eSRichard };
13689a1d03eSRichard 
13789a1d03eSRichard int CC::d = 1;
13889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: variable 'd' defined in a header file;
13989a1d03eSRichard 
14089a1d03eSRichard const char* ca = "foo";
14189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'ca' defined in a header file;
14289a1d03eSRichard 
14389a1d03eSRichard namespace {
1442469bd98SCarlos Galvez   int e = 2;  // OK: each TU defines the variable in a unique namespace.
14589a1d03eSRichard }
14689a1d03eSRichard 
14789a1d03eSRichard const char* const g = "foo"; // OK: internal linkage variable definition.
14889a1d03eSRichard static int h = 1; // OK: internal linkage variable definition.
14989a1d03eSRichard const int i = 1; // OK: internal linkage variable definition.
15089a1d03eSRichard extern int j; // OK: internal linkage variable definition.
15189a1d03eSRichard 
15289a1d03eSRichard template <typename T, typename U>
15389a1d03eSRichard struct CD {
15489a1d03eSRichard   int f();
15589a1d03eSRichard };
15689a1d03eSRichard 
15789a1d03eSRichard template <typename T>
15889a1d03eSRichard struct CD<T, int> {
15989a1d03eSRichard   int f();
16089a1d03eSRichard };
16189a1d03eSRichard 
16289a1d03eSRichard template <>
16389a1d03eSRichard struct CD<int, int> {
16489a1d03eSRichard   int f();
16589a1d03eSRichard };
16689a1d03eSRichard 
16789a1d03eSRichard int CD<int, int>::f() {
16889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: function 'f' defined in a header file;
16989a1d03eSRichard // CHECK-FIXES: inline int CD<int, int>::f() {
17089a1d03eSRichard   return 0;
17189a1d03eSRichard }
17289a1d03eSRichard 
17389a1d03eSRichard template <typename T>
17489a1d03eSRichard int CD<T, int>::f() { // OK: partial template specialization.
17589a1d03eSRichard   return 0;
17689a1d03eSRichard }
17789a1d03eSRichard 
17889a1d03eSRichard constexpr int k = 1; // OK: constexpr variable has internal linkage.
17989a1d03eSRichard 
18089a1d03eSRichard constexpr int f10() { return 0; } // OK: constexpr function definition.
18189a1d03eSRichard 
18289a1d03eSRichard const int f11() { return 0; }
18389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: function 'f11' defined in a header file;
18489a1d03eSRichard // CHECK-FIXES: inline const int f11() { return 0; }
18589a1d03eSRichard 
18689a1d03eSRichard template <typename T>
18789a1d03eSRichard const T f12();
18889a1d03eSRichard 
18989a1d03eSRichard template <>
19089a1d03eSRichard const int f12() { return 0; }
19189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: full function template specialization 'f12<int>' defined in a header file;
19289a1d03eSRichard // CHECK-FIXES: inline const int f12() { return 0; }
19389a1d03eSRichard 
19489a1d03eSRichard template <typename T1, typename T2>
19589a1d03eSRichard constexpr bool f13 = false;
19689a1d03eSRichard 
19789a1d03eSRichard template <typename T>
19889a1d03eSRichard constexpr bool f13<T, int> = true; // OK: template partial specialization
19989a1d03eSRichard 
20089a1d03eSRichard template <>
20189a1d03eSRichard constexpr bool f13<void, int> = false;
20289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: variable 'f13<void, int>' defined in a header file;
20389a1d03eSRichard 
20489a1d03eSRichard int main() {}
20589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'main' defined in a header file;
20689a1d03eSRichard // CHECK-FIXES: {{^}}int main() {
207