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