xref: /llvm-project/clang/test/PCH/cxx1y-variable-templates.cpp (revision 9a88aa0e2b6d09c7c7932e14224632b2033ad403)
1 // No PCH:
2 // RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s -DNONPCH
3 // RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s -DNONPCH -DERROR
4 //
5 // With PCH:
6 // RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t.a -DHEADER1
7 // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch %s -o %t.b -DHEADER2
8 // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s -DHEADERUSE
9 
10 // RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch -fpch-instantiate-templates %s -o %t.a -DHEADER1
11 // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch -fpch-instantiate-templates %s -o %t.b -DHEADER2
12 // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s -DHEADERUSE
13 
14 #ifndef ERROR
15 // expected-no-diagnostics
16 #endif
17 
18 #ifdef NONPCH
19 #if !defined(HEADER1)
20 #define HEADER1
21 #undef HEADER2
22 #undef HEADERUSE
23 #elif !defined(HEADER2)
24 #define HEADER2
25 #undef HEADERUSE
26 #else
27 #define HEADERUSE
28 #undef HEADER1
29 #undef HEADER2
30 #endif
31 #endif
32 
33 
34 // *** HEADER1: First header file
35 #if defined(HEADER1) && !defined(HEADER2) && !defined(HEADERUSE)
36 
37 template<typename T> T var0a = T();
38 template<typename T> extern T var0b;
39 
40 namespace join {
41   template<typename T> T va = T(100);
42   template<typename T> extern T vb;
43 
44   namespace diff_types {
45 #ifdef ERROR
46     template<typename T> extern float err0;
47     template<typename T> extern T err1;
48 #endif
49     template<typename T> extern T def;
50   }
51 
52 }
53 
54 namespace spec {
55   template<typename T> constexpr T va = T(10);
56   template<> constexpr float va<float> = 1.5;
57   template constexpr int va<int>;
58 
59   template<typename T> T vb = T();
60   template<> constexpr float vb<float> = 1.5;
61 
62   template<typename T> T vc = T();
63 
64   template<typename T> constexpr T vd = T(10);
65   template<typename T> T* vd<T*> = new T();
66 }
67 
68 namespace spec_join1 {
69   template<typename T> T va = T(10);
70 #ifdef ERROR
71   template<> float va<float>; // expected-note {{previous definition is here}}
72 #endif
73   extern template int va<int>;
74 
75   template<typename T> T vb = T(10);
76 #ifdef ERROR
77   template<> float vb<float>; // expected-note {{previous definition is here}}
78 #endif
79 
80   template<typename T> T vc = T(10);
81 
82   template<typename T> T vd = T(10);
83   template<typename T> extern T* vd<T*>;
84 }
85 
86 #endif
87 
88 
89 // *** HEADER2: Second header file -- including HEADER1
90 #if defined(HEADER2) && !defined(HEADERUSE)
91 
92 namespace join {
93   template<typename T> extern T va;
94   template<> constexpr float va<float> = 2.5;
95 
96   template<typename T> T vb = T(100);
97 
98   namespace diff_types {
99 #ifdef ERROR
100     template<typename T> extern T err0; // expected-error {{redeclaration of 'err0' with a different type: 'T' vs 'float'}}  // expected-note@46 {{previous declaration is here}}
101     template<typename T> extern float err1; // expected-error {{redeclaration of 'err1' with a different type: 'float' vs 'T'}} // expected-note@47 {{previous declaration is here}}
102 #endif
103     template<typename T> extern T def;
104   }
105 }
106 
107 namespace spec_join1 {
108   template<typename T> extern T va;
109 #ifdef ERROR
110   template<> float va<float> = 1.5; // expected-error {{redefinition of 'va<float>'}}
111 #endif
112   extern template int va<int>;
113 
114 #ifdef ERROR
115   template<> float vb<float> = 1.5; // expected-error {{redefinition of 'vb<float>'}}
116 #endif
117   template int vb<int>;
118 
119   template<> float vc<float> = 1.5;
120   template int vc<int>;
121 
122   template<typename T> extern T vd;
123   template<typename T> T* vd<T*> = new T();
124 }
125 
126 #endif
127 
128 // *** HEADERUSE: File using both header files -- including HEADER2
129 #ifdef HEADERUSE
130 
131 template int var0a<int>;
132 float fvara = var0a<float>;
133 
134 template<typename T> extern T var0a;
135 
136 template<typename T> T var0b = T();
137 template int var0b<int>;
138 float fvarb = var0b<float>;
139 
140 namespace join {
141   template const int va<const int>;
142   template<> const int va<int> = 50;
143   static_assert(va<float> == 2.5, "");
144   static_assert(va<int> == 50, "");
145 
146   template<> constexpr float vb<float> = 2.5;
147   template const int vb<const int>;
148   static_assert(vb<float> == 2.5, "");
149   static_assert(vb<const int> == 100, "");
150 
151   namespace diff_types {
152     template<typename T> T def = T();
153   }
154 
155 }
156 
157 namespace spec {
158   static_assert(va<float> == 1.5, "");
159   static_assert(va<int> == 10, "");
160 
161   template<typename T> T* vb<T*> = new T();
162   int* intpb = vb<int*>;
163   static_assert(vb<float> == 1.5, "");
164 
165   template<typename T> T* vc<T*> = new T();
166   template<> constexpr float vc<float> = 1.5;
167   int* intpc = vc<int*>;
168   static_assert(vc<float> == 1.5, "");
169 
170   char* intpd = vd<char*>;
171 }
172 
173 namespace spec_join1 {
174   template int va<int>;
175   int a = va<int>;
176 
177   template<typename T> extern T vb;
178   int b = vb<int>;
179 
180   int* intpb = vd<int*>;
181 }
182 
183 #endif
184