// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s struct Plain {}; enum Color { Red }; template struct Wrap {}; template struct Defaulted {}; template T defaulted_var = T{}; namespace ns { template void foo(T x) {} template T bar = T{}; template struct S { void method(T x) {} static T sval; static T arr[1]; template void tmpl(U u) {} template static U mvar; template struct Nested {}; struct Inner { T val; }; }; template T S::sval = T{}; template T S::arr[1] = {}; template template U S::mvar = U{}; template struct A { template struct B { template void deep(V v) {} }; }; } // (a) function template template void ns::foo(int); // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'foo' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: Function {{.*}} 'foo' 'void (int)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (int)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:31 'int' // CHECK-NEXT: BuiltinTypeLoc 'int' // CHECK-NEXT: BuiltinTypeLoc 'void' // CHECK-NEXT: TemplateArgument type 'int' // CHECK-NEXT: BuiltinType {{.*}} 'int' // (b) variable template template int ns::bar; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'bar' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'bar' 'int' // CHECK-NEXT: BuiltinTypeLoc 'int' // CHECK-NEXT: TemplateArgument type 'int' // CHECK-NEXT: BuiltinType {{.*}} 'int' // (c) class template template struct ns::S; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'S' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'S' // CHECK-NEXT: TemplateArgument type 'int' // CHECK-NEXT: BuiltinType {{.*}} 'int' // (d) member function template void ns::S::method(long); // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'method' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: CXXMethod {{.*}} 'method' 'void (long)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (long)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:39 'long' // CHECK-NEXT: BuiltinTypeLoc 'long' // CHECK-NEXT: BuiltinTypeLoc 'void' // (e) static data member template long ns::S::sval; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'sval' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: Var {{.*}} 'sval' 'long' // CHECK-NEXT: BuiltinTypeLoc 'long' // (e2) static data member with postfix type (array) template long ns::S::arr[1]; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'arr' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: Var {{.*}} 'arr' 'long[1]' // CHECK-NEXT: ConstantArrayTypeLoc 'long[1]' 1 // CHECK-NEXT: BuiltinTypeLoc 'long' // (f) member function template template void ns::S::tmpl(double); // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'tmpl' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: CXXMethod {{.*}} 'tmpl' 'void (double)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (double)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:47 'double' // CHECK-NEXT: BuiltinTypeLoc 'double' // CHECK-NEXT: BuiltinTypeLoc 'void' // CHECK-NEXT: TemplateArgument type 'double' // CHECK-NEXT: BuiltinType {{.*}} 'double' // (g) nested class template struct ns::S::Inner; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'Inner' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: CXXRecord {{.*}} 'Inner' // extern template variants extern template void ns::foo(float); // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'foo' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: Function {{.*}} 'foo' 'void (float)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (float)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:42 'float' // CHECK-NEXT: BuiltinTypeLoc 'float' // CHECK-NEXT: BuiltinTypeLoc 'void' // CHECK-NEXT: TemplateArgument type 'float' // CHECK-NEXT: BuiltinType {{.*}} 'float' extern template struct ns::S; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'S' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'S' // CHECK-NEXT: TemplateArgument type 'float' // CHECK-NEXT: BuiltinType {{.*}} 'float' // extern template: variable template extern template double ns::bar; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'bar' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'bar' 'double' // CHECK-NEXT: BuiltinTypeLoc 'double' // CHECK-NEXT: TemplateArgument type 'double' // CHECK-NEXT: BuiltinType {{.*}} 'double' // extern template: member function extern template void ns::S::method(double); // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'method' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: CXXMethod {{.*}} 'method' 'void (double)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (double)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:50 'double' // CHECK-NEXT: BuiltinTypeLoc 'double' // CHECK-NEXT: BuiltinTypeLoc 'void' // extern template: static data member extern template double ns::S::sval; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'sval' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: Var {{.*}} 'sval' 'double' // CHECK-NEXT: BuiltinTypeLoc 'double' // extern template: member function template extern template void ns::S::tmpl(float); // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'tmpl' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: CXXMethod {{.*}} 'tmpl' 'void (float)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (float)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:54 'float' // CHECK-NEXT: BuiltinTypeLoc 'float' // CHECK-NEXT: BuiltinTypeLoc 'void' // CHECK-NEXT: TemplateArgument type 'float' // CHECK-NEXT: BuiltinType {{.*}} 'float' // extern template: nested class extern template struct ns::S::Inner; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'Inner' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: CXXRecord {{.*}} 'Inner' // extern template: member variable template extern template double ns::S::mvar; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'mvar' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'mvar' 'double' // CHECK-NEXT: BuiltinTypeLoc 'double' // CHECK-NEXT: TemplateArgument type 'double' // CHECK-NEXT: BuiltinType {{.*}} 'double' // extern template: member class template extern template struct ns::S::Nested; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'Nested' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'Nested' // CHECK-NEXT: TemplateArgument type 'double' // CHECK-NEXT: BuiltinType {{.*}} 'double' // extern template: static data member (array) extern template double ns::S::arr[1]; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'arr' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: Var {{.*}} 'arr' 'double[1]' // CHECK-NEXT: ConstantArrayTypeLoc 'double[1]' 1 // CHECK-NEXT: BuiltinTypeLoc 'double' // extern template: deeply nested extern template void ns::A::B::deep(double); // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'deep' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::A::B' // CHECK-NEXT: CXXMethod {{.*}} 'deep' 'void (double)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (double)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:63 'double' // CHECK-NEXT: BuiltinTypeLoc 'double' // CHECK-NEXT: BuiltinTypeLoc 'void' // CHECK-NEXT: TemplateArgument type 'double' // CHECK-NEXT: BuiltinType {{.*}} 'double' // member variable template template double ns::S::mvar; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'mvar' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'mvar' 'double' // CHECK-NEXT: BuiltinTypeLoc 'double' // CHECK-NEXT: TemplateArgument type 'double' // CHECK-NEXT: BuiltinType {{.*}} 'double' // member class template template struct ns::S::Nested; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'Nested' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'Nested' // CHECK-NEXT: TemplateArgument type 'double' // CHECK-NEXT: BuiltinType {{.*}} 'double' // deeply nested: A::B::deep template void ns::A::B::deep(float); // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'deep' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::A::B' // CHECK-NEXT: CXXMethod {{.*}} 'deep' 'void (float)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (float)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:55 'float' // CHECK-NEXT: BuiltinTypeLoc 'float' // CHECK-NEXT: BuiltinTypeLoc 'void' // CHECK-NEXT: TemplateArgument type 'float' // CHECK-NEXT: BuiltinType {{.*}} 'float' // Same-namespace explicit instantiation (no cross-namespace qualifier) namespace ns { template void foo(short); // CHECK: ExplicitInstantiationDecl {{.*}} col:3 explicit_instantiation_definition 'foo' // CHECK-NEXT: Function {{.*}} 'foo' 'void (short)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (short)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:33 'short' // CHECK-NEXT: BuiltinTypeLoc 'short' // CHECK-NEXT: BuiltinTypeLoc 'void' // CHECK-NEXT: TemplateArgument type 'short' // CHECK-NEXT: BuiltinType {{.*}} 'short' template short bar; // CHECK: ExplicitInstantiationDecl {{.*}} col:3 explicit_instantiation_definition 'bar' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'bar' 'short' // CHECK-NEXT: BuiltinTypeLoc 'short' // CHECK-NEXT: TemplateArgument type 'short' // CHECK-NEXT: BuiltinType {{.*}} 'short' template struct S; // CHECK: ExplicitInstantiationDecl {{.*}} col:3 explicit_instantiation_definition 'S' // CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'S' // CHECK-NEXT: TemplateArgument type 'short' // CHECK-NEXT: BuiltinType {{.*}} 'short' } // empty <> (args deduced) template void ns::foo<>(double); // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'foo' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: Function {{.*}} 'foo' 'void (double)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (double)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:31 'double' // CHECK-NEXT: BuiltinTypeLoc 'double' // CHECK-NEXT: BuiltinTypeLoc 'void' template void ns::S::tmpl<>(float); // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'tmpl' // CHECK-NEXT: NestedNameSpecifier TypeSpec 'ns::S' // CHECK-NEXT: CXXMethod {{.*}} 'tmpl' 'void (float)' // CHECK-NEXT: FunctionProtoTypeLoc 'void (float)' cdecl // CHECK-NEXT: ParmVarDecl {{.*}} col:40 'float' // CHECK-NEXT: BuiltinTypeLoc 'float' // CHECK-NEXT: BuiltinTypeLoc 'void' // empty <> (default template arguments) template struct Defaulted<>; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'Defaulted' // CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'Defaulted' template int defaulted_var<>; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'defaulted_var' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'defaulted_var' 'int' // CHECK-NEXT: BuiltinTypeLoc 'int' extern template Plain ns::bar; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'bar' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'bar' 'Plain' // CHECK-NEXT: RecordTypeLoc 'Plain' // CHECK: TemplateArgument type 'Plain' template Plain ns::bar; // CHECK: ExplicitInstantiationDecl {{.*}} col:1 explicit_instantiation_definition 'bar' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'bar' 'Plain' // CHECK-NEXT: RecordTypeLoc 'Plain' // CHECK: TemplateArgument type 'Plain' extern template Color ns::bar; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'bar' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'bar' 'Color' // CHECK-NEXT: EnumTypeLoc 'Color' // CHECK: TemplateArgument type 'Color' extern template Wrap ns::bar>; // CHECK: ExplicitInstantiationDecl {{.*}} col:8 explicit_instantiation_declaration extern 'bar' // CHECK-NEXT: NestedNameSpecifier Namespace {{.*}} 'ns' // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'bar' 'Wrap' // CHECK-NEXT: TemplateSpecializationTypeLoc 'Wrap' namespace ns { extern template Wrap bar>; // CHECK: ExplicitInstantiationDecl {{.*}} col:10 explicit_instantiation_declaration extern 'bar' // CHECK-NOT: NestedNameSpecifier // CHECK-NEXT: VarTemplateSpecialization {{.*}} 'bar' 'Wrap' // CHECK-NEXT: TemplateSpecializationTypeLoc 'Wrap' }