| // 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 {{redeclaration of 'err0' with a different type: 'T' vs 'float'}} // expected-note@42 {{previous declaration is here}} |
| template<typename T> extern float err1; // expected-error {{redeclaration of 'err1' with a different type: 'float' vs 'T'}} // expected-note@43 {{previous declaration 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 |