// No PCH: // RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s -DNONPCH // RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s -DNONPCH -DERROR // // With PCH: // RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t.a -DHEADER1 // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch %s -o %t.b -DHEADER2 // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s -DHEADERUSE #ifndef ERROR // expected-no-diagnostics #endif #ifdef NONPCH #if !defined(HEADER1) #define HEADER1 #undef HEADER2 #undef HEADERUSE #elif !defined(HEADER2) #define HEADER2 #undef HEADERUSE #else #define HEADERUSE #undef HEADER1 #undef HEADER2 #endif #endif // *** HEADER1: First header file #if defined(HEADER1) && !defined(HEADER2) && !defined(HEADERUSE) template<typename T> T var0a = T(); template<typename T> extern T var0b; namespace join { template<typename T> T va = T(100); template<typename T> extern T vb; namespace diff_types { #ifdef ERROR template<typename T> extern float err0; template<typename T> extern T err1; #endif template<typename T> extern T def; } } namespace spec { template<typename T> constexpr T va = T(10); template<> constexpr float va<float> = 1.5; template constexpr int va<int>; template<typename T> T vb = T(); template<> constexpr float vb<float> = 1.5; template<typename T> T vc = T(); template<typename T> constexpr T vd = T(10); template<typename T> T* vd<T*> = new T(); } namespace spec_join1 { template<typename T> T va = T(10); template<> extern float va<float>; extern template int va<int>; template<typename T> T vb = T(10); template<> extern float vb<float>; template<typename T> T vc = T(10); template<typename T> T vd = T(10); template<typename T> extern T* vd<T*>; } #endif // *** HEADER2: Second header file -- including HEADER1 #if defined(HEADER2) && !defined(HEADERUSE) namespace join { template<typename T> extern T va; template<> constexpr float va<float> = 2.5; template<typename T> T vb = T(100); namespace diff_types { #ifdef ERROR 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}} 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}} #endif template<typename T> extern T def; } } namespace spec_join1 { template<typename T> extern T va; template<> float va<float> = 1.5; extern template int va<int>; template<> float vb<float> = 1.5; template int vb<int>; template<> float vc<float> = 1.5; template int vc<int>; template<typename T> extern T vd; template<typename T> T* vd<T*> = new T(); } #endif // *** HEADERUSE: File using both header files -- including HEADER2 #ifdef HEADERUSE template int var0a<int>; float fvara = var0a<float>; template<typename T> extern T var0a; template<typename T> T var0b = T(); template int var0b<int>; float fvarb = var0b<float>; namespace join { template const int va<const int>; template<> const int va<int> = 50; static_assert(va<float> == 2.5, ""); static_assert(va<int> == 50, ""); template<> constexpr float vb<float> = 2.5; template const int vb<const int>; static_assert(vb<float> == 2.5, ""); static_assert(vb<const int> == 100, ""); namespace diff_types { template<typename T> T def = T(); } } namespace spec { static_assert(va<float> == 1.5, ""); static_assert(va<int> == 10, ""); template<typename T> T* vb<T*> = new T(); int* intpb = vb<int*>; static_assert(vb<float> == 1.5, ""); template<typename T> T* vc<T*> = new T(); template<> constexpr float vc<float> = 1.5; int* intpc = vc<int*>; static_assert(vc<float> == 1.5, ""); char* intpd = vd<char*>; } namespace spec_join1 { template int va<int>; int a = va<int>; template<typename T> extern T vb; int b = vb<int>; int* intpb = vd<int*>; } #endif