Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2825,6 +2825,8 @@ "exported templates are unsupported">; def err_template_outside_namespace_or_class_scope : Error< "templates can only be declared in namespace or class scope">; +def err_template_inside_local_class : Error< + "templates cannot be declared inside of a local class">; def err_template_linkage : Error<"templates must have C++ linkage">; def err_template_typedef : Error<"a typedef cannot be a template">; def err_template_unnamed_class : Error< Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -5459,8 +5459,20 @@ while (Ctx && isa(Ctx)) Ctx = Ctx->getParent(); - if (Ctx && (Ctx->isFileContext() || Ctx->isRecord())) - return false; + if (Ctx) { + if (Ctx->isFileContext()) + return false; + if (CXXRecordDecl *RD = dyn_cast(Ctx)) { + // C++ [temp.mem]p2: + // A local class shall not have member templates. + if (RD->isLocalClass()) + return Diag(TemplateParams->getTemplateLoc(), + diag::err_template_inside_local_class) + << TemplateParams->getSourceRange(); + else + return false; + } + } return Diag(TemplateParams->getTemplateLoc(), diag::err_template_outside_namespace_or_class_scope) Index: test/CXX/temp/temp.decls/temp.mem/p2.cpp =================================================================== --- /dev/null +++ test/CXX/temp/temp.decls/temp.mem/p2.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template +void quux(); + +void fun() { + struct foo { + template struct bar {}; // expected-error{{templates cannot be declared inside of a local class}} + template void baz() {} // expected-error{{templates cannot be declared inside of a local class}} + template void qux(); // expected-error{{templates cannot be declared inside of a local class}} + }; +} Index: test/CodeGenCXX/mangle-local-class-names.cpp =================================================================== --- test/CodeGenCXX/mangle-local-class-names.cpp +++ test/CodeGenCXX/mangle-local-class-names.cpp @@ -75,16 +75,6 @@ } void CallOmittingCode() { OmittingCode(1); } -// CHECK: @_ZZ25LocalTemplateFunctionTestdEN5Local3fooIdEET_S1_ -int LocalTemplateFunctionTest(double d) { - struct Local { - template T foo(T t) { - return t; - } - }; - return Local().foo(d); -} - // CHECK: @_ZZ15LocalAnonStructvENUt0_1gEv inline void LocalAnonStruct() { if (0) { Index: test/PCH/cxx-local-templates.cpp =================================================================== --- test/PCH/cxx-local-templates.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t-cxx11 -// RUN: %clang_cc1 -ast-print -pedantic-errors -std=c++11 -include-pch %t-cxx11 %s | FileCheck -check-prefix=CHECK-PRINT %s - -#ifndef HEADER_INCLUDED - -#define HEADER_INCLUDED - -int nontemplate_test(double d) { - struct Local { - template T foo(T t) { - return t; - } - }; - return Local{}.foo(d); -} - -template -U template_test(U d) { - struct Local { - template T foo(T t) { - return t; - } - }; - return Local{}.foo(d); -} - -int nested_local() { - struct Inner1 { - int inner1_foo(char c) { - struct Inner2 { - template T inner2_foo(T t) { - return t; - } - }; - return Inner2{}.inner2_foo(3.14); - } - }; - return Inner1{}.inner1_foo('a'); -} - -#else - -// CHECK-PRINT: U template_test - -// CHECK-PRINT: int nontemplate_test(double) - -int nontemplate_test(double); - -template double template_test(double); -int test2(int y) { - return nontemplate_test(y) + template_test(y); -} - - -#endif Index: test/PCH/cxx1y-local-templates.cpp =================================================================== --- test/PCH/cxx1y-local-templates.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// RUN: %clang_cc1 -pedantic-errors -std=c++1y -emit-pch %s -o %t-cxx1y -// RUN: %clang_cc1 -ast-print -pedantic-errors -std=c++1y -include-pch %t-cxx1y %s | FileCheck -check-prefix=CHECK-PRINT %s - -#ifndef HEADER_INCLUDED - -#define HEADER_INCLUDED - -auto nested_local_call_all() { - struct Inner1 { - auto inner1_foo(char c) { - struct Inner2 { - template T inner2_foo(T t) { - return t; - } - }; - return Inner2{}; - } - }; - return Inner1{}.inner1_foo('a').inner2_foo(4); -} - - -auto nested_local() { - struct Inner1 { - auto inner1_foo(char c) { - struct Inner2 { - template T inner2_foo(T t) { - return t; - } - }; - return Inner2{}; - } - }; - return Inner1{}; -} - - -int test() { - auto A = nested_local_call_all(); - auto B = nested_local(); - auto C = B.inner1_foo('a'); - C.inner2_foo(3.14); - -} - - -#else - -// CHECK-PRINT: int nested_local_call_all -// CHECK-PRINT: nested_local -auto nested_local_call_all(); - -int test(int y) { - return nested_local_call_all(); -} - - -#endif Index: test/SemaTemplate/instantiate-exception-spec-cxx11.cpp =================================================================== --- test/SemaTemplate/instantiate-exception-spec-cxx11.cpp +++ test/SemaTemplate/instantiate-exception-spec-cxx11.cpp @@ -44,13 +44,14 @@ A().f(42); } + struct S { + template + static int f() noexcept(noexcept(A().f("boo!"))) { return 0; } // \ + // expected-note {{instantiation of exception spec}} + typedef decltype(f()) X; + }; + int test2() { - struct S { - template - static int f() noexcept(noexcept(A().f("boo!"))) { return 0; } // \ - // expected-note {{instantiation of exception spec}} - typedef decltype(f()) X; - }; S().f(); // ok S().f(); // expected-note {{instantiation of exception spec}} } Index: test/SemaTemplate/local-member-templates.cpp =================================================================== --- test/SemaTemplate/local-member-templates.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// RUN: %clang_cc1 -std=c++1y -verify %s -// RUN: %clang_cc1 -std=c++1y -verify %s -fdelayed-template-parsing - -namespace nested_local_templates_1 { - -template struct Outer { - template int outer_mem(T t, U u) { - struct Inner { - template int inner_mem(T t, U u, V v) { - struct InnerInner { - template int inner_inner_mem(W w, T t, U u, V v) { - return 0; - } - }; - InnerInner().inner_inner_mem("abc", t, u, v); - return 0; - } - }; - Inner i; - i.inner_mem(t, u, 3.14); - return 0; - } - - template int outer_mem(T t, U *u); -}; - -template int Outer::outer_mem(int, char); - -template template int Outer::outer_mem(T t, U *u) { - struct Inner { - template - int inner_mem(T t, U u, V v) { //expected-note{{candidate function}} - struct InnerInner { - template int inner_inner_mem(W w, T t, U u, V v) { return 0; } - }; - InnerInner().inner_inner_mem("abc", t, u, v); - return 0; - } - }; - Inner i; - i.inner_mem(t, U{}, i); - i.inner_mem(t, u, 3.14); //expected-error{{no matching member function for call to 'inner}} - return 0; -} - -template int Outer::outer_mem(int, char *); //expected-note{{in instantiation of function}} - -} // end ns - -namespace nested_local_templates_2 { - -template struct Outer { - template void outer_mem(T t, U u) { - struct Inner { - template struct InnerTemplateClass { - template - void itc_mem(T t, U u, V v, W w) { //expected-note{{candidate function}} - struct InnerInnerInner { - template void iii_mem(X x) {} - }; - InnerInnerInner i; - i.iii_mem("abc"); - } - }; - }; - Inner i; - typename Inner::template InnerTemplateClass ii; - ii.itc_mem(t, u, i, "jim"); - ii.itc_mem(t, u, 0, "abd"); //expected-error{{no matching member function}} - } -}; - -template void -Outer::outer_mem(int, char); //expected-note{{in instantiation of}} - -} - -namespace more_nested_local_templates { - -int test() { - struct Local { - template void foo(U u) { - struct Inner { - template - auto operator()(A a, U u2) -> U { - return u2; - }; - }; - Inner GL; - GL('a', u ); - GL(3.14, u ); - } - }; - Local l; - l.foo("nmabc"); - return 0; -} -int t = test(); -} \ No newline at end of file