// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s template class A {}; extern "C++" { template class B {}; template class A; template<> class A; template class A; template class B; template<> class B; template class B; } namespace N { template class C; } extern "C" { // expected-note 3 {{extern "C" language linkage specification begins here}} template class D; // expected-error{{templates must have C++ linkage}} template class A; // expected-error{{templates must have C++ linkage}} template<> class A; // expected-error{{templates must have C++ linkage}} template class A; // OK (surprisingly) FIXME: Should we warn on this? } extern "C" { // expected-note 2 {{extern "C" language linkage specification begins here}} class PR17968 { template class D; // expected-error{{templates must have C++ linkage}} template void f(); // expected-error{{templates must have C++ linkage}} }; } template class A; // expected-note{{previous template declaration is here}} template class A; // expected-error{{template parameter has a different kind in template redeclaration}} template class NonTypeTemplateParm; typedef int INT; template class NonTypeTemplateParm; // expected-note{{previous non-type template parameter with type 'INT' (aka 'int') is here}} template class NonTypeTemplateParm; // expected-error{{template non-type parameter has a different type 'long' in template redeclaration}} template class X> class TemplateTemplateParm; template class Y> class TemplateTemplateParm; // expected-note{{previous template declaration is here}} \ // expected-note{{previous template template parameter is here}} template class TemplateTemplateParm; // expected-error{{template parameter has a different kind in template redeclaration}} template class X> class TemplateTemplateParm; // expected-error{{too many template parameters in template template parameter redeclaration}} template struct test {}; // expected-note{{previous definition}} template struct test : T {}; // expected-error{{redefinition}} class X { public: template class C; }; void f() { template class X; // expected-error{{expression}} } template class X1 var; // expected-error {{variable has incomplete type 'class X1'}} \ // expected-note {{forward declaration of 'X1'}} namespace M { } template class M::C3 { }; // expected-error{{out-of-line definition of 'C3' does not match any declaration in namespace 'M'}} namespace PR8001 { template struct Foo { template class Bar; typedef Bar Baz; template struct Bar { Bar() {} }; }; void pr8001() { Foo::Baz x; Foo::Bar y(x); } } namespace rdar9676205 { template class tuple_element; template class pair; template class tuple_element<0, pair<_T1, _T2> > { template struct X { template ::value> struct Y : public X<_Up>, public Y<_Up> { }; }; }; } namespace redecl { int A; // expected-note {{here}} template struct A; // expected-error {{different kind of symbol}} int B; // expected-note {{here}} template struct B { // expected-error {{different kind of symbol}} }; template struct F; template struct K; int G, H; // expected-note {{here}} struct S { int C; // expected-note {{here}} template struct C; // expected-error {{different kind of symbol}} int D; // expected-note {{here}} template struct D { // expected-error {{different kind of symbol}} }; int E; template friend struct E { // expected-error {{cannot define a type in a friend}} }; int F; template friend struct F; // ok, redecl::F template struct G; // ok template friend struct H; // expected-error {{different kind of symbol}} int I, J, K; struct U { template struct I; // ok template struct J { // ok }; template friend struct K; // ok, redecl::K }; }; } extern "C" template // expected-error{{templates must have C++ linkage}} void DontCrashOnThis() { // expected-note@-1 {{extern "C" language linkage specification begins here}} T &pT = T(); pT; } namespace abstract_dependent_class { template struct A { virtual A *clone() = 0; // expected-note {{pure virtual}} }; template A *A::clone() { return new A; } // expected-error {{abstract class type 'A'}} } namespace qualified_out_of_line { struct rbnode {}; template struct pair {}; template struct rbtree { using base = rbnode; pair f(); }; template pair::base, typename rbtree::base> rbtree::f() { return {}; } }