// RUN: %clang_cc1 -ast-print %s -o - -std=c++17 | FileCheck %s namespace ns { template struct S { T x; }; template void foo(T) {} template T var = T(); } // CHECK: template struct ns::S; template struct ns::S; // CHECK: extern template struct ns::S; extern template struct ns::S; // CHECK: template void ns::foo(int); template void ns::foo(int); // CHECK: extern template void ns::foo(float); extern template void ns::foo(float); template void bar(T) {} // CHECK: template void bar(int); template void bar(int); // empty <> (args deduced) // CHECK: template void ns::foo(double); template void ns::foo<>(double); // CHECK: template int ns::var; template int ns::var; // CHECK: extern template float ns::var; extern template float ns::var; namespace ns { // CHECK: template struct S; template struct S; // CHECK: template void foo(short); template void foo(short); // CHECK: template short var; template short var; } template struct X { struct Inner {}; }; // CHECK: template struct X::Inner; template struct X::Inner; // CHECK: extern template struct X::Inner; extern template struct X::Inner; template struct Outer { void method(); template void f(U); template static U var; template struct Inner {}; static T sval; static T arr[1]; }; template void Outer::method() {} template template void Outer::f(U) {} template template U Outer::var = U{}; template T Outer::sval = T{}; template T Outer::arr[1] = {}; // CHECK: template void Outer::method(); template void Outer::method(); // CHECK: template void Outer::f(double); template void Outer::f(double); // CHECK: template double Outer::var; template double Outer::var; // CHECK: template struct Outer::Inner; template struct Outer::Inner; // CHECK: template int Outer::sval; template int Outer::sval; // CHECK: template int Outer::arr[1]; template int Outer::arr[1]; // CHECK: extern template void Outer::method(); extern template void Outer::method(); // CHECK: extern template void Outer::f(double); extern template void Outer::f(double); // CHECK: extern template double Outer::var; extern template double Outer::var; // CHECK: extern template struct Outer::Inner; extern template struct Outer::Inner; // CHECK: extern template int Outer::sval; extern template int Outer::sval; template struct A { template struct B { template void g(V); }; }; template template template void A::B::g(V) {} // CHECK: template void A::B::g(float); template void A::B::g(float); // CHECK: extern template void A::B::g(int); extern template void A::B::g(int); namespace GH197797 { struct S {}; enum E { X }; template struct Wrap {}; template T var = T{}; // CHECK: extern template S var; extern template S var; // CHECK: extern template E var; extern template E var; // CHECK: extern template Wrap var>; extern template Wrap var>; template T var2 = T{}; // CHECK: extern template ns::S var2>; extern template ns::S var2>; // CHECK: extern template ns::S var2>; extern template ns::S var2>; } // namespace GH197797 // empty <> (default template arguments) template struct Defaulted {}; // CHECK: template struct Defaulted; template struct Defaulted<>; template T defaulted_var = T{}; // CHECK: template int defaulted_var; template int defaulted_var<>;